Save This Page
Home » openjdk-7 » sun.jvm » hotspot » runtime » x86 » [javadoc | source]
    1   /*
    2    * Copyright (c) 2001, 2006, 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.x86;
   26   
   27   import sun.jvm.hotspot.debugger;
   28   import sun.jvm.hotspot.debugger.x86;
   29   import sun.jvm.hotspot.code;
   30   import sun.jvm.hotspot.interpreter;
   31   import sun.jvm.hotspot.runtime;
   32   
   33   /** <P> Should be able to be used on all x86 platforms we support
   34       (Win32, Solaris/x86, and soon Linux) to implement JavaThread's
   35       "currentFrameGuess()" functionality. Input is an X86ThreadContext;
   36       output is SP, FP, and PC for an X86Frame. Instantiation of the
   37       X86Frame is left to the caller, since we may need to subclass
   38       X86Frame to support signal handler frames on Unix platforms. </P>
   39   
   40       <P> Algorithm is to walk up the stack within a given range (say,
   41       512K at most) looking for a plausible PC and SP for a Java frame,
   42       also considering those coming in from the context. If we find a PC
   43       that belongs to the VM (i.e., in generated code like the
   44       interpreter or CodeCache) then we try to find an associated EBP.
   45       We repeat this until we either find a complete frame or run out of
   46       stack to look at. </P> */
   47   
   48   public class X86CurrentFrameGuess {
   49     private X86ThreadContext context;
   50     private JavaThread       thread;
   51     private Address          spFound;
   52     private Address          fpFound;
   53     private Address          pcFound;
   54   
   55     private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.x86.X86Frame.DEBUG")
   56                                          != null;
   57   
   58     public X86CurrentFrameGuess(X86ThreadContext context,
   59                                 JavaThread thread) {
   60       this.context = context;
   61       this.thread  = thread;
   62     }
   63   
   64     /** Returns false if not able to find a frame within a reasonable range. */
   65     public boolean run(long regionInBytesToSearch) {
   66       Address sp  = context.getRegisterAsAddress(X86ThreadContext.SP);
   67       Address pc  = context.getRegisterAsAddress(X86ThreadContext.PC);
   68       Address fp  = context.getRegisterAsAddress(X86ThreadContext.FP);
   69       if (sp == null) {
   70         // Bail out if no last java frame eithe
   71         if (thread.getLastJavaSP() != null) {
   72           setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
   73           return true;
   74         }
   75         // Bail out
   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 = frame.sender(map);
  141               }
  142             } catch (Exception e) {
  143               if (DEBUG) {
  144                 System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
  145               }
  146               // Bad SP. Try another.
  147             }
  148           }
  149   
  150           // Were not able to find a plausible SP to go with this PC.
  151           // Bail out.
  152           return false;
  153   
  154           /*
  155           // Original algorithm which does not work because SP was
  156           // pointing beyond where it should have:
  157   
  158           // For the server compiler, EBP is not guaranteed to be valid
  159           // for compiled code. We see whether the PC is in the
  160           // interpreter and take care of that, otherwise we run code
  161           // (unfortunately) duplicated from X86Frame.senderForCompiledFrame.
  162   
  163           CodeCache cc = vm.getCodeCache();
  164           if (cc.contains(pc)) {
  165             CodeBlob cb = cc.findBlob(pc);
  166   
  167             // See if we can derive a frame pointer from SP and PC
  168             // NOTE: This is the code duplicated from X86Frame
  169             Address saved_fp = null;
  170             int llink_offset = cb.getLinkOffset();
  171             if (llink_offset >= 0) {
  172               // Restore base-pointer, since next frame might be an interpreter frame.
  173               Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
  174               saved_fp = fp_addr.getAddressAt(0);
  175             }
  176   
  177             setValues(sp, saved_fp, pc);
  178             return true;
  179           }
  180           */
  181         }
  182       } else {
  183         // If the current program counter was not known to us as a Java
  184         // PC, we currently assume that we are in the run-time system
  185         // and attempt to look to thread-local storage for saved ESP and
  186         // EBP. Note that if these are null (because we were, in fact,
  187         // in Java code, i.e., vtable stubs or similar, and the SA
  188         // didn't have enough insight into the target VM to understand
  189         // that) then we are going to lose the entire stack trace for
  190         // the thread, which is sub-optimal. FIXME.
  191   
  192         if (DEBUG) {
  193           System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
  194                              thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
  195         }
  196         if (thread.getLastJavaSP() == null) {
  197           return false; // No known Java frames on stack
  198         }
  199         setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
  200         return true;
  201       }
  202     }
  203   
  204     public Address getSP() { return spFound; }
  205     public Address getFP() { return fpFound; }
  206     /** May be null if getting values from thread-local storage; take
  207         care to call the correct X86Frame constructor to recover this if
  208         necessary */
  209     public Address getPC() { return pcFound; }
  210   
  211     private void setValues(Address sp, Address fp, Address pc) {
  212       spFound = sp;
  213       fpFound = fp;
  214       pcFound = pc;
  215     }
  216   }

Save This Page
Home » openjdk-7 » sun.jvm » hotspot » runtime » x86 » [javadoc | source]