annotate agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86CurrentFrameGuess.java @ 6782:5a98bf7d847b

6879063: SA should use hsdis for disassembly Summary: We should in SA to use hsdis for it like the JVM does to replace the current java based disassembler. Reviewed-by: twisti, jrose, sla Contributed-by: yumin.qi@oracle.com
author minqi
date Mon, 24 Sep 2012 12:44:00 -0700
parents c18cbe5936b8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
2 * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 package sun.jvm.hotspot.runtime.x86;
a61af66fc99e Initial load
duke
parents:
diff changeset
26
a61af66fc99e Initial load
duke
parents:
diff changeset
27 import sun.jvm.hotspot.debugger.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
28 import sun.jvm.hotspot.debugger.x86.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
29 import sun.jvm.hotspot.code.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
30 import sun.jvm.hotspot.interpreter.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
31 import sun.jvm.hotspot.runtime.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 /** <P> Should be able to be used on all x86 platforms we support
a61af66fc99e Initial load
duke
parents:
diff changeset
34 (Win32, Solaris/x86, and soon Linux) to implement JavaThread's
a61af66fc99e Initial load
duke
parents:
diff changeset
35 "currentFrameGuess()" functionality. Input is an X86ThreadContext;
a61af66fc99e Initial load
duke
parents:
diff changeset
36 output is SP, FP, and PC for an X86Frame. Instantiation of the
a61af66fc99e Initial load
duke
parents:
diff changeset
37 X86Frame is left to the caller, since we may need to subclass
a61af66fc99e Initial load
duke
parents:
diff changeset
38 X86Frame to support signal handler frames on Unix platforms. </P>
a61af66fc99e Initial load
duke
parents:
diff changeset
39
a61af66fc99e Initial load
duke
parents:
diff changeset
40 <P> Algorithm is to walk up the stack within a given range (say,
a61af66fc99e Initial load
duke
parents:
diff changeset
41 512K at most) looking for a plausible PC and SP for a Java frame,
a61af66fc99e Initial load
duke
parents:
diff changeset
42 also considering those coming in from the context. If we find a PC
a61af66fc99e Initial load
duke
parents:
diff changeset
43 that belongs to the VM (i.e., in generated code like the
a61af66fc99e Initial load
duke
parents:
diff changeset
44 interpreter or CodeCache) then we try to find an associated EBP.
a61af66fc99e Initial load
duke
parents:
diff changeset
45 We repeat this until we either find a complete frame or run out of
a61af66fc99e Initial load
duke
parents:
diff changeset
46 stack to look at. </P> */
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 public class X86CurrentFrameGuess {
a61af66fc99e Initial load
duke
parents:
diff changeset
49 private X86ThreadContext context;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 private JavaThread thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
51 private Address spFound;
a61af66fc99e Initial load
duke
parents:
diff changeset
52 private Address fpFound;
a61af66fc99e Initial load
duke
parents:
diff changeset
53 private Address pcFound;
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.x86.X86Frame.DEBUG")
a61af66fc99e Initial load
duke
parents:
diff changeset
56 != null;
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 public X86CurrentFrameGuess(X86ThreadContext context,
a61af66fc99e Initial load
duke
parents:
diff changeset
59 JavaThread thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 this.context = context;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 this.thread = thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
62 }
a61af66fc99e Initial load
duke
parents:
diff changeset
63
a61af66fc99e Initial load
duke
parents:
diff changeset
64 /** Returns false if not able to find a frame within a reasonable range. */
a61af66fc99e Initial load
duke
parents:
diff changeset
65 public boolean run(long regionInBytesToSearch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 Address sp = context.getRegisterAsAddress(X86ThreadContext.SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
67 Address pc = context.getRegisterAsAddress(X86ThreadContext.PC);
a61af66fc99e Initial load
duke
parents:
diff changeset
68 Address fp = context.getRegisterAsAddress(X86ThreadContext.FP);
a61af66fc99e Initial load
duke
parents:
diff changeset
69 if (sp == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // Bail out if no last java frame eithe
a61af66fc99e Initial load
duke
parents:
diff changeset
71 if (thread.getLastJavaSP() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
72 setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
a61af66fc99e Initial load
duke
parents:
diff changeset
73 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75 // Bail out
a61af66fc99e Initial load
duke
parents:
diff changeset
76 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
77 }
a61af66fc99e Initial load
duke
parents:
diff changeset
78 Address end = sp.addOffsetTo(regionInBytesToSearch);
a61af66fc99e Initial load
duke
parents:
diff changeset
79 VM vm = VM.getVM();
a61af66fc99e Initial load
duke
parents:
diff changeset
80
a61af66fc99e Initial load
duke
parents:
diff changeset
81 setValues(null, null, null); // Assume we're not going to find anything
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83 if (vm.isJavaPCDbg(pc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 if (vm.isClientCompiler()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // If the topmost frame is a Java frame, we are (pretty much)
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // guaranteed to have a viable EBP. We should be more robust
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // than this (we have the potential for losing entire threads'
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // stack traces) but need to see how much work we really have
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // to do here. Searching the stack for an (SP, FP) pair is
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // hard since it's easy to misinterpret inter-frame stack
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // pointers as base-of-frame pointers; we also don't know the
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // sizes of C1 frames (not registered in the nmethod) so can't
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // derive them from ESP.
a61af66fc99e Initial load
duke
parents:
diff changeset
94
a61af66fc99e Initial load
duke
parents:
diff changeset
95 setValues(sp, fp, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
96 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
97 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
98 if (vm.getInterpreter().contains(pc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
99 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
a61af66fc99e Initial load
duke
parents:
diff changeset
101 sp + ", fp = " + fp + ", pc = " + pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103 setValues(sp, fp, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
106
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // For the server compiler, EBP is not guaranteed to be valid
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // for compiled code. In addition, an earlier attempt at a
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // non-searching algorithm (see below) failed because the
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // stack pointer from the thread context was pointing
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // (considerably) beyond the ostensible end of the stack, into
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // garbage; walking from the topmost frame back caused a crash.
a61af66fc99e Initial load
duke
parents:
diff changeset
113 //
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // This algorithm takes the current PC as a given and tries to
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // find the correct corresponding SP by walking up the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // and repeatedly performing stackwalks (very inefficient).
a61af66fc99e Initial load
duke
parents:
diff changeset
117 //
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // FIXME: there is something wrong with stackwalking across
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // adapter frames...this is likely to be the root cause of the
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // failure with the simpler algorithm below.
a61af66fc99e Initial load
duke
parents:
diff changeset
121
a61af66fc99e Initial load
duke
parents:
diff changeset
122 for (long offset = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
123 offset < regionInBytesToSearch;
a61af66fc99e Initial load
duke
parents:
diff changeset
124 offset += vm.getAddressSize()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 try {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 Address curSP = sp.addOffsetTo(offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
127 Frame frame = new X86Frame(curSP, null, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
128 RegisterMap map = thread.newRegisterMap(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
129 while (frame != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // We were able to traverse all the way to the
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // bottommost Java frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // This sp looks good. Keep it.
a61af66fc99e Initial load
duke
parents:
diff changeset
134 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 setValues(curSP, null, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
138 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140 frame = frame.sender(map);
a61af66fc99e Initial load
duke
parents:
diff changeset
141 }
a61af66fc99e Initial load
duke
parents:
diff changeset
142 } catch (Exception e) {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
144 System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // Bad SP. Try another.
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
149
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // Were not able to find a plausible SP to go with this PC.
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // Bail out.
a61af66fc99e Initial load
duke
parents:
diff changeset
152 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
153
a61af66fc99e Initial load
duke
parents:
diff changeset
154 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // Original algorithm which does not work because SP was
a61af66fc99e Initial load
duke
parents:
diff changeset
156 // pointing beyond where it should have:
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // For the server compiler, EBP is not guaranteed to be valid
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // for compiled code. We see whether the PC is in the
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // interpreter and take care of that, otherwise we run code
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // (unfortunately) duplicated from X86Frame.senderForCompiledFrame.
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 CodeCache cc = vm.getCodeCache();
a61af66fc99e Initial load
duke
parents:
diff changeset
164 if (cc.contains(pc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
165 CodeBlob cb = cc.findBlob(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 // See if we can derive a frame pointer from SP and PC
a61af66fc99e Initial load
duke
parents:
diff changeset
168 // NOTE: This is the code duplicated from X86Frame
a61af66fc99e Initial load
duke
parents:
diff changeset
169 Address saved_fp = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
170 int llink_offset = cb.getLinkOffset();
a61af66fc99e Initial load
duke
parents:
diff changeset
171 if (llink_offset >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
172 // Restore base-pointer, since next frame might be an interpreter frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
173 Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 saved_fp = fp_addr.getAddressAt(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
176
a61af66fc99e Initial load
duke
parents:
diff changeset
177 setValues(sp, saved_fp, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
178 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 }
a61af66fc99e Initial load
duke
parents:
diff changeset
180 */
a61af66fc99e Initial load
duke
parents:
diff changeset
181 }
a61af66fc99e Initial load
duke
parents:
diff changeset
182 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // If the current program counter was not known to us as a Java
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // PC, we currently assume that we are in the run-time system
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // and attempt to look to thread-local storage for saved ESP and
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // EBP. Note that if these are null (because we were, in fact,
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // in Java code, i.e., vtable stubs or similar, and the SA
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // didn't have enough insight into the target VM to understand
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // that) then we are going to lose the entire stack trace for
a61af66fc99e Initial load
duke
parents:
diff changeset
190 // the thread, which is sub-optimal. FIXME.
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
193 System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
a61af66fc99e Initial load
duke
parents:
diff changeset
194 thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
a61af66fc99e Initial load
duke
parents:
diff changeset
195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
196 if (thread.getLastJavaSP() == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
197 return false; // No known Java frames on stack
a61af66fc99e Initial load
duke
parents:
diff changeset
198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
199 setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
a61af66fc99e Initial load
duke
parents:
diff changeset
200 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 public Address getSP() { return spFound; }
a61af66fc99e Initial load
duke
parents:
diff changeset
205 public Address getFP() { return fpFound; }
a61af66fc99e Initial load
duke
parents:
diff changeset
206 /** May be null if getting values from thread-local storage; take
a61af66fc99e Initial load
duke
parents:
diff changeset
207 care to call the correct X86Frame constructor to recover this if
a61af66fc99e Initial load
duke
parents:
diff changeset
208 necessary */
a61af66fc99e Initial load
duke
parents:
diff changeset
209 public Address getPC() { return pcFound; }
a61af66fc99e Initial load
duke
parents:
diff changeset
210
a61af66fc99e Initial load
duke
parents:
diff changeset
211 private void setValues(Address sp, Address fp, Address pc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
212 spFound = sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 fpFound = fp;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 pcFound = pc;
a61af66fc99e Initial load
duke
parents:
diff changeset
215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
216 }