< prev index next >

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.runtime.amd64;
  26 
  27 import sun.jvm.hotspot.debugger.*;
  28 import sun.jvm.hotspot.debugger.amd64.*;
  29 import sun.jvm.hotspot.code.*;
  30 import sun.jvm.hotspot.interpreter.*;

  31 import sun.jvm.hotspot.runtime.*;
  32 import sun.jvm.hotspot.runtime.x86.*;


  33 
  34 /** <P> Should be able to be used on all amd64 platforms we support
  35     (Linux/amd64) to implement JavaThread's
  36     "currentFrameGuess()" functionality. Input is an AMD64ThreadContext;
  37     output is SP, FP, and PC for an AMD64Frame. Instantiation of the
  38     AMD64Frame is left to the caller, since we may need to subclass
  39     AMD64Frame to support signal handler frames on Unix platforms. </P>
  40 
  41     <P> Algorithm is to walk up the stack within a given range (say,
  42     512K at most) looking for a plausible PC and SP for a Java frame,
  43     also considering those coming in from the context. If we find a PC
  44     that belongs to the VM (i.e., in generated code like the
  45     interpreter or CodeCache) then we try to find an associated EBP.
  46     We repeat this until we either find a complete frame or run out of
  47     stack to look at. </P> */
  48 
  49 public class AMD64CurrentFrameGuess {
  50   private AMD64ThreadContext context;
  51   private JavaThread       thread;
  52   private Address          spFound;
  53   private Address          fpFound;
  54   private Address          pcFound;
  55 
  56   private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG")
  57                                        != null;
  58 
  59   public AMD64CurrentFrameGuess(AMD64ThreadContext context,
  60                               JavaThread thread) {
  61     this.context = context;
  62     this.thread  = thread;
  63   }
  64 

















































































































  65   /** Returns false if not able to find a frame within a reasonable range. */
  66   public boolean run(long regionInBytesToSearch) {
  67     Address sp  = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
  68     Address pc  = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
  69     Address fp  = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
  70     if (sp == null) {
  71       // Bail out if no last java frame either
  72       if (thread.getLastJavaSP() != null) {
  73         setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
  74         return true;
  75       }
  76       return false;
  77     }
  78     Address end = sp.addOffsetTo(regionInBytesToSearch);
  79     VM vm       = VM.getVM();
  80 
  81     setValues(null, null, null); // Assume we're not going to find anything
  82 
  83     if (vm.isJavaPCDbg(pc)) {


  84       if (vm.isClientCompiler()) {
  85         // If the topmost frame is a Java frame, we are (pretty much)
  86         // guaranteed to have a viable EBP. We should be more robust
  87         // than this (we have the potential for losing entire threads'
  88         // stack traces) but need to see how much work we really have
  89         // to do here. Searching the stack for an (SP, FP) pair is
  90         // hard since it's easy to misinterpret inter-frame stack
  91         // pointers as base-of-frame pointers; we also don't know the
  92         // sizes of C1 frames (not registered in the nmethod) so can't
  93         // derive them from ESP.
  94 
  95         setValues(sp, fp, pc);
  96         return true;
  97       } else {
  98         if (vm.getInterpreter().contains(pc)) {







  99           if (DEBUG) {
 100             System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
 101                                sp + ", fp = " + fp + ", pc = " + pc);


















 102           }
 103           setValues(sp, fp, pc);
 104           return true;
 105         }
 106 
 107         // For the server compiler, EBP is not guaranteed to be valid
 108         // for compiled code. In addition, an earlier attempt at a
 109         // non-searching algorithm (see below) failed because the
 110         // stack pointer from the thread context was pointing
 111         // (considerably) beyond the ostensible end of the stack, into
 112         // garbage; walking from the topmost frame back caused a crash.
 113         //
 114         // This algorithm takes the current PC as a given and tries to
 115         // find the correct corresponding SP by walking up the stack
 116         // and repeatedly performing stackwalks (very inefficient).
 117         //
 118         // FIXME: there is something wrong with stackwalking across
 119         // adapter frames...this is likely to be the root cause of the
 120         // failure with the simpler algorithm below.
 121 



 122         for (long offset = 0;
 123              offset < regionInBytesToSearch;
 124              offset += vm.getAddressSize()) {
 125           try {
 126             Address curSP = sp.addOffsetTo(offset);
 127             Frame frame = new X86Frame(curSP, null, pc);
 128             RegisterMap map = thread.newRegisterMap(false);
 129             while (frame != null) {
 130               if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
 131                 // We were able to traverse all the way to the
 132                 // bottommost Java frame.
 133                 // This sp looks good. Keep it.
 134                 if (DEBUG) {
 135                   System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
 136                 }
 137                 setValues(curSP, null, pc);
 138                 return true;
 139               }
 140               Frame oldFrame = frame;
 141               frame = frame.sender(map);
 142               if (frame.getSP().lessThanOrEqual(oldFrame.getSP())) {
 143                   // Frame points to itself or to a location in the wrong direction.
 144                   // Break the loop and move on to next offset.
 145                   if (DEBUG) {
 146                       System.out.println("AMD64CurrentFrameGuess.run: frame <= oldFrame: " + frame);
 147                   }
 148                   break;
 149               }
 150             }
 151           } catch (Exception e) {
 152             if (DEBUG) {
 153               System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
 154             }
 155             // Bad SP. Try another.
 156           }
 157         }
 158 
 159         // Were not able to find a plausible SP to go with this PC.
 160         // Bail out.
 161         return false;
 162 
 163         /*
 164         // Original algorithm which does not work because SP was
 165         // pointing beyond where it should have:
 166 


 171 
 172         CodeCache cc = vm.getCodeCache();
 173         if (cc.contains(pc)) {
 174           CodeBlob cb = cc.findBlob(pc);
 175 
 176           // See if we can derive a frame pointer from SP and PC
 177           // NOTE: This is the code duplicated from AMD64Frame
 178           Address saved_fp = null;
 179           int llink_offset = cb.getLinkOffset();
 180           if (llink_offset >= 0) {
 181             // Restore base-pointer, since next frame might be an interpreter frame.
 182             Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
 183             saved_fp = fp_addr.getAddressAt(0);
 184           }
 185 
 186           setValues(sp, saved_fp, pc);
 187           return true;
 188         }
 189         */
 190       }
 191     } else {



 192       // If the current program counter was not known to us as a Java
 193       // PC, we currently assume that we are in the run-time system
 194       // and attempt to look to thread-local storage for saved ESP and
 195       // EBP. Note that if these are null (because we were, in fact,
 196       // in Java code, i.e., vtable stubs or similar, and the SA
 197       // didn't have enough insight into the target VM to understand
 198       // that) then we are going to lose the entire stack trace for
 199       // the thread, which is sub-optimal. FIXME.
 200 
 201       if (DEBUG) {
 202         System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
 203                            thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
 204       }
 205       if (thread.getLastJavaSP() == null) {
 206         return false; // No known Java frames on stack
 207       }
 208       setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
 209       return true;
 210     }
 211   }
 212 
 213   public Address getSP() { return spFound; }
 214   public Address getFP() { return fpFound; }
 215   /** May be null if getting values from thread-local storage; take
 216       care to call the correct AMD64Frame constructor to recover this if
 217       necessary */
 218   public Address getPC() { return pcFound; }
 219 
 220   private void setValues(Address sp, Address fp, Address pc) {
 221     spFound = sp;
 222     fpFound = fp;
 223     pcFound = pc;
 224   }
 225 }
   1 /*
   2  * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.runtime.amd64;
  26 
  27 import sun.jvm.hotspot.debugger.*;
  28 import sun.jvm.hotspot.debugger.amd64.*;
  29 import sun.jvm.hotspot.code.*;
  30 import sun.jvm.hotspot.interpreter.*;
  31 import sun.jvm.hotspot.oops.*;
  32 import sun.jvm.hotspot.runtime.*;
  33 import sun.jvm.hotspot.runtime.x86.*;
  34 import sun.jvm.hotspot.types.*;
  35 import sun.jvm.hotspot.utilities.*;
  36 
  37 /** <P> Should be able to be used on all amd64 platforms we support
  38     (Linux/amd64) to implement JavaThread's
  39     "currentFrameGuess()" functionality. Input is an AMD64ThreadContext;
  40     output is SP, FP, and PC for an AMD64Frame. Instantiation of the
  41     AMD64Frame is left to the caller, since we may need to subclass
  42     AMD64Frame to support signal handler frames on Unix platforms. </P>
  43 
  44     <P> Algorithm is to walk up the stack within a given range (say,
  45     512K at most) looking for a plausible PC and SP for a Java frame,
  46     also considering those coming in from the context. If we find a PC
  47     that belongs to the VM (i.e., in generated code like the
  48     interpreter or CodeCache) then we try to find an associated EBP.
  49     We repeat this until we either find a complete frame or run out of
  50     stack to look at. </P> */
  51 
  52 public class AMD64CurrentFrameGuess {
  53   private AMD64ThreadContext context;
  54   private JavaThread       thread;
  55   private Address          spFound;
  56   private Address          fpFound;
  57   private Address          pcFound;
  58 
  59   private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG")
  60                                        != null;
  61 
  62   public AMD64CurrentFrameGuess(AMD64ThreadContext context,
  63                               JavaThread thread) {
  64     this.context = context;
  65     this.thread  = thread;
  66   }
  67 
  68   private boolean validateInterpreterFrame(Address sp, Address fp, Address pc) {
  69     VM vm = VM.getVM();
  70     X86Frame f = new X86Frame(sp, fp, pc);
  71 
  72     // First validate that frame->method is really a Method*
  73     Method method = null;
  74     try {
  75       method = f.getInterpreterFrameMethod();
  76     } catch (WrongTypeException | AddressException | NullPointerException e) {
  77       // This just means frame->method is not valid.
  78       if (DEBUG) {
  79         System.out.println("CurrentFrameGuess: frame->method is invalid");
  80       }
  81     }
  82 
  83     // Next make sure frame->bcp is really in the method's bytecodes
  84     if (method != null && f.getInterpreterFrameBCP() != null) {
  85       if (method.getConstMethod().isAddressInMethod(f.getInterpreterFrameBCP())) {
  86         // All's good. This is the normal path when the PC is in the interpreter.
  87         // The cases below are all exceptionally rare.
  88         setValues(sp, fp, pc);
  89         return true;
  90       } else {
  91         if (DEBUG) {
  92           System.out.println("CurrentFrameGuess: frame->bcp is invalid");
  93         }
  94       }
  95     }
  96 
  97     // Either frame->method is not a Method* or frame->bcp is not valid. That means either
  98     // we have pushed the new interpreter frame, but have not intialized it yet, or
  99     // we have yet to push the new interpreter frame, and the "current" frame is not an
 100     // interpreter frame. Figure out which is the case.
 101 
 102     // Try to find the return address in RAX or on the stack. If we can't
 103     // find what appears to be a valid codecache address in either of these
 104     // two locations, then we canot determine the frame.
 105     Address returnAddress = context.getRegisterAsAddress(AMD64ThreadContext.RAX);
 106     CodeCache c = VM.getVM().getCodeCache();
 107     if (returnAddress == null || !c.contains(returnAddress)) {
 108       returnAddress = sp.getAddressAt(0);  // check top of stack
 109       if (returnAddress == null || !c.contains(returnAddress)) {
 110         if (DEBUG) {
 111           System.out.println("CurrentFrameGuess: Cannot find valid returnAddress");
 112         }
 113         setValues(sp, fp, pc);
 114         return false; // couldn't find a valid PC for frame.
 115       } else {
 116         if (DEBUG) {
 117           System.out.println("CurrentFrameGuess: returnAddress found on stack: " + returnAddress);
 118         }
 119       }
 120     } else {
 121       if (DEBUG) {
 122         System.out.println("CurrentFrameGuess: returnAddress found in RAX: " + returnAddress);
 123       }
 124     }
 125 
 126     // See what return address is stored in the frame. Most likely it is not valid, but
 127     // it's validity will help us determine the state of the new frame push.
 128     Address returnAddress2 = null;
 129     try {
 130       returnAddress2 = f.getSenderPC();
 131     } catch (AddressException e) {
 132       // Just ignore. This is expected sometimes. 
 133       if (DEBUG) {
 134         System.out.println("CurrentFrameGuess: senderPC is invalid");
 135       }
 136     }
 137     if (DEBUG) {
 138       System.out.println("CurrentFrameGuess: returnAddress2: " + returnAddress2);
 139     }
 140 
 141     if (returnAddress.equals(returnAddress2)) {
 142       // If these two ways of fetching the return address produce the same address, 
 143       // then that means we have pushed the new frame, but have not finished
 144       // initializing it yet. Otherwise we would also have found a valid frame->method
 145       // and frame->bcp. Because this frame is incomplete, we instead use
 146       // the previous frame as the current frame.
 147       if (DEBUG) {
 148         System.out.println("CurrentFrameGuess: frame pushed but not initaliazed.");
 149       }
 150       sp = f.getSenderSP();
 151       fp = f.getLink();
 152       setValues(sp, fp, returnAddress);
 153       // If this previous frame is interpreted, then we are done and setValues() has been
 154       // called with a valid interpreter frame. Otherwise return false and the caller will
 155       // need to determine frame.
 156       if (vm.getInterpreter().contains(returnAddress)) {
 157         if (DEBUG) {
 158           System.out.println("CurrentFrameGuess: Interpreted: using previous frame.");
 159         }
 160         return true;
 161       } else {
 162         if (DEBUG) {
 163           System.out.println("CurrentFrameGuess: Not Interpreted: using previous frame.");
 164         }
 165         return false;
 166       }
 167     } else {
 168       // We haven't even pushed the new frame yet. sp and fp are for the previous
 169       // frame that is making the call to the interpreter. Since this frame is
 170       // not a valid interpreter frame (we know either frame->method or frame->bcp
 171       // are not valid), it must be something else. Assume compiled or native and
 172       // let the  caller figure it out.
 173       setValues(sp, fp, returnAddress);
 174       if (DEBUG) {
 175         System.out.println("CurrentFrameGuess: Frame not yet pushed. Previous frame not interpreted.");
 176       }
 177       return false;
 178     }
 179   }
 180 
 181   /** Returns false if not able to find a frame within a reasonable range. */
 182   public boolean run(long regionInBytesToSearch) {
 183     Address sp  = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
 184     Address pc  = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
 185     Address fp  = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
 186     if (sp == null) {
 187       return checkLastJavaSP();





 188     }
 189     Address end = sp.addOffsetTo(regionInBytesToSearch);
 190     VM vm       = VM.getVM();
 191 
 192     setValues(null, null, null); // Assume we're not going to find anything
 193 
 194     if (!vm.isJavaPCDbg(pc)) {
 195       return checkLastJavaSP();
 196     } else {
 197       if (vm.isClientCompiler()) {
 198         // If the topmost frame is a Java frame, we are (pretty much)
 199         // guaranteed to have a viable EBP. We should be more robust
 200         // than this (we have the potential for losing entire threads'
 201         // stack traces) but need to see how much work we really have
 202         // to do here. Searching the stack for an (SP, FP) pair is
 203         // hard since it's easy to misinterpret inter-frame stack
 204         // pointers as base-of-frame pointers; we also don't know the
 205         // sizes of C1 frames (not registered in the nmethod) so can't
 206         // derive them from ESP.
 207 
 208         setValues(sp, fp, pc);
 209         return true;
 210       } else {
 211         if (vm.getInterpreter().contains(pc)) {
 212           // pc points into the interpreter, but that doesn't necessarily mean the current 
 213           // frame is interpreted. We may be in interpreter method entry code before the frame
 214           // has been pushed, or possibly after it has been pushed but before it has been
 215           // initialized. See TemplateInterpreterGenerator::generate_normal_entry(). So we
 216           // need to do a few sanity checks here, and try to correct the situation if
 217           // we are in the middle of a frame push.
 218           if (validateInterpreterFrame(sp, fp, pc)) {
 219             if (DEBUG) {
 220               System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
 221                                  spFound + ", fpFound = " + fp + ", pcFound = " + pc);
 222             }
 223             return true; // We're done. setValues() has been called for valid interpreter frame.
 224           } else {
 225             // This does not appear to be a valid interpreter frame. Possibly we are in the
 226             // middle of pushing a new frame. Update the frame values to those suggested
 227             // by validateInterpreterFrame() and then fall through to check if it is compiled.
 228             sp = spFound;
 229             fp = fpFound;
 230             pc = pcFound;
 231             setValues(null, null, null);
 232             if (pcFound == null) {
 233               return false;
 234             }
 235             // pc may have changed, so we need to redo the isJavaPCDbg(pc) check before
 236             // falling into code below that assumes the frame is compiled.
 237             if (!vm.isJavaPCDbg(pc)) {
 238               return checkLastJavaSP();
 239             }
 240           }


 241         }
 242 
 243         // For the server compiler, EBP is not guaranteed to be valid
 244         // for compiled code. In addition, an earlier attempt at a
 245         // non-searching algorithm (see below) failed because the
 246         // stack pointer from the thread context was pointing
 247         // (considerably) beyond the ostensible end of the stack, into
 248         // garbage; walking from the topmost frame back caused a crash.
 249         //
 250         // This algorithm takes the current PC as a given and tries to
 251         // find the correct corresponding SP by walking up the stack
 252         // and repeatedly performing stackwalks (very inefficient).
 253         //
 254         // FIXME: there is something wrong with stackwalking across
 255         // adapter frames...this is likely to be the root cause of the
 256         // failure with the simpler algorithm below.
 257 
 258         if (DEBUG) {
 259           System.out.println("CurrentFrameGuess: sp = " + sp + ", pc = " + pc);
 260         }
 261         for (long offset = 0;
 262              offset < regionInBytesToSearch;
 263              offset += vm.getAddressSize()) {
 264           try {
 265             Address curSP = sp.addOffsetTo(offset);
 266             Frame frame = new X86Frame(curSP, null, pc);
 267             RegisterMap map = thread.newRegisterMap(false);
 268             while (frame != null) {
 269               if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
 270                 // We were able to traverse all the way to the
 271                 // bottommost Java frame.
 272                 // This sp looks good. Keep it.
 273                 if (DEBUG) {
 274                   System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
 275                 }
 276                 setValues(curSP, null, pc);
 277                 return true;
 278               }
 279               Frame oldFrame = frame;
 280               frame = frame.sender(map);
 281               if (frame.getSP().lessThanOrEqual(oldFrame.getSP())) {
 282                   // Frame points to itself or to a location in the wrong direction.
 283                   // Break the loop and move on to next offset.
 284                   if (DEBUG) {
 285                     System.out.println("CurrentFrameGuess: frame <= oldFrame: " + frame);
 286                   }
 287                   break;
 288               }
 289             }
 290           } catch (Exception e) {
 291             if (DEBUG) {
 292               System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
 293             }
 294             // Bad SP. Try another.
 295           }
 296         }
 297 
 298         // Were not able to find a plausible SP to go with this PC.
 299         // Bail out.
 300         return false;
 301 
 302         /*
 303         // Original algorithm which does not work because SP was
 304         // pointing beyond where it should have:
 305 


 310 
 311         CodeCache cc = vm.getCodeCache();
 312         if (cc.contains(pc)) {
 313           CodeBlob cb = cc.findBlob(pc);
 314 
 315           // See if we can derive a frame pointer from SP and PC
 316           // NOTE: This is the code duplicated from AMD64Frame
 317           Address saved_fp = null;
 318           int llink_offset = cb.getLinkOffset();
 319           if (llink_offset >= 0) {
 320             // Restore base-pointer, since next frame might be an interpreter frame.
 321             Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
 322             saved_fp = fp_addr.getAddressAt(0);
 323           }
 324 
 325           setValues(sp, saved_fp, pc);
 326           return true;
 327         }
 328         */
 329       }
 330     }
 331   }
 332 
 333   private boolean checkLastJavaSP() {
 334     // If the current program counter was not known to us as a Java
 335     // PC, we currently assume that we are in the run-time system
 336     // and attempt to look to thread-local storage for saved ESP and
 337     // EBP. Note that if these are null (because we were, in fact,
 338     // in Java code, i.e., vtable stubs or similar, and the SA
 339     // didn't have enough insight into the target VM to understand
 340     // that) then we are going to lose the entire stack trace for
 341     // the thread, which is sub-optimal. FIXME.
 342 
 343     if (DEBUG) {
 344       System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
 345                          thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
 346     }
 347     if (thread.getLastJavaSP() == null) {
 348       return false; // No known Java frames on stack
 349     }
 350     setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
 351     return true;
 352   }

 353 
 354   public Address getSP() { return spFound; }
 355   public Address getFP() { return fpFound; }
 356   /** May be null if getting values from thread-local storage; take
 357       care to call the correct AMD64Frame constructor to recover this if
 358       necessary */
 359   public Address getPC() { return pcFound; }
 360 
 361   private void setValues(Address sp, Address fp, Address pc) {
 362     spFound = sp;
 363     fpFound = fp;
 364     pcFound = pc;
 365   }
 366 }
< prev index next >