< 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 >