* src/vmcore/linker.c (build_display_inner): Use MNEW instead of malloc.
[cacao.git] / src / vm / jit / trap.c
1 /* src/vm/jit/trap.c - hardware traps
2
3    Copyright (C) 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29
30 /* Include machine dependent trap stuff. */
31
32 #include "md-trap.h"
33
34 #include "native/llni.h"
35
36 #include "toolbox/logging.h"
37
38 #include "vm/exceptions.h"
39 #include "vm/vm.h"
40
41 #include "vm/jit/code.h"
42 #include "vm/jit/disass.h"
43 #include "vm/jit/jit.h"
44 #include "vm/jit/methodtree.h"
45 #include "vm/jit/patcher-common.h"
46 #include "vm/jit/replace.h"
47 #include "vm/jit/stacktrace.h"
48
49 #include "vmcore/options.h"
50 #include "vmcore/system.h"
51
52
53 /**
54  * Mmap the first memory page to support hardware exceptions and check
55  * the maximum hardware trap displacement on the architectures where
56  * it is required (TRAP_INSTRUCTION_IS_LOAD defined to 1).
57  */
58 void trap_init(void)
59 {
60 #if !(defined(__ARM__) && defined(__LINUX__))
61         /* On arm-linux the first memory page can't be mmap'ed, as it
62            contains the exception vectors. */
63
64         int pagesize;
65
66         /* mmap a memory page at address 0x0, so our hardware-exceptions
67            work. */
68
69         pagesize = system_getpagesize();
70
71         (void) system_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
72 #endif
73
74         TRACESUBSYSTEMINITIALIZATION("trap_init");
75
76 #if !defined(TRAP_INSTRUCTION_IS_LOAD)
77 # error TRAP_INSTRUCTION_IS_LOAD is not defined in your md-trap.h
78 #endif
79
80 #if TRAP_INSTRUCTION_IS_LOAD == 1
81         /* Check if we get into trouble with our hardware-exceptions. */
82
83         if (TRAP_END > OFFSET(java_bytearray_t, data))
84                 vm_abort("trap_init: maximum hardware trap displacement is greater than the array-data offset: %d > %d", TRAP_END, OFFSET(java_bytearray_t, data));
85 #endif
86 }
87
88
89 /**
90  * Handles the signal which is generated by trap instructions, caught
91  * by a signal handler and calls the correct function.
92  *
93  * @param type trap number
94  * @param 
95  */
96 void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context)
97 {
98         stackframeinfo_t  sfi;
99         int32_t           index;
100         java_handle_t    *o;
101         methodinfo       *m;
102         java_handle_t    *p;
103
104 #if !defined(NDEBUG)
105         if (opt_TraceTraps)
106                 log_println("[signal_handle: trap %d]", type);
107 #endif
108         
109 #if defined(ENABLE_VMLOG)
110         vmlog_cacao_signl_type(type);
111 #endif
112
113         /* Prevent compiler warnings. */
114
115         o = NULL;
116         m = NULL;
117
118         /* wrap the value into a handle if it is a reference */
119         /* BEFORE: creating stackframeinfo */
120
121         switch (type) {
122         case TRAP_ClassCastException:
123                 o = LLNI_WRAP((java_object_t *) val);
124                 break;
125
126         case TRAP_COMPILER:
127                 /* In this case the passed PV points to the compiler stub.  We
128                    get the methodinfo pointer here and set PV to NULL so
129                    stacktrace_stackframeinfo_add determines the PV for the
130                    parent Java method. */
131
132                 m  = code_get_methodinfo_for_pv(pv);
133                 pv = NULL;
134                 break;
135
136         default:
137                 /* do nothing */
138                 break;
139         }
140
141         /* Fill and add a stackframeinfo. */
142
143         stacktrace_stackframeinfo_add(&sfi, pv, sp, ra, xpc);
144
145         switch (type) {
146         case TRAP_NullPointerException:
147                 p = exceptions_new_nullpointerexception();
148                 break;
149
150         case TRAP_ArithmeticException:
151                 p = exceptions_new_arithmeticexception();
152                 break;
153
154         case TRAP_ArrayIndexOutOfBoundsException:
155                 index = (s4) val;
156                 p = exceptions_new_arrayindexoutofboundsexception(index);
157                 break;
158
159         case TRAP_ArrayStoreException:
160                 p = exceptions_new_arraystoreexception();
161                 break;
162
163         case TRAP_ClassCastException:
164                 p = exceptions_new_classcastexception(o);
165                 break;
166
167         case TRAP_CHECK_EXCEPTION:
168                 p = exceptions_fillinstacktrace();
169                 break;
170
171         case TRAP_PATCHER:
172 #if defined(ENABLE_REPLACEMENT)
173                 if (replace_me_wrapper(xpc, context)) {
174                         p = NULL;
175                         break;
176                 }
177 #endif
178                 p = patcher_handler(xpc);
179                 break;
180
181         case TRAP_COMPILER:
182                 p = jit_compile_handle(m, sfi.pv, ra, (void *) val);
183                 break;
184
185         default:
186                 /* Let's try to get a backtrace. */
187
188                 (void) methodtree_find(xpc);
189
190                 /* If that does not work, print more debug info. */
191
192                 log_println("signal_handle: unknown hardware exception type %d", type);
193
194 #if SIZEOF_VOID_P == 8
195                 log_println("PC=0x%016lx", xpc);
196 #else
197                 log_println("PC=0x%08x", xpc);
198 #endif
199
200 #if defined(ENABLE_DISASSEMBLER)
201                 log_println("machine instruction at PC:");
202                 disassinstr(xpc);
203 #endif
204
205                 vm_abort("Exiting...");
206
207                 /* keep compiler happy */
208
209                 p = NULL;
210         }
211
212         /* Remove stackframeinfo. */
213
214         stacktrace_stackframeinfo_remove(&sfi);
215
216         /* unwrap and return the exception object */
217         /* AFTER: removing stackframeinfo */
218
219         if (type == TRAP_COMPILER)
220                 return p;
221         else
222                 return LLNI_UNWRAP(p);
223 }
224
225
226 /*
227  * These are local overrides for various environment variables in Emacs.
228  * Please do not remove this and leave it at the end of the file, where
229  * Emacs will automagically detect them.
230  * ---------------------------------------------------------------------
231  * Local variables:
232  * mode: c
233  * indent-tabs-mode: t
234  * c-basic-offset: 4
235  * tab-width: 4
236  * End:
237  */