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 4342 2006-01-22 19:57:51Z twisti $
45 #include "native/native.h"
47 #include "vm/global.h" /* required here for native includes */
48 #include "native/include/java_lang_ClassLoader.h"
49 #include "native/include/java_lang_Throwable.h"
50 #include "native/include/java_lang_VMThrowable.h"
52 #include "toolbox/logging.h"
53 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/loader.h"
57 #include "vm/options.h"
58 #include "vm/stringlocal.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen-common.h"
61 #include "vm/jit/methodheader.h"
64 /* lineNumberTableEntry *******************************************************/
66 /* Keep the type of line the same as the pointer type, otherwise we run into */
67 /* alignment troubles (like on MIPS64). */
69 typedef struct lineNumberTableEntry {
72 } lineNumberTableEntry;
75 typedef struct lineNumberTableEntryInlineBegin {
76 /* this should have the same layout and size as the lineNumberTableEntry */
79 } lineNumberTableEntryInlineBegin;
82 typedef bool(*CacaoStackTraceCollector)(void **, stackTraceBuffer*);
85 #define BLOCK_INITIALSIZE 40
86 #define BLOCK_SIZEINCREMENT 40
89 /* global variables ***********************************************************/
91 #if !defined(USE_THREADS)
92 stackframeinfo *_no_threads_stackframeinfo = NULL;
96 /* stacktrace_create_stackframeinfo ********************************************
98 Creates an stackframe info structure for inline code in the
101 *******************************************************************************/
103 #if defined(ENABLE_INTRP)
104 void stacktrace_create_stackframeinfo(stackframeinfo *sfi, u1 *pv, u1 *sp,
107 stackframeinfo **psfi;
110 /* get current stackframe info pointer */
112 psfi = STACKFRAMEINFO;
114 /* if we don't have pv handy */
117 #if defined(ENABLE_INTRP)
119 pv = codegen_findmethod(ra);
123 #if defined(ENABLE_JIT)
124 pv = md_codegen_findmethod(ra);
129 /* get methodinfo pointer from data segment */
131 m = *((methodinfo **) (pv + MethodPointer));
133 /* fill new stackframe info structure */
141 /* xpc is the same as ra, but is required in fillInStackTrace */
145 /* store new stackframe info pointer */
149 #endif /* defined(ENABLE_INTRP) */
152 /* stacktrace_create_inline_stackframeinfo *************************************
154 Creates an stackframe info structure for an inline exception stub.
156 *******************************************************************************/
158 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
159 u1 *sp, u1 *ra, u1 *xpc)
161 stackframeinfo **psfi;
163 /* get current stackframe info pointer */
165 psfi = STACKFRAMEINFO;
167 #if defined(ENABLE_INTRP)
169 /* if we don't have pv handy */
172 pv = codegen_findmethod(ra);
177 /* fill new stackframe info structure */
186 /* store new stackframe info pointer */
192 /* stacktrace_create_extern_stackframeinfo *************************************
194 Creates an stackframe info structure for an extern exception
195 (hardware or assembler).
197 *******************************************************************************/
199 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
200 u1 *sp, u1 *ra, u1 *xpc)
202 stackframeinfo **psfi;
203 #if !defined(__I386__) && !defined(__X86_64__)
206 #if defined(ENABLE_JIT)
210 /* get current stackframe info pointer */
212 psfi = STACKFRAMEINFO;
214 /* sometimes we don't have pv handy (e.g. in asmpart.S:
215 L_asm_call_jit_compiler_exception or in the interpreter). */
218 #if defined(ENABLE_INTRP)
220 pv = codegen_findmethod(ra);
224 #if defined(ENABLE_JIT)
225 pv = md_codegen_findmethod(ra);
230 #if defined(ENABLE_JIT)
231 # if defined(ENABLE_INTRP)
232 /* When using the interpreter, we pass RA to the function. */
236 # if defined(__I386__) || defined(__X86_64__)
237 /* On i386 and x86_64 we always have to get the return address
240 framesize = *((u4 *) (pv + FrameSize));
242 ra = md_stacktrace_get_returnaddress(sp, framesize);
244 /* If the method is a non-leaf function, we need to get the return
245 address from the stack. For leaf functions the return address
246 is set correctly. This makes the assembler and the signal
247 handler code simpler. */
249 isleafmethod = *((s4 *) (pv + IsLeaf));
252 framesize = *((u4 *) (pv + FrameSize));
254 ra = md_stacktrace_get_returnaddress(sp, framesize);
257 # if defined(ENABLE_INTRP)
260 #endif /* defined(ENABLE_JIT) */
262 /* fill new stackframe info structure */
271 /* store new stackframe info pointer */
277 /* stacktrace_create_native_stackframeinfo *************************************
279 Creates a stackframe info structure for a native stub.
281 *******************************************************************************/
283 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
286 stackframeinfo **psfi;
289 /* get methodinfo pointer from data segment */
291 m = *((methodinfo **) (pv + MethodPointer));
293 /* get current stackframe info pointer */
295 psfi = STACKFRAMEINFO;
297 /* fill new stackframe info structure */
306 /* store new stackframe info pointer */
312 /* stacktrace_remove_stackframeinfo ********************************************
316 *******************************************************************************/
318 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
320 stackframeinfo **psfi;
322 /* get current stackframe info pointer */
324 psfi = STACKFRAMEINFO;
326 /* restore the old pointer */
332 /* stacktrace_inline_arithmeticexception ***************************************
334 Creates an ArithemticException for inline stub.
336 *******************************************************************************/
338 java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
342 java_objectheader *o;
344 /* create stackframeinfo */
346 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
348 /* create exception */
350 o = new_arithmeticexception();
352 /* remove stackframeinfo */
354 stacktrace_remove_stackframeinfo(&sfi);
360 /* stacktrace_inline_arrayindexoutofboundsexception ****************************
362 Creates an ArrayIndexOutOfBoundsException for inline stub.
364 *******************************************************************************/
366 java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
373 java_objectheader *o;
375 /* create stackframeinfo */
377 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
379 /* create exception */
381 o = new_arrayindexoutofboundsexception(index);
383 /* remove stackframeinfo */
385 stacktrace_remove_stackframeinfo(&sfi);
391 /* stacktrace_inline_arraystoreexception ***************************************
393 Creates an ArrayStoreException for inline stub.
395 *******************************************************************************/
397 java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
401 java_objectheader *o;
403 /* create stackframeinfo */
405 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
407 /* create exception */
409 o = new_arraystoreexception();
411 /* remove stackframeinfo */
413 stacktrace_remove_stackframeinfo(&sfi);
419 /* stacktrace_inline_classcastexception ****************************************
421 Creates an ClassCastException for inline stub.
423 *******************************************************************************/
425 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
429 java_objectheader *o;
431 /* create stackframeinfo */
433 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
435 /* create exception */
437 o = new_classcastexception();
439 /* remove stackframeinfo */
441 stacktrace_remove_stackframeinfo(&sfi);
447 /* stacktrace_inline_nullpointerexception **************************************
449 Creates an NullPointerException for inline stub.
451 *******************************************************************************/
453 java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
457 java_objectheader *o;
459 /* create stackframeinfo */
461 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
463 /* create exception */
465 o = new_nullpointerexception();
467 /* remove stackframeinfo */
469 stacktrace_remove_stackframeinfo(&sfi);
475 /* stacktrace_hardware_arithmeticexception *************************************
477 Creates an ArithemticException for inline stub.
479 *******************************************************************************/
481 java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
485 java_objectheader *o;
487 /* create stackframeinfo */
489 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
491 /* create exception */
493 o = new_arithmeticexception();
495 /* remove stackframeinfo */
497 stacktrace_remove_stackframeinfo(&sfi);
503 /* stacktrace_hardware_nullpointerexception ************************************
505 Creates an NullPointerException for the SIGSEGV signal handler.
507 *******************************************************************************/
509 java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
513 java_objectheader *o;
515 /* create stackframeinfo */
517 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
519 /* create exception */
521 o = new_nullpointerexception();
523 /* remove stackframeinfo */
525 stacktrace_remove_stackframeinfo(&sfi);
531 /* stacktrace_inline_fillInStackTrace ******************************************
533 Fills in the correct stacktrace into an existing exception object
534 (this one is for inline exception stubs).
536 *******************************************************************************/
538 java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
542 java_objectheader *o;
545 /* create stackframeinfo */
547 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
553 /* clear exception */
555 *exceptionptr = NULL;
557 /* resolve methodinfo pointer from exception object */
559 m = class_resolvemethod(o->vftbl->class,
560 utf_fillInStackTrace,
561 utf_void__java_lang_Throwable);
565 ASM_CALLJAVAFUNCTION(m, o, NULL, NULL, NULL);
567 /* remove stackframeinfo */
569 stacktrace_remove_stackframeinfo(&sfi);
575 /* addEntry ********************************************************************
579 *******************************************************************************/
581 static void addEntry(stackTraceBuffer *buffer, methodinfo *method, u2 line)
583 if (buffer->size > buffer->full) {
584 stacktraceelement *tmp = &(buffer->start[buffer->full]);
586 tmp->method = method;
587 tmp->linenumber = line;
588 buffer->full = buffer->full + 1;
591 stacktraceelement *newBuffer;
594 (stacktraceelement *) malloc((buffer->size + BLOCK_SIZEINCREMENT) *
595 sizeof(stacktraceelement));
597 if (newBuffer == 0) {
598 log_text("OOM during stacktrace creation");
602 memcpy(newBuffer, buffer->start, buffer->size * sizeof(stacktraceelement));
603 if (buffer->needsFree)
606 buffer->start = newBuffer;
607 buffer->size = buffer->size + BLOCK_SIZEINCREMENT;
608 buffer->needsFree = 1;
610 addEntry(buffer, method, line);
615 /* stacktrace_fillInStackTrace_methodRecursive *********************************
619 *******************************************************************************/
621 static bool stacktrace_fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,
623 lineNumberTableEntry *lntentry,
628 lineNumberTableEntryInlineBegin *lntinline;
631 /* find the line number for the specified pc (going backwards) */
633 for (; lntsize > 0; lntsize--, lntentry--) {
634 /* did we reach the current line? */
636 if (pc >= lntentry->pc) {
637 /* check for special inline entries */
639 switch (lntentry->line) {
641 /* XXX TWISTI we have to think about this inline stuff again */
643 case -1: /* begin of inlined method */
644 lntinline = (lineNumberTableEntryInlineBegin *) (--lntentry);
646 lntsize--; lntsize--;
647 if (stacktrace_fillInStackTrace_methodRecursive(buffer,
653 addEntry(buffer, m, ilStart->lineNrOuter);
659 case -2: /* end of inlined method */
661 *entriesAhead = ahead;
667 addEntry(buffer, m, lntentry->line);
673 /* check if we are before the actual JIT code */
675 if ((ptrint) pc < (ptrint) m->entrypoint) {
676 dolog("Current pc before start of code: %p < %p", pc, m->entrypoint);
680 /* otherwise just add line 0 */
682 addEntry(buffer, m, 0);
688 /* stacktrace_fillInStackTrace_method ******************************************
692 *******************************************************************************/
694 static void stacktrace_fillInStackTrace_method(stackTraceBuffer *buffer,
695 methodinfo *method, u1 *pv,
698 ptrint lntsize; /* size of line number table */
699 u1 *lntstart; /* start of line number table */
700 lineNumberTableEntry *lntentry; /* points to last entry in the table */
702 /* get size of line number table */
704 lntsize = *((ptrint *) (pv + LineNumberTableSize));
705 lntstart = *((u1 **) (pv + LineNumberTableStart));
707 /* subtract the size of the line number entry of the structure, since the */
708 /* line number table start points to the pc */
710 lntentry = (lineNumberTableEntry *) (lntstart - SIZEOF_VOID_P);
713 /* this happens when an exception is thrown in the native stub */
715 addEntry(buffer, method, 0);
718 if (!stacktrace_fillInStackTrace_methodRecursive(buffer,
723 log_text("Trace point not found in suspected method");
730 /* cacao_stacktrace_fillInStackTrace *******************************************
734 *******************************************************************************/
736 bool cacao_stacktrace_fillInStackTrace(void **target,
737 CacaoStackTraceCollector coll,
738 threadobject* thread)
740 static bool cacao_stacktrace_fillInStackTrace(void **target,
741 CacaoStackTraceCollector coll)
745 stacktraceelement primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)];
746 stackTraceBuffer buffer;
756 /* prevent compiler warnings */
762 /* In most cases this should be enough -> one malloc less. I don't think */
763 /* temporary data should be allocated with the GC, only the result. */
765 buffer.needsFree = 0;
766 buffer.start = primaryBlock;
767 buffer.size = BLOCK_INITIALSIZE; /* *sizeof(stacktraceelement); */
770 /* the first element in the stackframe chain must always be a native */
771 /* stackframeinfo (VMThrowable.fillInStackTrace is a native function) */
775 sfi = *STACKFRAMEINFO; /* invocation from Throwable */
777 sfi = thread->info._stackframeinfo; /* invocation from JVMTI */
779 sfi = *STACKFRAMEINFO;
787 #define PRINTMETHODS 0
790 printf("\n\nfillInStackTrace start:\n");
794 /* loop while we have a method pointer (asm_calljavafunction has NULL) or */
795 /* there is a stackframeinfo in the chain */
800 /* m == NULL should only happen for the first time and inline */
801 /* stackframe infos, like from the exception stubs or the patcher */
805 /* for native stub stackframe infos, pv is always NULL */
807 if (sfi->pv == NULL) {
808 /* get methodinfo, sp and ra from the current stackframe info */
811 sp = sfi->sp; /* sp of parent Java function */
815 addEntry(&buffer, m, 0);
818 printf("ra=%p sp=%p, ", ra, sp);
819 utf_display_classname(m->class->name);
821 utf_display(m->name);
822 utf_display(m->descriptor);
823 printf(": native stub\n");
826 /* this is an native stub stackframe info, so we can get the */
827 /* parent pv from the return address (ICMD_INVOKE*) */
829 #if defined(ENABLE_INTRP)
831 pv = codegen_findmethod(ra);
835 #if defined(ENABLE_JIT)
836 pv = md_codegen_findmethod(ra);
840 /* get methodinfo pointer from parent data segment */
842 m = *((methodinfo **) (pv + MethodPointer));
845 /* Inline stackframe infos are special: they have a xpc of */
846 /* the actual exception position and the return address saved */
847 /* since an inline stackframe info can also be in a leaf */
848 /* method (no return address saved on stack!!!). */
849 /* ATTENTION: This one is also for hardware exceptions!!! */
851 /* get methodinfo, sp and ra from the current stackframe info */
853 m = sfi->method; /* m == NULL */
854 pv = sfi->pv; /* pv of parent Java function */
855 sp = sfi->sp; /* sp of parent Java function */
856 ra = sfi->ra; /* ra of parent Java function */
857 xpc = sfi->xpc; /* actual exception position */
860 printf("ra=%p sp=%p, ", ra, sp);
861 printf("NULL: inline stub\n");
865 /* get methodinfo from current Java method */
867 m = *((methodinfo **) (pv + MethodPointer));
869 /* if m == NULL, this is a asm_calljavafunction call */
873 printf("ra=%p sp=%p, ", ra, sp);
874 utf_display_classname(m->class->name);
876 utf_display(m->name);
877 utf_display(m->descriptor);
878 printf(": inline stub parent");
882 #if defined(ENABLE_INTRP)
886 /* add it to the stacktrace */
888 stacktrace_fillInStackTrace_method(&buffer, m, pv,
889 (u1 *) ((ptrint) xpc));
891 /* get the current stack frame size */
893 framesize = *((u4 *) (pv + FrameSize));
896 printf(", framsize=%d\n", framesize);
900 /* set stack pointer to stackframe of parent Java */
901 /* function of the current Java function */
903 #if defined(__I386__) || defined (__X86_64__)
904 sp += framesize + SIZEOF_VOID_P;
909 /* get data segment and methodinfo pointer from parent */
912 #if defined(ENABLE_JIT)
913 pv = md_codegen_findmethod(ra);
916 m = *((methodinfo **) (pv + MethodPointer));
918 #if defined(ENABLE_INTRP)
924 printf("ra=%p sp=%p, ", ra, sp);
925 printf("asm_calljavafunction\n");
931 /* get previous stackframeinfo in the chain */
937 printf("ra=%p sp=%p, ", ra, sp);
938 utf_display_classname(m->class->name);
940 utf_display(m->name);
941 utf_display(m->descriptor);
946 /* JIT method found, add it to the stacktrace (we subtract 1 from */
947 /* the return address since it points the the instruction after */
950 stacktrace_fillInStackTrace_method(&buffer, m, pv,
951 (u1 *) ((ptrint) ra) - 1);
953 /* get the current stack frame size */
955 framesize = *((u4 *) (pv + FrameSize));
958 printf(", framsize=%d\n", framesize);
962 /* get return address of current stack frame */
964 #if defined(ENABLE_JIT)
965 # if defined(ENABLE_INTRP)
967 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
970 ra = md_stacktrace_get_returnaddress(sp, framesize);
972 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
975 /* get data segment and methodinfo pointer from parent method */
977 #if defined(ENABLE_INTRP)
979 pv = codegen_findmethod(ra);
983 #if defined(ENABLE_JIT)
984 pv = md_codegen_findmethod(ra);
988 m = *((methodinfo **) (pv + MethodPointer));
992 #if defined(ENABLE_INTRP)
994 sp = *(u1 **)(sp - framesize);
998 #if defined(__I386__) || defined (__X86_64__)
999 sp += framesize + SIZEOF_VOID_P;
1008 result = coll(target, &buffer);
1010 if (buffer.needsFree)
1017 /* stackTraceCollector *********************************************************
1021 *******************************************************************************/
1023 bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
1025 static bool stackTraceCollector(void **target, stackTraceBuffer *buffer)
1028 stackTraceBuffer *dest;
1030 dest = *target = heap_allocate(sizeof(stackTraceBuffer) + buffer->full * sizeof(stacktraceelement), true, 0);
1035 memcpy(*target, buffer, sizeof(stackTraceBuffer));
1036 memcpy(dest + 1, buffer->start, buffer->full * sizeof(stacktraceelement));
1038 dest->needsFree = 0;
1039 dest->size = dest->full;
1040 dest->start = (stacktraceelement *) (dest + 1);
1046 bool cacao_stacktrace_NormalTrace(void **target)
1049 return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector, NULL);
1051 return cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector);
1058 static bool classContextCollector(void **target, stackTraceBuffer *buffer)
1060 java_objectarray *oa;
1061 stacktraceelement *current;
1062 stacktraceelement *start;
1067 size = buffer->full;
1070 for (i = 0; i < size; i++)
1071 if (buffer->start[i].method != 0)
1074 start = buffer->start;
1078 if (targetSize > 0) {
1079 if (start->method &&
1080 (start->method->class == class_java_lang_SecurityManager)) {
1086 oa = builtin_anewarray(targetSize, class_java_lang_Class);
1091 for(i = 0, current = start; i < targetSize; i++, current++) {
1092 if (!current->method) {
1097 oa->data[i] = (java_objectheader *) current->method->class;
1107 java_objectarray *cacao_createClassContextArray(void)
1109 java_objectarray *array = NULL;
1112 if (!cacao_stacktrace_fillInStackTrace((void **) &array,
1113 &classContextCollector, NULL))
1115 if (!cacao_stacktrace_fillInStackTrace((void **) &array,
1116 &classContextCollector))
1124 /* stacktrace_classLoaderCollector *********************************************
1128 *******************************************************************************/
1130 static bool stacktrace_classLoaderCollector(void **target,
1131 stackTraceBuffer *buffer)
1133 stacktraceelement *current;
1134 stacktraceelement *start;
1139 size = buffer->full;
1140 start = &(buffer->start[0]);
1142 for(i = 0, current = start; i < size; i++, current++) {
1143 m = current->method;
1148 if (m->class == class_java_security_PrivilegedAction) {
1153 if (m->class->classloader) {
1154 *target = (java_lang_ClassLoader *) m->class->classloader;
1165 /* cacao_currentClassLoader ****************************************************
1169 *******************************************************************************/
1171 java_objectheader *cacao_currentClassLoader(void)
1173 java_objectheader *header = NULL;
1177 if (!cacao_stacktrace_fillInStackTrace((void**)&header,
1178 &stacktrace_classLoaderCollector,
1181 if (!cacao_stacktrace_fillInStackTrace((void**)&header,
1182 &stacktrace_classLoaderCollector))
1190 static bool getStackCollector(void **target, stackTraceBuffer *buffer)
1192 java_objectarray *oa;
1193 java_objectarray *classes;
1194 java_objectarray *methodnames;
1195 java_lang_String *str;
1197 stacktraceelement *current;
1200 /* *result = (java_objectarray **) target; */
1202 size = buffer->full;
1204 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1209 classes = builtin_anewarray(size, class_java_lang_Class);
1214 methodnames = builtin_anewarray(size, class_java_lang_String);
1219 oa->data[0] = (java_objectheader *) classes;
1220 oa->data[1] = (java_objectheader *) methodnames;
1222 for (i = 0, current = &(buffer->start[0]); i < size; i++, current++) {
1223 c = current->method->class;
1225 classes->data[i] = (java_objectheader *) c;
1226 str = javastring_new(current->method->name);
1231 methodnames->data[i] = (java_objectheader *) str;
1240 java_objectarray *cacao_getStackForVMAccessController(void)
1242 java_objectarray *result = NULL;
1245 if (!cacao_stacktrace_fillInStackTrace((void **) &result,
1246 &getStackCollector,NULL))
1248 if (!cacao_stacktrace_fillInStackTrace((void **) &result,
1249 &getStackCollector))
1257 /* stacktrace_print_trace_from_buffer ******************************************
1259 Print the stacktrace of a given stackTraceBuffer with CACAO intern
1260 methods (no Java help). This method is used by
1261 stacktrace_dump_trace and builtin_trace_exception.
1263 *******************************************************************************/
1265 static void stacktrace_print_trace_from_buffer(stackTraceBuffer *stb)
1267 stacktraceelement *ste;
1273 for (i = 0; i < stb->size; i++, ste++) {
1277 utf_display_classname(m->class->name);
1279 utf_display(m->name);
1280 utf_display(m->descriptor);
1282 if (m->flags & ACC_NATIVE) {
1283 puts("(Native Method)");
1287 utf_display(m->class->sourcefile);
1288 printf(":%d)\n", (u4) ste->linenumber);
1292 /* just to be sure */
1298 /* stacktrace_dump_trace *******************************************************
1300 This method is call from signal_handler_sigusr1 to dump the
1301 stacktrace of the current thread to stdout.
1303 *******************************************************************************/
1305 void stacktrace_dump_trace(void)
1307 stackTraceBuffer *buffer;
1310 /* get thread stackframeinfo */
1312 info = &THREADINFO->_stackframeinfo;
1314 /* fill stackframeinfo structure */
1316 tmp.oldThreadspecificHeadValue = *info;
1317 tmp.addressOfThreadspecificHead = info;
1320 tmp.ra = _mc->gregs[REG_RIP];
1325 /* generate stacktrace */
1327 cacao_stacktrace_NormalTrace((void **) &buffer);
1329 /* print stacktrace */
1332 stacktrace_print_trace_from_buffer(buffer);
1335 puts("\t<<No stacktrace available>>");
1341 /* stacktrace_print_trace ******************************************************
1343 Print the stacktrace of a given exception. More or less a wrapper
1344 to stacktrace_print_trace_from_buffer.
1346 *******************************************************************************/
1348 void stacktrace_print_trace(java_objectheader *xptr)
1350 java_lang_Throwable *t;
1351 java_lang_VMThrowable *vmt;
1352 stackTraceBuffer *stb;
1354 t = (java_lang_Throwable *) xptr;
1356 /* now print the stacktrace */
1359 stb = (stackTraceBuffer *) vmt->vmData;
1361 stacktrace_print_trace_from_buffer(stb);
1366 * These are local overrides for various environment variables in Emacs.
1367 * Please do not remove this and leave it at the end of the file, where
1368 * Emacs will automagically detect them.
1369 * ---------------------------------------------------------------------
1372 * indent-tabs-mode: t