< 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,128 @@
    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);
+   private Address getNextPC(boolean useDwarf) {
+     try {
+       long ofs = useDwarf ? dwarf.getReturnAddressOffsetFromCFA()
+                           : ADDRESS_SIZE;
+       return cfa.getAddressAt(ofs);
+     } catch (UnmappedAddressException | UnalignedAddressException e) {
+       return null;
+     }
+   }
+
+   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 (dwarf == null) {
+       nextCFA = cfa.getAddressAt(0);
+       if (nextDwarf != null) {
+         nextCFA = nextCFA.addOffsetTo(- nextDwarf.getBasePointerOffsetFromCFA());
+       }
+       return isValidFrame(nextCFA, context) ? nextCFA : null;
+     }
 
-      if ( (rbp == null) || rbp.lessThan(rsp) ) {
+     nextCFA = cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA());
+     if (nextCFA == null) {
         return null;
       }
 
-      // Check alignment of rbp
-      if ( dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) {
+     if (nextDwarf == null) {
+       return isValidFrame(nextCFA, context) ? nextCFA : null;
+     } else {
+       int nextCFAReg = nextDwarf.getCFARegister();
+       if (!dwarf.isBPOffsetAvailable() &&
+           (nextCFAReg == AMD64ThreadContext.RBP) &&
+           (nextCFAReg != dwarf.getCFARegister())) {
+         nextCFA = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
+         if (nextCFA == null) {
+           return null;
+         }
+         nextCFA = nextCFA.getAddressAt(0);
+         if (nextCFA == null) {
         return null;
       }
+       }
+     }
+
+     nextCFA = nextCFA.addOffsetTo(- nextDwarf.getBasePointerOffsetFromCFA());
+     return isValidFrame(nextCFA, context) ? nextCFA : null;
+   }
 
-      Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE);
-      if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) {
+   private CFrame javaSender(ThreadContext context) {
+     Address nextCFA;
+     Address nextPC;
+
+     nextPC = getNextPC(false);
+     if (nextPC == null) {
         return null;
       }
-      Address nextPC  = rbp.getAddressAt( 1 * ADDRESS_SIZE);
+
+     DwarfParser nextDwarf = null;
+     long libptr = dbg.findLibPtrByAddress(nextPC);
+     if (libptr != 0L) { // Native frame
+       try {
+         nextDwarf = new DwarfParser(libptr);
+       } catch (DebuggerException e) {
+         nextCFA = getNextCFA(null, context);
+         return (nextCFA == null) ? null : new LinuxAMD64CFrame(dbg, nextCFA, nextPC, null);
+       }
+       nextDwarf.processDwarf(nextPC);
+     }
+
+     nextCFA = getNextCFA(nextDwarf, context);
+     return (nextCFA == null) ? null
+                              : new LinuxAMD64CFrame(dbg, nextCFA, nextPC, nextDwarf);
+   }
+
+   public CFrame sender(ThreadProxy thread) {
+     ThreadContext context = thread.getContext();
+
+     if (dwarf == null) { // Java frame
+       return javaSender(context);
+     }
+
+     Address nextPC = getNextPC(true);
       if (nextPC == null) {
         return null;
       }
-      return new LinuxAMD64CFrame(dbg, nextRBP, nextPC);
+
+     Address nextCFA;
+     DwarfParser nextDwarf = dwarf;
+     if (!dwarf.isIn(nextPC)) {
+       long libptr = dbg.findLibPtrByAddress(nextPC);
+       if (libptr == 0L) {
+         // Next frame might be Java frame
+         nextCFA = getNextCFA(null, context);
+         return (nextCFA == null) ? null : new LinuxAMD64CFrame(dbg, nextCFA, nextPC, null);
+       }
+       try {
+         nextDwarf = new DwarfParser(libptr);
+       } catch (DebuggerException e) {
+         nextCFA = getNextCFA(null, context);
+         return (nextCFA == null) ? null : new LinuxAMD64CFrame(dbg, nextCFA, nextPC, null);
+       }
+     }
+
+     nextDwarf.processDwarf(nextPC);
+     nextCFA = getNextCFA(nextDwarf, context);
+     return (nextCFA == null) ? null : new LinuxAMD64CFrame(dbg, nextCFA, nextPC, nextDwarf);
    }
 
    // 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 >