diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java index c119e374d6639..01a71c8f44c5a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -86,18 +86,22 @@ public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException { String cpu = dbg.getCPU(); if (cpu.equals("amd64") || cpu.equals("x86_64")) { AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext(); + Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP); + if (rsp == null) return null; Address rbp = context.getRegisterAsAddress(AMD64ThreadContext.RBP); if (rbp == null) return null; Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP); if (pc == null) return null; - return new BsdAMD64CFrame(dbg, rbp, pc); + return new BsdAMD64CFrame(dbg, rsp, rbp, pc); } else if (cpu.equals("aarch64")) { AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext(); + Address sp = context.getRegisterAsAddress(AARCH64ThreadContext.SP); + if (sp == null) return null; Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP); if (fp == null) return null; Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC); if (pc == null) return null; - return new BsdAARCH64CFrame(dbg, fp, pc); + return new BsdAARCH64CFrame(dbg, sp, fp, pc); } else { throw new DebuggerException(cpu + " is not yet supported"); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java index ebc5c7d716efd..185148b39b460 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, Red Hat Inc. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,15 +26,19 @@ package sun.jvm.hotspot.debugger.bsd.aarch64; +import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.aarch64.*; import sun.jvm.hotspot.debugger.bsd.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.cdbg.basic.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.aarch64.*; public final class BsdAARCH64CFrame extends BasicCFrame { - public BsdAARCH64CFrame(BsdDebugger dbg, Address fp, Address pc) { + public BsdAARCH64CFrame(BsdDebugger dbg, Address sp, Address fp, Address pc) { super(dbg.getCDebugger()); + this.sp = sp; this.fp = fp; this.pc = pc; this.dbg = dbg; @@ -54,28 +58,65 @@ public Address localVariableBase() { return fp; } + @Override public CFrame sender(ThreadProxy thread) { - AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext(); - Address rsp = context.getRegisterAsAddress(AARCH64ThreadContext.SP); + return sender(thread, null, null, null); + } - if ((fp == null) || fp.lessThan(rsp)) { - return null; + @Override + public CFrame sender(ThreadProxy thread, Address nextSP, Address nextFP, Address nextPC) { + // Check fp + // Skip if both nextFP and nextPC are given - do not need to load from fp. + if (nextFP == null && nextPC == null) { + if (fp == null) { + return null; + } + + // Check alignment of fp + if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) { + return null; + } } - // Check alignment of fp - if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) { + if (nextFP == null) { + nextFP = fp.getAddressAt(0); + } + if (nextFP == null) { return null; } - Address nextFP = fp.getAddressAt(0 * ADDRESS_SIZE); - if (nextFP == null || nextFP.lessThanOrEqual(fp)) { - return null; + if (nextPC == null) { + nextPC = fp.getAddressAt(ADDRESS_SIZE); } - Address nextPC = fp.getAddressAt(1 * ADDRESS_SIZE); if (nextPC == null) { return null; } - return new BsdAARCH64CFrame(dbg, nextFP, nextPC); + + if (nextSP == null) { + CodeCache cc = VM.getVM().getCodeCache(); + CodeBlob currentBlob = cc.findBlobUnsafe(pc()); + + // This case is different from HotSpot. See JDK-8371194 for details. + if (currentBlob != null && (currentBlob.isContinuationStub() || currentBlob.isNativeMethod())) { + // Use FP since it should always be valid for these cases. + // TODO: These should be walked as Frames not CFrames. + nextSP = fp.addOffsetTo(2 * ADDRESS_SIZE); + } else { + CodeBlob codeBlob = cc.findBlobUnsafe(nextPC); + boolean useCodeBlob = codeBlob != null && codeBlob.getFrameSize() > 0; + nextSP = useCodeBlob ? nextFP.addOffsetTo((2 * ADDRESS_SIZE) - codeBlob.getFrameSize()) : nextFP; + } + } + if (nextSP == null) { + return null; + } + + return new BsdAARCH64CFrame(dbg, nextSP, nextFP, nextPC); + } + + @Override + public Frame toFrame() { + return new AARCH64Frame(sp, fp, pc); } // package/class internals only diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java index 8d0d94b11b709..9077e0007a51a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,13 @@ import sun.jvm.hotspot.debugger.bsd.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.cdbg.basic.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.amd64.*; public final class BsdAMD64CFrame extends BasicCFrame { - public BsdAMD64CFrame(BsdDebugger dbg, Address rbp, Address rip) { + public BsdAMD64CFrame(BsdDebugger dbg, Address rsp, Address rbp, Address rip) { super(dbg.getCDebugger()); + this.rsp = rsp; this.rbp = rbp; this.rip = rip; this.dbg = dbg; @@ -52,32 +55,49 @@ public Address localVariableBase() { return rbp; } + @Override public CFrame sender(ThreadProxy thread) { - AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext(); - Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP); + return sender(thread, null, null, null); + } - if ( (rbp == null) || rbp.lessThan(rsp) ) { - return null; + @Override + public CFrame sender(ThreadProxy thread, Address sp, Address fp, Address pc) { + // Check fp + // Skip if both fp and pc are given - do not need to load from rbp. + if (fp == null && pc == null) { + if (rbp == null) { + return null; + } + + // Check alignment of rbp + if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + return null; + } } - // Check alignment of rbp - if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + Address nextRSP = sp != null ? sp : rbp.addOffsetTo(2 * ADDRESS_SIZE); + if (nextRSP == null) { return null; } - - Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) { + Address nextRBP = fp != null ? fp : rbp.getAddressAt(0); + if (nextRBP == null) { return null; } - Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE); + Address nextPC = pc != null ? pc : rbp.getAddressAt(ADDRESS_SIZE); if (nextPC == null) { return null; } - return new BsdAMD64CFrame(dbg, nextRBP, nextPC); + return new BsdAMD64CFrame(dbg, nextRSP, nextRBP, nextPC); + } + + @Override + public Frame toFrame() { + return new AMD64Frame(rsp, rbp, rip); } // package/class internals only private static final int ADDRESS_SIZE = 8; + private Address rsp; private Address rip; private Address rbp; private BsdDebugger dbg;