Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public interface CFrame {
/** Returns null when no more frames on stack */
public CFrame sender(ThreadProxy th);

/** Find sender frame with given FP and PC */
public default CFrame sender(ThreadProxy th, Address fp, Address pc) {
return sender(th);
}

/** Get the program counter of this frame */
public Address pc();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,36 @@ 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);
}

if ((fp == null) || fp.lessThan(rsp)) {
return null;
@Override
public CFrame sender(ThreadProxy thread, 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 * ADDRESS_SIZE);
}
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(1 * ADDRESS_SIZE);
}
Address nextPC = fp.getAddressAt(1 * ADDRESS_SIZE);
if (nextPC == null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,22 @@ private Address getNextPC(boolean useDwarf) {
}

private boolean isValidFrame(Address nextCFA, ThreadContext context) {
return (nextCFA != null) &&
!nextCFA.lessThan(context.getRegisterAsAddress(AMD64ThreadContext.RSP));
return nextCFA != null;
}

private Address getNextCFA(DwarfParser nextDwarf, ThreadContext context) {
private Address getNextCFA(DwarfParser nextDwarf, ThreadContext context, Address senderFP) {
Address nextCFA;

if (senderFP == null) {
senderFP = cfa.getAddressAt(0); // RBP by default
}

if (nextDwarf == null) { // Next frame is Java
nextCFA = (dwarf == null) ? cfa.getAddressAt(0) // Current frame is Java (Use RBP)
nextCFA = (dwarf == null) ? senderFP // Current frame is Java
: cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA()); // Current frame is Native
} else { // Next frame is Native
if (dwarf == null) { // Current frame is Java (Use RBP)
nextCFA = cfa.getAddressAt(0);
if (dwarf == null) { // Current frame is Java
nextCFA = senderFP;
} else { // Current frame is Native
int nextCFAReg = nextDwarf.getCFARegister();
if (!dwarf.isBPOffsetAvailable() && // Use RBP as CFA
Expand All @@ -132,14 +135,19 @@ private Address getNextCFA(DwarfParser nextDwarf, ThreadContext context) {
}

@Override
public CFrame sender(ThreadProxy thread) {
public CFrame sender(ThreadProxy th) {
return sender(th, null, null);
}

@Override
public CFrame sender(ThreadProxy th, Address fp, Address pc) {
if (finalFrame) {
return null;
}

ThreadContext context = thread.getContext();
ThreadContext context = th.getContext();

Address nextPC = getNextPC(dwarf != null);
Address nextPC = pc != null ? pc : getNextPC(dwarf != null);
if (nextPC == null) {
return null;
}
Expand All @@ -165,7 +173,7 @@ public CFrame sender(ThreadProxy thread) {
}
}

Address nextCFA = getNextCFA(nextDwarf, context);
Address nextCFA = getNextCFA(nextDwarf, context, fp);
return isValidFrame(nextCFA, context) ? new LinuxAMD64CFrame(dbg, nextCFA, nextPC, nextDwarf)
: null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,27 +57,40 @@ public Address localVariableBase() {
return fp;
}

@Override
public CFrame sender(ThreadProxy thread) {
RISCV64ThreadContext context = (RISCV64ThreadContext) thread.getContext();
Address rsp = context.getRegisterAsAddress(RISCV64ThreadContext.SP);
return sender(thread, null, null);
}

if ((fp == null) || fp.lessThan(rsp)) {
return null;
@Override
public CFrame sender(ThreadProxy thread, 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(C_FRAME_LINK_OFFSET * ADDRESS_SIZE);
}
if (nextFP == null) {
return null;
}

Address nextFP = fp.getAddressAt(C_FRAME_LINK_OFFSET * ADDRESS_SIZE);
if (nextFP == null || nextFP.lessThanOrEqual(fp)) {
return null;
if (nextPC == null) {
nextPC = fp.getAddressAt(C_FRAME_RETURN_ADDR_OFFSET * ADDRESS_SIZE);
}
Address nextPC = fp.getAddressAt(C_FRAME_RETURN_ADDR_OFFSET * ADDRESS_SIZE);
if (nextPC == null) {
return null;
}

return new LinuxRISCV64CFrame(dbg, nextFP, nextPC);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public void run(PrintStream out, Debugger dbg) {
jthread.printThreadInfoOn(out);
}
while (f != null) {
Address senderFP = null;
Address senderPC = null;
ClosestSymbol sym = f.closestSymbolToPC();
Address pc = f.pc();
out.print(pc + "\t");
Expand All @@ -125,13 +127,13 @@ public void run(PrintStream out, Debugger dbg) {
out.println();
} else {
// look for one or more java frames
String[] names = null;
JavaNameInfo nameInfo = null;
// check interpreter frame
Interpreter interp = VM.getVM().getInterpreter();
if (interp.contains(pc)) {
names = getJavaNames(th, f.localVariableBase());
nameInfo = getJavaNames(th, f.localVariableBase());
// print codelet name if we can't determine method
if (names == null || names.length == 0) {
if (nameInfo == null || nameInfo.names() == null || nameInfo.names().length == 0) {
out.print("<interpreter> ");
InterpreterCodelet ic = interp.getCodeletContaining(pc);
if (ic != null) {
Expand All @@ -154,9 +156,9 @@ public void run(PrintStream out, Debugger dbg) {
}
out.println(" (Native method)");
} else {
names = getJavaNames(th, f.localVariableBase());
nameInfo = getJavaNames(th, f.localVariableBase());
// just print compiled code, if can't determine method
if (names == null || names.length == 0) {
if (nameInfo == null || nameInfo.names() == null || nameInfo.names().length == 0) {
out.println("<Unknown compiled code>");
}
}
Expand All @@ -168,17 +170,21 @@ public void run(PrintStream out, Debugger dbg) {
}
}
// print java frames, if any
if (names != null && names.length != 0) {
// print java frame(s)
for (int i = 0; i < names.length; i++) {
if (i > 0) {
out.print(fillerForAddress);
if (nameInfo != null) {
if (nameInfo.names() != null && nameInfo.names().length != 0) {
// print java frame(s)
for (int i = 0; i < nameInfo.names().length; i++) {
if (i > 0) {
out.print(fillerForAddress);
}
out.println(nameInfo.names()[i]);
}
out.println(names[i]);
}
senderFP = nameInfo.senderFP();
senderPC = nameInfo.senderPC();
}
}
f = f.sender(th);
f = f.sender(th, senderFP, senderPC);
}
} catch (Exception exp) {
exp.printStackTrace();
Expand Down Expand Up @@ -239,17 +245,22 @@ private void printUnknown(PrintStream out) {
out.println("\t????????");
}

private String[] getJavaNames(ThreadProxy th, Address fp) {
private static record JavaNameInfo(String[] names, Address senderFP, Address senderPC) {};

private JavaNameInfo getJavaNames(ThreadProxy th, Address fp) {
if (fp == null) {
return null;
}
JavaVFrame[] jvframes = jframeCache.get(th);
if (jvframes == null) return null; // not a java thread

List<String> names = new ArrayList<>(10);
JavaVFrame bottomJVFrame = null;
for (int fCount = 0; fCount < jvframes.length; fCount++) {
JavaVFrame vf = jvframes[fCount];
Frame f = vf.getFrame();
if (fp.equals(f.getFP())) {
bottomJVFrame = vf;
StringBuilder sb = new StringBuilder();
Method method = vf.getMethod();
// a special char to identify java frames in output
Expand Down Expand Up @@ -280,8 +291,16 @@ private String[] getJavaNames(ThreadProxy th, Address fp) {
names.add(sb.toString());
}
}
String[] res = names.toArray(new String[0]);
return res;

Address senderFP = null;
Address senderPC = null;
if (bottomJVFrame != null) {
Frame senderFrame = bottomJVFrame.getFrame().sender((RegisterMap)bottomJVFrame.getRegisterMap().clone());
senderFP = senderFrame.getFP();
senderPC = senderFrame.getPC();
}

return new JavaNameInfo(names.toArray(new String[0]), senderFP, senderPC);
}

public void setVerbose(boolean verbose) {
Expand Down
Loading