first part of stacktraces on x86_64
[cacao.git] / src / native / vm / VMThrowable.c
1 /* src/native/vm/VMThrowable.c - java/lang/VMThrowable
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: VMThrowable.c 2358 2005-04-22 22:01:51Z jowenn $
32
33 */
34
35
36 #include "native/jni.h"
37 #include "native/native.h"
38 #include "native/include/java_lang_Class.h"
39 #include "native/include/java_lang_Throwable.h"
40 #include "native/include/java_lang_VMClass.h"
41 #include "native/include/java_lang_VMThrowable.h"
42 #include "vm/builtin.h"
43 #include "vm/class.h"
44 #include "vm/loader.h"
45 #include "vm/stringlocal.h"
46 #include "vm/tables.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/stacktrace.h"
49
50
51 /*
52  * Class:     java/lang/VMThrowable
53  * Method:    fillInStackTrace
54  * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
55  */
56 JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, java_lang_Throwable *par1)
57 {
58         java_lang_VMThrowable *vmthrow;
59
60         vmthrow = (java_lang_VMThrowable *) native_new_and_init(class_java_lang_VMThrowable);
61
62         if (!vmthrow)
63                 panic("Needed instance of class  java.lang.VMThrowable could not be created");
64
65 #if defined(__I386__) || defined(__ALPHA__) || defined(__X86_64__)
66         cacao_stacktrace_NormalTrace(&(vmthrow->vmData));
67 #endif
68         return vmthrow;
69 }
70
71
72 static
73 java_objectarray* generateStackTraceArray(JNIEnv *env,stacktraceelement *el,long size)
74 {
75         long resultPos;
76         methodinfo *m;
77         classinfo *c;
78         java_objectarray *oa;
79
80         if (!load_class_bootstrap(utf_new_char("java/lang/StackTraceElement"),&c))
81                 return NULL;
82         if (!c->linked)
83                 if (!link_class(c))
84                         return NULL;
85
86         m = class_findmethod(c,
87                                                  utf_init,
88                                                  utf_new_char("(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V"));
89
90         if (!m)
91                 panic("java.lang.StackTraceElement misses needed constructor"); 
92
93         oa = builtin_anewarray(size, c);
94
95         if (!oa)
96                 return 0;
97
98 /*      printf("Should return an array with %ld element(s)\n",size);*/
99         /*pos--;*/
100         
101         for(resultPos=0;size>0;size--,el++,resultPos++) {
102                 java_objectheader *element;
103
104                 if (el->method==0) {
105                         resultPos--;
106                         continue;
107                 }
108
109                 element=builtin_new(c);
110                 if (!element) {
111                         panic("Memory for stack trace element could not be allocated");
112                 }
113 #ifdef __GNUC__
114 #warning call constructor once jni is fixed to allow more than three parameters
115 #endif
116 #if 0
117                 (*env)->CallVoidMethod(env,element,m,
118                         javastring_new(el->method->class->sourcefile),
119                         source[size].linenumber,
120                         javastring_new(el->method->class->name),
121                         javastring_new(el->method->name),
122                         el->method->flags & ACC_NATIVE);
123 #else
124                 if (!(el->method->flags & ACC_NATIVE))setfield_critical(c,element,"fileName",          
125                 "Ljava/lang/String;",  jobject, 
126                 (jobject) javastring_new(el->method->class->sourcefile));
127 /*              setfield_critical(c,element,"className",          "Ljava/lang/String;",  jobject,  */
128 /*              (jobject) javastring_new(el->method->class->name)); */
129                 setfield_critical(c,element,"declaringClass",          "Ljava/lang/String;",  jobject, 
130                 (jobject) Java_java_lang_VMClass_getName(env, NULL, (java_lang_Class *) el->method->class));
131                 setfield_critical(c,element,"methodName",          "Ljava/lang/String;",  jobject, 
132                 (jobject) javastring_new(el->method->name));
133                 setfield_critical(c,element,"lineNumber",          "I",  jint, 
134                 (jint) ((el->method->flags & ACC_NATIVE) ? -1:(el->linenumber)));
135                 setfield_critical(c,element,"isNative",          "Z",  jboolean, 
136                 (jboolean) ((el->method->flags & ACC_NATIVE) ? 1:0));
137
138
139 #endif                  
140
141                 oa->data[resultPos]=element;
142         }
143
144         return oa;
145
146 }
147
148
149 /*
150  * Class:     java/lang/VMThrowable
151  * Method:    getStackTrace
152  * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
153  */
154 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *par1)
155 {
156 #if defined(__I386__) || defined(__ALPHA__) || defined (__x86_64__)
157         stackTraceBuffer *buf=(stackTraceBuffer*)this->vmData;
158         u8 size;
159         stacktraceelement *el;
160         classinfo  *excClass=par1->header.vftbl->class;
161         long destElementCount;
162         stacktraceelement *tmpEl;
163
164         if (!buf) panic("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code");
165         
166         size=buf->full;
167         if (size<2) panic("Invalid java.lang.VMThrowable.vmData field in java.lang.VMThrowable.getStackTrace native code (length<2)");
168         size -=2;
169         el=&(buf->start[2]); /* element 0==VMThrowable.fillInStackTrace native call, 1==Throwable.fillInStackTrace*/
170         if (size && el->method!=0) { /* => not a builtin native wrapper*/
171                 if ((el->method->class->name == utf_java_lang_Throwable) &&
172                         (el->method->name == utf_init)) {
173                         /* We assume that we are within the initializer of the exception object, the exception object itself should not appear
174                                 in the stack trace, so we skip till we reach the first function, which is not an init function or till we reach the exception object class*/
175                         for (; (size>0) && (el->method->name == utf_init) && (el->method->class!=excClass); el++, size--) {
176                                 /* just loop*/
177                         }
178                         size --;
179                         el++;
180                         /*if (size<1) {
181                                 log_text("Invalid stacktrace for VMThrowable.getStackTrace()");
182                         }*/
183                 }
184         }
185
186         
187         for (destElementCount = 0, tmpEl=el; size>0; size--,tmpEl++) {
188                 if (tmpEl->method!=0) destElementCount++;
189         }
190
191         return generateStackTraceArray(env,el,destElementCount);
192 #else
193         return 0;
194 #endif
195 }
196
197
198 /*
199  * These are local overrides for various environment variables in Emacs.
200  * Please do not remove this and leave it at the end of the file, where
201  * Emacs will automagically detect them.
202  * ---------------------------------------------------------------------
203  * Local variables:
204  * mode: c
205  * indent-tabs-mode: t
206  * c-basic-offset: 4
207  * tab-width: 4
208  * End:
209  */