Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java @ 218:a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
Summary: Fixed stack walking code in sparc to start frame walk from last_java_sp.
Reviewed-by: sgoldman
author | swamyv |
---|---|
date | Tue, 24 Jun 2008 21:37:10 -0700 |
parents | a61af66fc99e |
children | c18cbe5936b8 |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright 2000-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 package sun.jvm.hotspot.runtime.sparc; | |
26 | |
27 import java.util.*; | |
28 | |
29 import sun.jvm.hotspot.asm.sparc.*; | |
30 import sun.jvm.hotspot.code.*; | |
31 import sun.jvm.hotspot.compiler.*; | |
32 import sun.jvm.hotspot.debugger.*; | |
33 import sun.jvm.hotspot.debugger.cdbg.*; | |
34 import sun.jvm.hotspot.oops.*; | |
35 import sun.jvm.hotspot.runtime.*; | |
36 import sun.jvm.hotspot.runtime.posix.*; | |
37 import sun.jvm.hotspot.types.*; | |
38 import sun.jvm.hotspot.utilities.*; | |
39 | |
40 /** Specialization of and implementation of abstract methods of the | |
41 Frame class for the SPARC CPU. (FIXME: this is as quick a port as | |
42 possible to get things running; will have to do a better job right | |
43 away.) */ | |
44 | |
45 public class SPARCFrame extends Frame { | |
46 // The pc value is the raw return address, plus 8 (pcReturnOffset()). | |
47 // the value of sp and youngerSP that is stored in this object | |
48 // is always, always, always the value that would be found in the | |
49 // register (or window save area) while the target VM was executing. | |
50 // The caller of the constructor will alwasy know if has a biased or | |
51 // unbiased version of the stack pointer and can convert real (unbiased) | |
52 // value via a helper routine we supply. | |
53 // Whenever we return sp or youngerSP values we do not return the internal | |
54 // value but the real (unbiased) pointers since these are the true, usable | |
55 // memory addresses. The outlier case is that of the null pointer. The current | |
56 // mechanism makes null pointers always look null whether biased or not. | |
57 // This seems to cause no problems. In theory null real pointers could be biased | |
58 // just like other values however this has impact on things like addOffsetTo() | |
59 // to be able to take an Address that represents null and add an offset to it. | |
60 // This doesn't seem worth the bother and the impact on the rest of the code | |
61 // when the biasSP and unbiasSP can make this invisible. | |
62 // | |
63 // The general rule in this code is that when we have a variable like FP, youngerSP, SP | |
64 // that these are real (i.e. unbiased) addresses. The instance variables in a Frame are | |
65 // always raw values. The other rule is that it except for the frame constructors and | |
66 // the unBiasSP helper all methods accept parameters that are real addresses. | |
67 // | |
68 | |
69 /** Optional next-younger SP (used to locate O7, the PC) */ | |
70 private Address raw_youngerSP; | |
71 | |
72 /** Intepreter adjusts the stack pointer to make all locals contiguous */ | |
73 private long interpreterSPAdjustmentOffset; | |
74 | |
75 /** Number of stack entries for longs */ | |
76 private static final int WORDS_PER_LONG = 2; | |
77 | |
78 /** Normal SPARC return is 2 words past PC */ | |
79 public static final int PC_RETURN_OFFSET = 8; | |
80 | |
81 /** Size of each block, in order of increasing address */ | |
82 public static final int REGISTER_SAVE_WORDS = 16; | |
83 // FIXME: read these from the remote process | |
84 //#ifdef _LP64 | |
85 // callee_aggregate_return_pointer_words = 0, | |
86 //#else | |
87 // callee_aggregate_return_pointer_words = 1, | |
88 //#endif | |
89 public static final int CALLEE_AGGREGATE_RETURN_POINTER_WORDS = 1; | |
90 public static final int CALLEE_REGISTER_ARGUMENT_SAVE_AREA_WORDS = 6; | |
91 | |
92 // offset of each block, in order of increasing address: | |
93 public static final int REGISTER_SAVE_WORDS_SP_OFFSET = 0; | |
94 public static final int CALLEE_AGGREGATE_RETURN_POINTER_SP_OFFSET = REGISTER_SAVE_WORDS_SP_OFFSET + REGISTER_SAVE_WORDS; | |
95 public static final int CALLEE_REGISTER_ARGUMENT_SAVE_AREA_SP_OFFSET = (CALLEE_AGGREGATE_RETURN_POINTER_SP_OFFSET + | |
96 CALLEE_AGGREGATE_RETURN_POINTER_WORDS); | |
97 public static final int MEMORY_PARAMETER_WORD_SP_OFFSET = (CALLEE_REGISTER_ARGUMENT_SAVE_AREA_SP_OFFSET + | |
98 CALLEE_REGISTER_ARGUMENT_SAVE_AREA_WORDS); | |
99 public static final int VARARGS_OFFSET = MEMORY_PARAMETER_WORD_SP_OFFSET; | |
100 | |
101 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.sparc.SPARCFrame.DEBUG") != null; | |
102 | |
103 public static Address unBiasSP(Address raw_sp) { | |
104 if (raw_sp != null) { | |
105 return raw_sp.addOffsetTo(VM.getVM().getStackBias()); | |
106 } else { | |
107 return null; | |
108 } | |
109 } | |
110 | |
111 public static Address biasSP(Address real_sp) { | |
112 if (real_sp != null) { | |
113 if (DEBUG) { | |
114 System.out.println("biasing realsp: " + real_sp + " biased: " + real_sp.addOffsetTo(-VM.getVM().getStackBias()) ); | |
115 } | |
116 return real_sp.addOffsetTo(-VM.getVM().getStackBias()); | |
117 } else { | |
118 if (DEBUG) { | |
119 System.out.println("biasing null realsp"); | |
120 } | |
121 return null; | |
122 } | |
123 } | |
124 // | |
125 // This is used to find the younger sp for a thread thatn has stopped but hasn't | |
126 // conveniently told us the information where we can find the pc or the frame | |
127 // containing the pc that corresponds to last_java_sp. This method will walk | |
128 // the frames trying to find the frame which we contains the data we need. | |
129 // | |
130 public static Address findYoungerSP(Address top, Address find) { | |
131 // top and find are unBiased sp values | |
132 // we return an unBiased value | |
133 Address findRaw = biasSP(find); | |
134 if (top == null || find == null || findRaw == null) { | |
135 throw new RuntimeException("bad values for findYoungerSP top: " + top + " find: " + find); | |
136 } | |
137 // It would be unusual to find more than 20 native frames before we find the java frame | |
138 // we are looking for. | |
139 final int maxFrames = 20; | |
140 int count = 0; | |
141 Address search = top; | |
142 Address next; | |
143 Address pc; | |
144 if (DEBUG) { | |
145 System.out.println("findYoungerSP top: " + top + " find: " + find + " findRaw: " + findRaw); | |
146 } | |
147 while ( count != maxFrames && search != null) { | |
148 next = search.getAddressAt(SPARCRegisters.I6.spOffsetInSavedWindow()); | |
149 pc = search.getAddressAt(SPARCRegisters.I7.spOffsetInSavedWindow()); | |
150 if (DEBUG) { | |
151 System.out.println("findYoungerSP next: " + next + " pc: " + pc); | |
152 } | |
153 if (next.equals(findRaw)) { | |
154 return search; | |
155 } | |
156 search = unBiasSP(next); | |
157 } | |
158 if (DEBUG) { | |
159 System.out.println("findYoungerSP: never found younger, top: " + top + " find: " + find); | |
160 } | |
161 return null; | |
162 } | |
163 | |
164 public Address getSP() { | |
165 if (DEBUG) { | |
166 System.out.println("getSP raw: " + raw_sp + " unbiased: " + unBiasSP(raw_sp)); | |
167 } | |
168 return unBiasSP(raw_sp); | |
169 } | |
170 | |
171 public Address getID() { | |
172 return getSP(); | |
173 } | |
174 | |
175 public Address getYoungerSP() { | |
176 if (DEBUG) { | |
177 System.out.println("getYoungerSP: " + raw_youngerSP + " unbiased: " + unBiasSP(raw_youngerSP)); | |
178 } | |
179 return unBiasSP(raw_youngerSP); | |
180 } | |
181 | |
182 /** This constructor relies on the fact that the creator of a frame | |
183 has flushed register windows which the frame will refer to, and | |
184 that those register windows will not be reloaded until the frame | |
185 is done reading and writing the stack. Moreover, if the | |
186 "younger_pc" argument points into the register save area of the | |
187 next younger frame (though it need not), the register window for | |
188 that next younger frame must also stay flushed. (The caller is | |
189 responsible for ensuring this.) */ | |
190 public SPARCFrame(Address raw_sp, Address raw_youngerSP, boolean youngerFrameIsInterpreted) { | |
191 super(); | |
192 if (DEBUG) { | |
193 System.out.println("Constructing frame(1) raw_sp: " + raw_sp + " raw_youngerSP: " + raw_youngerSP); | |
194 } | |
195 if (Assert.ASSERTS_ENABLED) { | |
196 Assert.that((unBiasSP(raw_sp).andWithMask(VM.getVM().getAddressSize() - 1) == null), | |
197 "Expected raw sp likely got real sp, value was " + raw_sp); | |
198 if (raw_youngerSP != null) { | |
199 Assert.that((unBiasSP(raw_youngerSP).andWithMask(VM.getVM().getAddressSize() - 1) == null), | |
200 "Expected raw youngerSP likely got real youngerSP, value was " + raw_youngerSP); | |
201 } | |
202 } | |
203 this.raw_sp = raw_sp; | |
204 this.raw_youngerSP = raw_youngerSP; | |
205 if (raw_youngerSP == null) { | |
206 // make a deficient frame which doesn't know where its PC is | |
207 pc = null; | |
208 } else { | |
209 Address youngerSP = unBiasSP(raw_youngerSP); | |
210 pc = youngerSP.getAddressAt(SPARCRegisters.I7.spOffsetInSavedWindow()).addOffsetTo(PC_RETURN_OFFSET); | |
211 | |
212 if (Assert.ASSERTS_ENABLED) { | |
213 Assert.that(youngerSP.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()). | |
214 equals(raw_sp), | |
215 "youngerSP must be valid"); | |
216 } | |
217 } | |
218 | |
219 if (youngerFrameIsInterpreted) { | |
220 long IsavedSP = SPARCRegisters.IsavedSP.spOffsetInSavedWindow(); | |
221 // compute adjustment to this frame's SP made by its interpreted callee | |
222 interpreterSPAdjustmentOffset = 0; | |
223 Address savedSP = unBiasSP(getYoungerSP().getAddressAt(IsavedSP)); | |
224 if (savedSP == null) { | |
225 if ( DEBUG) { | |
226 System.out.println("WARNING: IsavedSP was null for frame " + this); | |
227 } | |
228 } else { | |
229 interpreterSPAdjustmentOffset = savedSP.minus(getSP()); | |
230 } | |
231 } else { | |
232 interpreterSPAdjustmentOffset = 0; | |
233 } | |
234 if ( pc != null) { | |
235 // Look for a deopt pc and if it is deopted convert to original pc | |
236 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); | |
237 if (cb != null && cb.isJavaMethod()) { | |
238 NMethod nm = (NMethod) cb; | |
239 if (pc.equals(nm.deoptBegin())) { | |
240 // adjust pc if frame is deoptimized. | |
241 pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); | |
242 deoptimized = true; | |
243 } | |
244 } | |
245 } | |
246 } | |
247 | |
248 /** Make a deficient frame which doesn't know where its PC is (note | |
249 no youngerSP argument) */ | |
250 public SPARCFrame(Address raw_sp, Address pc) { | |
251 super(); | |
252 if (DEBUG) { | |
253 System.out.println("Constructing frame(2) raw_sp: " + raw_sp ); | |
254 } | |
255 this.raw_sp = raw_sp; | |
256 if (Assert.ASSERTS_ENABLED) { | |
257 Assert.that((unBiasSP(raw_sp).andWithMask(VM.getVM().getAddressSize() - 1) == null), | |
258 "Expected raw sp likely got real sp, value was " + raw_sp); | |
259 } | |
260 raw_youngerSP = null; | |
261 this.pc = pc; | |
262 interpreterSPAdjustmentOffset = 0; | |
263 } | |
264 | |
265 /** Only used internally */ | |
266 private SPARCFrame() { | |
267 } | |
268 | |
269 public Object clone() { | |
270 SPARCFrame frame = new SPARCFrame(); | |
271 frame.raw_sp = raw_sp; | |
272 frame.pc = pc; | |
273 frame.raw_youngerSP = raw_youngerSP; | |
274 frame.interpreterSPAdjustmentOffset = interpreterSPAdjustmentOffset; | |
275 frame.deoptimized = deoptimized; | |
276 return frame; | |
277 } | |
278 | |
279 public boolean equals(Object arg) { | |
280 if (arg == null) { | |
281 return false; | |
282 } | |
283 | |
284 if (!(arg instanceof SPARCFrame)) { | |
285 return false; | |
286 } | |
287 | |
288 SPARCFrame other = (SPARCFrame) arg; | |
289 | |
290 return (AddressOps.equal(getSP(), other.getSP()) && | |
291 AddressOps.equal(getFP(), other.getFP()) && | |
292 AddressOps.equal(getPC(), other.getPC())); | |
293 } | |
294 | |
295 public int hashCode() { | |
296 if (raw_sp == null) { | |
297 return 0; | |
298 } | |
299 | |
300 return raw_sp.hashCode(); | |
301 } | |
302 | |
303 public String toString() { | |
304 Address fp = getFP(); | |
305 Address sp = getSP(); | |
306 Address youngerSP = getYoungerSP(); | |
307 | |
308 return "sp: " + (sp == null? "null" : sp.toString()) + | |
309 ", younger_sp: " + (youngerSP == null? "null" : youngerSP.toString()) + | |
310 ", fp: " + (fp == null? "null" : fp.toString()) + | |
311 ", pc: " + (pc == null? "null" : pc.toString()); | |
312 } | |
313 | |
314 /** <P> Identifies a signal handler frame on the stack. </P> | |
315 | |
316 <P> There are a few different algorithms for doing this, and | |
317 they vary from platform to platform. For example, based on a | |
318 conversation with Dave Dice, Solaris/x86 will be substantially | |
319 simpler to handle than Solaris/SPARC because the signal handler | |
320 frame can be identified because of a program counter == -1. </P> | |
321 | |
322 <P> The dbx group provided code and advice on these topics; the | |
323 code below evolved from theirs, but is not correct/robust. | |
324 Without going into too many details, it seems that looking for | |
325 the incoming argument to the sigacthandler frame (which is what | |
326 this code identifies) is not guaranteed to be stable across | |
327 versions of Solaris, since that function is supplied by | |
328 libthread and is not guaranteed not to clobber I2 before it | |
329 calls __sighndlr later. From discussions, it sounds like a | |
330 robust algorithm which wouldn't require traversal of the | |
331 ucontext chain (used by dbx, but which Dave Dice thinks isn't | |
332 robust in the face of libthread -- need to follow up) would be | |
333 to be able to properly identify the __sighndlr frame, then get | |
334 I2 and treat that as a ucontext. To identify __sighndlr we would | |
335 need to look up that symbol in the remote process and look for a | |
336 program counter within a certain (small) distance. </P> | |
337 | |
338 <P> If the underlying Debugger supports CDebugger interface, we | |
339 take the approach of __sighnldr symbol. This approach is more robust | |
340 compared to the original hueristic approach. Of course, if there | |
341 is no CDebugger support, we fallback to the hueristic approach. </P> | |
342 | |
343 <P> The current implementation seems to work with Solaris 2.8. | |
344 A nice property of this system is that if we find a core file | |
345 this algorithm doesn't work on, we can change the code and try | |
346 again, so I'm putting this in as the current mechanism for | |
347 finding signal handler frames on Solaris/SPARC. </P> */ | |
348 public boolean isSignalHandlerFrameDbg() { | |
349 CDebugger cdbg = VM.getVM().getDebugger().getCDebugger(); | |
350 if (cdbg != null) { | |
351 LoadObject dso = cdbg.loadObjectContainingPC(getPC()); | |
352 if (dso != null) { | |
353 ClosestSymbol cs = dso.closestSymbolToPC(getPC()); | |
354 if (cs != null && cs.getName().equals("__sighndlr")) { | |
355 return true; | |
356 } else { | |
357 return false; | |
358 } | |
359 } else { | |
360 return false; | |
361 } | |
362 } else { | |
363 if (getYoungerSP() == null) { | |
364 // System.err.println(" SPARCFrame.isSignalHandlerFrameDbg: youngerSP = " + getYoungerSP()); | |
365 return false; | |
366 } | |
367 Address i2 = getSP().getAddressAt(SPARCRegisters.I2.spOffsetInSavedWindow()); | |
368 if (i2 == null) { | |
369 return false; | |
370 } | |
371 Address fp = getFP(); | |
372 // My (mistaken) understanding of the dbx group's code was that | |
373 // the signal handler frame could be identified by testing the | |
374 // incoming argument to see whether it was a certain distance | |
375 // below the frame pointer; in fact, their code did substantially | |
376 // more than this (traversal of the ucontext chain, which this | |
377 // code can't do because the topmost ucontext is not currently | |
378 // available via the proc_service APIs in dbx). The current code | |
379 // appears to work, but is probably not robust. | |
380 int MAJOR_HACK_OFFSET = 8; // Difference between expected location of the ucontext and reality | |
381 // System.err.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + | |
382 // ", fp = " + fp + ", raw_youngerSP = " + getYoungerSP()); | |
383 boolean res = i2.equals(fp.addOffsetTo(VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET))); | |
384 if (res) { | |
385 // Qualify this with another test (FIXME: this is a gross heuristic found while testing) | |
386 Address sigInfoAddr = getSP().getAddressAt(SPARCRegisters.I5.spOffsetInSavedWindow()); | |
387 if (sigInfoAddr == null) { | |
388 System.err.println("Frame with fp = " + fp + " looked like a signal handler frame but wasn't"); | |
389 res = false; | |
390 } | |
391 } | |
392 return res; | |
393 } | |
394 } | |
395 | |
396 public int getSignalNumberDbg() { | |
397 // From looking at the stack trace in dbx, it looks like the | |
398 // siginfo* comes into sigacthandler in I5. It would be much more | |
399 // robust to look at the __sighndlr frame instead, but we can't | |
400 // currently identify that frame. | |
401 | |
402 Address sigInfoAddr = getSP().getAddressAt(SPARCRegisters.I5.spOffsetInSavedWindow()); | |
403 // Read si_signo out of siginfo* | |
404 return (int) sigInfoAddr.getCIntegerAt(0, 4, false); | |
405 } | |
406 | |
407 public String getSignalNameDbg() { | |
408 return POSIXSignals.getSignalName(getSignalNumberDbg()); | |
409 } | |
410 | |
411 public boolean isInterpretedFrameValid() { | |
412 if (Assert.ASSERTS_ENABLED) { | |
413 Assert.that(isInterpretedFrame(), "Not an interpreted frame"); | |
414 } | |
415 // These are reasonable sanity checks | |
416 if (getFP() == null || (getFP().andWithMask(2 * VM.getVM().getAddressSize() - 1)) != null) { | |
417 return false; | |
418 } | |
419 if (getSP() == null || (getSP().andWithMask(2 * VM.getVM().getAddressSize() - 1)) != null) { | |
420 return false; | |
421 } | |
422 if (getFP().addOffsetTo(INTERPRETER_FRAME_VM_LOCAL_WORDS * VM.getVM().getAddressSize()).lessThan(getSP())) { | |
423 return false; | |
424 } | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
425 |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
426 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
427 |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
428 if (VM.getVM().getObjectHeap().isValidMethod(methodHandle) == false) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
429 return false; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
430 } |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
431 |
0 | 432 // These are hacks to keep us out of trouble. |
433 // The problem with these is that they mask other problems | |
434 if (getFP().lessThanOrEqual(getSP())) { // this attempts to deal with unsigned comparison above | |
435 return false; | |
436 } | |
437 if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { // stack frames shouldn't be large. | |
438 return false; | |
439 } | |
440 // FIXME: this is not atomic with respect to GC and is unsuitable | |
441 // for use in a non-debugging, or reflective, system. Need to | |
442 // figure out how to express this. | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
443 Address bcx = addressOfInterpreterFrameBCX().getAddressAt(0); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
444 |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
445 Method method; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
446 try { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
447 method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
448 } catch (UnknownOopException ex) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
449 return false; |
0 | 450 } |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
451 int bci = bcpToBci(bcx, method); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
452 //validate bci |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
453 if (bci < 0) return false; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
454 |
0 | 455 return true; |
456 } | |
457 | |
458 //-------------------------------------------------------------------------------- | |
459 // Accessors: | |
460 // | |
461 | |
462 /** Accessors */ | |
463 | |
464 public long frameSize() { | |
465 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); | |
466 } | |
467 | |
468 public Address getLink() { | |
469 return unBiasSP(getFP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); | |
470 } | |
471 | |
472 // FIXME: not implementable yet | |
473 // public void setLink(Address addr) { | |
474 // if (Assert.ASSERTS_ENABLED) { | |
475 // Assert.that(getLink().equals(addr), "frame nesting is controlled by hardware"); | |
476 // } | |
477 // } | |
478 | |
479 public Frame sender(RegisterMap regMap, CodeBlob cb) { | |
480 SPARCRegisterMap map = (SPARCRegisterMap) regMap; | |
481 | |
482 if (Assert.ASSERTS_ENABLED) { | |
483 Assert.that(map != null, "map must be set"); | |
484 } | |
485 | |
486 // Default is we don't have to follow them. The sender_for_xxx | |
487 // will update it accordingly | |
488 map.setIncludeArgumentOops(false); | |
489 | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
490 if (isEntryFrame()) { |
0 | 491 return senderForEntryFrame(map); |
492 } | |
493 | |
494 Address youngerSP = getSP(); | |
495 Address sp = getSenderSP(); | |
496 boolean isInterpreted = false; | |
497 | |
498 // FIXME: this is a hack to get stackwalking to work in the face | |
499 // of a signal like a SEGV. For debugging purposes it's important | |
500 // that (a) we are able to traverse the stack if we take a signal | |
501 // and (b) that we get the correct program counter in this | |
502 // situation. If we are not using alternate signal stacks then (a) | |
503 // seems to work all the time (on SPARC), but (b) is violated for | |
504 // the frame just below the signal handler. | |
505 | |
506 // The mechanism for finding the ucontext is not robust. In | |
507 // addition, we may find that we need to be able to fetch more | |
508 // registers from the ucontext than just the program counter, | |
509 // since the register windows on the stack are "stale". This will | |
510 // require substantial restructuring of this frame code, so has | |
511 // been avoided for now. | |
512 | |
513 // It is difficult to find a clean solution for mixing debugging | |
514 // situations with VM frame traversal. One could consider | |
515 // implementing generic frame traversal in the dbx style and only | |
516 // using the VM's stack walking mechanism on a per-frame basis, | |
517 // for example to traverse Java-level activations in a compiled | |
518 // frame. However, this will probably not interact well with the | |
519 // mechanism for finding oops on the stack. | |
520 | |
521 if (VM.getVM().isDebugging()) { | |
522 // If we are a signal handler frame, use a trick: make the | |
523 // youngerSP of the caller frame point to the top of the | |
524 // ucontext's contained register set. This should allow fetching | |
525 // of the registers for the frame just below the signal handler | |
526 // frame in the usual fashion. | |
527 if (isSignalHandlerFrameDbg()) { | |
528 | |
529 if (DEBUG) { | |
530 System.out.println("SPARCFrame.sender: found signal handler frame"); | |
531 } | |
532 | |
533 // Try to give a valid SP and PC for a "deficient frame" since | |
534 // we don't have a real register save area; making this class | |
535 // work by reading its information from a ucontext as well as | |
536 // a register save area is a major undertaking and has been | |
537 // deferred for now. It is very important that the PC is | |
538 // correct, which is why we don't just fall through to the | |
539 // other code (which would read the PC from the stale register | |
540 // window and thereby fail to get the actual location of the | |
541 // fault). | |
542 | |
543 long offset = getMContextAreaOffsetInUContext(); | |
544 Address fp = sp; | |
545 // System.out.println(" FP: " + fp); | |
546 fp = fp.addOffsetTo(getUContextOffset() + getMContextAreaOffsetInUContext()); | |
547 // System.out.println(" start of mcontext: " + fp); | |
548 // FIXME: put these elsewhere. These are the register numbers | |
549 // in /usr/include/sys/regset.h. They might belong in | |
550 // SPARCReigsters.java, but we currently don't have that list | |
551 // of numbers in the SA code (because all of the registers are | |
552 // listed as instances of SPARCRegister) and it appears that | |
553 // our numbering of the registers and this one don't match up. | |
554 int PC_OFFSET_IN_GREGSET = 1; | |
555 int SP_OFFSET_IN_GREGSET = 17; | |
556 raw_sp = fp.getAddressAt(VM.getVM().getAddressSize() * SP_OFFSET_IN_GREGSET); | |
557 Address pc = fp.getAddressAt(VM.getVM().getAddressSize() * PC_OFFSET_IN_GREGSET); | |
558 return new SPARCFrame(raw_sp, pc); | |
559 } | |
560 } | |
561 | |
562 if (!VM.getVM().isCore()) { | |
563 // Note: The version of this operation on any platform with callee-save | |
564 // registers must update the register map (if not null). | |
565 // In order to do this correctly, the various subtypes of | |
566 // of frame (interpreted, compiled, glue, native), | |
567 // must be distinguished. There is no need on SPARC for | |
568 // such distinctions, because all callee-save registers are | |
569 // preserved for all frames via SPARC-specific mechanisms. | |
570 // | |
571 // *** HOWEVER, *** if and when we make any floating-point | |
572 // registers callee-saved, then we will have to copy over | |
573 // the RegisterMap update logic from the Intel code. | |
574 | |
575 | |
576 // The constructor of the sender must know whether this frame is interpreted so it can set the | |
577 // sender's _interpreter_sp_adjustment field. | |
578 if (VM.getVM().getInterpreter().contains(pc)) { | |
579 isInterpreted = true; | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
580 map.makeIntegerRegsUnsaved(); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
581 map.shiftWindow(sp, youngerSP); |
0 | 582 } else { |
583 // Find a CodeBlob containing this frame's pc or elide the lookup and use the | |
584 // supplied blob which is already known to be associated with this frame. | |
585 cb = VM.getVM().getCodeCache().findBlob(pc); | |
586 if (cb != null) { | |
587 | |
588 if (cb.callerMustGCArguments(map.getThread())) { | |
589 map.setIncludeArgumentOops(true); | |
590 } | |
591 | |
592 // Update the location of all implicitly saved registers | |
593 // as the address of these registers in the register save | |
594 // area (for %o registers we use the address of the %i | |
595 // register in the next younger frame) | |
596 map.shiftWindow(sp, youngerSP); | |
597 if (map.getUpdateMap()) { | |
598 if (cb.getOopMaps() != null) { | |
599 OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); | |
600 } | |
601 } | |
602 } | |
603 } | |
604 } // #ifndef CORE | |
605 | |
606 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); | |
607 } | |
608 | |
609 protected boolean hasSenderPD() { | |
610 try { | |
611 // FIXME: should not happen!!! | |
612 if (getSP() == null) { | |
613 return false; | |
614 } | |
615 if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) { | |
616 return false; | |
617 } | |
618 return true; | |
619 } catch (RuntimeException e) { | |
620 if (DEBUG) { | |
621 System.out.println("Bad frame " + this); | |
622 } | |
623 throw e; | |
624 } | |
625 } | |
626 | |
627 //-------------------------------------------------------------------------------- | |
628 // Return address: | |
629 // | |
630 | |
631 public Address getSenderPC() { | |
632 return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET); | |
633 } | |
634 | |
635 // FIXME: currently unimplementable | |
636 // inline void frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; } | |
637 | |
638 public Address getUnextendedSP() { | |
639 return getSP().addOffsetTo(interpreterSPAdjustmentOffset); | |
640 } | |
641 | |
642 public Address getSenderSP() { | |
643 return getFP(); | |
644 } | |
645 | |
646 /** Given the next-younger sp for a given frame's sp, compute the | |
647 frame. We need the next-younger sp, because its register save | |
648 area holds the flushed copy of its I7, which is the PC of the | |
649 frame we are interested in. */ | |
650 public SPARCFrame afterSave() { | |
651 return new SPARCFrame(biasSP(getYoungerSP()), null); | |
652 } | |
653 | |
654 /** Accessors for the instance variables */ | |
655 public Address getFP() { | |
656 Address sp = getSP(); | |
657 if (sp == null) { | |
658 System.out.println("SPARCFrame.getFP(): sp == null"); | |
659 } | |
660 Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow()); | |
661 try { | |
662 Address fp = unBiasSP(fpAddr.getAddressAt(0)); | |
663 if (fp == null) { | |
664 System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")"); | |
665 } | |
666 return fp; | |
667 } catch (RuntimeException e) { | |
668 System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")"); | |
669 return null; | |
670 } | |
671 } | |
672 | |
673 private Address addressOfFPSlot(int index) { | |
674 return getFP().addOffsetTo(index * VM.getVM().getAddressSize()); | |
675 } | |
676 | |
677 // FIXME: temporarily elided | |
678 // // All frames | |
679 // | |
680 // intptr_t* fp_addr_at(int index) const { return &fp()[index]; } | |
681 // intptr_t* sp_addr_at(int index) const { return &sp()[index]; } | |
682 // intptr_t fp_at( int index) const { return *fp_addr_at(index); } | |
683 // intptr_t sp_at( int index) const { return *sp_addr_at(index); } | |
684 // | |
685 // private: | |
686 // inline address* I7_addr() const; | |
687 // inline address* O7_addr() const; | |
688 // | |
689 // inline address* I0_addr() const; | |
690 // inline address* O0_addr() const; | |
691 // | |
692 // public: | |
693 // // access to SPARC arguments and argument registers | |
694 // | |
695 // intptr_t* register_addr(Register reg) const { | |
696 // return sp_addr_at(reg.sp_offset_in_saved_window()); | |
697 // } | |
698 // intptr_t* memory_param_addr(int param_ix, bool is_in) const { | |
699 // int offset = callee_register_argument_save_area_sp_offset + param_ix; | |
700 // if (is_in) | |
701 // return fp_addr_at(offset); | |
702 // else | |
703 // return sp_addr_at(offset); | |
704 // } | |
705 // intptr_t* param_addr(int param_ix, bool is_in) const { | |
706 // if (param_ix >= callee_register_argument_save_area_words) | |
707 // return memory_param_addr(param_ix, is_in); | |
708 // else if (is_in) | |
709 // return register_addr(Argument(param_ix, true).as_register()); | |
710 // else { | |
711 // // the registers are stored in the next younger frame | |
712 // // %%% is this really necessary? | |
713 // frame next_younger = after_save(); | |
714 // return next_younger.register_addr(Argument(param_ix, true).as_register()); | |
715 // } | |
716 // } | |
717 | |
718 //-------------------------------------------------------------------------------- | |
719 // Interpreter frames: | |
720 // | |
721 | |
722 /** 2 words, also used to save float regs across calls to C */ | |
723 public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2; | |
724 public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4; | |
725 /** For native calls only */ | |
726 public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5; | |
727 /** For native calls only */ | |
728 public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6; | |
729 /** Should be same as above, and should be zero mod 8 */ | |
730 public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6; | |
731 public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET; | |
732 | |
733 /** Interpreter frame set-up needs to save 2 extra words in outgoing | |
734 param area for class and jnienv arguments for native stubs (see | |
735 nativeStubGen_sparc.cpp) */ | |
736 public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2; | |
737 | |
738 // FIXME: elided for now | |
739 // | |
740 // // the compiler frame has many of the same fields as the interpreter frame | |
741 // // %%%%% factor out declarations of the shared fields | |
742 // enum compiler_frame_fixed_locals { | |
743 // compiler_frame_d_scratch_fp_offset = -2, | |
744 // compiler_frame_vm_locals_fp_offset = -2, // should be same as above | |
745 // | |
746 // compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset | |
747 // }; | |
748 // | |
749 // private: | |
750 // | |
751 // // where LcpoolCache is saved: | |
752 // constantPoolCacheOop* interpreter_frame_cpoolcache_addr() const { | |
753 // return (constantPoolCacheOop*)sp_addr_at( LcpoolCache.sp_offset_in_saved_window()); | |
754 // } | |
755 // | |
756 // // where Lmonitors is saved: | |
757 // BasicObjectLock** interpreter_frame_monitors_addr() const { | |
758 // return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window()); | |
759 // } | |
760 // intptr_t** interpreter_frame_esp_addr() const { | |
761 // return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window()); | |
762 // } | |
763 // | |
764 // inline void interpreter_frame_set_tos_address(intptr_t* x); | |
765 // | |
766 // // next two fns read and write Lmonitors value, | |
767 // private: | |
768 // BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); } | |
769 // void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; } | |
770 // | |
771 //#ifndef CORE | |
772 //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const { | |
773 // COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset); ) | |
774 // COMPILER2_ONLY(return oopmapreg_to_location(reg, ®_map); ) | |
775 //} | |
776 //#endif | |
777 | |
778 // FIXME: NOT FINISHED | |
779 public Address addressOfInterpreterFrameLocals() { | |
780 return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow()); | |
781 } | |
782 | |
783 // FIXME: this is not atomic with respect to GC and is unsuitable | |
784 // for use in a non-debugging, or reflective, system. | |
785 private Address addressOfInterpreterFrameBCX() { | |
786 // %%%%% reinterpreting Lbcp as a bcx | |
787 return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow()); | |
788 } | |
789 | |
790 public int getInterpreterFrameBCI() { | |
791 // FIXME: this is not atomic with respect to GC and is unsuitable | |
792 // for use in a non-debugging, or reflective, system. Need to | |
793 // figure out how to express this. | |
794 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); | |
795 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); | |
796 Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); | |
797 return bcpToBci(bcp, method); | |
798 } | |
799 | |
800 public Address addressOfInterpreterFrameExpressionStack() { | |
801 return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize()); | |
802 } | |
803 | |
804 public int getInterpreterFrameExpressionStackDirection() { | |
805 return -1; | |
806 } | |
807 | |
808 /** Top of expression stack */ | |
809 public Address addressOfInterpreterFrameTOS() { | |
810 return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize()); | |
811 } | |
812 | |
813 /** Expression stack from top down */ | |
814 public Address addressOfInterpreterFrameTOSAt(int slot) { | |
815 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); | |
816 } | |
817 | |
818 public Address getInterpreterFrameSenderSP() { | |
819 if (Assert.ASSERTS_ENABLED) { | |
820 Assert.that(isInterpretedFrame(), "interpreted frame expected"); | |
821 } | |
822 return getFP(); | |
823 } | |
824 | |
825 // FIXME: elided for now | |
826 //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { | |
827 // *interpreter_frame_esp_addr() = x - 1; | |
828 //} | |
829 | |
830 //-------------------------------------------------------------------------------- | |
831 // Monitors: | |
832 // | |
833 | |
834 private Address addressOfInterpreterFrameMonitors() { | |
835 return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0); | |
836 } | |
837 | |
838 // Monitors | |
839 public BasicObjectLock interpreterFrameMonitorBegin() { | |
840 int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG); | |
841 return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords)); | |
842 } | |
843 | |
844 public BasicObjectLock interpreterFrameMonitorEnd() { | |
845 return new BasicObjectLock(addressOfInterpreterFrameMonitors()); | |
846 } | |
847 | |
848 public int interpreterFrameMonitorSize() { | |
849 return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize()); | |
850 } | |
851 | |
852 // FIXME: elided for now | |
853 // // monitor elements | |
854 // | |
855 // // in keeping with Intel side: end is lower in memory than begin; | |
856 // // and beginning element is oldest element | |
857 // // Also begin is one past last monitor. | |
858 // | |
859 // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { | |
860 // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); | |
861 // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); | |
862 // } | |
863 // | |
864 // inline BasicObjectLock* frame::interpreter_frame_monitor_end() const { | |
865 // return interpreter_frame_monitors(); | |
866 // } | |
867 // | |
868 // | |
869 // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { | |
870 // interpreter_frame_set_monitors(value); | |
871 // } | |
872 // | |
873 // | |
874 // inline int frame::interpreter_frame_monitor_size() { | |
875 // return round_to(BasicObjectLock::size(), WordsPerLong); | |
876 // } | |
877 | |
878 public Address addressOfInterpreterFrameMethod() { | |
879 return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow()); | |
880 } | |
881 | |
882 public Address addressOfInterpreterFrameCPCache() { | |
883 return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow()); | |
884 } | |
885 | |
886 //-------------------------------------------------------------------------------- | |
887 // Entry frames: | |
888 // | |
889 | |
890 public JavaCallWrapper getEntryFrameCallWrapper() { | |
891 // Note: adjust this code if the link argument in StubGenerator::call_stub() changes! | |
892 SPARCArgument link = new SPARCArgument(0, false); | |
893 return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class, | |
894 getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow())); | |
895 } | |
896 | |
897 // | |
898 // | |
899 // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const { | |
900 // // note: adjust this code if the link argument in StubGenerator::call_stub() changes! | |
901 // const Argument link = Argument(0, false); | |
902 // return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()]; | |
903 // } | |
904 | |
905 //-------------------------------------------------------------------------------- | |
906 // Safepoints: | |
907 // | |
908 | |
909 protected Address addressOfSavedOopResult() { | |
910 return addressOfO0(); | |
911 } | |
912 | |
913 protected Address addressOfSavedReceiver() { | |
914 return addressOfO0(); | |
915 } | |
916 | |
917 | |
918 //-------------------------------------------------------------------------------- | |
919 // Internals only below this point | |
920 // | |
921 | |
922 private Address addressOfI7() { | |
923 return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow()); | |
924 } | |
925 | |
926 private Address addressOfO7() { | |
927 return afterSave().addressOfI7(); | |
928 } | |
929 | |
930 private Address addressOfI0() { | |
931 return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow()); | |
932 } | |
933 | |
934 private Address addressOfO0() { | |
935 return afterSave().addressOfI0(); | |
936 } | |
937 | |
938 private static boolean addressesEqual(Address a1, Address a2) { | |
939 if ((a1 == null) && (a2 == null)) { | |
940 return true; | |
941 } | |
942 | |
943 if ((a1 == null) || (a2 == null)) { | |
944 return false; | |
945 } | |
946 | |
947 return (a1.equals(a2)); | |
948 } | |
949 | |
950 | |
951 private Frame senderForEntryFrame(RegisterMap regMap) { | |
952 SPARCRegisterMap map = (SPARCRegisterMap) regMap; | |
953 | |
954 if (Assert.ASSERTS_ENABLED) { | |
955 Assert.that(map != null, "map must be set"); | |
956 } | |
957 // Java frame called from C; skip all C frames and return top C | |
958 // frame of that chunk as the sender | |
959 JavaCallWrapper jcw = getEntryFrameCallWrapper(); | |
960 if (Assert.ASSERTS_ENABLED) { | |
961 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); | |
962 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); | |
963 } | |
964 Address lastJavaSP = jcw.getLastJavaSP(); | |
965 Address lastJavaPC = jcw.getLastJavaPC(); | |
966 map.clear(); | |
967 | |
968 if (!VM.getVM().isCore()) { | |
969 map.makeIntegerRegsUnsaved(); | |
970 map.shiftWindow(lastJavaSP, null); | |
971 } | |
972 | |
973 if (Assert.ASSERTS_ENABLED) { | |
974 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); | |
975 } | |
976 | |
977 if (lastJavaPC != null) { | |
978 return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC); | |
979 } else { | |
980 Address youngerSP = getNextYoungerSP(lastJavaSP, getSP()); | |
981 return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false); | |
982 } | |
983 } | |
984 | |
985 private static Address getNextYoungerSP(Address oldSP, Address youngSP) { | |
986 Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null); | |
987 if (Assert.ASSERTS_ENABLED) { | |
988 Assert.that(sp != null, "missed the SP"); | |
989 } | |
990 return sp; | |
991 } | |
992 | |
993 private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) { | |
994 if (youngSP == null) { | |
995 // FIXME | |
996 throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)"); | |
997 } | |
998 | |
999 if (sp == null) { | |
1000 sp = youngSP; | |
1001 } | |
1002 | |
1003 Address previousSP = null; | |
1004 | |
1005 /** Minimum frame size is 16 */ | |
1006 int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize())); | |
1007 | |
1008 while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) { | |
1009 if (maxFrames-- <= 0) { | |
1010 // too many frames have gone by; invalid parameters given to this function | |
1011 break; | |
1012 } | |
1013 previousSP = sp; | |
1014 sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); | |
1015 } | |
1016 | |
1017 return (sp.equals(oldSP) ? previousSP : null); | |
1018 } | |
1019 | |
1020 private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) { | |
1021 long mask = VM.getVM().getAddressSize(); | |
1022 mask = 2 * mask - 1; | |
1023 return ((sp.andWithMask(mask) == null) && | |
1024 (sp.lessThanOrEqual(oldSP)) && | |
1025 (sp.greaterThanOrEqual(youngSP))); | |
1026 } | |
1027 | |
1028 // FIXME: this is a hopefully temporary hack (not sure what is going on) | |
1029 public long getUContextOffset() { | |
1030 // FIXME: there is something I clearly don't understand about the | |
1031 // way the signal handler frame is laid out, because I shouldn't need this extra offset | |
1032 int MAJOR_HACK_OFFSET = 8; | |
1033 // System.out.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP); | |
1034 return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET); | |
1035 } | |
1036 | |
1037 public long getMContextAreaOffsetInUContext() { | |
1038 // From dbx-related sources: | |
1039 // /* | |
1040 // * struct sigframe is declaredf in the kernel sources in | |
1041 // * .../uts/sun4c/os/machdep.c/sendsig() | |
1042 // * unfortunately we only get a pointer to the 'uc' passed | |
1043 // * to the sighandler so we need to do this stuff to get | |
1044 // * to 'rwin'. | |
1045 // * Have to do it like this to take account of alignment. | |
1046 // */ | |
1047 // static struct sigframe { | |
1048 // struct rwindow rwin; | |
1049 // ucontext_t uc; | |
1050 // } sf_help; | |
1051 | |
1052 // From /usr/include/sys/ucontext.h: | |
1053 // #if !defined(_XPG4_2) || defined(__EXTENSIONS__) | |
1054 // struct ucontext { | |
1055 // #else | |
1056 // struct __ucontext { | |
1057 // #endif | |
1058 // uint_t uc_flags; | |
1059 // ucontext_t *uc_link; | |
1060 // sigset_t uc_sigmask; | |
1061 // stack_t uc_stack; | |
1062 // mcontext_t uc_mcontext; | |
1063 // #ifdef __sparcv9 | |
1064 // long uc_filler[4]; | |
1065 // #else /* __sparcv9 */ | |
1066 // long uc_filler[23]; | |
1067 // #endif /* __sparcv9 */ | |
1068 // }; | |
1069 | |
1070 // This walks to the start of the gregs in the mcontext_t | |
1071 // (first entry in that data structure). Really should read | |
1072 // this from header file. | |
1073 | |
1074 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM | |
1075 // (When you have a hammer, everything looks like a nail) | |
1076 long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize()); // uc_flags | |
1077 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus | |
1078 // doubleword alignment for structs? | |
1079 offset += 16 + // uc_sigmask | |
1080 2 * VM.getVM().getAddressSize() + 4; // uc_stack | |
1081 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs? | |
1082 | |
1083 // System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset); | |
1084 | |
1085 return offset; | |
1086 } | |
1087 } |