< prev index next >
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -29,15 +29,16 @@
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.*;
final public class LinuxAMD64CFrame extends BasicCFrame {
- public LinuxAMD64CFrame(LinuxDebugger dbg, Address rbp, Address rip) {
+ public LinuxAMD64CFrame(LinuxDebugger dbg, Address cfa, Address rip, DwarfParser dwarf) {
super(dbg.getCDebugger());
- this.rbp = rbp;
+ this.cfa = cfa;
this.rip = rip;
this.dbg = dbg;
+ this.dwarf = dwarf;
}
// override base class impl to avoid ELF parsing
public ClosestSymbol closestSymbolToPC() {
// try native lookup in debugger.
@@ -47,38 +48,112 @@
public Address pc() {
return rip;
}
public Address localVariableBase() {
- return rbp;
+ return cfa;
}
- public CFrame sender(ThreadProxy thread) {
- AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext();
- Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
-
- if ( (rbp == null) || rbp.lessThan(rsp) ) {
+ private boolean isValidFrame(Address nextCFA, ThreadProxy thread) {
+ return (nextCFA != null) &&
+ !nextCFA.addOffsetTo(1 * 1024 * 1024 * 1024).lessThan(cfa) && // FIXME: assume to 1GB diff
+ !nextCFA.lessThan(thread.getContext().getRegisterAsAddress(AMD64ThreadContext.RSP));
+ }
+
+ private CFrame javaSender(ThreadProxy thread) {
+ Address nextCFA;
+ Address nextPC;
+ try { // FIXME: cannot read RBP from CFA in some case
+ nextCFA = cfa.getAddressAt(0);
+ // FIXME: assume to 1GB diff of stack
+ if (!isValidFrame(nextCFA, thread)) {
return null;
}
- // Check alignment of rbp
- if ( dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) {
+ nextPC = nextCFA.getAddressAt( 1 * ADDRESS_SIZE);
+ if (nextPC == null) {
+ return null;
+ }
+ } catch (UnmappedAddressException | UnalignedAddressException e) {
return null;
}
- Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE);
- if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) {
+ DwarfParser nextDwarf = null;
+ long libptr = dbg.findLibPtrByAddress(nextPC);
+ if (libptr != 0L) { // Native frame
+ try {
+ nextDwarf = new DwarfParser(libptr);
+ } catch (DebuggerException e) {
+ return new LinuxAMD64CFrame(dbg, nextCFA, nextPC, null);
+ }
+ nextDwarf.processDwarf(nextPC);
+ nextCFA = nextCFA.addOffsetTo(- nextDwarf.getBasePointerOffsetFromCFA());
+ if (!isValidFrame(nextCFA, thread)) {
return null;
}
- Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE);
+ }
+
+ return new LinuxAMD64CFrame(dbg, nextCFA, nextPC, nextDwarf);
+ }
+
+ public CFrame sender(ThreadProxy thread) {
+ if (dwarf == null) { // Java frame
+ return javaSender(thread);
+ }
+
+ Address nextPC;
+ Address nextCFA;
+ try { // FIXME: cannot read RBP from CFA in some case
+ nextPC = cfa.getAddressAt(dwarf.getReturnAddressOffsetFromCFA());
if (nextPC == null) {
return null;
}
- return new LinuxAMD64CFrame(dbg, nextRBP, nextPC);
+
+ nextCFA = cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA());
+ if (!isValidFrame(nextCFA, thread)) {
+ return null;
+ }
+ } catch (UnmappedAddressException | UnalignedAddressException e) {
+ return null;
+ }
+
+ DwarfParser nextDwarf = dwarf;
+ if (!dwarf.isIn(nextPC)) {
+ long libptr = dbg.findLibPtrByAddress(nextPC);
+ if (libptr == 0L) {
+ // Next frame might be Java frame
+ return new LinuxAMD64CFrame(dbg, nextCFA, nextPC, null);
+ }
+ try {
+ nextDwarf = new DwarfParser(libptr);
+ } catch (DebuggerException e) {
+ nextCFA = cfa.getAddressAt(0);
+ return isValidFrame(nextCFA, thread) ? new LinuxAMD64CFrame(dbg, nextCFA, nextPC, null)
+ : null;
+ }
+ }
+
+ nextDwarf.processDwarf(nextPC);
+
+ int nextCFAReg = nextDwarf.getCFARegister();
+ if (!dwarf.isBPOffsetAvailable() &&
+ (nextCFAReg == AMD64ThreadContext.RBP) &&
+ (nextCFAReg != dwarf.getCFARegister())) {
+ nextCFA = thread.getContext()
+ .getRegisterAsAddress(AMD64ThreadContext.RBP);
+ if (!isValidFrame(nextCFA, thread)) {
+ return null;
+ }
+ }
+
+ nextCFA = nextCFA.addOffsetTo(- nextDwarf.getBasePointerOffsetFromCFA());
+ return isValidFrame(nextCFA, thread) ? new LinuxAMD64CFrame(dbg, nextCFA, nextPC, nextDwarf)
+ : null;
}
// package/class internals only
private static final int ADDRESS_SIZE = 8;
private Address rip;
- private Address rbp;
+ private Address cfa;
private LinuxDebugger dbg;
+ private DwarfParser dwarf;
}
< prev index next >