Line data Source code
1 : /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 : Copyright (C) 2009 Theobroma Systems Ltd.
6 :
7 : This file is part of CACAO.
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License as
11 : published by the Free Software Foundation; either version 2, or (at
12 : your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 : 02110-1301, USA.
23 :
24 : */
25 :
26 :
27 : #include "config.h"
28 :
29 : #include <cassert>
30 : #include <cstdlib>
31 : #include <cstring>
32 : #include <stdint.h>
33 :
34 : #include "vm/types.hpp"
35 :
36 : #include "arch.hpp"
37 : #include "md.hpp"
38 :
39 : #include "mm/gc.hpp"
40 :
41 : #include "vm/jit/stacktrace.hpp"
42 :
43 : #include "native/llni.hpp"
44 :
45 : #include "threads/thread.hpp"
46 :
47 : #include "toolbox/logging.hpp"
48 :
49 : #include "vm/array.hpp"
50 : #include "vm/jit/builtin.hpp"
51 : #include "vm/class.hpp"
52 : #include "vm/cycles-stats.hpp"
53 : #include "vm/exceptions.hpp"
54 : #include "vm/globals.hpp"
55 : #include "vm/javaobjects.hpp"
56 : #include "vm/loader.hpp"
57 : #include "vm/method.hpp"
58 : #include "vm/options.hpp"
59 : #include "vm/string.hpp"
60 : #include "vm/vm.hpp"
61 :
62 : #include "vm/jit/codegen-common.hpp"
63 : #include "vm/jit/linenumbertable.hpp"
64 : #include "vm/jit/methodheader.hpp"
65 : #include "vm/jit/methodtree.hpp"
66 :
67 : /* global variables ***********************************************************/
68 :
69 : CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
70 : CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
71 : CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
72 : CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
73 : CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
74 : CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
75 :
76 :
77 : /* stacktrace_stackframeinfo_add ***********************************************
78 :
79 : Fills a stackframe info structure with the given or calculated
80 : values and adds it to the chain.
81 :
82 : *******************************************************************************/
83 :
84 3355662 : void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
85 : {
86 : stackframeinfo_t *currentsfi;
87 : codeinfo *code;
88 : #if defined(ENABLE_JIT)
89 : s4 framesize;
90 : #endif
91 :
92 : /* Get current stackframe info. */
93 :
94 3355662 : currentsfi = threads_get_current_stackframeinfo();
95 :
96 : /* sometimes we don't have pv handy (e.g. in asmpart.S:
97 : L_asm_call_jit_compiler_exception or in the interpreter). */
98 :
99 3355641 : if (pv == NULL) {
100 : #if defined(ENABLE_INTRP)
101 : if (opt_intrp)
102 : pv = methodtree_find(ra);
103 : else
104 : #endif
105 : {
106 : #if defined(ENABLE_JIT)
107 : # if defined(__SPARC_64__)
108 : pv = md_get_pv_from_stackframe(sp);
109 : # else
110 197569 : pv = md_codegen_get_pv_from_pc(ra);
111 : # endif
112 : #endif
113 : }
114 : }
115 :
116 : /* Get codeinfo pointer for the parent Java method. */
117 :
118 3355641 : code = code_get_codeinfo_for_pv(pv);
119 :
120 : /* XXX */
121 : /* assert(m != NULL); */
122 :
123 : #if defined(ENABLE_JIT)
124 : # if defined(ENABLE_INTRP)
125 : /* When using the interpreter, we pass RA to the function. */
126 :
127 : if (!opt_intrp) {
128 : # endif
129 : # if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
130 : /* On i386 and x86_64 we always have to get the return address
131 : from the stack. */
132 : /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
133 : the RA from stack. */
134 :
135 3355701 : framesize = md_stacktrace_get_framesize(code);
136 :
137 3355601 : ra = md_stacktrace_get_returnaddress(sp, framesize);
138 : # else
139 : /* If the method is a non-leaf function, we need to get the
140 : return address from the stack. For leaf functions the
141 : return address is set correctly. This makes the assembler
142 : and the signal handler code simpler. The code is NULL is
143 : the asm_vm_call_method special case. */
144 :
145 : if ((code == NULL) || !code_is_leafmethod(code)) {
146 : framesize = md_stacktrace_get_framesize(code);
147 :
148 : ra = md_stacktrace_get_returnaddress(sp, framesize);
149 : }
150 : # endif
151 : # if defined(ENABLE_INTRP)
152 : }
153 : # endif
154 : #endif
155 :
156 : /* Calculate XPC when not given. The XPC is then the return
157 : address of the current method minus 1 because the RA points to
158 : the instruction after the call instruction. This is required
159 : e.g. for method stubs. */
160 :
161 3355638 : if (xpc == NULL) {
162 3116671 : xpc = (void *) (((intptr_t) ra) - 1);
163 : }
164 :
165 : /* Fill new stackframeinfo structure. */
166 :
167 3355638 : sfi->prev = currentsfi;
168 3355638 : sfi->code = code;
169 3355638 : sfi->pv = pv;
170 3355638 : sfi->sp = sp;
171 3355638 : sfi->ra = ra;
172 3355638 : sfi->xpc = xpc;
173 :
174 : #if !defined(NDEBUG)
175 3355638 : if (opt_DebugStackFrameInfo) {
176 0 : log_start();
177 : log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
178 0 : sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
179 0 : method_print(sfi->code->m);
180 0 : log_print("]");
181 0 : log_finish();
182 : }
183 : #endif
184 :
185 : /* Store new stackframeinfo pointer. */
186 :
187 3355638 : threads_set_current_stackframeinfo(sfi);
188 :
189 : /* set the native world flag for the current thread */
190 : /* ATTENTION: This flag tells the GC how to treat this thread in case of
191 : a collection. Set this flag _after_ a valid stackframe info was set. */
192 :
193 : THREAD_NATIVEWORLD_ENTER;
194 3355803 : }
195 :
196 :
197 : /* stacktrace_stackframeinfo_remove ********************************************
198 :
199 : Remove the given stackframeinfo from the chain in the current
200 : thread.
201 :
202 : *******************************************************************************/
203 :
204 3355232 : void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
205 : {
206 : /* Clear the native world flag for the current thread. */
207 : /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
208 :
209 : THREAD_NATIVEWORLD_EXIT;
210 :
211 : #if !defined(NDEBUG)
212 3355232 : if (opt_DebugStackFrameInfo) {
213 0 : log_start();
214 : log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
215 0 : sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
216 0 : method_print(sfi->code->m);
217 0 : log_print("]");
218 0 : log_finish();
219 : }
220 : #endif
221 :
222 : /* Set previous stackframe info. */
223 :
224 3355232 : threads_set_current_stackframeinfo(sfi->prev);
225 3355284 : }
226 :
227 :
228 : /* stacktrace_stackframeinfo_fill **********************************************
229 :
230 : Fill the temporary stackframeinfo structure with the values given
231 : in sfi.
232 :
233 : IN:
234 : tmpsfi ... temporary stackframeinfo
235 : sfi ...... stackframeinfo to be used in the next iteration
236 :
237 : *******************************************************************************/
238 :
239 127459 : static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
240 : {
241 : /* Sanity checks. */
242 :
243 127459 : assert(tmpsfi != NULL);
244 127459 : assert(sfi != NULL);
245 :
246 : /* Fill the temporary stackframeinfo. */
247 :
248 127459 : tmpsfi->code = sfi->code;
249 127459 : tmpsfi->pv = sfi->pv;
250 127459 : tmpsfi->sp = sfi->sp;
251 127459 : tmpsfi->ra = sfi->ra;
252 127459 : tmpsfi->xpc = sfi->xpc;
253 :
254 : /* Set the previous stackframe info of the temporary one to the
255 : next in the chain. */
256 :
257 127459 : tmpsfi->prev = sfi->prev;
258 :
259 : #if !defined(NDEBUG)
260 127459 : if (opt_DebugStackTrace)
261 0 : log_println("[stacktrace fill]");
262 : #endif
263 127459 : }
264 :
265 :
266 : /* stacktrace_stackframeinfo_next **********************************************
267 :
268 : Walk the stack (or the stackframeinfo-chain) to the next method and
269 : return the new stackframe values in the temporary stackframeinfo
270 : passed.
271 :
272 : ATTENTION: This function does NOT skip builtin methods!
273 :
274 : IN:
275 : tmpsfi ... temporary stackframeinfo of current method
276 :
277 : *******************************************************************************/
278 :
279 1925446 : static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
280 : {
281 : codeinfo *code;
282 : void *pv;
283 : void *sp;
284 : void *ra;
285 : //void *xpc;
286 : uint32_t framesize;
287 : stackframeinfo_t *prevsfi;
288 :
289 : /* Sanity check. */
290 :
291 1925446 : assert(tmpsfi != NULL);
292 :
293 : /* Get values from the stackframeinfo. */
294 :
295 1925446 : code = tmpsfi->code;
296 1925446 : pv = tmpsfi->pv;
297 1925446 : sp = tmpsfi->sp;
298 1925446 : ra = tmpsfi->ra;
299 : //xpc = tmpsfi->xpc;
300 :
301 : /* Get the current stack frame size. */
302 :
303 1925446 : framesize = md_stacktrace_get_framesize(code);
304 :
305 : /* Get the RA of the current stack frame (RA to the parent Java
306 : method) if the current method is a non-leaf method. Otherwise
307 : the value in the stackframeinfo is correct (from the signal
308 : handler). */
309 :
310 : #if defined(ENABLE_JIT)
311 : # if defined(ENABLE_INTRP)
312 : if (opt_intrp)
313 : ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
314 : else
315 : # endif
316 : {
317 1925446 : if (!code_is_leafmethod(code))
318 1925436 : ra = md_stacktrace_get_returnaddress(sp, framesize);
319 : }
320 : #else
321 : ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
322 : #endif
323 :
324 : /* Get the PV for the parent Java method. */
325 :
326 : #if defined(ENABLE_INTRP)
327 : if (opt_intrp)
328 : pv = methodtree_find(ra);
329 : else
330 : #endif
331 : {
332 : #if defined(ENABLE_JIT)
333 : # if defined(__SPARC_64__)
334 : sp = md_get_framepointer(sp);
335 : pv = md_get_pv_from_stackframe(sp);
336 : # else
337 1925446 : pv = md_codegen_get_pv_from_pc(ra);
338 : # endif
339 : #endif
340 : }
341 :
342 : /* Get the codeinfo pointer for the parent Java method. */
343 :
344 1925446 : code = code_get_codeinfo_for_pv(pv);
345 :
346 : /* Calculate the SP for the parent Java method. */
347 :
348 : #if defined(ENABLE_INTRP)
349 : if (opt_intrp)
350 : sp = *(u1 **) (sp - framesize);
351 : else
352 : #endif
353 : {
354 : #if STACKFRAME_RA_BETWEEN_FRAMES
355 1925446 : sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
356 : #elif defined(__SPARC_64__)
357 : /* already has the new sp */
358 : #else
359 : sp = (void *) (((intptr_t) sp) + framesize);
360 : #endif
361 : }
362 :
363 : /* If the new codeinfo pointer is NULL we reached a
364 : asm_vm_call_method function. In this case we get the next
365 : values from the previous stackframeinfo in the chain.
366 : Otherwise the new values have been calculated before. */
367 :
368 1925446 : if (code == NULL) {
369 125940 : prevsfi = tmpsfi->prev;
370 :
371 : /* If the previous stackframeinfo in the chain is NULL we
372 : reached the top of the stacktrace. We set code and prev to
373 : NULL to mark the end, which is checked in
374 : stacktrace_stackframeinfo_end_check. */
375 :
376 125940 : if (prevsfi == NULL) {
377 42110 : tmpsfi->code = NULL;
378 42110 : tmpsfi->prev = NULL;
379 42110 : return;
380 : }
381 :
382 : /* Fill the temporary stackframeinfo with the new values. */
383 :
384 83830 : stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
385 : }
386 : else {
387 : /* Store the new values in the stackframeinfo. NOTE: We
388 : subtract 1 from the RA to get the XPC, because the RA
389 : points to the instruction after the call instruction. */
390 :
391 1799506 : tmpsfi->code = code;
392 1799506 : tmpsfi->pv = pv;
393 1799506 : tmpsfi->sp = sp;
394 1799506 : tmpsfi->ra = ra;
395 1799506 : tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
396 : }
397 :
398 : #if !defined(NDEBUG)
399 : /* Print current method information. */
400 :
401 1883336 : if (opt_DebugStackTrace) {
402 0 : log_start();
403 : log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
404 : tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
405 0 : tmpsfi->xpc);
406 0 : method_print(tmpsfi->code->m);
407 0 : log_print("]");
408 0 : log_finish();
409 : }
410 : #endif
411 : }
412 :
413 :
414 : /* stacktrace_stackframeinfo_end_check *****************************************
415 :
416 : Check if we reached the end of the stacktrace.
417 :
418 : IN:
419 : tmpsfi ... temporary stackframeinfo of current method
420 :
421 : RETURN:
422 : true .... the end is reached
423 : false ... the end is not reached
424 :
425 : *******************************************************************************/
426 :
427 1969072 : static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
428 : {
429 : /* Sanity check. */
430 :
431 1969072 : assert(tmpsfi != NULL);
432 :
433 1969072 : if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
434 : #if !defined(NDEBUG)
435 42110 : if (opt_DebugStackTrace)
436 0 : log_println("[stacktrace stop]");
437 : #endif
438 :
439 42110 : return true;
440 : }
441 :
442 1926962 : return false;
443 : }
444 :
445 :
446 : /* stacktrace_depth ************************************************************
447 :
448 : Calculates and returns the depth of the current stacktrace.
449 :
450 : IN:
451 : sfi ... stackframeinfo where to start the stacktrace
452 :
453 : RETURN:
454 : depth of the stacktrace
455 :
456 : *******************************************************************************/
457 :
458 21055 : static int stacktrace_depth(stackframeinfo_t *sfi)
459 : {
460 : stackframeinfo_t tmpsfi;
461 : int depth;
462 : methodinfo *m;
463 :
464 : #if !defined(NDEBUG)
465 21055 : if (opt_DebugStackTrace)
466 0 : log_println("[stacktrace_depth]");
467 : #endif
468 :
469 : /* XXX This is not correct, but a workaround for threads-dump for
470 : now. */
471 : /* assert(sfi != NULL); */
472 21055 : if (sfi == NULL)
473 0 : return 0;
474 :
475 : /* Iterate over all stackframes. */
476 :
477 21055 : depth = 0;
478 :
479 982999 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
480 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
481 : stacktrace_stackframeinfo_next(&tmpsfi)) {
482 : /* Get methodinfo. */
483 :
484 961944 : m = tmpsfi.code->m;
485 :
486 : /* Skip builtin methods. */
487 :
488 961944 : if (m->flags & ACC_METHOD_BUILTIN)
489 17 : continue;
490 :
491 961927 : depth++;
492 : }
493 :
494 21055 : return depth;
495 : }
496 :
497 :
498 : /* stacktrace_get **************************************************************
499 :
500 : Builds and returns a stacktrace starting from the given stackframe
501 : info and returns the stacktrace structure wrapped in a Java
502 : byte-array to not confuse the GC.
503 :
504 : IN:
505 : sfi ... stackframe info to start stacktrace from
506 :
507 : RETURN:
508 : stacktrace as Java byte-array
509 :
510 : *******************************************************************************/
511 :
512 21051 : java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
513 : {
514 : stacktrace_t *st;
515 : stacktrace_entry_t *ste;
516 :
517 : CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
518 :
519 : #if !defined(NDEBUG)
520 21051 : if (opt_DebugStackTrace)
521 0 : log_println("[stacktrace_get]");
522 : #endif
523 :
524 21051 : bool skip_fillInStackTrace = true;
525 21051 : bool skip_init = true;
526 :
527 21051 : int depth = stacktrace_depth(sfi);
528 :
529 21051 : if (depth == 0)
530 0 : return NULL;
531 :
532 : // Allocate memory from the GC heap and copy the stacktrace buffer.
533 : // ATTENTION: Use a Java byte-array for this to not confuse the GC.
534 : // FIXME: We waste some memory here as we skip some entries later.
535 :
536 21051 : int32_t ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
537 :
538 21051 : ByteArray ba(ba_size);
539 :
540 21051 : if (ba.is_null())
541 0 : goto return_NULL;
542 :
543 : // Get a stacktrace entry pointer.
544 : // ATTENTION: We need a critical section here because we use the
545 : // byte-array data pointer directly.
546 :
547 : LLNI_CRITICAL_START;
548 :
549 21051 : st = (stacktrace_t *) ba.get_raw_data_ptr();
550 21051 : ste = st->entries;
551 :
552 : // Iterate over the whole stack.
553 : stackframeinfo_t tmpsfi;
554 :
555 982883 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
556 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
557 : stacktrace_stackframeinfo_next(&tmpsfi)) {
558 : // Get the methodinfo
559 :
560 961832 : methodinfo *m = tmpsfi.code->m;
561 :
562 : // Skip builtin methods
563 :
564 961832 : if (m->flags & ACC_METHOD_BUILTIN)
565 14 : continue;
566 :
567 : // This logic is taken from
568 : // hotspot/src/share/vm/classfile/javaClasses.cpp
569 : // (java_lang_Throwable::fill_in_stack_trace)
570 :
571 : // the current stack contains the following frames:
572 : // * one or more fillInStackTrace frames for the exception class, we skip these
573 : // * zero or more <init> frames for the exception class, we skip these
574 : // * rest of the stack
575 :
576 : // skip Throwable.fillInStackTrace
577 :
578 961818 : if (skip_fillInStackTrace) {
579 63153 : if (m->name == utf8::fillInStackTrace) {
580 42102 : continue;
581 : } else {
582 : // we saw all fillInStackTrace frames, stop skipping
583 21051 : skip_fillInStackTrace = false;
584 : }
585 : }
586 :
587 : // Skip <init> methods of any classes deriving from java.lang.Throwable
588 :
589 919716 : if (skip_init == true) {
590 105253 : if (m->name == utf8::init && class_issubclass(m->clazz, class_java_lang_Throwable)) {
591 84241 : continue;
592 : } else {
593 : // we saw all <init> frames, stop skipping
594 21012 : skip_init = false;
595 : }
596 : }
597 :
598 : // Store the stacktrace entry and increment the pointer.
599 :
600 835475 : ste->code = tmpsfi.code;
601 835475 : ste->pc = tmpsfi.xpc;
602 :
603 835475 : ste++;
604 : }
605 :
606 : // Store the number of entries in the stacktrace structure
607 :
608 21051 : st->length = ste - st->entries;
609 :
610 : LLNI_CRITICAL_END;
611 :
612 : CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
613 : stacktrace_overhead)
614 21051 : return ba.get_handle();
615 :
616 : return_NULL:
617 : CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
618 : stacktrace_overhead)
619 :
620 0 : return NULL;
621 : }
622 :
623 :
624 : /* stacktrace_get_current ******************************************************
625 :
626 : Builds and returns a stacktrace from the current thread and returns
627 : the stacktrace structure wrapped in a Java byte-array to not
628 : confuse the GC.
629 :
630 : RETURN:
631 : stacktrace as Java byte-array
632 :
633 : *******************************************************************************/
634 :
635 21051 : java_handle_bytearray_t *stacktrace_get_current(void)
636 : {
637 : stackframeinfo_t *sfi;
638 : java_handle_bytearray_t *ba;
639 :
640 21051 : sfi = threads_get_current_stackframeinfo();
641 21051 : ba = stacktrace_get(sfi);
642 :
643 21051 : return ba;
644 : }
645 :
646 :
647 : /**
648 : * Creates a java.lang.StackTraceElement for one element of the given
649 : * stacktrace.
650 : *
651 : * @param st Given stacktrace.
652 : * @param index Index of element inside stacktrace.
653 : * @return The filled StackTraceElement object.
654 : */
655 : #if defined(ENABLE_JAVASE)
656 121 : java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t* st, int32_t index)
657 : {
658 121 : assert(st != NULL);
659 :
660 121 : if ((index < 0) || (index >= st->length)) {
661 : /* XXX This should be an IndexOutOfBoundsException (check this
662 : again). */
663 0 : exceptions_throw_arrayindexoutofboundsexception();
664 0 : return NULL;
665 : }
666 :
667 : // Get the stacktrace entry.
668 121 : stacktrace_entry_t* ste = &(st->entries[index]);
669 :
670 : // Get the codeinfo, methodinfo and classinfo.
671 121 : codeinfo* code = ste->code;
672 121 : methodinfo* m = code->m;
673 121 : classinfo* c = m->clazz;
674 :
675 : // Get filename.
676 : java_handle_t* filename;
677 :
678 121 : if (!(m->flags & ACC_NATIVE)) {
679 118 : if (c->sourcefile != NULL)
680 118 : filename = JavaString::literal(c->sourcefile);
681 : else
682 0 : filename = NULL;
683 : }
684 : else
685 3 : filename = NULL;
686 :
687 : // Get line number.
688 : int32_t linenumber;
689 :
690 121 : if (m->flags & ACC_NATIVE) {
691 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
692 3 : linenumber = -1;
693 : #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
694 : linenumber = -2;
695 : #else
696 : # error unknown classpath configuration
697 : #endif
698 : }
699 : else {
700 : // FIXME linenumbertable->find could change the methodinfo
701 : // pointer when hitting an inlined method.
702 118 : linenumber = code->linenumbertable->find(&m, ste->pc);
703 118 : linenumber = (linenumber == 0) ? -1 : linenumber;
704 : }
705 :
706 : // Get declaring class name.
707 121 : java_handle_t* declaringclass = JavaString(class_get_classname(c)).intern();
708 :
709 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
710 : // Allocate a new StackTraceElement object.
711 121 : java_handle_t* h = builtin_new(class_java_lang_StackTraceElement);
712 :
713 121 : if (h == NULL)
714 0 : return NULL;
715 :
716 121 : java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, JavaString::from_utf8(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0));
717 : #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
718 : // Allocate a new StackTraceElement object.
719 : java_lang_StackTraceElement jlste(declaringclass, JavaString::literal(m->name), filename, linenumber);
720 :
721 : if (jlste.is_null())
722 : return NULL;
723 : #else
724 : # error unknown classpath configuration
725 : #endif
726 :
727 121 : return jlste.get_handle();
728 : }
729 : #endif
730 :
731 :
732 : /**
733 : * Creates a complete array of java.lang.StackTraceElement objects
734 : * for the given stacktrace.
735 : *
736 : * @param st Given stacktrace.
737 : * @return Array of filled StackTraceElement objects.
738 : */
739 : #if defined(ENABLE_JAVASE)
740 66 : java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st)
741 : {
742 : // Get length of stacktrace. If stacktrace is not available
743 : // an empty array should be returned.
744 66 : int32_t length = (st != NULL) ? st->length : 0;
745 :
746 : // Create the stacktrace element array.
747 66 : ObjectArray oa(length, class_java_lang_StackTraceElement);
748 :
749 66 : if (oa.is_null())
750 0 : return NULL;
751 :
752 : // Iterate over all stacktrace elements.
753 187 : for (int i = 0; i < length; i++) {
754 :
755 : // Get stacktrace element at current index.
756 121 : java_handle_t* h = stacktrace_get_StackTraceElement(st, i);
757 :
758 121 : if (h == NULL)
759 0 : return NULL;
760 :
761 : // Store stacktrace element in array.
762 121 : oa.set_element(i, h);
763 : }
764 :
765 66 : return oa.get_handle();
766 : }
767 : #endif
768 :
769 :
770 : /* stacktrace_get_caller_class *************************************************
771 :
772 : Get the class on the stack at the given depth. This function skips
773 : various special classes or methods.
774 :
775 : ARGUMENTS:
776 : depth ... depth to get caller class of
777 :
778 : RETURN:
779 : caller class
780 :
781 : *******************************************************************************/
782 :
783 : #if defined(ENABLE_JAVASE)
784 779 : classinfo *stacktrace_get_caller_class(int depth)
785 : {
786 : stackframeinfo_t *sfi;
787 : stackframeinfo_t tmpsfi;
788 : methodinfo *m;
789 : classinfo *c;
790 : int i;
791 :
792 : #if !defined(NDEBUG)
793 779 : if (opt_DebugStackTrace)
794 0 : log_println("[stacktrace_get_caller_class]");
795 : #endif
796 :
797 : /* Get the stackframeinfo of the current thread. */
798 :
799 779 : sfi = threads_get_current_stackframeinfo();
800 :
801 : /* Iterate over the whole stack until we reached the requested
802 : depth. */
803 :
804 779 : i = 0;
805 :
806 2337 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
807 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
808 : stacktrace_stackframeinfo_next(&tmpsfi)) {
809 :
810 2337 : m = tmpsfi.code->m;
811 2337 : c = m->clazz;
812 :
813 : /* Skip builtin methods. */
814 :
815 2337 : if (m->flags & ACC_METHOD_BUILTIN)
816 0 : continue;
817 :
818 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
819 : /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
820 : (vframeStreamCommon::security_get_caller_frame). */
821 :
822 : /* This is java.lang.reflect.Method.invoke(), skip it. */
823 :
824 : if (m == method_java_lang_reflect_Method_invoke)
825 : continue;
826 :
827 : /* This is an auxiliary frame, skip it. */
828 :
829 : if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
830 : continue;
831 : #endif
832 :
833 : /* We reached the requested depth. */
834 :
835 2337 : if (i >= depth)
836 779 : return c;
837 :
838 1558 : i++;
839 : }
840 :
841 0 : return NULL;
842 : }
843 : #endif
844 :
845 :
846 : /**
847 : * Returns the first non-null (user-defined) classloader on the stack.
848 : *
849 : * @return The first non-null classloader or NULL if none is found.
850 : */
851 0 : classloader_t* stacktrace_first_nonnull_classloader(void)
852 : {
853 : stackframeinfo_t *sfi;
854 : stackframeinfo_t tmpsfi;
855 : methodinfo *m;
856 : classloader_t *cl;
857 :
858 : #if !defined(NDEBUG)
859 0 : if (opt_DebugStackTrace)
860 0 : log_println("[stacktrace_first_nonnull_classloader]");
861 : #endif
862 :
863 : /* Get the stackframeinfo of the current thread. */
864 :
865 0 : sfi = threads_get_current_stackframeinfo();
866 :
867 : /* Iterate over the whole stack. */
868 :
869 0 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
870 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
871 : stacktrace_stackframeinfo_next(&tmpsfi)) {
872 :
873 0 : m = tmpsfi.code->m;
874 0 : cl = class_get_classloader(m->clazz);
875 :
876 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
877 : /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
878 : (vframeStreamCommon::skip_reflection_related_frames). */
879 : if (class_issubclass(m->clazz, class_sun_reflect_MethodAccessorImpl) ||
880 : class_issubclass(m->clazz, class_sun_reflect_ConstructorAccessorImpl))
881 : continue;
882 : #endif
883 :
884 0 : if (cl != NULL)
885 0 : return cl;
886 : }
887 :
888 0 : return NULL;
889 : }
890 :
891 :
892 : /**
893 : * Checks if a given classloader is equal to the the second classloader
894 : * or one of its ancestors (parents).
895 : *
896 : * XXX: This helper method should be moved to java_lang_Classloader.
897 : */
898 : #if defined(ENABLE_JAVASE)
899 0 : static bool is_ancestor_of(classloader_t* loader, classloader_t* parent)
900 : {
901 : // Iterate over chain of possible parents.
902 0 : while (parent != NULL) {
903 :
904 : // Check if given loader is parent.
905 0 : if (loader == parent)
906 0 : return true;
907 :
908 : // Jump to next parent.
909 0 : java_lang_ClassLoader jlcl(parent);
910 0 : parent = jlcl.get_parent();
911 : }
912 :
913 0 : return false;
914 : }
915 : #endif /* defined(ENABLE_JAVASE) */
916 :
917 :
918 : /**
919 : * Returns the first non-system (user-defined) classloader on the stack.
920 : * A non-system classloader is a non-null classloader being not equal to
921 : * the system classloader (or one of its ancestors).
922 : *
923 : * @return The first non-system classloader or NULL if none is found.
924 : */
925 : #if defined(ENABLE_JAVASE)
926 0 : classloader_t* stacktrace_first_nonsystem_classloader(void)
927 : {
928 : stackframeinfo_t *sfi;
929 : stackframeinfo_t tmpsfi;
930 : methodinfo *m;
931 : classloader_t *cl;
932 : classloader_t *syscl;
933 :
934 : #if !defined(NDEBUG)
935 0 : if (opt_DebugStackTrace)
936 0 : log_println("[stacktrace_first_nonsystem_classloader]");
937 : #endif
938 :
939 : // Get the stackframeinfo of the current thread.
940 0 : sfi = threads_get_current_stackframeinfo();
941 :
942 : // Get the system class class loader.
943 0 : syscl = java_lang_ClassLoader::invoke_getSystemClassLoader();
944 :
945 : // Iterate over the whole stack.
946 0 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
947 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
948 : stacktrace_stackframeinfo_next(&tmpsfi)) {
949 :
950 0 : m = tmpsfi.code->m;
951 0 : cl = class_get_classloader(m->clazz);
952 :
953 0 : if (cl == NULL)
954 0 : continue;
955 :
956 : // XXX if a method in a class in a trusted loader is in a
957 : // doPrivileged, return NULL (or break) here.
958 :
959 0 : if (!is_ancestor_of(cl, syscl))
960 0 : return cl;
961 : }
962 :
963 0 : return NULL;
964 : }
965 : #endif /* defined(ENABLE_JAVASE) */
966 :
967 :
968 : /* stacktrace_getClassContext **************************************************
969 :
970 : Creates a Class context array.
971 :
972 : RETURN VALUE:
973 : the array of java.lang.Class objects, or
974 : NULL if an exception has been thrown
975 :
976 : *******************************************************************************/
977 :
978 3 : java_handle_objectarray_t *stacktrace_getClassContext(void)
979 : {
980 : stackframeinfo_t *sfi;
981 : stackframeinfo_t tmpsfi;
982 : int depth;
983 : int i;
984 : methodinfo *m;
985 :
986 : CYCLES_STATS_DECLARE_AND_START
987 :
988 : #if !defined(NDEBUG)
989 3 : if (opt_DebugStackTrace)
990 0 : log_println("[stacktrace_getClassContext]");
991 : #endif
992 :
993 3 : sfi = threads_get_current_stackframeinfo();
994 :
995 : /* Get the depth of the current stack. */
996 :
997 3 : depth = stacktrace_depth(sfi);
998 :
999 : /* The first stackframe corresponds to the method whose
1000 : implementation calls this native function. We remove that
1001 : entry. */
1002 :
1003 3 : depth--;
1004 3 : stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1005 3 : stacktrace_stackframeinfo_next(&tmpsfi);
1006 :
1007 : /* Allocate the Class array. */
1008 :
1009 3 : ClassArray ca(depth);
1010 :
1011 3 : if (ca.is_null()) {
1012 : CYCLES_STATS_END(stacktrace_getClassContext);
1013 :
1014 0 : return NULL;
1015 : }
1016 :
1017 : /* Fill the Class array from the stacktrace list. */
1018 : /* Iterate over the whole stack. */
1019 :
1020 3 : i = 0;
1021 :
1022 71 : for (;
1023 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1024 : stacktrace_stackframeinfo_next(&tmpsfi)) {
1025 : /* Get methodinfo. */
1026 :
1027 68 : m = tmpsfi.code->m;
1028 :
1029 : /* Skip builtin methods. */
1030 :
1031 68 : if (m->flags & ACC_METHOD_BUILTIN)
1032 3 : continue;
1033 :
1034 : /* Store the class in the array. */
1035 :
1036 65 : ca.set_element(i, m->clazz);
1037 :
1038 65 : i++;
1039 : }
1040 :
1041 : LLNI_CRITICAL_END;
1042 :
1043 : CYCLES_STATS_END(stacktrace_getClassContext)
1044 :
1045 3 : return ca.get_handle();
1046 : }
1047 :
1048 :
1049 : /* stacktrace_getCurrentClass **************************************************
1050 :
1051 : Find the current class by walking the stack trace.
1052 :
1053 : Quote from the JNI documentation:
1054 :
1055 : In the Java 2 Platform, FindClass locates the class loader
1056 : associated with the current native method. If the native code
1057 : belongs to a system class, no class loader will be
1058 : involved. Otherwise, the proper class loader will be invoked to
1059 : load and link the named class. When FindClass is called through the
1060 : Invocation Interface, there is no current native method or its
1061 : associated class loader. In that case, the result of
1062 : ClassLoader.getBaseClassLoader is used."
1063 :
1064 : *******************************************************************************/
1065 :
1066 : #if defined(ENABLE_JAVASE)
1067 740 : classinfo *stacktrace_get_current_class(void)
1068 : {
1069 : stackframeinfo_t *sfi;
1070 : stackframeinfo_t tmpsfi;
1071 : methodinfo *m;
1072 :
1073 : CYCLES_STATS_DECLARE_AND_START;
1074 :
1075 : #if !defined(NDEBUG)
1076 740 : if (opt_DebugStackTrace)
1077 0 : log_println("[stacktrace_get_current_class]");
1078 : #endif
1079 :
1080 : /* Get the stackframeinfo of the current thread. */
1081 :
1082 740 : sfi = threads_get_current_stackframeinfo();
1083 :
1084 : /* If the stackframeinfo is NULL then FindClass is called through
1085 : the Invocation Interface and we return NULL */
1086 :
1087 740 : if (sfi == NULL) {
1088 : CYCLES_STATS_END(stacktrace_getCurrentClass);
1089 :
1090 0 : return NULL;
1091 : }
1092 :
1093 : /* Iterate over the whole stack. */
1094 :
1095 740 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1096 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1097 : stacktrace_stackframeinfo_next(&tmpsfi)) {
1098 : /* Get the methodinfo. */
1099 :
1100 740 : m = tmpsfi.code->m;
1101 :
1102 740 : if (m->clazz == class_java_security_PrivilegedAction) {
1103 : CYCLES_STATS_END(stacktrace_getCurrentClass);
1104 :
1105 0 : return NULL;
1106 : }
1107 :
1108 740 : if (m->clazz != NULL) {
1109 : CYCLES_STATS_END(stacktrace_getCurrentClass);
1110 :
1111 740 : return m->clazz;
1112 : }
1113 : }
1114 :
1115 : /* No Java method found on the stack. */
1116 :
1117 : CYCLES_STATS_END(stacktrace_getCurrentClass);
1118 :
1119 0 : return NULL;
1120 : }
1121 : #endif /* ENABLE_JAVASE */
1122 :
1123 :
1124 : /* stacktrace_get_stack ********************************************************
1125 :
1126 : Create a 2-dimensional array for java.security.VMAccessControler.
1127 :
1128 : RETURN VALUE:
1129 : the arrary, or
1130 : NULL if an exception has been thrown
1131 :
1132 : *******************************************************************************/
1133 :
1134 : #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1135 1 : java_handle_objectarray_t *stacktrace_get_stack(void)
1136 : {
1137 : stackframeinfo_t *sfi;
1138 : stackframeinfo_t tmpsfi;
1139 : int depth;
1140 : methodinfo *m;
1141 : java_handle_t *string;
1142 : int i;
1143 :
1144 : CYCLES_STATS_DECLARE_AND_START
1145 :
1146 : #if !defined(NDEBUG)
1147 1 : if (opt_DebugStackTrace)
1148 0 : log_println("[stacktrace_get_stack]");
1149 : #endif
1150 :
1151 : /* Get the stackframeinfo of the current thread. */
1152 :
1153 1 : sfi = threads_get_current_stackframeinfo();
1154 :
1155 : /* Get the depth of the current stack. */
1156 :
1157 1 : depth = stacktrace_depth(sfi);
1158 :
1159 1 : if (depth == 0)
1160 0 : return NULL;
1161 :
1162 : /* Allocate the required arrays. */
1163 :
1164 1 : ObjectArray oa(2, arrayclass_java_lang_Object);
1165 1 : ClassArray classes(depth);
1166 1 : ObjectArray methodnames(depth, class_java_lang_String);
1167 :
1168 1 : if (oa.is_null())
1169 0 : goto return_NULL;
1170 :
1171 1 : if (classes.is_null())
1172 0 : goto return_NULL;
1173 :
1174 1 : if (methodnames.is_null())
1175 0 : goto return_NULL;
1176 :
1177 : /* Set up the 2-dimensional array. */
1178 :
1179 1 : oa.set_element(0, (java_handle_t *) classes.get_handle());
1180 1 : oa.set_element(1, (java_handle_t *) methodnames.get_handle());
1181 :
1182 : /* Iterate over the whole stack. */
1183 : /* TODO We should use a critical section here to speed things
1184 : up. */
1185 :
1186 1 : i = 0;
1187 :
1188 42 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1189 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1190 : stacktrace_stackframeinfo_next(&tmpsfi)) {
1191 : /* Get the methodinfo. */
1192 :
1193 41 : m = tmpsfi.code->m;
1194 :
1195 : /* Skip builtin methods. */
1196 :
1197 41 : if (m->flags & ACC_METHOD_BUILTIN)
1198 0 : continue;
1199 :
1200 : /* Store the class in the array. */
1201 :
1202 41 : classes.set_element(i, m->clazz);
1203 :
1204 : /* Store the name in the array. */
1205 :
1206 41 : string = JavaString::from_utf8(m->name);
1207 :
1208 41 : if (string == NULL)
1209 0 : goto return_NULL;
1210 :
1211 41 : methodnames.set_element(i, string);
1212 :
1213 41 : i++;
1214 : }
1215 :
1216 : CYCLES_STATS_END(stacktrace_get_stack)
1217 :
1218 1 : return oa.get_handle();
1219 :
1220 : return_NULL:
1221 : CYCLES_STATS_END(stacktrace_get_stack)
1222 :
1223 0 : return NULL;
1224 : }
1225 : #endif
1226 :
1227 :
1228 : /* stacktrace_print_entry ****************************************************
1229 :
1230 : Print line for a stacktrace entry.
1231 :
1232 : ARGUMENTS:
1233 : m ............ methodinfo of the entry
1234 : linenumber ... linenumber of the entry
1235 :
1236 : *******************************************************************************/
1237 :
1238 0 : static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1239 : {
1240 : /* Sanity check. */
1241 :
1242 0 : assert(m != NULL);
1243 :
1244 0 : printf("\tat ");
1245 :
1246 0 : if (m->flags & ACC_METHOD_BUILTIN)
1247 0 : printf("NULL");
1248 : else
1249 0 : utf_display_printable_ascii_classname(m->clazz->name);
1250 :
1251 0 : printf(".");
1252 0 : utf_display_printable_ascii(m->name);
1253 0 : utf_display_printable_ascii(m->descriptor);
1254 :
1255 0 : if (m->flags & ACC_NATIVE) {
1256 0 : puts("(Native Method)");
1257 : }
1258 : else {
1259 0 : if (m->flags & ACC_METHOD_BUILTIN) {
1260 0 : puts("(builtin)");
1261 : }
1262 : else {
1263 0 : printf("(");
1264 0 : utf_display_printable_ascii(m->clazz->sourcefile);
1265 0 : printf(":%d)\n", linenumber);
1266 : }
1267 : }
1268 :
1269 0 : fflush(stdout);
1270 0 : }
1271 :
1272 :
1273 : /* stacktrace_print ************************************************************
1274 :
1275 : Print the given stacktrace with CACAO intern methods only (no Java
1276 : code required).
1277 :
1278 : This method is used by stacktrace_dump_trace and
1279 : builtin_trace_exception.
1280 :
1281 : IN:
1282 : st ... stacktrace to print
1283 :
1284 : *******************************************************************************/
1285 :
1286 0 : void stacktrace_print(stacktrace_t *st)
1287 : {
1288 : stacktrace_entry_t *ste;
1289 : methodinfo *m;
1290 : int32_t linenumber;
1291 : int i;
1292 :
1293 0 : ste = &(st->entries[0]);
1294 :
1295 0 : for (i = 0; i < st->length; i++, ste++) {
1296 0 : m = ste->code->m;
1297 :
1298 : /* Get the line number. */
1299 :
1300 0 : linenumber = ste->code->linenumbertable->find(&m, ste->pc);
1301 :
1302 0 : stacktrace_print_entry(m, linenumber);
1303 : }
1304 0 : }
1305 :
1306 :
1307 : /* stacktrace_print_current ****************************************************
1308 :
1309 : Print the current stacktrace of the current thread.
1310 :
1311 : NOTE: This function prints all frames of the stacktrace and does
1312 : not skip frames like stacktrace_get.
1313 :
1314 : *******************************************************************************/
1315 :
1316 0 : void stacktrace_print_current(void)
1317 : {
1318 : stackframeinfo_t *sfi;
1319 : stackframeinfo_t tmpsfi;
1320 : codeinfo *code;
1321 : methodinfo *m;
1322 : int32_t linenumber;
1323 :
1324 0 : sfi = threads_get_current_stackframeinfo();
1325 :
1326 0 : if (sfi == NULL) {
1327 0 : puts("\t<<No stacktrace available>>");
1328 0 : fflush(stdout);
1329 0 : return;
1330 : }
1331 :
1332 0 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1333 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1334 : stacktrace_stackframeinfo_next(&tmpsfi)) {
1335 : /* Get the methodinfo. */
1336 :
1337 0 : code = tmpsfi.code;
1338 0 : m = code->m;
1339 :
1340 : // Get the line number.
1341 0 : linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1342 :
1343 0 : stacktrace_print_entry(m, linenumber);
1344 : }
1345 : }
1346 :
1347 :
1348 : /**
1349 : * Creates a stacktrace for the given thread.
1350 : *
1351 : * @param t Given thread.
1352 : * @return Current stacktrace of the given thread.
1353 : *
1354 : * XXX: Creation of the stacktrace starts at the most recent
1355 : * stackframeinfo block. If the thread is not inside the native
1356 : * world, the created stacktrace is not complete!
1357 : */
1358 0 : stacktrace_t* stacktrace_get_of_thread(threadobject* t)
1359 : {
1360 : stackframeinfo_t* sfi;
1361 : java_handle_bytearray_t* stba;
1362 : stacktrace_t* st;
1363 :
1364 0 : sfi = t->_stackframeinfo;
1365 0 : stba = stacktrace_get(sfi);
1366 :
1367 0 : ByteArray ba(stba);
1368 :
1369 0 : if (ba.is_null())
1370 0 : return NULL;
1371 :
1372 0 : st = (stacktrace_t*) ba.get_raw_data_ptr();
1373 :
1374 0 : return st;
1375 : }
1376 :
1377 :
1378 : /* stacktrace_print_of_thread **************************************************
1379 :
1380 : Print the current stacktrace of the given thread. It will only work
1381 : for suspended threads.
1382 :
1383 : ARGUMENTS:
1384 : t ... thread
1385 :
1386 : *******************************************************************************/
1387 :
1388 0 : void stacktrace_print_of_thread(threadobject *t)
1389 : {
1390 : stackframeinfo_t *sfi;
1391 : stackframeinfo_t tmpsfi;
1392 : codeinfo *code;
1393 : methodinfo *m;
1394 : int32_t linenumber;
1395 :
1396 : /* Build a stacktrace for the passed thread. */
1397 :
1398 0 : sfi = t->_stackframeinfo;
1399 :
1400 0 : if (!t->suspended || sfi == NULL) {
1401 0 : puts("\t<<No stacktrace available>>");
1402 0 : fflush(stdout);
1403 0 : return;
1404 : }
1405 :
1406 0 : for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1407 : stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1408 : stacktrace_stackframeinfo_next(&tmpsfi)) {
1409 : /* Get the methodinfo. */
1410 :
1411 0 : code = tmpsfi.code;
1412 0 : m = code->m;
1413 :
1414 : // Get the line number.
1415 0 : linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1416 :
1417 0 : stacktrace_print_entry(m, linenumber);
1418 : }
1419 : }
1420 :
1421 :
1422 : /* stacktrace_print_exception **************************************************
1423 :
1424 : Print the stacktrace of a given exception (more or less a wrapper
1425 : to stacktrace_print).
1426 :
1427 : IN:
1428 : h ... handle of exception to print
1429 :
1430 : *******************************************************************************/
1431 :
1432 0 : void stacktrace_print_exception(java_handle_t *h)
1433 : {
1434 0 : if (h == NULL)
1435 0 : return;
1436 :
1437 0 : java_lang_Throwable t(h);
1438 :
1439 : /* now print the stacktrace */
1440 :
1441 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1442 :
1443 0 : java_lang_VMThrowable vmt(t.get_vmState());
1444 0 : ByteArray backtrace(vmt.get_vmdata());
1445 :
1446 : #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1447 :
1448 : ByteArray backtrace(t.get_backtrace());
1449 :
1450 : #else
1451 : # error unknown classpath configuration
1452 : #endif
1453 :
1454 : // Sanity check.
1455 :
1456 0 : assert(backtrace.is_non_null());
1457 :
1458 : /* We need a critical section here as we use the byte-array data
1459 : pointer directly. */
1460 :
1461 : LLNI_CRITICAL_START;
1462 :
1463 0 : stacktrace_t* st = (stacktrace_t*) backtrace.get_raw_data_ptr();
1464 :
1465 0 : stacktrace_print(st);
1466 :
1467 0 : LLNI_CRITICAL_END;
1468 : }
1469 :
1470 :
1471 : #if defined(ENABLE_CYCLES_STATS)
1472 : void stacktrace_print_cycles_stats(FILE *file)
1473 : {
1474 : CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1475 : CYCLES_STATS_PRINT(stacktrace_get, file);
1476 : CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
1477 : CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1478 : CYCLES_STATS_PRINT(stacktrace_get_stack, file);
1479 : }
1480 : #endif
1481 :
1482 : /*
1483 : * These are local overrides for various environment variables in Emacs.
1484 : * Please do not remove this and leave it at the end of the file, where
1485 : * Emacs will automagically detect them.
1486 : * ---------------------------------------------------------------------
1487 : * Local variables:
1488 : * mode: c++
1489 : * indent-tabs-mode: t
1490 : * c-basic-offset: 4
1491 : * tab-width: 4
1492 : * End:
1493 : * vim:noexpandtab:sw=4:ts=4:
1494 : */
|