1 /* src/vm/jit/stacktrace.c - machine independet stacktrace system
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Joseph Wenninger
29 Changes: Christian Thalinger
32 $Id: stacktrace.c 4457 2006-02-06 01:28:07Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
49 #include "vm/global.h" /* required here for native includes */
50 #include "native/include/java_lang_ClassLoader.h"
51 #include "native/include/java_lang_Throwable.h"
52 #include "native/include/java_lang_VMThrowable.h"
54 #if defined(USE_THREADS)
55 # if defined(NATIVE_THREADS)
56 # include "threads/native/threads.h"
58 # include "threads/green/threads.h"
61 # include "threads/none/threads.h"
64 #include "toolbox/logging.h"
65 #include "vm/builtin.h"
67 #include "vm/exceptions.h"
68 #include "vm/loader.h"
69 #include "vm/options.h"
70 #include "vm/stringlocal.h"
71 #include "vm/jit/asmpart.h"
72 #include "vm/jit/codegen-common.h"
73 #include "vm/jit/methodheader.h"
76 /* linenumbertable_entry ******************************************************/
78 /* Keep the type of line the same as the pointer type, otherwise we
79 run into alignment troubles (like on MIPS64). */
81 typedef struct linenumbertable_entry linenumbertable_entry;
83 struct linenumbertable_entry {
84 ptrint line; /* NOTE: see doc/inlining_stacktrace.txt for */
85 u1 *pc; /* special meanings of line and pc. */
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 stacktrace_create */
144 /* store new stackframe info pointer */
148 #endif /* defined(ENABLE_INTRP) */
151 /* stacktrace_create_inline_stackframeinfo *************************************
153 Creates an stackframe info structure for an inline exception stub.
155 *******************************************************************************/
157 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
158 u1 *sp, u1 *ra, u1 *xpc)
160 stackframeinfo **psfi;
162 /* get current stackframe info pointer */
164 psfi = STACKFRAMEINFO;
166 #if defined(ENABLE_INTRP)
168 /* if we don't have pv handy */
171 pv = codegen_findmethod(ra);
176 /* fill new stackframe info structure */
185 /* store new stackframe info pointer */
191 /* stacktrace_create_extern_stackframeinfo *************************************
193 Creates an stackframe info structure for an extern exception
194 (hardware or assembler).
196 *******************************************************************************/
198 void stacktrace_create_extern_stackframeinfo(stackframeinfo *sfi, u1 *pv,
199 u1 *sp, u1 *ra, u1 *xpc)
201 stackframeinfo **psfi;
202 #if !defined(__I386__) && !defined(__X86_64__)
205 #if defined(ENABLE_JIT)
209 /* get current stackframe info pointer */
211 psfi = STACKFRAMEINFO;
213 /* sometimes we don't have pv handy (e.g. in asmpart.S:
214 L_asm_call_jit_compiler_exception or in the interpreter). */
217 #if defined(ENABLE_INTRP)
219 pv = codegen_findmethod(ra);
223 #if defined(ENABLE_JIT)
224 pv = md_codegen_findmethod(ra);
229 #if defined(ENABLE_JIT)
230 # if defined(ENABLE_INTRP)
231 /* When using the interpreter, we pass RA to the function. */
235 # if defined(__I386__) || defined(__X86_64__)
236 /* On i386 and x86_64 we always have to get the return address
239 framesize = *((u4 *) (pv + FrameSize));
241 ra = md_stacktrace_get_returnaddress(sp, framesize);
243 /* If the method is a non-leaf function, we need to get the return
244 address from the stack. For leaf functions the return address
245 is set correctly. This makes the assembler and the signal
246 handler code simpler. */
248 isleafmethod = *((s4 *) (pv + IsLeaf));
251 framesize = *((u4 *) (pv + FrameSize));
253 ra = md_stacktrace_get_returnaddress(sp, framesize);
256 # if defined(ENABLE_INTRP)
259 #endif /* defined(ENABLE_JIT) */
261 /* fill new stackframe info structure */
270 /* store new stackframe info pointer */
276 /* stacktrace_create_native_stackframeinfo *************************************
278 Creates a stackframe info structure for a native stub.
280 *******************************************************************************/
282 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
285 stackframeinfo **psfi;
288 /* get methodinfo pointer from data segment */
290 m = *((methodinfo **) (pv + MethodPointer));
292 /* get current stackframe info pointer */
294 psfi = STACKFRAMEINFO;
296 /* fill new stackframe info structure */
305 /* store new stackframe info pointer */
311 /* stacktrace_remove_stackframeinfo ********************************************
315 *******************************************************************************/
317 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
319 stackframeinfo **psfi;
321 /* get current stackframe info pointer */
323 psfi = STACKFRAMEINFO;
325 /* restore the old pointer */
331 /* stacktrace_inline_arithmeticexception ***************************************
333 Creates an ArithemticException for inline stub.
335 *******************************************************************************/
337 java_objectheader *stacktrace_inline_arithmeticexception(u1 *pv, u1 *sp,
341 java_objectheader *o;
343 /* create stackframeinfo */
345 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
347 /* create exception */
349 o = new_arithmeticexception();
351 /* remove stackframeinfo */
353 stacktrace_remove_stackframeinfo(&sfi);
359 /* stacktrace_inline_arrayindexoutofboundsexception ****************************
361 Creates an ArrayIndexOutOfBoundsException for inline stub.
363 *******************************************************************************/
365 java_objectheader *stacktrace_inline_arrayindexoutofboundsexception(u1 *pv,
372 java_objectheader *o;
374 /* create stackframeinfo */
376 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
378 /* create exception */
380 o = new_arrayindexoutofboundsexception(index);
382 /* remove stackframeinfo */
384 stacktrace_remove_stackframeinfo(&sfi);
390 /* stacktrace_inline_arraystoreexception ***************************************
392 Creates an ArrayStoreException for inline stub.
394 *******************************************************************************/
396 java_objectheader *stacktrace_inline_arraystoreexception(u1 *pv, u1 *sp, u1 *ra,
400 java_objectheader *o;
402 /* create stackframeinfo */
404 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
406 /* create exception */
408 o = new_arraystoreexception();
410 /* remove stackframeinfo */
412 stacktrace_remove_stackframeinfo(&sfi);
418 /* stacktrace_inline_classcastexception ****************************************
420 Creates an ClassCastException for inline stub.
422 *******************************************************************************/
424 java_objectheader *stacktrace_inline_classcastexception(u1 *pv, u1 *sp, u1 *ra,
428 java_objectheader *o;
430 /* create stackframeinfo */
432 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
434 /* create exception */
436 o = new_classcastexception();
438 /* remove stackframeinfo */
440 stacktrace_remove_stackframeinfo(&sfi);
446 /* stacktrace_inline_nullpointerexception **************************************
448 Creates an NullPointerException for inline stub.
450 *******************************************************************************/
452 java_objectheader *stacktrace_inline_nullpointerexception(u1 *pv, u1 *sp,
456 java_objectheader *o;
458 /* create stackframeinfo */
460 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
462 /* create exception */
464 o = new_nullpointerexception();
466 /* remove stackframeinfo */
468 stacktrace_remove_stackframeinfo(&sfi);
474 /* stacktrace_hardware_arithmeticexception *************************************
476 Creates an ArithemticException for inline stub.
478 *******************************************************************************/
480 java_objectheader *stacktrace_hardware_arithmeticexception(u1 *pv, u1 *sp,
484 java_objectheader *o;
486 /* create stackframeinfo */
488 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
490 /* create exception */
492 o = new_arithmeticexception();
494 /* remove stackframeinfo */
496 stacktrace_remove_stackframeinfo(&sfi);
502 /* stacktrace_hardware_nullpointerexception ************************************
504 Creates an NullPointerException for the SIGSEGV signal handler.
506 *******************************************************************************/
508 java_objectheader *stacktrace_hardware_nullpointerexception(u1 *pv, u1 *sp,
512 java_objectheader *o;
514 /* create stackframeinfo */
516 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
518 /* create exception */
520 o = new_nullpointerexception();
522 /* remove stackframeinfo */
524 stacktrace_remove_stackframeinfo(&sfi);
530 /* stacktrace_inline_fillInStackTrace ******************************************
532 Fills in the correct stacktrace into an existing exception object
533 (this one is for inline exception stubs).
535 *******************************************************************************/
537 java_objectheader *stacktrace_inline_fillInStackTrace(u1 *pv, u1 *sp, u1 *ra,
541 java_objectheader *o;
544 /* create stackframeinfo */
546 stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra, xpc);
552 /* clear exception */
554 *exceptionptr = NULL;
556 /* resolve methodinfo pointer from exception object */
558 m = class_resolvemethod(o->vftbl->class,
559 utf_fillInStackTrace,
560 utf_void__java_lang_Throwable);
564 ASM_CALLJAVAFUNCTION(m, o, NULL, NULL, NULL);
566 /* remove stackframeinfo */
568 stacktrace_remove_stackframeinfo(&sfi);
574 /* stacktrace_add_entry ********************************************************
576 Adds a new entry to the stacktrace buffer.
578 *******************************************************************************/
580 static void stacktrace_add_entry(stacktracebuffer *stb, methodinfo *m, u2 line)
582 stacktrace_entry *ste;
584 /* check if we already reached the buffer capacity */
586 if (stb->used >= stb->capacity) {
587 /* reallocate new memory */
589 stb->entries = DMREALLOC(stb->entries, stacktrace_entry, stb->capacity,
590 stb->capacity + STACKTRACE_CAPACITY_INCREMENT);
592 /* set new buffer capacity */
594 stb->capacity = stb->capacity + STACKTRACE_CAPACITY_INCREMENT;
597 /* insert the current entry */
599 ste = &(stb->entries[stb->used]);
602 ste->linenumber = line;
604 /* increase entries used count */
610 /* stacktrace_add_method_intern ************************************************
612 This function is used by stacktrace_add_method to search the line number
613 table for the line corresponding to a given pc. The function recurses for
616 *******************************************************************************/
618 static bool stacktrace_add_method_intern(stacktracebuffer *stb,
620 linenumbertable_entry *lntentry,
624 linenumbertable_entry *lntinline; /* special entry for inlined method */
629 /* Find the line number for the specified PC (going backwards
630 in the linenumber table). The linenumber table size is zero
633 for (; lntsize > 0; lntsize--, lntentry--) {
635 /* did we reach the current line? */
636 /* Note: In case of inlining this may actually compare the pc against a */
637 /* methodinfo *, yielding a non-sensical result. This is no problem, */
638 /* however, as we ignore such entries in the switch below. This way we */
639 /* optimize for the common case (ie. a real pc in lntentry->pc). */
640 if (pc >= lntentry->pc) {
642 /* check for special inline entries */
643 /* (see doc/inlining_stacktrace.txt for details */
644 if ((s4)lntentry->line < 0) {
645 switch (lntentry->line) {
647 /* begin of inlined method (ie. INLINE_END instruction) */
649 lntinline = --lntentry; /* get entry with methodinfo * */
650 lntentry--; /* skip the special entry */
653 /* search inside the inlined method */
654 if (stacktrace_add_method_intern(
656 (methodinfo*) lntinline->pc,
661 /* the inlined method contained the pc */
662 assert(lntinline->line <= -3);
663 stacktrace_add_entry(stb, m, (-3) - lntinline->line);
666 /* pc was not in inlined method, continue search. */
667 /* Entries inside the inlined method will be skipped */
668 /* because their lntentry->pc is higher than pc. */
672 /* end of inlined method */
675 /* default: is only reached for an -3-line entry after a skipped */
676 /* -2 entry. We can safely ignore it and continue searching. */
680 /* found a normal entry */
681 stacktrace_add_entry(stb, m, lntentry->line);
691 /* stacktrace_add_method *******************************************************
693 Add stacktrace entries[1] for the given method to the stacktrace buffer.
696 stb.........stacktracebuffer to fill
697 m...........method for which entries should be created
698 pv..........pv of method
699 pc..........position of program counter within the method's code
702 true, if stacktrace entries were successfully created, false otherwise.
704 [1] In case of inlined methods there may be more than one stacktrace
705 entry for a codegen-level method. (see doc/inlining_stacktrace.txt)
707 *******************************************************************************/
709 static bool stacktrace_add_method(stacktracebuffer *stb, methodinfo *m, u1 *pv,
712 ptrint lntsize; /* size of line number table */
713 u1 *lntstart; /* start of line number table */
714 linenumbertable_entry *lntentry; /* points to last entry in the table */
716 /* get size of line number table */
718 lntsize = *((ptrint *) (pv + LineNumberTableSize));
719 lntstart = *((u1 **) (pv + LineNumberTableStart));
721 /* Subtract the size of the line number entry of the structure,
722 since the line number table start points to the pc. */
724 lntentry = (linenumbertable_entry *) (lntstart - SIZEOF_VOID_P);
726 /* check if we are before the actual JIT code */
728 if ((ptrint) pc < (ptrint) m->entrypoint) {
729 dolog("Current PC before start of code: %p < %p", pc, m->entrypoint);
733 /* search the line number table */
735 if (stacktrace_add_method_intern(stb, m, lntentry, lntsize, pc))
738 /* If we get here, just add the entry with line number 0. */
740 stacktrace_add_entry(stb, m, 0);
746 /* stacktrace_create ***********************************************************
748 Generates a stacktrace from the thread passed into a
749 stacktracebuffer. The stacktracebuffer is allocated on the GC
752 *******************************************************************************/
754 stacktracebuffer *stacktrace_create(threadobject* thread)
756 stacktracebuffer *stb;
757 stacktracebuffer *gcstb;
767 /* mark start of dump memory area */
769 dumpsize = dump_size();
771 /* prevent compiler warnings */
777 /* create a stacktracebuffer in dump memory */
779 stb = DNEW(stacktracebuffer);
781 stb->capacity = STACKTRACE_CAPACITY_DEFAULT;
783 stb->entries = DMNEW(stacktrace_entry, STACKTRACE_CAPACITY_DEFAULT);
785 /* The first element in the stackframe chain must always be a
786 native stackframeinfo (VMThrowable.fillInStackTrace is a native
789 #if defined(USE_THREADS)
790 sfi = thread->info._stackframeinfo;
792 sfi = _no_threads_stackframeinfo;
795 #define PRINTMETHODS 0
798 printf("\n\nfillInStackTrace start:\n");
802 /* Loop while we have a method pointer (asm_calljavafunction has
803 NULL) or there is a stackframeinfo in the chain. */
808 /* m == NULL should only happen for the first time and inline
809 stackframe infos, like from the exception stubs or the
813 /* for native stub stackframe infos, pv is always NULL */
815 if (sfi->pv == NULL) {
816 /* get methodinfo, sp and ra from the current stackframe info */
819 sp = sfi->sp; /* sp of parent Java function */
823 stacktrace_add_entry(stb, m, 0);
826 printf("ra=%p sp=%p, ", ra, sp);
828 printf(": native stub\n");
831 /* This is an native stub stackframe info, so we can
832 get the parent pv from the return address
835 #if defined(ENABLE_INTRP)
837 pv = codegen_findmethod(ra);
841 #if defined(ENABLE_JIT)
842 pv = md_codegen_findmethod(ra);
846 /* get methodinfo pointer from parent data segment */
848 m = *((methodinfo **) (pv + MethodPointer));
851 /* Inline stackframe infos are special: they have a
852 xpc of the actual exception position and the return
853 address saved since an inline stackframe info can
854 also be in a leaf method (no return address saved
855 on stack!!!). ATTENTION: This one is also for
856 hardware exceptions!!! */
858 /* get methodinfo, sp and ra from the current stackframe info */
860 m = sfi->method; /* m == NULL */
861 pv = sfi->pv; /* pv of parent Java function */
862 sp = sfi->sp; /* sp of parent Java function */
863 ra = sfi->ra; /* ra of parent Java function */
864 xpc = sfi->xpc; /* actual exception position */
867 printf("ra=%p sp=%p, ", ra, sp);
868 printf("NULL: inline stub\n");
872 /* get methodinfo from current Java method */
874 m = *((methodinfo **) (pv + MethodPointer));
876 /* if m == NULL, this is a asm_calljavafunction call */
880 printf("ra=%p sp=%p, ", ra, sp);
882 printf(": inline stub parent");
886 #if defined(ENABLE_INTRP)
890 /* add the method to the stacktrace */
892 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) xpc));
894 /* get the current stack frame size */
896 framesize = *((u4 *) (pv + FrameSize));
899 printf(", framesize=%d\n", framesize);
903 /* set stack pointer to stackframe of parent Java */
904 /* function of the current Java function */
906 #if defined(__I386__) || defined (__X86_64__)
907 sp += framesize + SIZEOF_VOID_P;
912 /* get data segment and methodinfo pointer from parent */
915 #if defined(ENABLE_JIT)
916 pv = md_codegen_findmethod(ra);
919 m = *((methodinfo **) (pv + MethodPointer));
921 #if defined(ENABLE_INTRP)
927 printf("ra=%p sp=%p, ", ra, sp);
928 printf("asm_calljavafunction\n");
934 /* get previous stackframeinfo in the chain */
940 printf("ra=%p sp=%p, ", ra, sp);
946 /* JIT method found, add it to the stacktrace (we subtract
947 1 from the return address since it points the the
948 instruction after call). */
950 stacktrace_add_method(stb, m, pv, (u1 *) ((ptrint) ra) - 1);
952 /* get the current stack frame size */
954 framesize = *((u4 *) (pv + FrameSize));
957 printf(", framesize=%d\n", framesize);
961 /* get return address of current stack frame */
963 #if defined(ENABLE_JIT)
964 # if defined(ENABLE_INTRP)
966 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
969 ra = md_stacktrace_get_returnaddress(sp, framesize);
971 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
974 /* get data segment and methodinfo pointer from parent method */
976 #if defined(ENABLE_INTRP)
978 pv = codegen_findmethod(ra);
982 #if defined(ENABLE_JIT)
983 pv = md_codegen_findmethod(ra);
987 m = *((methodinfo **) (pv + MethodPointer));
991 #if defined(ENABLE_INTRP)
993 sp = *(u1 **) (sp - framesize);
997 #if defined(__I386__) || defined (__X86_64__)
998 sp += framesize + SIZEOF_VOID_P;
1006 /* allocate memory from the GC heap and copy the stacktrace buffer */
1008 gcstb = GCNEW(stacktracebuffer);
1011 gcstb->capacity = stb->capacity;
1012 gcstb->used = stb->used;
1013 gcstb->entries = GCMNEW(stacktrace_entry, stb->used);
1015 MCOPY(gcstb->entries, stb->entries, stacktrace_entry, stb->used);
1017 /* just to be sure */
1020 assert(gcstb != NULL);
1022 /* release dump memory */
1024 dump_release(dumpsize);
1026 /* return the stacktracebuffer */
1032 /* stacktrace_fillInStackTrace *************************************************
1034 Generate a stacktrace from the current thread for
1035 java.lang.VMThrowable.fillInStackTrace.
1037 *******************************************************************************/
1039 stacktracebuffer *stacktrace_fillInStackTrace(void)
1041 stacktracebuffer *stb;
1043 /* create a stacktrace from the current thread */
1045 stb = stacktrace_create(THREADOBJECT);
1051 /* stacktrace_getClassContext **************************************************
1053 Creates a Class context array.
1055 *******************************************************************************/
1057 java_objectarray *stacktrace_getClassContext(void)
1059 stacktracebuffer *stb;
1060 stacktrace_entry *ste;
1061 java_objectarray *oa;
1065 /* create a stacktrace for the current thread */
1067 stb = stacktrace_create(THREADOBJECT);
1069 /* calculate the size of the Class array */
1071 for (i = 0, oalength = 0; i < stb->used; i++)
1072 if (stb->entries[i].method != NULL)
1075 ste = &(stb->entries[0]);
1079 /* XXX document me */
1083 (ste->method->class == class_java_lang_SecurityManager)) {
1089 /* allocate the Class array */
1091 oa = builtin_anewarray(oalength, class_java_lang_Class);
1096 /* fill the Class array from the stacktracebuffer */
1098 for(i = 0; i < oalength; i++, ste++) {
1099 if (ste->method == NULL) {
1104 oa->data[i] = (java_objectheader *) ste->method->class;
1111 /* stacktrace_getCurrentClassLoader ********************************************
1113 Find the current class loader by walking the stack trace. The first
1114 non-NULL (ie. non-bootstrap) class loader found -- starting with the
1115 innermost activation record -- is returned. If no class loader is
1116 found, NULL is returned.
1118 *******************************************************************************/
1120 java_objectheader *stacktrace_getCurrentClassLoader(void)
1122 stacktracebuffer *stb;
1123 stacktrace_entry *ste;
1125 java_objectheader *cl;
1130 /* create a stacktrace for the current thread */
1132 stb = stacktrace_create(THREADOBJECT);
1134 /* iterate over all stacktrace entries and find the first suitable
1137 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1143 if (m->class == class_java_security_PrivilegedAction) {
1148 if (m->class->classloader) {
1149 cl = m->class->classloader;
1154 /* return the classloader */
1160 /* stacktrace_getStack *********************************************************
1162 Create a 2-dimensional array for java.security.VMAccessControler.
1164 *******************************************************************************/
1166 java_objectarray *stacktrace_getStack(void)
1168 stacktracebuffer *stb;
1169 stacktrace_entry *ste;
1170 java_objectarray *oa;
1171 java_objectarray *classes;
1172 java_objectarray *methodnames;
1174 java_lang_String *str;
1177 /* create a stacktrace for the current thread */
1179 stb = stacktrace_create(THREADOBJECT);
1181 /* get the first stacktrace entry */
1183 ste = &(stb->entries[0]);
1185 /* allocate all required arrays */
1187 oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1192 classes = builtin_anewarray(stb->used, class_java_lang_Class);
1197 methodnames = builtin_anewarray(stb->used, class_java_lang_String);
1202 /* set up the 2-dimensional array */
1204 oa->data[0] = (java_objectheader *) classes;
1205 oa->data[1] = (java_objectheader *) methodnames;
1207 /* iterate over all stacktrace entries */
1209 for (i = 0, ste = &(stb->entries[0]); i < stb->used; i++, ste++) {
1210 c = ste->method->class;
1212 classes->data[i] = (java_objectheader *) c;
1213 str = javastring_new(ste->method->name);
1218 methodnames->data[i] = (java_objectheader *) str;
1221 /* return the 2-dimensional array */
1227 /* stacktrace_print_trace_from_buffer ******************************************
1229 Print the stacktrace of a given stacktracebuffer with CACAO intern
1230 methods (no Java help). This method is used by
1231 stacktrace_dump_trace and builtin_trace_exception.
1233 *******************************************************************************/
1235 static void stacktrace_print_trace_from_buffer(stacktracebuffer *stb)
1237 stacktrace_entry *ste;
1241 ste = &(stb->entries[0]);
1243 for (i = 0; i < stb->used; i++, ste++) {
1247 utf_display_classname(m->class->name);
1249 utf_display(m->name);
1250 utf_display(m->descriptor);
1252 if (m->flags & ACC_NATIVE) {
1253 puts("(Native Method)");
1257 utf_display(m->class->sourcefile);
1258 printf(":%d)\n", (u4) ste->linenumber);
1262 /* just to be sure */
1268 /* stacktrace_dump_trace *******************************************************
1270 This method is call from signal_handler_sigusr1 to dump the
1271 stacktrace of the current thread to stdout.
1273 *******************************************************************************/
1275 void stacktrace_dump_trace(void)
1277 stacktracebuffer *stb;
1280 /* get methodinfo pointer from data segment */
1282 m = *((methodinfo **) (pv + MethodPointer));
1284 /* get current stackframe info pointer */
1286 psfi = STACKFRAMEINFO;
1288 /* fill new stackframe info structure */
1296 /* store new stackframe info pointer */
1301 /* create a stacktrace for the current thread */
1303 stb = stacktrace_create(THREADOBJECT);
1305 /* print stacktrace */
1308 stacktrace_print_trace_from_buffer(stb);
1311 puts("\t<<No stacktrace available>>");
1317 /* stacktrace_print_trace ******************************************************
1319 Print the stacktrace of a given exception. More or less a wrapper
1320 to stacktrace_print_trace_from_buffer.
1322 *******************************************************************************/
1324 void stacktrace_print_trace(java_objectheader *xptr)
1326 java_lang_Throwable *t;
1327 java_lang_VMThrowable *vmt;
1328 stacktracebuffer *stb;
1330 t = (java_lang_Throwable *) xptr;
1335 /* now print the stacktrace */
1338 stb = (stacktracebuffer *) vmt->vmData;
1340 stacktrace_print_trace_from_buffer(stb);
1345 * These are local overrides for various environment variables in Emacs.
1346 * Please do not remove this and leave it at the end of the file, where
1347 * Emacs will automagically detect them.
1348 * ---------------------------------------------------------------------
1351 * indent-tabs-mode: t
1355 * vim:noexpandtab:sw=4:ts=4: