* Merged with default branch at rev 16f3633aaa5a.
[cacao.git] / src / vm / jit / arm / linux / md-os.c
1 /* src/vm/jit/arm/linux/md-os.c - machine dependent arm linux functions
2
3    Copyright (C) 1996-2005, 2006, 2007 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
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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32
33 #include "vm/types.h"
34
35 #include "vm/jit/arm/md-abi.h"
36
37 #define ucontext broken_glibc_ucontext
38 #define ucontext_t broken_glibc_ucontext_t
39 #include <ucontext.h>
40 #undef ucontext
41 #undef ucontext_t
42
43 typedef struct ucontext {
44    unsigned long     uc_flags;
45    struct ucontext  *uc_link;
46    stack_t           uc_stack;
47    struct sigcontext uc_mcontext;
48    sigset_t          uc_sigmask;
49 } ucontext_t;
50
51 #define scontext_t struct sigcontext
52
53 #if defined(ENABLE_THREADS)
54 # include "threads/native/threads.h"
55 #endif
56
57 #include "vm/exceptions.h"
58 #include "vm/signallocal.h"
59 #include "vm/stringlocal.h"
60
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/stacktrace.h"
63
64
65 /* md_signal_handler_sigsegv ***************************************************
66
67    Signal handler for hardware exceptions.
68
69 *******************************************************************************/
70
71 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
72 {
73         stackframeinfo  sfi;
74         ucontext_t     *_uc;
75         scontext_t     *_sc;
76         u1             *pv;
77         u1             *sp;
78         u1             *ra;
79         u1             *xpc;
80         u4              mcode;
81         intptr_t        addr;
82         int             type;
83         intptr_t        val;
84         void           *p;
85
86         _uc = (ucontext_t*) _p;
87         _sc = &_uc->uc_mcontext;
88
89         /* ATTENTION: glibc included messed up kernel headers we needed a
90            workaround for the ucontext structure. */
91
92         pv  = (u1 *) _sc->arm_ip;
93         sp  = (u1 *) _sc->arm_sp;
94         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
95         xpc = (u1 *) _sc->arm_pc;
96
97         /* get exception-throwing instruction */
98
99         if (xpc == NULL)
100                 vm_abort("md_signal_handler_sigsegv: the program counter is NULL");
101
102         mcode = *((s4 *) xpc);
103
104         /* this is a NullPointerException */
105
106         addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
107         type = EXCEPTION_HARDWARE_NULLPOINTER;
108         val  = 0;
109
110         if (addr != 0)
111                 vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", addr);
112
113         /* create stackframeinfo */
114
115         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
116
117         /* Handle the type. */
118
119         p = signal_handle(xpc, type, val);
120
121         /* remove stackframeinfo */
122
123         stacktrace_remove_stackframeinfo(&sfi);
124
125         /* set registers */
126
127         _sc->arm_r10 = (intptr_t) p;
128         _sc->arm_fp  = (intptr_t) xpc;
129         _sc->arm_pc  = (intptr_t) asm_handle_exception;
130 }
131
132
133 /* md_signal_handler_sigill ****************************************************
134
135    Illegal Instruction signal handler for hardware exception checks.
136
137 *******************************************************************************/
138
139 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
140 {
141         stackframeinfo  sfi;
142         ucontext_t     *_uc;
143         scontext_t     *_sc;
144         u1             *pv;
145         u1             *sp;
146         u1             *ra;
147         u1             *xpc;
148         u4              mcode;
149         int             type;
150         intptr_t        val;
151         void           *p;
152
153         _uc = (ucontext_t*) _p;
154         _sc = &_uc->uc_mcontext;
155
156         /* ATTENTION: glibc included messed up kernel headers we needed a
157            workaround for the ucontext structure. */
158
159         pv  = (u1 *) _sc->arm_ip;
160         sp  = (u1 *) _sc->arm_sp;
161         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
162         xpc = (u1 *) _sc->arm_pc;
163
164         /* get exception-throwing instruction */
165
166         mcode = *((u4 *) xpc);
167
168         /* check for undefined instruction we use */
169
170         if ((mcode & 0x0ff000f0) != 0x07f000f0)
171                 vm_abort("md_signal_handler_sigill: unknown illegal instruction");
172
173         type = (mcode >> 8) & 0x0fff;
174         val  = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
175
176         /* create stackframeinfo */
177
178         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
179
180         /* Handle the type. */
181
182         p = signal_handle(xpc, type, val);
183
184         /* remove stackframeinfo */
185
186         stacktrace_remove_stackframeinfo(&sfi);
187
188         /* set registers if we have an exception, return continue execution
189            otherwise (this is needed for patchers to work) */
190
191         if (p != NULL) {
192                 _sc->arm_r10 = (intptr_t) p;
193                 _sc->arm_fp  = (intptr_t) xpc;
194                 _sc->arm_pc  = (intptr_t) asm_handle_exception;
195         }
196 }
197
198
199 /* md_signal_handler_sigusr1 ***************************************************
200
201    Signal handler for suspending threads.
202
203 *******************************************************************************/
204
205 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
206 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
207 {
208         ucontext_t *_uc;
209         scontext_t *_sc;
210         u1         *pc;
211         u1         *sp;
212
213         _uc = (ucontext_t *) _p;
214         _sc = &_uc->uc_mcontext;
215
216         /* get the PC and SP for this thread */
217         pc = (u1 *) _sc->arm_pc;
218         sp = (u1 *) _sc->arm_sp;
219
220         /* now suspend the current thread */
221         threads_suspend_ack(pc, sp);
222 }
223 #endif
224
225
226 /* md_signal_handler_sigusr2 ***************************************************
227
228    Signal handler for profiling sampling.
229
230 *******************************************************************************/
231
232 #if defined(ENABLE_THREADS)
233 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
234 {
235         threadobject *thread;
236         ucontext_t   *_uc;
237         scontext_t   *_sc;
238         u1           *pc;
239
240         thread = THREADOBJECT;
241
242         _uc = (ucontext_t*) _p;
243         _sc = &_uc->uc_mcontext;
244
245         pc = (u1 *) _sc->arm_pc;
246
247         thread->pc = pc;
248 }
249 #endif
250
251
252 /* md_critical_section_restart *************************************************
253
254    Search the critical sections tree for a matching section and set
255    the PC to the restart point, if necessary.
256
257 *******************************************************************************/
258
259 #if defined(ENABLE_THREADS)
260 void md_critical_section_restart(ucontext_t *_uc)
261 {
262         scontext_t *_sc;
263         u1         *pc;
264         u1         *npc;
265
266         _sc = &_uc->uc_mcontext;
267
268         pc = (u1 *) _sc->arm_pc;
269
270         npc = critical_find_restart_point(pc);
271
272         if (npc != NULL)
273                 _sc->arm_pc = (ptrint) npc;
274 }
275 #endif
276
277
278 /*
279  * These are local overrides for various environment variables in Emacs.
280  * Please do not remove this and leave it at the end of the file, where
281  * Emacs will automagically detect them.
282  * ---------------------------------------------------------------------
283  * Local variables:
284  * mode: c
285  * indent-tabs-mode: t
286  * c-basic-offset: 4
287  * tab-width: 4
288  * End:
289  */
290