6205517b4454540f09b50dd188aa9a91c86f9e9d
[cacao.git] / src / vm / jit / stacktrace.c
1 /* src/vm/jit/stacktrace.c
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Joseph Wenninger
28
29    Changes: Christian Thalinger
30
31    $Id: stacktrace.c 2975 2005-07-10 22:20:21Z twisti $
32
33 */
34
35
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "config.h"
41 #include "asmoffsets.h"
42
43 #include "mm/boehm.h"
44 #include "native/native.h"
45
46 #include "vm/global.h"                   /* required here for native includes */
47 #include "native/include/java_lang_ClassLoader.h"
48
49 #include "toolbox/logging.h"
50 #include "vm/builtin.h"
51 #include "vm/class.h"
52 #include "vm/exceptions.h"
53 #include "vm/loader.h"
54 #include "vm/stringlocal.h"
55 #include "vm/tables.h"
56 #include "vm/jit/asmpart.h"
57 #include "vm/jit/codegen.inc.h"
58
59
60 #undef JWDEBUG
61 #undef JWDEBUG2
62 #undef JWDEBUG3
63
64 /*JoWenn: simplify collectors (trace doesn't contain internal methods)*/
65
66 /* the line number is only u2, but to avoid alignment problems it is made the same size as a native
67         pointer. In the structures where this is used, values of -1 or -2 have a special meainging, so
68         if java bytecode is ever extended to support more than 65535 lines/file, this could will have to
69         be changed.*/
70
71 #if defined(_ALPHA_) || defined(__X86_64__)
72         #define LineNumber u8
73 #else
74         #define LineNumber u4
75 #endif
76
77 typedef struct lineNumberTableEntry {
78 /* The special value of -1 means that a inlined function starts, a value of -2 means that an inlined function ends*/
79         LineNumber lineNr;
80         u1 *pc;
81 } lineNumberTableEntry;
82
83 typedef struct lineNumberTableEntryInlineBegin {
84 /*this should have the same layout and size as the lineNumberTableEntry*/
85         LineNumber lineNrOuter;
86         methodinfo *method;
87 } lineNumberTableEntryInlineBegin;
88
89
90 typedef void(*CacaoStackTraceCollector)(void **,stackTraceBuffer*);
91
92 #define BLOCK_INITIALSIZE 40
93 #define BLOCK_SIZEINCREMENT 40
94
95
96 /* stacktrace_create_inline_stackframeinfo *************************************
97
98    Creates an stackframe info structure for an inline exception.
99
100 *******************************************************************************/
101
102 void stacktrace_create_inline_stackframeinfo(stackframeinfo *sfi, u1 *pv,
103                                                                                          u1 *sp, functionptr ra)
104 {
105         void **osfi;
106
107         /* get current stackframe info pointer */
108
109         osfi = builtin_asm_get_stackframeinfo();
110
111         /* sometimes we don't have pv in asmpart.S handy */
112
113         if (pv == NULL)
114                 pv = (u1 *) (ptrint) codegen_findmethod(ra);
115
116         /* fill new stackframe info structure */
117
118         sfi->oldThreadspecificHeadValue = *osfi;
119         sfi->addressOfThreadspecificHead = osfi;
120         sfi->method = NULL;
121         sfi->pv = pv;
122         sfi->beginOfJavaStackframe = sp;
123         sfi->returnToFromNative = ra;
124
125         /* store new stackframe info pointer */
126
127         *osfi = sfi;
128 }
129
130
131 /* stacktrace_create_native_stackframeinfo *************************************
132
133    Creates a stackframe info structure for a native stub.
134
135 *******************************************************************************/
136
137 void stacktrace_create_native_stackframeinfo(stackframeinfo *sfi, u1 *pv,
138                                                                                          u1 *sp, functionptr ra)
139 {
140         void       **osfi;
141         methodinfo  *m;
142
143         /* get methodinfo pointer from data segment */
144
145         m = *((methodinfo **) (pv + MethodPointer));
146
147         /* get current stackframe info pointer */
148
149         osfi = builtin_asm_get_stackframeinfo();
150
151         /* fill new stackframe info structure */
152
153         sfi->oldThreadspecificHeadValue = *osfi;
154         sfi->addressOfThreadspecificHead = osfi;
155         sfi->method = m;
156         sfi->pv = NULL;
157         sfi->beginOfJavaStackframe = sp;
158         sfi->returnToFromNative = ra;
159
160         /* store new stackframe info pointer */
161
162         *osfi = sfi;
163 }
164
165
166 /* stacktrace_remove_stackframeinfo ********************************************
167
168    XXX
169
170 *******************************************************************************/
171
172 void stacktrace_remove_stackframeinfo(stackframeinfo *sfi)
173 {
174         void **osfi;
175
176         /* get address of pointer */
177
178         osfi = sfi->addressOfThreadspecificHead;
179
180         /* restore the old pointer */
181
182         *osfi = sfi->oldThreadspecificHeadValue;
183 }
184
185
186 /* stacktrace_new_arithmeticexception ******************************************
187
188    Creates an ArithemticException for inline stub.
189
190 *******************************************************************************/
191
192 java_objectheader *stacktrace_new_arithmeticexception(u1 *pv, u1 *sp,
193                                                                                                           functionptr ra)
194 {
195         stackframeinfo     sfi;
196         java_objectheader *o;
197
198         /* create stackframeinfo */
199
200         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
201
202         /* create exception */
203
204         o = new_arithmeticexception();
205
206         /* remove stackframeinfo */
207
208         stacktrace_remove_stackframeinfo(&sfi);
209
210         return o;
211 }
212
213
214 /* stacktrace_new_arrayindexoutofboundsexception *******************************
215
216    Creates an ArrayIndexOutOfBoundsException for inline stub.
217
218 *******************************************************************************/
219
220 java_objectheader *stacktrace_new_arrayindexoutofboundsexception(u1 *pv,
221                                                                                                                                  u1 *sp,
222                                                                                                                                  functionptr ra,
223                                                                                                                                  s4 index)
224 {
225         stackframeinfo     sfi;
226         java_objectheader *o;
227
228         /* create stackframeinfo */
229
230         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
231
232         /* create exception */
233
234         o = new_arrayindexoutofboundsexception(index);
235
236         /* remove stackframeinfo */
237
238         stacktrace_remove_stackframeinfo(&sfi);
239
240         return o;
241 }
242
243
244 /* stacktrace_new_arraystoreexception ******************************************
245
246    Creates an ArrayStoreException for inline stub.
247
248 *******************************************************************************/
249
250 java_objectheader *stacktrace_new_arraystoreexception(u1 *pv, u1 *sp,
251                                                                                                           functionptr ra)
252 {
253         stackframeinfo     sfi;
254         java_objectheader *o;
255
256         /* create stackframeinfo */
257
258         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
259
260         /* create exception */
261
262         o = new_arraystoreexception();
263
264         /* remove stackframeinfo */
265
266         stacktrace_remove_stackframeinfo(&sfi);
267
268         return o;
269 }
270
271
272 /* stacktrace_new_classcastexception *******************************************
273
274    Creates an ClassCastException for inline stub.
275
276 *******************************************************************************/
277
278 java_objectheader *stacktrace_new_classcastexception(u1 *pv, u1 *sp,
279                                                                                                          functionptr ra)
280 {
281         stackframeinfo     sfi;
282         java_objectheader *o;
283
284         /* create stackframeinfo */
285
286         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
287
288         /* create exception */
289
290         o = new_classcastexception();
291
292         /* remove stackframeinfo */
293
294         stacktrace_remove_stackframeinfo(&sfi);
295
296         return o;
297 }
298
299
300 /* stacktrace_new_negativearraysizeexception ***********************************
301
302    Creates an NegativeArraySizeException for inline stub.
303
304 *******************************************************************************/
305
306 java_objectheader *stacktrace_new_negativearraysizeexception(u1 *pv, u1 *sp,
307                                                                                                                          functionptr ra)
308 {
309         stackframeinfo     sfi;
310         java_objectheader *o;
311
312         /* create stackframeinfo */
313
314         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
315
316         /* create exception */
317
318         o = new_negativearraysizeexception();
319
320         /* remove stackframeinfo */
321
322         stacktrace_remove_stackframeinfo(&sfi);
323
324         return o;
325 }
326
327
328 /* stacktrace_new_nullpointerexception *****************************************
329
330    Creates an NullPointerException for inline stub.
331
332 *******************************************************************************/
333
334 java_objectheader *stacktrace_new_nullpointerexception(u1 *pv, u1 *sp,
335                                                                                                            functionptr ra)
336 {
337         stackframeinfo     sfi;
338         java_objectheader *o;
339
340         /* create stackframeinfo */
341
342         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
343
344         /* create exception */
345
346         o = new_nullpointerexception();
347
348         /* remove stackframeinfo */
349
350         stacktrace_remove_stackframeinfo(&sfi);
351
352         return o;
353 }
354
355
356 /* stacktrace_fillInStackTrace *************************************************
357
358    Fills in the correct stacktrace into an existing exception object.
359
360 *******************************************************************************/
361
362 java_objectheader *stacktrace_fillInStackTrace(u1 *pv, u1 *sp, functionptr ra)
363 {
364         stackframeinfo     sfi;
365         java_objectheader *o;
366         methodinfo        *m;
367
368         /* create stackframeinfo */
369
370         stacktrace_create_inline_stackframeinfo(&sfi, pv, sp, ra);
371
372         /* get exception */
373
374         o = *exceptionptr;
375
376         /* clear exception */
377
378         *exceptionptr = NULL;
379
380         /* resolve methodinfo pointer from exception object */
381
382         m = class_resolvemethod(o->vftbl->class,
383                                                         utf_fillInStackTrace,
384                                                         utf_void__java_lang_Throwable);
385
386         /* call function */
387
388         asm_calljavafunction(m, o, NULL, NULL, NULL);
389
390         /* remove stackframeinfo */
391
392         stacktrace_remove_stackframeinfo(&sfi);
393
394         return o;
395 }
396
397
398 static void addEntry(stackTraceBuffer* buffer,methodinfo*method ,LineNumber line) {
399         if (buffer->size>buffer->full) {
400                 stacktraceelement *tmp=&(buffer->start[buffer->full]);
401                 tmp->method=method;
402                 tmp->linenumber=line;
403                 buffer->full = buffer->full + 1;
404 #if (defined(JWDEBUG) || defined (JWDEBUG2))
405                 log_text("addEntry (stacktrace):");
406                 printf("method %p\n",method);
407                 if (method) printf("method->name %p\n",method->name);
408                 if (method) utf_display(method->name); else printf("Native");
409                 if (method) {printf("\n");utf_display(method->class->name);}
410                 printf("\nnext buffer item %d\nLine:%ld\n",buffer->full,line);
411 #endif
412         } else {
413                 stacktraceelement *newBuffer;
414
415 #ifdef JWDEBUG
416                 log_text("stacktrace buffer full, resizing");
417 #endif
418
419                 newBuffer =
420                         (stacktraceelement *) malloc((buffer->size + BLOCK_SIZEINCREMENT) *
421                                                                                  sizeof(stacktraceelement));
422
423                 if (newBuffer==0) {
424                         log_text("OOM during stacktrace creation");
425                         assert(0);
426                 }
427
428                 memcpy(newBuffer,buffer->start,buffer->size*sizeof(stacktraceelement));
429                 if (buffer->needsFree) free(buffer->start);
430                 buffer->start=newBuffer;
431                 buffer->size=buffer->size+BLOCK_SIZEINCREMENT;
432                 buffer->needsFree=1;
433                 addEntry(buffer,method,line);
434         }
435 }
436
437
438 /* stacktrace_fillInStackTrace_methodRecursive *********************************
439
440    XXX
441
442 *******************************************************************************/
443
444 static int stacktrace_fillInStackTrace_methodRecursive(stackTraceBuffer *buffer,
445                                                                                                            methodinfo *method,
446                                                                                                            lineNumberTableEntry *startEntry,
447                                                                                                            lineNumberTableEntry **entry,
448                                                                                                            size_t *entriesAhead,
449                                                                                                            u1 *address)
450 {
451
452         size_t ahead=*entriesAhead;
453         lineNumberTableEntry *ent=*entry;
454         lineNumberTableEntryInlineBegin *ilStart;
455
456         for (; ahead > 0; ahead--, ent++) {
457                 if (address >= ent->pc) {
458                         switch (ent->lineNr) {
459                         case -1: /* begin of inlined method */
460                                 ilStart=(lineNumberTableEntryInlineBegin*)(++ent);
461                                 ent ++;
462                                 ahead--; ahead--;
463                                 if (stacktrace_fillInStackTrace_methodRecursive(buffer,ilStart->method,ent,&ent,&ahead,address)) {
464                                         addEntry(buffer,method,ilStart->lineNrOuter);
465                                         return 1;
466                                 }
467                                 break;
468                         case -2: /* end of inlined method */
469                                 *entry=ent;
470                                 *entriesAhead=ahead;
471                                 return 0;
472                                 break;
473                         default:
474                                 if (address == ent->pc) {
475                                         addEntry(buffer, method, ent->lineNr);
476                                         return 1;
477                                 }
478                                 break;
479                         }
480
481                 } else {
482                         if (address > startEntry->pc) {
483                                 ent--;
484                                 addEntry(buffer, method, ent->lineNr);
485                                 return 1;
486
487                         } else {
488                                 printf("trace point: %p\n", address);
489                                 log_text("trace point before method");
490                                 assert(0);
491                         }
492                 }
493         }
494
495         ent--;
496         addEntry(buffer, method, ent->lineNr);
497         return 1;
498 }
499
500
501 /* stacktrace_fillInStackTrace_method ******************************************
502
503    XXX
504
505 *******************************************************************************/
506
507 static void stacktrace_fillInStackTrace_method(stackTraceBuffer *buffer,
508                                                                                            methodinfo *method, u1 *dataSeg,
509                                                                                            u1 *address)
510 {
511         size_t lineNumberTableSize=(*((size_t*)(dataSeg+LineNumberTableSize)));
512         lineNumberTableEntry *ent;
513         void **calc;
514         lineNumberTableEntry *startEntry;
515
516         if (lineNumberTableSize == 0) {
517                 /* right now this happens only on i386,if the native stub causes an */
518                 /* exception in a <clinit> invocation (jowenn) */
519
520                 addEntry(buffer, method, 0);
521                 return;
522
523         } else {
524                 calc = (void **) (dataSeg + LineNumberTableStart);
525                 ent = (lineNumberTableEntry *) (((char *) (*calc) - (sizeof(lineNumberTableEntry) - SIZEOF_VOID_P)));
526
527                 ent -= (lineNumberTableSize - 1);
528                 startEntry = ent;
529
530                 if (!stacktrace_fillInStackTrace_methodRecursive(buffer, method,
531                                                                                                                  startEntry, &ent,
532                                                                                                                  &lineNumberTableSize,
533                                                                                                                  address)) {
534                         log_text("Trace point not found in suspected method");
535                         assert(0);
536                 }
537         }
538 }
539
540
541 /* cacao_stacktrace_fillInStackTrace *******************************************
542
543    XXX
544
545 *******************************************************************************/
546
547 void cacao_stacktrace_fillInStackTrace(void **target,
548                                                                            CacaoStackTraceCollector coll)
549 {
550         stacktraceelement      primaryBlock[BLOCK_INITIALSIZE*sizeof(stacktraceelement)];
551         stackTraceBuffer  buffer;
552         stackframeinfo   *info;
553         methodinfo       *m;
554         u1               *pv;
555         u1               *sp;
556         u4                framesize;
557         functionptr       ra;
558
559
560         /* In most cases this should be enough -> one malloc less. I don't think  */
561         /* temporary data should be allocated with the GC, only the result.       */
562
563         buffer.needsFree = 0;
564         buffer.start = primaryBlock;
565         buffer.size = BLOCK_INITIALSIZE; /*  *sizeof(stacktraceelement); */
566         buffer.full = 0;
567
568         info = *((void **) builtin_asm_get_stackframeinfo());
569
570         if (!info) {
571                 *target = NULL;
572                 return;
573
574         } else {
575                 m = NULL;
576
577                 while (m || info) {
578                         /* some builtin native */
579
580                         if (m == NULL) {
581                                 m = info->method;
582                                 ra = (functionptr) info->returnToFromNative;
583
584 #if 0
585                                 if (m) {
586                                         utf_display_classname(m->class->name);
587                                         printf(".");
588                                         utf_display(m->name);
589                                         utf_display(m->descriptor);
590                                         printf(": native\n");
591
592                                         addEntry(&buffer, m, 0);
593                                 } else {
594                                         printf("NULL: native\n");
595                                 }
596 #else
597                                 if (m) {
598                                         addEntry(&buffer, m, 0);
599                                 }
600 #endif
601
602                                 /* get data segment address */
603
604                                 if (info->pv) {
605                                         /* this is an inline info */
606
607                                         pv = info->pv;
608
609                                 } else {
610                                         /* this is an native stub info */
611
612                                         pv = (u1 *) (ptrint) codegen_findmethod(ra);
613                                 }
614
615                                 /* get methodinfo pointer from data segment */
616
617                                 m = *((methodinfo **) (pv + MethodPointer));
618
619                                 /* get stackpointer from stackframeinfo structure */
620
621                                 sp = (u1 *) info->beginOfJavaStackframe;
622
623                                 info = info->oldThreadspecificHeadValue;
624
625                         } else {
626                                 /* JIT method */
627
628 #if 0
629                                 utf_display_classname(m->class->name);
630                                 printf(".");
631                                 utf_display(m->name);
632                                 utf_display(m->descriptor);
633                                 printf(": JIT\n");
634 #endif
635
636                                 /* add the current method to the stacktrace */
637
638                                 stacktrace_fillInStackTrace_method(&buffer, m, pv,
639                                                                                                    (u1 *) ((ptrint) ra) - 1);
640
641                                 /* get the current stack frame size */
642
643                                 framesize = *((u4 *) (pv + FrameSize));
644
645                                 /* get return address of current stack frame */
646
647                                 ra = md_stacktrace_get_returnaddress(sp, framesize);
648
649                                 /* get data segment and methodinfo pointer from parent method */
650
651                                 pv = (u1 *) (ptrint) codegen_findmethod(ra);
652                                 m = *((methodinfo **) (pv + MethodPointer));
653
654                                 /* walk the stack */
655
656 #if defined(__I386__) || defined (__X86_64__)
657                                 sp += framesize + SIZEOF_VOID_P;
658 #else
659                                 sp += framesize;
660 #endif
661                         }
662                 }
663                         
664                 if (coll)
665                         coll(target, &buffer);
666
667                 if (buffer.needsFree)
668                         free(buffer.start);
669
670                 return;
671         }
672
673         *target = NULL;
674 }
675
676
677 static
678 void stackTraceCollector(void **target, stackTraceBuffer *buffer) {
679         stackTraceBuffer *dest=*target=heap_allocate(sizeof(stackTraceBuffer)+buffer->full*sizeof(stacktraceelement),true,0);
680         memcpy(*target,buffer,sizeof(stackTraceBuffer));
681         memcpy(dest+1,buffer->start,buffer->full*sizeof(stacktraceelement));
682
683         dest->needsFree=0;
684         dest->size=dest->full;
685         dest->start=(stacktraceelement*)(dest+1);
686
687         /*
688         if (buffer->full>0) {
689                 printf("SOURCE BUFFER:%s\n",buffer->start[0].method->name->text);
690                 printf("DEST BUFFER:%s\n",dest->start[0].method->name->text);
691         } else printf("Buffer is empty\n");
692         */
693 }
694
695
696 void cacao_stacktrace_NormalTrace(void **target)
697 {
698         cacao_stacktrace_fillInStackTrace(target, &stackTraceCollector);
699 }
700
701
702
703 static void classContextCollector(void **target, stackTraceBuffer *buffer)
704 {
705         java_objectarray  *tmpArray;
706         stacktraceelement *current;
707         stacktraceelement *start;
708         size_t size;
709         size_t targetSize;
710         s4 i;
711
712         size = buffer->full;
713         targetSize = 0;
714
715         for (i = 0; i < size; i++)
716                 if (buffer->start[i].method != 0)
717                         targetSize++;
718
719         start = buffer->start;
720         start++;
721         targetSize--;
722
723         if (targetSize > 0) {
724                 if (start->method && (start->method->class == class_java_lang_SecurityManager)) {
725                         targetSize--;
726                         start++;
727                 }
728         }
729
730         tmpArray = builtin_anewarray(targetSize, class_java_lang_Class);
731
732         for(i = 0, current = start; i < targetSize; i++, current++) {
733                 /* XXX TWISTI: should we use this skipping for native stubs? */
734
735                 if (!current->method) {
736                         i--;
737                         continue;
738                 }
739
740                 use_class_as_object(current->method->class);
741
742                 tmpArray->data[i] = (java_objectheader *) current->method->class;
743         }
744
745         *target = tmpArray;
746 }
747
748
749
750 java_objectarray *cacao_createClassContextArray(void)
751 {
752         java_objectarray *array=0;
753
754         cacao_stacktrace_fillInStackTrace((void **) &array, &classContextCollector);
755
756         return array;
757 }
758
759
760 /* stacktrace_classLoaderCollector *********************************************
761
762    XXX
763
764 *******************************************************************************/
765
766 static void stacktrace_classLoaderCollector(void **target,
767                                                                                         stackTraceBuffer *buffer)
768 {
769         stacktraceelement *current;
770         stacktraceelement *start;
771         methodinfo        *m;
772         ptrint             size;
773         s4                 i;
774
775         size = buffer->full;
776         start = &(buffer->start[0]);
777
778         for(i = 0, current = start; i < size; i++, current++) {
779                 m = current->method;
780
781                 if (!m)
782                         continue;
783
784                 if (m->class == class_java_security_PrivilegedAction) {
785                         *target = NULL;
786                         return;
787                 }
788
789                 if (m->class->classloader) {
790                         *target = (java_lang_ClassLoader *) m->class->classloader;
791                         return;
792                 }
793         }
794
795         *target = NULL;
796 }
797
798
799 /* cacao_currentClassLoader ****************************************************
800
801    XXX
802
803 *******************************************************************************/
804
805 java_objectheader *cacao_currentClassLoader(void)
806 {
807         java_objectheader *header=0;
808
809         cacao_stacktrace_fillInStackTrace((void**)&header,
810                                                                           &stacktrace_classLoaderCollector);
811
812         return header;
813 }
814
815
816 static
817 void callingMethodCollector(void **target, stackTraceBuffer *buffer) {  
818         if (buffer->full >2) (*target)=buffer->start[2].method;
819         else (*target=0);
820 }
821
822 methodinfo *cacao_callingMethod() {
823         methodinfo *method;
824         cacao_stacktrace_fillInStackTrace((void**)&method,&callingMethodCollector);
825         return method;
826 }
827
828
829 static
830 void getStackCollector(void **target, stackTraceBuffer *buffer)
831 {
832         java_objectarray *classes;
833         java_objectarray *methodnames;
834         java_objectarray **result=(java_objectarray**)target;
835         java_lang_String *str;
836         classinfo *c;
837         stacktraceelement *current;
838         int i,size;
839
840         /*log_text("getStackCollector");*/
841
842         size = buffer->full;
843
844         *result = builtin_anewarray(2, arrayclass_java_lang_Object);
845
846         if (!(*result))
847                 return;
848
849         classes = builtin_anewarray(size, class_java_lang_Class);
850
851         if (!classes)
852                 return;
853
854         methodnames = builtin_anewarray(size, class_java_lang_String);
855
856         if (!methodnames)
857                 return;
858
859         (*result)->data[0] = (java_objectheader *) classes;
860         (*result)->data[1] = (java_objectheader *) methodnames;
861
862         /*log_text("Before for loop");*/
863         for (i = 0, current = &(buffer->start[0]); i < size; i++, current++) {
864                 /*log_text("In loop");*/
865                 c = current->method->class;
866                 use_class_as_object(c);
867                 classes->data[i] = (java_objectheader *) c;
868                 str = javastring_new(current->method->name);
869                 if (!str)
870                         return;
871                 methodnames->data[i] = (java_objectheader *) str;
872                 /*printf("getStackCollector: %s.%s\n",c->name->text,current->method->name->text);*/
873         }
874
875         /*if (*exceptionptr) panic("Exception in getStackCollector");*/
876
877         /*log_text("loop left");*/
878         return;
879
880 }
881
882
883 java_objectarray *cacao_getStackForVMAccessController(void)
884 {
885         java_objectarray *result = NULL;
886
887         cacao_stacktrace_fillInStackTrace((void **) &result, &getStackCollector);
888
889         return result;
890 }
891
892
893 /* stacktrace_dump_trace *******************************************************
894
895    This method is call from signal_handler_sigusr1 to dump the
896    stacktrace of the current thread to stdout.
897
898 *******************************************************************************/
899
900 void stacktrace_dump_trace(void)
901 {
902         stackTraceBuffer      *buffer;
903         stacktraceelement     *element;
904         methodinfo            *m;
905         s4                     i;
906
907 #if 0
908         /* get thread stackframeinfo */
909
910         info = &THREADINFO->_stackframeinfo;
911
912         /* fill stackframeinfo structure */
913
914         tmp.oldThreadspecificHeadValue = *info;
915         tmp.addressOfThreadspecificHead = info;
916         tmp.method = NULL;
917         tmp.beginOfJavaStackframe = NULL;
918         tmp.returnToFromNative = _mc->gregs[REG_RIP];
919
920         *info = &tmp;
921 #endif
922
923         /* generate stacktrace */
924
925         cacao_stacktrace_NormalTrace((void **) &buffer);
926
927         /* print stacktrace */
928
929         if (buffer) {
930                 element = buffer->start;
931
932                 for (i = 0; i < buffer->size; i++, element++) {
933                         m = element->method;
934
935                         printf("\tat ");
936                         utf_display_classname(m->class->name);
937                         printf(".");
938                         utf_display(m->name);
939                         utf_display(m->descriptor);
940
941                         if (m->flags & ACC_NATIVE) {
942                                 printf("(Native Method)\n");
943
944                         } else {
945                                 printf("(");
946                                 utf_display(m->class->sourcefile);
947                                 printf(":%d)\n", (u4) element->linenumber);
948                         }
949                 }
950         }
951
952         /* flush stdout */
953
954         fflush(stdout);
955 }
956
957
958 /*
959  * These are local overrides for various environment variables in Emacs.
960  * Please do not remove this and leave it at the end of the file, where
961  * Emacs will automagically detect them.
962  * ---------------------------------------------------------------------
963  * Local variables:
964  * mode: c
965  * indent-tabs-mode: t
966  * c-basic-offset: 4
967  * tab-width: 4
968  * End:
969  */