Skip to content

Commit cece06f

Browse files
committed
8373110: jstack --mixed frames are broken on macOS after JDK-8371194
Reviewed-by: dholmes Backport-of: b848ddf
1 parent 8e0d736 commit cece06f

File tree

3 files changed

+94
-29
lines changed

3 files changed

+94
-29
lines changed

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -86,18 +86,22 @@ public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException {
8686
String cpu = dbg.getCPU();
8787
if (cpu.equals("amd64") || cpu.equals("x86_64")) {
8888
AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext();
89+
Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
90+
if (rsp == null) return null;
8991
Address rbp = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
9092
if (rbp == null) return null;
9193
Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
9294
if (pc == null) return null;
93-
return new BsdAMD64CFrame(dbg, rbp, pc);
95+
return new BsdAMD64CFrame(dbg, rsp, rbp, pc);
9496
} else if (cpu.equals("aarch64")) {
9597
AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
98+
Address sp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
99+
if (sp == null) return null;
96100
Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
97101
if (fp == null) return null;
98102
Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
99103
if (pc == null) return null;
100-
return new BsdAARCH64CFrame(dbg, fp, pc);
104+
return new BsdAARCH64CFrame(dbg, sp, fp, pc);
101105
} else {
102106
throw new DebuggerException(cpu + " is not yet supported");
103107
}

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2015, Red Hat Inc.
44
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
55
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -26,15 +26,19 @@
2626

2727
package sun.jvm.hotspot.debugger.bsd.aarch64;
2828

29+
import sun.jvm.hotspot.code.*;
2930
import sun.jvm.hotspot.debugger.*;
3031
import sun.jvm.hotspot.debugger.aarch64.*;
3132
import sun.jvm.hotspot.debugger.bsd.*;
3233
import sun.jvm.hotspot.debugger.cdbg.*;
3334
import sun.jvm.hotspot.debugger.cdbg.basic.*;
35+
import sun.jvm.hotspot.runtime.*;
36+
import sun.jvm.hotspot.runtime.aarch64.*;
3437

3538
public final class BsdAARCH64CFrame extends BasicCFrame {
36-
public BsdAARCH64CFrame(BsdDebugger dbg, Address fp, Address pc) {
39+
public BsdAARCH64CFrame(BsdDebugger dbg, Address sp, Address fp, Address pc) {
3740
super(dbg.getCDebugger());
41+
this.sp = sp;
3842
this.fp = fp;
3943
this.pc = pc;
4044
this.dbg = dbg;
@@ -54,28 +58,65 @@ public Address localVariableBase() {
5458
return fp;
5559
}
5660

61+
@Override
5762
public CFrame sender(ThreadProxy thread) {
58-
AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
59-
Address rsp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
63+
return sender(thread, null, null, null);
64+
}
6065

61-
if ((fp == null) || fp.lessThan(rsp)) {
62-
return null;
66+
@Override
67+
public CFrame sender(ThreadProxy thread, Address nextSP, Address nextFP, Address nextPC) {
68+
// Check fp
69+
// Skip if both nextFP and nextPC are given - do not need to load from fp.
70+
if (nextFP == null && nextPC == null) {
71+
if (fp == null) {
72+
return null;
73+
}
74+
75+
// Check alignment of fp
76+
if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
77+
return null;
78+
}
6379
}
6480

65-
// Check alignment of fp
66-
if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
81+
if (nextFP == null) {
82+
nextFP = fp.getAddressAt(0);
83+
}
84+
if (nextFP == null) {
6785
return null;
6886
}
6987

70-
Address nextFP = fp.getAddressAt(0 * ADDRESS_SIZE);
71-
if (nextFP == null || nextFP.lessThanOrEqual(fp)) {
72-
return null;
88+
if (nextPC == null) {
89+
nextPC = fp.getAddressAt(ADDRESS_SIZE);
7390
}
74-
Address nextPC = fp.getAddressAt(1 * ADDRESS_SIZE);
7591
if (nextPC == null) {
7692
return null;
7793
}
78-
return new BsdAARCH64CFrame(dbg, nextFP, nextPC);
94+
95+
if (nextSP == null) {
96+
CodeCache cc = VM.getVM().getCodeCache();
97+
CodeBlob currentBlob = cc.findBlobUnsafe(pc());
98+
99+
// This case is different from HotSpot. See JDK-8371194 for details.
100+
if (currentBlob != null && (currentBlob.isContinuationStub() || currentBlob.isNativeMethod())) {
101+
// Use FP since it should always be valid for these cases.
102+
// TODO: These should be walked as Frames not CFrames.
103+
nextSP = fp.addOffsetTo(2 * ADDRESS_SIZE);
104+
} else {
105+
CodeBlob codeBlob = cc.findBlobUnsafe(nextPC);
106+
boolean useCodeBlob = codeBlob != null && codeBlob.getFrameSize() > 0;
107+
nextSP = useCodeBlob ? nextFP.addOffsetTo((2 * ADDRESS_SIZE) - codeBlob.getFrameSize()) : nextFP;
108+
}
109+
}
110+
if (nextSP == null) {
111+
return null;
112+
}
113+
114+
return new BsdAARCH64CFrame(dbg, nextSP, nextFP, nextPC);
115+
}
116+
117+
@Override
118+
public Frame toFrame() {
119+
return new AARCH64Frame(sp, fp, pc);
79120
}
80121

81122
// package/class internals only

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,10 +29,13 @@
2929
import sun.jvm.hotspot.debugger.bsd.*;
3030
import sun.jvm.hotspot.debugger.cdbg.*;
3131
import sun.jvm.hotspot.debugger.cdbg.basic.*;
32+
import sun.jvm.hotspot.runtime.*;
33+
import sun.jvm.hotspot.runtime.amd64.*;
3234

3335
public final class BsdAMD64CFrame extends BasicCFrame {
34-
public BsdAMD64CFrame(BsdDebugger dbg, Address rbp, Address rip) {
36+
public BsdAMD64CFrame(BsdDebugger dbg, Address rsp, Address rbp, Address rip) {
3537
super(dbg.getCDebugger());
38+
this.rsp = rsp;
3639
this.rbp = rbp;
3740
this.rip = rip;
3841
this.dbg = dbg;
@@ -52,32 +55,49 @@ public Address localVariableBase() {
5255
return rbp;
5356
}
5457

58+
@Override
5559
public CFrame sender(ThreadProxy thread) {
56-
AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext();
57-
Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
60+
return sender(thread, null, null, null);
61+
}
5862

59-
if ( (rbp == null) || rbp.lessThan(rsp) ) {
60-
return null;
63+
@Override
64+
public CFrame sender(ThreadProxy thread, Address sp, Address fp, Address pc) {
65+
// Check fp
66+
// Skip if both fp and pc are given - do not need to load from rbp.
67+
if (fp == null && pc == null) {
68+
if (rbp == null) {
69+
return null;
70+
}
71+
72+
// Check alignment of rbp
73+
if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) {
74+
return null;
75+
}
6176
}
6277

63-
// Check alignment of rbp
64-
if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) {
78+
Address nextRSP = sp != null ? sp : rbp.addOffsetTo(2 * ADDRESS_SIZE);
79+
if (nextRSP == null) {
6580
return null;
6681
}
67-
68-
Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE);
69-
if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) {
82+
Address nextRBP = fp != null ? fp : rbp.getAddressAt(0);
83+
if (nextRBP == null) {
7084
return null;
7185
}
72-
Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE);
86+
Address nextPC = pc != null ? pc : rbp.getAddressAt(ADDRESS_SIZE);
7387
if (nextPC == null) {
7488
return null;
7589
}
76-
return new BsdAMD64CFrame(dbg, nextRBP, nextPC);
90+
return new BsdAMD64CFrame(dbg, nextRSP, nextRBP, nextPC);
91+
}
92+
93+
@Override
94+
public Frame toFrame() {
95+
return new AMD64Frame(rsp, rbp, rip);
7796
}
7897

7998
// package/class internals only
8099
private static final int ADDRESS_SIZE = 8;
100+
private Address rsp;
81101
private Address rip;
82102
private Address rbp;
83103
private BsdDebugger dbg;

0 commit comments

Comments
 (0)