< 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, 2020, 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,40 @@
 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 static LinuxAMD64CFrame getTopFrame(LinuxDebugger dbg, Address rip, ThreadContext context) {
+      Address libptr = dbg.findLibPtrByAddress(rip);
+      Address cfa = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
+      DwarfParser dwarf = null;
+
+      if (libptr != null) { // Native frame
+        try {
+          dwarf = new DwarfParser(libptr);
+          dwarf.processDwarf(rip);
+          cfa = ((dwarf.getCFARegister() == AMD64ThreadContext.RBP) &&
+                 !dwarf.isBPOffsetAvailable())
+                    ? context.getRegisterAsAddress(AMD64ThreadContext.RBP)
+                    : context.getRegisterAsAddress(dwarf.getCFARegister())
+                             .addOffsetTo(dwarf.getCFAOffset());
+        } catch (DebuggerException e) {
+          // Bail out to Java frame case
+        }
+      }
+
+      return (cfa == null) ? null
+                           : new LinuxAMD64CFrame(dbg, cfa, rip, dwarf);
+   }
+
+   private 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 +72,99 @@
    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 Address getNextPC(boolean useDwarf) {
+     try {
+       long offs = useDwarf ? dwarf.getReturnAddressOffsetFromCFA()
+                            : ADDRESS_SIZE;
+       return cfa.getAddressAt(offs);
+     } catch (UnmappedAddressException | UnalignedAddressException e) {
         return null;
       }
+   }
 
-      // Check alignment of rbp
-      if ( dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) {
+   private boolean isValidFrame(Address nextCFA, ThreadContext context) {
+     return (nextCFA != null) &&
+             !nextCFA.lessThan(context.getRegisterAsAddress(AMD64ThreadContext.RSP));
+   }
+
+   private Address getNextCFA(DwarfParser nextDwarf, ThreadContext context) {
+     Address nextCFA;
+
+     if (nextDwarf == null) { // Next frame is Java
+       nextCFA = (dwarf == null) ? cfa.getAddressAt(0) // Current frame is Java (Use RBP)
+                                 : 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);
+       } else { // Current frame is Native
+         int nextCFAReg = nextDwarf.getCFARegister();
+         if (!dwarf.isBPOffsetAvailable() && // Use RBP as CFA
+             (nextCFAReg == AMD64ThreadContext.RBP) &&
+             (nextCFAReg != dwarf.getCFARegister())) {
+           nextCFA = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
+           if (nextCFA == null) {
         return null;
       }
+           nextCFA = nextCFA.getAddressAt(0);
+         } else {
+           nextCFA = cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA());
+         }
+       }
+       if (nextCFA != null) {
+         nextCFA = nextCFA.addOffsetTo(-nextDwarf.getBasePointerOffsetFromCFA());
+       }
+     }
 
-      Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE);
-      if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) {
-        return null;
+     return isValidFrame(nextCFA, context) ? nextCFA : null;
       }
-      Address nextPC  = rbp.getAddressAt( 1 * ADDRESS_SIZE);
+
+   private DwarfParser getNextDwarf(Address nextPC) {
+     DwarfParser nextDwarf = null;
+
+     if ((dwarf != null) && dwarf.isIn(nextPC)) {
+       nextDwarf = dwarf;
+     } else {
+       Address libptr = dbg.findLibPtrByAddress(nextPC);
+       if (libptr != null) {
+         try {
+           nextDwarf = new DwarfParser(libptr);
+         } catch (DebuggerException e) {
+           // Bail out to Java frame
+         }
+       }
+     }
+
+     if (nextDwarf != null) {
+       nextDwarf.processDwarf(nextPC);
+     }
+
+     return nextDwarf;
+   }
+
+   @Override
+   public CFrame sender(ThreadProxy thread) {
+     ThreadContext context = thread.getContext();
+
+     Address nextPC = getNextPC(dwarf != null);
       if (nextPC == null) {
         return null;
       }
-      return new LinuxAMD64CFrame(dbg, nextRBP, nextPC);
+
+     DwarfParser nextDwarf = getNextDwarf(nextPC);
+     Address nextCFA = getNextCFA(nextDwarf, context);
+     return isValidFrame(nextCFA, context) ? 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 >