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 }
|
|
425 // These are hacks to keep us out of trouble.
|
|
426 // The problem with these is that they mask other problems
|
|
427 if (getFP().lessThanOrEqual(getSP())) { // this attempts to deal with unsigned comparison above
|
|
428 return false;
|
|
429 }
|
|
430 if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { // stack frames shouldn't be large.
|
|
431 return false;
|
|
432 }
|
|
433 // FIXME: this is not atomic with respect to GC and is unsuitable
|
|
434 // for use in a non-debugging, or reflective, system. Need to
|
|
435 // figure out how to express this.
|
|
436 if (addressOfInterpreterFrameBCX().getAddressAt(0) == null) {
|
|
437 return false; // BCP not yet set up
|
|
438 }
|
|
439 return true;
|
|
440 }
|
|
441
|
|
442 //--------------------------------------------------------------------------------
|
|
443 // Accessors:
|
|
444 //
|
|
445
|
|
446 /** Accessors */
|
|
447
|
|
448 public long frameSize() {
|
|
449 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
|
|
450 }
|
|
451
|
|
452 public Address getLink() {
|
|
453 return unBiasSP(getFP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()));
|
|
454 }
|
|
455
|
|
456 // FIXME: not implementable yet
|
|
457 // public void setLink(Address addr) {
|
|
458 // if (Assert.ASSERTS_ENABLED) {
|
|
459 // Assert.that(getLink().equals(addr), "frame nesting is controlled by hardware");
|
|
460 // }
|
|
461 // }
|
|
462
|
|
463 public Frame sender(RegisterMap regMap, CodeBlob cb) {
|
|
464 SPARCRegisterMap map = (SPARCRegisterMap) regMap;
|
|
465
|
|
466 if (Assert.ASSERTS_ENABLED) {
|
|
467 Assert.that(map != null, "map must be set");
|
|
468 }
|
|
469
|
|
470 // Default is we don't have to follow them. The sender_for_xxx
|
|
471 // will update it accordingly
|
|
472 map.setIncludeArgumentOops(false);
|
|
473
|
|
474 if (cb == null && isEntryFrame()) {
|
|
475 return senderForEntryFrame(map);
|
|
476 }
|
|
477
|
|
478 Address youngerSP = getSP();
|
|
479 Address sp = getSenderSP();
|
|
480 boolean isInterpreted = false;
|
|
481
|
|
482 // FIXME: this is a hack to get stackwalking to work in the face
|
|
483 // of a signal like a SEGV. For debugging purposes it's important
|
|
484 // that (a) we are able to traverse the stack if we take a signal
|
|
485 // and (b) that we get the correct program counter in this
|
|
486 // situation. If we are not using alternate signal stacks then (a)
|
|
487 // seems to work all the time (on SPARC), but (b) is violated for
|
|
488 // the frame just below the signal handler.
|
|
489
|
|
490 // The mechanism for finding the ucontext is not robust. In
|
|
491 // addition, we may find that we need to be able to fetch more
|
|
492 // registers from the ucontext than just the program counter,
|
|
493 // since the register windows on the stack are "stale". This will
|
|
494 // require substantial restructuring of this frame code, so has
|
|
495 // been avoided for now.
|
|
496
|
|
497 // It is difficult to find a clean solution for mixing debugging
|
|
498 // situations with VM frame traversal. One could consider
|
|
499 // implementing generic frame traversal in the dbx style and only
|
|
500 // using the VM's stack walking mechanism on a per-frame basis,
|
|
501 // for example to traverse Java-level activations in a compiled
|
|
502 // frame. However, this will probably not interact well with the
|
|
503 // mechanism for finding oops on the stack.
|
|
504
|
|
505 if (VM.getVM().isDebugging()) {
|
|
506 // If we are a signal handler frame, use a trick: make the
|
|
507 // youngerSP of the caller frame point to the top of the
|
|
508 // ucontext's contained register set. This should allow fetching
|
|
509 // of the registers for the frame just below the signal handler
|
|
510 // frame in the usual fashion.
|
|
511 if (isSignalHandlerFrameDbg()) {
|
|
512
|
|
513 if (DEBUG) {
|
|
514 System.out.println("SPARCFrame.sender: found signal handler frame");
|
|
515 }
|
|
516
|
|
517 // Try to give a valid SP and PC for a "deficient frame" since
|
|
518 // we don't have a real register save area; making this class
|
|
519 // work by reading its information from a ucontext as well as
|
|
520 // a register save area is a major undertaking and has been
|
|
521 // deferred for now. It is very important that the PC is
|
|
522 // correct, which is why we don't just fall through to the
|
|
523 // other code (which would read the PC from the stale register
|
|
524 // window and thereby fail to get the actual location of the
|
|
525 // fault).
|
|
526
|
|
527 long offset = getMContextAreaOffsetInUContext();
|
|
528 Address fp = sp;
|
|
529 // System.out.println(" FP: " + fp);
|
|
530 fp = fp.addOffsetTo(getUContextOffset() + getMContextAreaOffsetInUContext());
|
|
531 // System.out.println(" start of mcontext: " + fp);
|
|
532 // FIXME: put these elsewhere. These are the register numbers
|
|
533 // in /usr/include/sys/regset.h. They might belong in
|
|
534 // SPARCReigsters.java, but we currently don't have that list
|
|
535 // of numbers in the SA code (because all of the registers are
|
|
536 // listed as instances of SPARCRegister) and it appears that
|
|
537 // our numbering of the registers and this one don't match up.
|
|
538 int PC_OFFSET_IN_GREGSET = 1;
|
|
539 int SP_OFFSET_IN_GREGSET = 17;
|
|
540 raw_sp = fp.getAddressAt(VM.getVM().getAddressSize() * SP_OFFSET_IN_GREGSET);
|
|
541 Address pc = fp.getAddressAt(VM.getVM().getAddressSize() * PC_OFFSET_IN_GREGSET);
|
|
542 // System.out.println(" next frame's SP: " + sp + " PC: " + pc);
|
|
543 return new SPARCFrame(raw_sp, pc);
|
|
544 }
|
|
545 }
|
|
546
|
|
547 if (!VM.getVM().isCore()) {
|
|
548 // Note: The version of this operation on any platform with callee-save
|
|
549 // registers must update the register map (if not null).
|
|
550 // In order to do this correctly, the various subtypes of
|
|
551 // of frame (interpreted, compiled, glue, native),
|
|
552 // must be distinguished. There is no need on SPARC for
|
|
553 // such distinctions, because all callee-save registers are
|
|
554 // preserved for all frames via SPARC-specific mechanisms.
|
|
555 //
|
|
556 // *** HOWEVER, *** if and when we make any floating-point
|
|
557 // registers callee-saved, then we will have to copy over
|
|
558 // the RegisterMap update logic from the Intel code.
|
|
559
|
|
560
|
|
561 // The constructor of the sender must know whether this frame is interpreted so it can set the
|
|
562 // sender's _interpreter_sp_adjustment field.
|
|
563 if (VM.getVM().getInterpreter().contains(pc)) {
|
|
564 isInterpreted = true;
|
|
565 if (VM.getVM().isClientCompiler()) {
|
|
566 map.makeIntegerRegsUnsaved();
|
|
567 map.shiftWindow(sp, youngerSP);
|
|
568 }
|
|
569 } else {
|
|
570 // Find a CodeBlob containing this frame's pc or elide the lookup and use the
|
|
571 // supplied blob which is already known to be associated with this frame.
|
|
572 cb = VM.getVM().getCodeCache().findBlob(pc);
|
|
573 if (cb != null) {
|
|
574
|
|
575 if (cb.callerMustGCArguments(map.getThread())) {
|
|
576 map.setIncludeArgumentOops(true);
|
|
577 }
|
|
578
|
|
579 // Update the location of all implicitly saved registers
|
|
580 // as the address of these registers in the register save
|
|
581 // area (for %o registers we use the address of the %i
|
|
582 // register in the next younger frame)
|
|
583 map.shiftWindow(sp, youngerSP);
|
|
584 if (map.getUpdateMap()) {
|
|
585 if (cb.getOopMaps() != null) {
|
|
586 OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
|
|
587 }
|
|
588 }
|
|
589 }
|
|
590 }
|
|
591 } // #ifndef CORE
|
|
592
|
|
593 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted);
|
|
594 }
|
|
595
|
|
596 protected boolean hasSenderPD() {
|
|
597 try {
|
|
598 // FIXME: should not happen!!!
|
|
599 if (getSP() == null) {
|
|
600 return false;
|
|
601 }
|
|
602 if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) {
|
|
603 return false;
|
|
604 }
|
|
605 return true;
|
|
606 } catch (RuntimeException e) {
|
|
607 if (DEBUG) {
|
|
608 System.out.println("Bad frame " + this);
|
|
609 }
|
|
610 throw e;
|
|
611 }
|
|
612 }
|
|
613
|
|
614 //--------------------------------------------------------------------------------
|
|
615 // Return address:
|
|
616 //
|
|
617
|
|
618 public Address getSenderPC() {
|
|
619 return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET);
|
|
620 }
|
|
621
|
|
622 // FIXME: currently unimplementable
|
|
623 // inline void frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; }
|
|
624
|
|
625 public Address getUnextendedSP() {
|
|
626 return getSP().addOffsetTo(interpreterSPAdjustmentOffset);
|
|
627 }
|
|
628
|
|
629 public Address getSenderSP() {
|
|
630 return getFP();
|
|
631 }
|
|
632
|
|
633 /** Given the next-younger sp for a given frame's sp, compute the
|
|
634 frame. We need the next-younger sp, because its register save
|
|
635 area holds the flushed copy of its I7, which is the PC of the
|
|
636 frame we are interested in. */
|
|
637 public SPARCFrame afterSave() {
|
|
638 return new SPARCFrame(biasSP(getYoungerSP()), null);
|
|
639 }
|
|
640
|
|
641 /** Accessors for the instance variables */
|
|
642 public Address getFP() {
|
|
643 Address sp = getSP();
|
|
644 if (sp == null) {
|
|
645 System.out.println("SPARCFrame.getFP(): sp == null");
|
|
646 }
|
|
647 Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow());
|
|
648 try {
|
|
649 Address fp = unBiasSP(fpAddr.getAddressAt(0));
|
|
650 if (fp == null) {
|
|
651 System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")");
|
|
652 }
|
|
653 return fp;
|
|
654 } catch (RuntimeException e) {
|
|
655 System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")");
|
|
656 return null;
|
|
657 }
|
|
658 }
|
|
659
|
|
660 private Address addressOfFPSlot(int index) {
|
|
661 return getFP().addOffsetTo(index * VM.getVM().getAddressSize());
|
|
662 }
|
|
663
|
|
664 // FIXME: temporarily elided
|
|
665 // // All frames
|
|
666 //
|
|
667 // intptr_t* fp_addr_at(int index) const { return &fp()[index]; }
|
|
668 // intptr_t* sp_addr_at(int index) const { return &sp()[index]; }
|
|
669 // intptr_t fp_at( int index) const { return *fp_addr_at(index); }
|
|
670 // intptr_t sp_at( int index) const { return *sp_addr_at(index); }
|
|
671 //
|
|
672 // private:
|
|
673 // inline address* I7_addr() const;
|
|
674 // inline address* O7_addr() const;
|
|
675 //
|
|
676 // inline address* I0_addr() const;
|
|
677 // inline address* O0_addr() const;
|
|
678 //
|
|
679 // public:
|
|
680 // // access to SPARC arguments and argument registers
|
|
681 //
|
|
682 // intptr_t* register_addr(Register reg) const {
|
|
683 // return sp_addr_at(reg.sp_offset_in_saved_window());
|
|
684 // }
|
|
685 // intptr_t* memory_param_addr(int param_ix, bool is_in) const {
|
|
686 // int offset = callee_register_argument_save_area_sp_offset + param_ix;
|
|
687 // if (is_in)
|
|
688 // return fp_addr_at(offset);
|
|
689 // else
|
|
690 // return sp_addr_at(offset);
|
|
691 // }
|
|
692 // intptr_t* param_addr(int param_ix, bool is_in) const {
|
|
693 // if (param_ix >= callee_register_argument_save_area_words)
|
|
694 // return memory_param_addr(param_ix, is_in);
|
|
695 // else if (is_in)
|
|
696 // return register_addr(Argument(param_ix, true).as_register());
|
|
697 // else {
|
|
698 // // the registers are stored in the next younger frame
|
|
699 // // %%% is this really necessary?
|
|
700 // frame next_younger = after_save();
|
|
701 // return next_younger.register_addr(Argument(param_ix, true).as_register());
|
|
702 // }
|
|
703 // }
|
|
704
|
|
705 //--------------------------------------------------------------------------------
|
|
706 // Interpreter frames:
|
|
707 //
|
|
708
|
|
709 /** 2 words, also used to save float regs across calls to C */
|
|
710 public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2;
|
|
711 public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4;
|
|
712 /** For native calls only */
|
|
713 public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5;
|
|
714 /** For native calls only */
|
|
715 public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6;
|
|
716 /** Should be same as above, and should be zero mod 8 */
|
|
717 public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6;
|
|
718 public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET;
|
|
719
|
|
720 /** Interpreter frame set-up needs to save 2 extra words in outgoing
|
|
721 param area for class and jnienv arguments for native stubs (see
|
|
722 nativeStubGen_sparc.cpp) */
|
|
723 public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2;
|
|
724
|
|
725 // FIXME: elided for now
|
|
726 //
|
|
727 // // the compiler frame has many of the same fields as the interpreter frame
|
|
728 // // %%%%% factor out declarations of the shared fields
|
|
729 // enum compiler_frame_fixed_locals {
|
|
730 // compiler_frame_d_scratch_fp_offset = -2,
|
|
731 // compiler_frame_vm_locals_fp_offset = -2, // should be same as above
|
|
732 //
|
|
733 // compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset
|
|
734 // };
|
|
735 //
|
|
736 // private:
|
|
737 //
|
|
738 // // where LcpoolCache is saved:
|
|
739 // constantPoolCacheOop* interpreter_frame_cpoolcache_addr() const {
|
|
740 // return (constantPoolCacheOop*)sp_addr_at( LcpoolCache.sp_offset_in_saved_window());
|
|
741 // }
|
|
742 //
|
|
743 // // where Lmonitors is saved:
|
|
744 // BasicObjectLock** interpreter_frame_monitors_addr() const {
|
|
745 // return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window());
|
|
746 // }
|
|
747 // intptr_t** interpreter_frame_esp_addr() const {
|
|
748 // return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window());
|
|
749 // }
|
|
750 //
|
|
751 // inline void interpreter_frame_set_tos_address(intptr_t* x);
|
|
752 //
|
|
753 // // next two fns read and write Lmonitors value,
|
|
754 // private:
|
|
755 // BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); }
|
|
756 // void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; }
|
|
757 //
|
|
758 //#ifndef CORE
|
|
759 //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const {
|
|
760 // COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset); )
|
|
761 // COMPILER2_ONLY(return oopmapreg_to_location(reg, ®_map); )
|
|
762 //}
|
|
763 //#endif
|
|
764
|
|
765 // FIXME: NOT FINISHED
|
|
766 public Address addressOfInterpreterFrameLocals() {
|
|
767 return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow());
|
|
768 }
|
|
769
|
|
770 // FIXME: this is not atomic with respect to GC and is unsuitable
|
|
771 // for use in a non-debugging, or reflective, system.
|
|
772 private Address addressOfInterpreterFrameBCX() {
|
|
773 // %%%%% reinterpreting Lbcp as a bcx
|
|
774 return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow());
|
|
775 }
|
|
776
|
|
777 public int getInterpreterFrameBCI() {
|
|
778 // FIXME: this is not atomic with respect to GC and is unsuitable
|
|
779 // for use in a non-debugging, or reflective, system. Need to
|
|
780 // figure out how to express this.
|
|
781 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
|
|
782 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0);
|
|
783 Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle);
|
|
784 return bcpToBci(bcp, method);
|
|
785 }
|
|
786
|
|
787 public Address addressOfInterpreterFrameExpressionStack() {
|
|
788 return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize());
|
|
789 }
|
|
790
|
|
791 public int getInterpreterFrameExpressionStackDirection() {
|
|
792 return -1;
|
|
793 }
|
|
794
|
|
795 /** Top of expression stack */
|
|
796 public Address addressOfInterpreterFrameTOS() {
|
|
797 return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize());
|
|
798 }
|
|
799
|
|
800 /** Expression stack from top down */
|
|
801 public Address addressOfInterpreterFrameTOSAt(int slot) {
|
|
802 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
|
|
803 }
|
|
804
|
|
805 public Address getInterpreterFrameSenderSP() {
|
|
806 if (Assert.ASSERTS_ENABLED) {
|
|
807 Assert.that(isInterpretedFrame(), "interpreted frame expected");
|
|
808 }
|
|
809 return getFP();
|
|
810 }
|
|
811
|
|
812 // FIXME: elided for now
|
|
813 //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) {
|
|
814 // *interpreter_frame_esp_addr() = x - 1;
|
|
815 //}
|
|
816
|
|
817 //--------------------------------------------------------------------------------
|
|
818 // Monitors:
|
|
819 //
|
|
820
|
|
821 private Address addressOfInterpreterFrameMonitors() {
|
|
822 return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0);
|
|
823 }
|
|
824
|
|
825 // Monitors
|
|
826 public BasicObjectLock interpreterFrameMonitorBegin() {
|
|
827 int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG);
|
|
828 return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords));
|
|
829 }
|
|
830
|
|
831 public BasicObjectLock interpreterFrameMonitorEnd() {
|
|
832 return new BasicObjectLock(addressOfInterpreterFrameMonitors());
|
|
833 }
|
|
834
|
|
835 public int interpreterFrameMonitorSize() {
|
|
836 return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize());
|
|
837 }
|
|
838
|
|
839 // FIXME: elided for now
|
|
840 // // monitor elements
|
|
841 //
|
|
842 // // in keeping with Intel side: end is lower in memory than begin;
|
|
843 // // and beginning element is oldest element
|
|
844 // // Also begin is one past last monitor.
|
|
845 //
|
|
846 // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
|
|
847 // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong);
|
|
848 // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words);
|
|
849 // }
|
|
850 //
|
|
851 // inline BasicObjectLock* frame::interpreter_frame_monitor_end() const {
|
|
852 // return interpreter_frame_monitors();
|
|
853 // }
|
|
854 //
|
|
855 //
|
|
856 // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
|
|
857 // interpreter_frame_set_monitors(value);
|
|
858 // }
|
|
859 //
|
|
860 //
|
|
861 // inline int frame::interpreter_frame_monitor_size() {
|
|
862 // return round_to(BasicObjectLock::size(), WordsPerLong);
|
|
863 // }
|
|
864
|
|
865 public Address addressOfInterpreterFrameMethod() {
|
|
866 return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow());
|
|
867 }
|
|
868
|
|
869 public Address addressOfInterpreterFrameCPCache() {
|
|
870 return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow());
|
|
871 }
|
|
872
|
|
873 //--------------------------------------------------------------------------------
|
|
874 // Entry frames:
|
|
875 //
|
|
876
|
|
877 public JavaCallWrapper getEntryFrameCallWrapper() {
|
|
878 // Note: adjust this code if the link argument in StubGenerator::call_stub() changes!
|
|
879 SPARCArgument link = new SPARCArgument(0, false);
|
|
880 return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class,
|
|
881 getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow()));
|
|
882 }
|
|
883
|
|
884 //
|
|
885 //
|
|
886 // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const {
|
|
887 // // note: adjust this code if the link argument in StubGenerator::call_stub() changes!
|
|
888 // const Argument link = Argument(0, false);
|
|
889 // return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()];
|
|
890 // }
|
|
891
|
|
892 //--------------------------------------------------------------------------------
|
|
893 // Safepoints:
|
|
894 //
|
|
895
|
|
896 protected Address addressOfSavedOopResult() {
|
|
897 return addressOfO0();
|
|
898 }
|
|
899
|
|
900 protected Address addressOfSavedReceiver() {
|
|
901 return addressOfO0();
|
|
902 }
|
|
903
|
|
904
|
|
905 //--------------------------------------------------------------------------------
|
|
906 // Internals only below this point
|
|
907 //
|
|
908
|
|
909 private Address addressOfI7() {
|
|
910 return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow());
|
|
911 }
|
|
912
|
|
913 private Address addressOfO7() {
|
|
914 return afterSave().addressOfI7();
|
|
915 }
|
|
916
|
|
917 private Address addressOfI0() {
|
|
918 return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow());
|
|
919 }
|
|
920
|
|
921 private Address addressOfO0() {
|
|
922 return afterSave().addressOfI0();
|
|
923 }
|
|
924
|
|
925 private static boolean addressesEqual(Address a1, Address a2) {
|
|
926 if ((a1 == null) && (a2 == null)) {
|
|
927 return true;
|
|
928 }
|
|
929
|
|
930 if ((a1 == null) || (a2 == null)) {
|
|
931 return false;
|
|
932 }
|
|
933
|
|
934 return (a1.equals(a2));
|
|
935 }
|
|
936
|
|
937
|
|
938 private Frame senderForEntryFrame(RegisterMap regMap) {
|
|
939 SPARCRegisterMap map = (SPARCRegisterMap) regMap;
|
|
940
|
|
941 if (Assert.ASSERTS_ENABLED) {
|
|
942 Assert.that(map != null, "map must be set");
|
|
943 }
|
|
944 // Java frame called from C; skip all C frames and return top C
|
|
945 // frame of that chunk as the sender
|
|
946 JavaCallWrapper jcw = getEntryFrameCallWrapper();
|
|
947 if (Assert.ASSERTS_ENABLED) {
|
|
948 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
|
|
949 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
|
|
950 }
|
|
951 Address lastJavaSP = jcw.getLastJavaSP();
|
|
952 Address lastJavaPC = jcw.getLastJavaPC();
|
|
953 map.clear();
|
|
954
|
|
955 if (!VM.getVM().isCore()) {
|
|
956 map.makeIntegerRegsUnsaved();
|
|
957 map.shiftWindow(lastJavaSP, null);
|
|
958 }
|
|
959
|
|
960 if (Assert.ASSERTS_ENABLED) {
|
|
961 Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
|
962 }
|
|
963
|
|
964 if (lastJavaPC != null) {
|
|
965 return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC);
|
|
966 } else {
|
|
967 Address youngerSP = getNextYoungerSP(lastJavaSP, getSP());
|
|
968 return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false);
|
|
969 }
|
|
970 }
|
|
971
|
|
972 private static Address getNextYoungerSP(Address oldSP, Address youngSP) {
|
|
973 Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null);
|
|
974 if (Assert.ASSERTS_ENABLED) {
|
|
975 Assert.that(sp != null, "missed the SP");
|
|
976 }
|
|
977 return sp;
|
|
978 }
|
|
979
|
|
980 private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) {
|
|
981 if (youngSP == null) {
|
|
982 // FIXME
|
|
983 throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)");
|
|
984 }
|
|
985
|
|
986 if (sp == null) {
|
|
987 sp = youngSP;
|
|
988 }
|
|
989
|
|
990 Address previousSP = null;
|
|
991
|
|
992 /** Minimum frame size is 16 */
|
|
993 int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize()));
|
|
994
|
|
995 while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) {
|
|
996 if (maxFrames-- <= 0) {
|
|
997 // too many frames have gone by; invalid parameters given to this function
|
|
998 break;
|
|
999 }
|
|
1000 previousSP = sp;
|
|
1001 sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()));
|
|
1002 }
|
|
1003
|
|
1004 return (sp.equals(oldSP) ? previousSP : null);
|
|
1005 }
|
|
1006
|
|
1007 private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) {
|
|
1008 long mask = VM.getVM().getAddressSize();
|
|
1009 mask = 2 * mask - 1;
|
|
1010 return ((sp.andWithMask(mask) == null) &&
|
|
1011 (sp.lessThanOrEqual(oldSP)) &&
|
|
1012 (sp.greaterThanOrEqual(youngSP)));
|
|
1013 }
|
|
1014
|
|
1015 // FIXME: this is a hopefully temporary hack (not sure what is going on)
|
|
1016 public long getUContextOffset() {
|
|
1017 // FIXME: there is something I clearly don't understand about the
|
|
1018 // way the signal handler frame is laid out, because I shouldn't need this extra offset
|
|
1019 int MAJOR_HACK_OFFSET = 8;
|
|
1020 // System.out.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP);
|
|
1021 return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET);
|
|
1022 }
|
|
1023
|
|
1024 public long getMContextAreaOffsetInUContext() {
|
|
1025 // From dbx-related sources:
|
|
1026 // /*
|
|
1027 // * struct sigframe is declaredf in the kernel sources in
|
|
1028 // * .../uts/sun4c/os/machdep.c/sendsig()
|
|
1029 // * unfortunately we only get a pointer to the 'uc' passed
|
|
1030 // * to the sighandler so we need to do this stuff to get
|
|
1031 // * to 'rwin'.
|
|
1032 // * Have to do it like this to take account of alignment.
|
|
1033 // */
|
|
1034 // static struct sigframe {
|
|
1035 // struct rwindow rwin;
|
|
1036 // ucontext_t uc;
|
|
1037 // } sf_help;
|
|
1038
|
|
1039 // From /usr/include/sys/ucontext.h:
|
|
1040 // #if !defined(_XPG4_2) || defined(__EXTENSIONS__)
|
|
1041 // struct ucontext {
|
|
1042 // #else
|
|
1043 // struct __ucontext {
|
|
1044 // #endif
|
|
1045 // uint_t uc_flags;
|
|
1046 // ucontext_t *uc_link;
|
|
1047 // sigset_t uc_sigmask;
|
|
1048 // stack_t uc_stack;
|
|
1049 // mcontext_t uc_mcontext;
|
|
1050 // #ifdef __sparcv9
|
|
1051 // long uc_filler[4];
|
|
1052 // #else /* __sparcv9 */
|
|
1053 // long uc_filler[23];
|
|
1054 // #endif /* __sparcv9 */
|
|
1055 // };
|
|
1056
|
|
1057 // This walks to the start of the gregs in the mcontext_t
|
|
1058 // (first entry in that data structure). Really should read
|
|
1059 // this from header file.
|
|
1060
|
|
1061 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM
|
|
1062 // (When you have a hammer, everything looks like a nail)
|
|
1063 long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize()); // uc_flags
|
|
1064 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus
|
|
1065 // doubleword alignment for structs?
|
|
1066 offset += 16 + // uc_sigmask
|
|
1067 2 * VM.getVM().getAddressSize() + 4; // uc_stack
|
|
1068 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs?
|
|
1069
|
|
1070 // System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset);
|
|
1071
|
|
1072 return offset;
|
|
1073 }
|
|
1074 }
|