1 /* src/vm/jit/stacktrace.c - machine independet stacktrace system
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Joseph Wenninger
29 Changes: Christian Thalinger
31 $Id: stacktrace.c 3779 2005-11-23 22:36:59Z twisti $
43 #include "native/native.h"
45 #include "vm/global.h" /* required here for native includes */
46 #include "native/include/java_lang_ClassLoader.h"
47 #include "native/include/java_lang_Throwable.h"
48 #include "native/include/java_lang_VMThrowable.h"
50 #include "toolbox/logging.h"
51 #include "vm/builtin.h"
53 #include "vm/exceptions.h"
54 #include "vm/loader.h"
55 #include "vm/options.h"
56 #include "vm/stringlocal.h"
57 #include "vm/tables.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen.inc.h"
60 #include "vm/jit/methodheader.h"
63 /* lineNumberTableEntry *******************************************************/
65 /* Keep the type of line the same as the pointer type, otherwise we run into */
66 /* alignment troubles (like on MIPS64). */
68 typedef struct lineNumberTableEntry {
71 } lineNumberTableEntry;
74 typedef struct lineNumberTableEntryInlineBegin {
75 /* this should have the same layout and size as the lineNumberTableEntry */
78 } lineNumberTableEntryInlineBegin;
81 typedef bool(*CacaoStackTraceCollector)(void **, stackTraceBuffer*);
84 #define BLOCK_INITIALSIZE 40
85 #define BLOCK_SIZEINCREMENT 40
88 /* global variables ***********************************************************/
90 #if !defined(USE_THREADS)
91 stackframeinfo *_no_threads_stackframeinfo = NULL;
95 /* stacktrace_create_stackframeinfo ********************************************
97 Creates an stackframe info structure for inline code in the
100 *******************************************************************************/
102 #if defined(ENABLE_INTRP)
103 void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
106 stackframeinfo **psfi;
109 /* get current stackframe info pointer */
111 psfi = STACKFRAMEINFO;
113 /* if we don't have pv handy */
116 #if defined(ENABLE_INTRP)
118 pv = codegen_findmethod(ra);
122 #if defined(ENABLE_JIT)
123 pv = md_codegen_findmethod(ra);
128 /* get methodinfo pointer from data segment */
130 m = *((methodinfo **) (pv + MethodPointer));
132 /* fill new stackframe info structure */
140 /* xpc is the same as ra, but is required in fillInStackTrace */
144 /* store new stackframe info pointer */
148 #endif /* defined(ENABLE_INTRP) */
150 /* stacktrace_create_inline_stackframeinfo *************************************
152 Creates an stackframe info structure for an inline exception stub.
154 *******************************************************************************/
156 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
157 u1 *sp, u1 *ra, u1 *xpc)
159 stackframeinfo **psfi;
161 /* get current stackframe info pointer */
163 psfi = STACKFRAMEINFO;
165 #if defined(ENABLE_INTRP)
167 /* if we don't have pv handy */
170 pv = codegen_findmethod(ra);
175 /* fill new stackframe info structure */
184 /* store new stackframe info pointer */
190 /* stacktrace_create_extern_stackframeinfo *************************************
192 Creates an stackframe info structure for an extern exception
193 (hardware or assembler).
195 *******************************************************************************/
197 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
198 u1 *sp, u1 *ra, u1 *xpc)
200 stackframeinfo **psfi;
201 #if !defined(__I386__) && !defined(__X86_64__)
206 /* get current stackframe info pointer */
208 psfi = STACKFRAMEINFO;
210 /* sometimes we don't have pv handy (e.g. in asmpart.S:
211 L_asm_call_jit_compiler_exception or in the interpreter). */
214 #if defined(ENABLE_INTRP)
216 pv = codegen_findmethod(ra);
220 #if defined(ENABLE_JIT)
221 pv = md_codegen_findmethod(ra);
226 #if defined(ENABLE_INTRP)
227 /* When using the interpreter, we pass RA to the function. */
231 # if defined(__I386__) || defined(__X86_64__)
232 /* On i386 and x86_64 we always have to get the return address
235 framesize = *((u4 *) (pv + FrameSize));
237 ra = md_stacktrace_get_returnaddress(sp, framesize);
239 /* If the method is a non-leaf function, we need to get the return
240 address from the stack. For leaf functions the return address
241 is set correctly. This makes the assembler and the signal
242 handler code simpler. */
244 isleafmethod = *((s4 *) (pv + IsLeaf));
247 framesize = *((u4 *) (pv + FrameSize));
249 ra = md_stacktrace_get_returnaddress(sp, framesize);
252 #if defined(ENABLE_INTRP)
256 /* fill new stackframe info structure */
265 /* store new stackframe info pointer */
271 /* stacktrace_create_native_stackframeinfo *************************************
273 Creates a stackframe info structure for a native stub.
275 *******************************************************************************/
277 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
280 stackframeinfo **psfi;
283 /* get methodinfo pointer from data segment */
285 m = *((methodinfo **) (pv + MethodPointer));
287 /* get current stackframe info pointer */
289 psfi = STACKFRAMEINFO;
291 /* fill new stackframe info structure */
300 /* store new stackframe info pointer */
306 /* stacktrace_remove_stackframeinfo ********************************************
310 *******************************************************************************/
312 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
314 stackframeinfo **psfi;
316 /* get current stackframe info pointer */
318 psfi = STACKFRAMEINFO;
320 /* restore the old pointer */
326 /* stacktrace_inline_arithmeticexception ***************************************
328 Creates an ArithemticException for inline stub.
330 *******************************************************************************/
332 java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
336 java_objectheader *o;
338 /* create stackframeinfo */
340 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
342 /* create exception */
344 o = new_arithmeticexception();
346 /* remove stackframeinfo */
348 stacktrace_remove_stackframeinfo(&sfi);
354 /* stacktrace_inline_arrayindexoutofboundsexception ****************************
356 Creates an ArrayIndexOutOfBoundsException for inline stub.
358 *******************************************************************************/
360 java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
367 java_objectheader *o;
369 /* create stackframeinfo */
371 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
373 /* create exception */
375 o = new_arrayindexoutofboundsexception(index);
377 /* remove stackframeinfo */
379 stacktrace_remove_stackframeinfo(&sfi);
385 /* stacktrace_inline_arraystoreexception ***************************************
387 Creates an ArrayStoreException for inline stub.
389 *******************************************************************************/
391 java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
395 java_objectheader *o;
397 /* create stackframeinfo */
399 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
401 /* create exception */
403 o = new_arraystoreexception();
405 /* remove stackframeinfo */
407 stacktrace_remove_stackframeinfo(&sfi);
413 /* stacktrace_inline_classcastexception ****************************************
415 Creates an ClassCastException for inline stub.
417 *******************************************************************************/
419 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
423 java_objectheader *o;
425 /* create stackframeinfo */
427 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
429 /* create exception */
431 o = new_classcastexception();
433 /* remove stackframeinfo */
435 stacktrace_remove_stackframeinfo(&sfi);
441 /* stacktrace_inline_nullpointerexception **************************************
443 Creates an NullPointerException for inline stub.
445 *******************************************************************************/
447 java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
451 java_objectheader *o;
453 /* create stackframeinfo */
455 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
457 /* create exception */
459 o = new_nullpointerexception();
461 /* remove stackframeinfo */
463 stacktrace_remove_stackframeinfo(&sfi);
469 /* stacktrace_hardware_arithmeticexception *************************************
471 Creates an ArithemticException for inline stub.
473 *******************************************************************************/
475 java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
479 java_objectheader *o;
481 /* create stackframeinfo */
483 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
485 /* create exception */
487 o = new_arithmeticexception();
489 /* remove stackframeinfo */
491 stacktrace_remove_stackframeinfo(&sfi);
497 /* stacktrace_hardware_nullpointerexception ************************************
499 Creates an NullPointerException for the SIGSEGV signal handler.
501 *******************************************************************************/
503 java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
507 java_objectheader *o;
509 /* create stackframeinfo */
511 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
513 /* create exception */
515 o = new_nullpointerexception();
517 /* remove stackframeinfo */
519 stacktrace_remove_stackframeinfo(&sfi);
525 /* stacktrace_inline_fillInStackTrace ******************************************
527 Fills in the correct stacktrace into an existing exception object
528 (this one is for inline exception stubs).
530 *******************************************************************************/
532 java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
536 java_objectheader *o;
539 /* create stackframeinfo */
541 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
547 /* clear exception */
549 *exceptionptr = NULL;
551 /* resolve methodinfo pointer from exception object */
553 m = class_resolvemethod(o->vftbl->class,
554 utf_fillInStackTrace,
555 utf_void__java_lang_Throwable);
559 asm_calljavafunction(m, o, NULL, NULL, NULL);
561 /* remove stackframeinfo */
563 stacktrace_remove_stackframeinfo(&sfi);
569 /* addEntry ********************************************************************
573 *******************************************************************************/
575 static void addEntry(stackTraceBuffer *buffer, methodinfo *method, u2 line)
577 if (buffer->size > buffer->full) {
578 stacktraceelement *tmp = &(buffer->start[buffer->full]);
580 tmp->method = method;
581 tmp->linenumber = line;
582 buffer->full = buffer->full + 1;
585 stacktraceelement *newBuffer;
588 (stacktraceelement *) malloc((buffer->size + BLOCK_SIZEINCREMENT) *
589 sizeof(stacktraceelement));
591 if (newBuffer == 0) {
592 log_text("OOM during stacktrace creation");
596 memcpy(newBuffer, buffer->start, buffer->size * sizeof(stacktraceelement));
597 if (buffer->needsFree)
600 buffer->start = newBuffer;
601 buffer->size = buffer->size + BLOCK_SIZEINCREMENT;
602 buffer->needsFree = 1;
604 addEntry(buffer, method, line);
609 /* stacktrace_fillInStackTrace_methodRecursive *********************************
613 *******************************************************************************/
615 static bool stacktrace_fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,
617 lineNumberTableEntry *lntentry,
622 lineNumberTableEntryInlineBegin *lntinline;
625 /* find the line number for the specified pc (going backwards) */
627 for (; lntsize > 0; lntsize--, lntentry--) {
628 /* did we reach the current line? */
630 if (pc >= lntentry->pc) {
631 /* check for special inline entries */
633 switch (lntentry->line) {
635 /* XXX TWISTI we have to think about this inline stuff again */
637 case -1: /* begin of inlined method */
638 lntinline = (lineNumberTableEntryInlineBegin *) (--lntentry);
640 lntsize--; lntsize--;
641 if (stacktrace_fillInStackTrace_methodRecursive(buffer,
647 addEntry(buffer, m, ilStart->lineNrOuter);
653 case -2: /* end of inlined method */
655 *entriesAhead = ahead;
661 addEntry(buffer, m, lntentry->line);
667 /* check if we are before the actual JIT code */
669 if ((ptrint) pc < (ptrint) m->entrypoint) {
670 dolog("Current pc before start of code: %p < %p", pc, m->entrypoint);
674 /* otherwise just add line 0 */
676 addEntry(buffer, m, 0);
682 /* stacktrace_fillInStackTrace_method ******************************************
686 *******************************************************************************/
688 static void stacktrace_fillInStackTrace_method(stackTraceBuffer *buffer,
689 methodinfo *method, u1 *pv,
692 ptrint lntsize; /* size of line number table */
693 u1 *lntstart; /* start of line number table */
694 lineNumberTableEntry *lntentry; /* points to last entry in the table */
696 /* get size of line number table */
698 lntsize = *((ptrint *) (pv + LineNumberTableSize));
699 lntstart = *((u1 **) (pv + LineNumberTableStart));
701 /* subtract the size of the line number entry of the structure, since the */
702 /* line number table start points to the pc */
704 lntentry = (lineNumberTableEntry *) (lntstart - SIZEOF_VOID_P);
707 /* this happens when an exception is thrown in the native stub */
709 addEntry(buffer, method, 0);
712 if (!stacktrace_fillInStackTrace_methodRecursive(buffer,
717 log_text("Trace point not found in suspected method");
724 /* cacao_stacktrace_fillInStackTrace *******************************************
728 *******************************************************************************/
730 bool cacao_stacktrace_fillInStackTrace(void **target,
731 CacaoStackTraceCollector coll,
732 threadobject* thread)
734 static bool cacao_stacktrace_fillInStackTrace(void **target,
735 CacaoStackTraceCollector coll)
739 stacktraceelement primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)];
740 stackTraceBuffer buffer;
750 /* prevent compiler warnings */
756 /* In most cases this should be enough -> one malloc less. I don't think */
757 /* temporary data should be allocated with the GC, only the result. */
759 buffer.needsFree = 0;
760 buffer.start = primaryBlock;
761 buffer.size = BLOCK_INITIALSIZE; /* *sizeof(stacktraceelement); */
764 /* the first element in the stackframe chain must always be a native */
765 /* stackframeinfo (VMThrowable.fillInStackTrace is a native function) */
769 sfi = *STACKFRAMEINFO; /* invocation from Throwable */
771 sfi = thread->info._stackframeinfo; /* invocation from JVMTI */
773 sfi = *STACKFRAMEINFO;
781 #define PRINTMETHODS 0
784 printf("\n\nfillInStackTrace start:\n");
788 /* loop while we have a method pointer (asm_calljavafunction has NULL) or */
789 /* there is a stackframeinfo in the chain */
794 /* m == NULL should only happen for the first time and inline */
795 /* stackframe infos, like from the exception stubs or the patcher */
799 /* for native stub stackframe infos, pv is always NULL */
801 if (sfi->pv == NULL) {
802 /* get methodinfo, sp and ra from the current stackframe info */
805 sp = sfi->sp; /* sp of parent Java function */
809 addEntry(&buffer, m, 0);
812 printf("ra=%p sp=%p, ", ra, sp);
813 utf_display_classname(m->class->name);
815 utf_display(m->name);
816 utf_display(m->descriptor);
817 printf(": native stub\n");
820 /* this is an native stub stackframe info, so we can get the */
821 /* parent pv from the return address (ICMD_INVOKE*) */
823 #if defined(ENABLE_INTRP)
825 pv = codegen_findmethod(ra);
829 #if defined(ENABLE_JIT)
830 pv = md_codegen_findmethod(ra);
834 /* get methodinfo pointer from parent data segment */
836 m = *((methodinfo **) (pv + MethodPointer));
839 /* Inline stackframe infos are special: they have a xpc of */
840 /* the actual exception position and the return address saved */
841 /* since an inline stackframe info can also be in a leaf */
842 /* method (no return address saved on stack!!!). */
843 /* ATTENTION: This one is also for hardware exceptions!!! */
845 /* get methodinfo, sp and ra from the current stackframe info */
847 m = sfi->method; /* m == NULL */
848 pv = sfi->pv; /* pv of parent Java function */
849 sp = sfi->sp; /* sp of parent Java function */
850 ra = sfi->ra; /* ra of parent Java function */
851 xpc = sfi->xpc; /* actual exception position */
854 printf("ra=%p sp=%p, ", ra, sp);
855 printf("NULL: inline stub\n");
859 /* get methodinfo from current Java method */
861 m = *((methodinfo **) (pv + MethodPointer));
863 /* if m == NULL, this is a asm_calljavafunction call */
867 printf("ra=%p sp=%p, ", ra, sp);
868 utf_display_classname(m->class->name);
870 utf_display(m->name);
871 utf_display(m->descriptor);
872 printf(": inline stub parent");
876 #if defined(ENABLE_INTRP)
880 /* add it to the stacktrace */
882 stacktrace_fillInStackTrace_method(&buffer, m, pv,
883 (u1 *) ((ptrint) xpc));
885 /* get the current stack frame size */
887 framesize = *((u4 *) (pv + FrameSize));
890 printf(", framsize=%d\n", framesize);
894 /* set stack pointer to stackframe of parent Java */
895 /* function of the current Java function */
897 #if defined(__I386__) || defined (__X86_64__)
898 sp += framesize + SIZEOF_VOID_P;
903 /* get data segment and methodinfo pointer from parent */
906 #if defined(ENABLE_JIT)
907 pv = md_codegen_findmethod(ra);
910 m = *((methodinfo **) (pv + MethodPointer));
912 #if defined(ENABLE_INTRP)
918 printf("ra=%p sp=%p, ", ra, sp);
919 printf("asm_calljavafunction\n");
925 /* get previous stackframeinfo in the chain */
931 printf("ra=%p sp=%p, ", ra, sp);
932 utf_display_classname(m->class->name);
934 utf_display(m->name);
935 utf_display(m->descriptor);
940 /* JIT method found, add it to the stacktrace (we subtract 1 from */
941 /* the return address since it points the the instruction after */
944 stacktrace_fillInStackTrace_method(&buffer, m, pv,
945 (u1 *) ((ptrint) ra) - 1);
947 /* get the current stack frame size */
949 framesize = *((u4 *) (pv + FrameSize));
952 printf(", framsize=%d\n", framesize);
956 /* get return address of current stack frame */
958 ra = md_stacktrace_get_returnaddress(sp, framesize);
960 /* get data segment and methodinfo pointer from parent method */
962 #if defined(ENABLE_INTRP)
964 pv = codegen_findmethod(ra);
968 #if defined(ENABLE_JIT)
969 pv = md_codegen_findmethod(ra);
973 m = *((methodinfo **) (pv + MethodPointer));
977 #if defined(ENABLE_INTRP)
979 sp = *(u1 **)(sp - framesize);
983 #if defined(__I386__) || defined (__X86_64__)
984 sp += framesize + SIZEOF_VOID_P;
993 result = coll(target, &buffer);
995 if (buffer.needsFree)
1002 /* stackTraceCollector *********************************************************
1006 *******************************************************************************/
1008 bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
1010 static bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
1013 stackTraceBuffer *dest;
1015 dest = *target = heap_allocate(sizeof(stackTraceBuffer) + buffer->full * sizeof(stacktraceelement), true, 0);
1020 memcpy(*target, buffer, sizeof(stackTraceBuffer));
1021 memcpy(dest + 1, buffer->start, buffer->full * sizeof(stacktraceelement));
1023 dest->needsFree = 0;
1024 dest->size = dest->full;
1025 dest->start = (stacktraceelement *) (dest + 1);
1031 bool cacao_stacktrace_NormalTrace(void **target)
1034 return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector, NULL);
1036 return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector);
1043 static bool classContextCollector(void **target, stackTraceBuffer *buffer)
1045 java_objectarray *oa;
1046 stacktraceelement *current;
1047 stacktraceelement *start;
1052 size = buffer->full;
1055 for (i = 0; i < size; i++)
1056 if (buffer->start[i].method != 0)
1059 start = buffer->start;
1063 if (targetSize > 0) {
1064 if (start->method &&
1065 (start->method->class == class_java_lang_SecurityManager)) {
1071 oa = builtin_anewarray(targetSize, class_java_lang_Class);
1076 for(i = 0, current = start; i < targetSize; i++, current++) {
1077 if (!current->method) {
1082 use_class_as_object(current->method->class);
1084 oa->data[i] = (java_objectheader *) current->method->class;
1094 java_objectarray *cacao_createClassContextArray(void)
1096 java_objectarray *array = NULL;
1099 if (!cacao_stacktrace_fillInStackTrace((void **) &array,
1100 &classContextCollector, NULL))
1102 if (!cacao_stacktrace_fillInStackTrace((void **) &array,
1103 &classContextCollector))
1111 /* stacktrace_classLoaderCollector *********************************************
1115 *******************************************************************************/
1117 static bool stacktrace_classLoaderCollector(void **target,
1118 stackTraceBuffer *buffer)
1120 stacktraceelement *current;
1121 stacktraceelement *start;
1126 size = buffer->full;
1127 start = &(buffer->start[0]);
1129 for(i = 0, current = start; i < size; i++, current++) {
1130 m = current->method;
1135 if (m->class == class_java_security_PrivilegedAction) {
1140 if (m->class->classloader) {
1141 *target = (java_lang_ClassLoader *) m->class->classloader;
1152 /* cacao_currentClassLoader ****************************************************
1156 *******************************************************************************/
1158 java_objectheader *cacao_currentClassLoader(void)
1160 java_objectheader *header = NULL;
1164 if (!cacao_stacktrace_fillInStackTrace((void**)&header,
1165 &stacktrace_classLoaderCollector,
1168 if (!cacao_stacktrace_fillInStackTrace((void**)&header,
1169 &stacktrace_classLoaderCollector))
1177 static bool getStackCollector(void **target, stackTraceBuffer *buffer)
1179 java_objectarray *oa;
1180 java_objectarray *classes;
1181 java_objectarray *methodnames;
1182 java_lang_String *str;
1184 stacktraceelement *current;
1187 /* *result = (java_objectarray **) target; */
1189 size = buffer->full;
1191 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1196 classes = builtin_anewarray(size, class_java_lang_Class);
1201 methodnames = builtin_anewarray(size, class_java_lang_String);
1206 oa->data[0] = (java_objectheader *) classes;
1207 oa->data[1] = (java_objectheader *) methodnames;
1209 for (i = 0, current = &(buffer->start[0]); i < size; i++, current++) {
1210 c = current->method->class;
1212 use_class_as_object(c);
1214 classes->data[i] = (java_objectheader *) c;
1215 str = javastring_new(current->method->name);
1220 methodnames->data[i] = (java_objectheader *) str;
1229 java_objectarray *cacao_getStackForVMAccessController(void)
1231 java_objectarray *result = NULL;
1234 if (!cacao_stacktrace_fillInStackTrace((void **) &result,
1235 &getStackCollector,NULL))
1237 if (!cacao_stacktrace_fillInStackTrace((void **) &result,
1238 &getStackCollector))
1246 /* stacktrace_print_trace_from_buffer ******************************************
1248 Print the stacktrace of a given stackTraceBuffer with CACAO intern
1249 methods (no Java help). This method is used by
1250 stacktrace_dump_trace and builtin_trace_exception.
1252 *******************************************************************************/
1254 static void stacktrace_print_trace_from_buffer(stackTraceBuffer *stb)
1256 stacktraceelement *ste;
1262 for (i = 0; i < stb->size; i++, ste++) {
1266 utf_display_classname(m->class->name);
1268 utf_display(m->name);
1269 utf_display(m->descriptor);
1271 if (m->flags & ACC_NATIVE) {
1272 puts("(Native Method)");
1276 utf_display(m->class->sourcefile);
1277 printf(":%d)\n", (u4) ste->linenumber);
1281 /* just to be sure */
1287 /* stacktrace_dump_trace *******************************************************
1289 This method is call from signal_handler_sigusr1 to dump the
1290 stacktrace of the current thread to stdout.
1292 *******************************************************************************/
1294 void stacktrace_dump_trace(void)
1296 stackTraceBuffer *buffer;
1299 /* get thread stackframeinfo */
1301 info = &THREADINFO->_stackframeinfo;
1303 /* fill stackframeinfo structure */
1305 tmp.oldThreadspecificHeadValue = *info;
1306 tmp.addressOfThreadspecificHead = info;
1309 tmp.ra = _mc->gregs[REG_RIP];
1314 /* generate stacktrace */
1316 cacao_stacktrace_NormalTrace((void **) &buffer);
1318 /* print stacktrace */
1321 stacktrace_print_trace_from_buffer(buffer);
1324 puts("\t<<No stacktrace available>>");
1330 /* stacktrace_print_trace ******************************************************
1332 Print the stacktrace of a given exception. More or less a wrapper
1333 to stacktrace_print_trace_from_buffer.
1335 *******************************************************************************/
1337 void stacktrace_print_trace(java_objectheader *xptr)
1339 java_lang_Throwable *t;
1340 java_lang_VMThrowable *vmt;
1341 stackTraceBuffer *stb;
1343 t = (java_lang_Throwable *) xptr;
1345 /* now print the stacktrace */
1348 stb = (stackTraceBuffer *) vmt->vmData;
1350 stacktrace_print_trace_from_buffer(stb);
1355 * These are local overrides for various environment variables in Emacs.
1356 * Please do not remove this and leave it at the end of the file, where
1357 * Emacs will automagically detect them.
1358 * ---------------------------------------------------------------------
1361 * indent-tabs-mode: t