* src/vm/jit/patcher-common.c: Moved to .cpp.
[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, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #include "config.h"
28
29 #include <stdint.h>
30
31 #include "vm/types.h"
32
33 #include "vm/jit/disass.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 #include "threads/thread.hpp"
54
55 #include "vm/os.hpp"
56 #include "vm/signallocal.h"
57 #include "vm/vm.hpp"
58
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/executionstate.h"
61 #include "vm/jit/patcher-common.hpp"
62 #include "vm/jit/trap.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         ucontext_t     *_uc;
74         scontext_t     *_sc;
75         u1             *pv;
76         u1             *sp;
77         u1             *ra;
78         u1             *xpc;
79         u4              mcode;
80         intptr_t        addr;
81         int             type;
82         intptr_t        val;
83         void           *p;
84
85         _uc = (ucontext_t*) _p;
86         _sc = &_uc->uc_mcontext;
87
88         /* ATTENTION: glibc included messed up kernel headers we needed a
89            workaround for the ucontext structure. */
90
91         pv  = (u1 *) _sc->arm_ip;
92         sp  = (u1 *) _sc->arm_sp;
93         ra  = (u1 *) _sc->arm_lr;                    /* this is correct for leafs */
94         xpc = (u1 *) _sc->arm_pc;
95
96         /* get exception-throwing instruction */
97
98         if (xpc == NULL)
99                 vm_abort("md_signal_handler_sigsegv: the program counter is NULL");
100
101         mcode = *((s4 *) xpc);
102
103         /* This is a NullPointerException. */
104
105         addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
106         type = addr;
107         val  = 0;
108
109         /* Handle the trap. */
110
111         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
112
113         /* set registers */
114
115         _sc->arm_r10 = (uintptr_t) p;
116         _sc->arm_fp  = (uintptr_t) xpc;
117         _sc->arm_pc  = (uintptr_t) asm_handle_exception;
118 }
119
120
121 /* md_signal_handler_sigill ****************************************************
122
123    Illegal Instruction signal handler for hardware exception checks.
124
125 *******************************************************************************/
126
127 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
128 {
129         ucontext_t* _uc = (ucontext_t*) _p;
130         scontext_t* _sc = &_uc->uc_mcontext;
131
132         /* ATTENTION: glibc included messed up kernel headers we needed a
133            workaround for the ucontext structure. */
134
135         void* pv  = (void*) _sc->arm_ip;
136         void* sp  = (void*) _sc->arm_sp;
137         void* ra  = (void*) _sc->arm_lr; // The RA is correct for leaf methods.
138         void* xpc = (void*) _sc->arm_pc;
139
140         // Get the exception-throwing instruction.
141         uint32_t mcode = *((uint32_t*) xpc);
142
143         // Check if the trap instruction is valid.
144         // TODO Move this into patcher_handler.
145         if (patcher_is_valid_trap_instruction_at(xpc) == false) {
146                 // Check if the PC has been patched during our way to this
147                 // signal handler (see PR85).
148                 // NOTE: ARM uses SIGILL for other traps too, but it's OK to
149                 // do this check anyway because it will fail.
150                 if (patcher_is_patched_at(xpc) == true)
151                         return;
152
153                 // We have a problem...
154                 log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%x", mcode, xpc);
155 #if defined(ENABLE_DISASSEMBLER)
156                 (void) disassinstr(xpc);
157 #endif
158                 vm_abort("Aborting...");
159         }
160
161         int      type = (mcode >> 8) & 0x0fff;
162         intptr_t val  = *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
163
164         // Handle the trap.
165         void* p = trap_handle(type, val, pv, sp, ra, xpc, _p);
166
167         // Set registers if we have an exception, continue execution
168         // otherwise.
169         if (p != NULL) {
170                 _sc->arm_r10 = (uintptr_t) p;
171                 _sc->arm_fp  = (uintptr_t) xpc;
172                 _sc->arm_pc  = (uintptr_t) asm_handle_exception;
173         }
174 }
175
176
177 /* md_signal_handler_sigusr1 ***************************************************
178
179    Signal handler for suspending threads.
180
181 *******************************************************************************/
182
183 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
184 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
185 {
186         ucontext_t *_uc;
187         scontext_t *_sc;
188         u1         *pc;
189         u1         *sp;
190
191         _uc = (ucontext_t *) _p;
192         _sc = &_uc->uc_mcontext;
193
194         /* get the PC and SP for this thread */
195         pc = (u1 *) _sc->arm_pc;
196         sp = (u1 *) _sc->arm_sp;
197
198         /* now suspend the current thread */
199         threads_suspend_ack(pc, sp);
200 }
201 #endif
202
203
204 /* md_signal_handler_sigusr2 ***************************************************
205
206    Signal handler for profiling sampling.
207
208 *******************************************************************************/
209
210 #if defined(ENABLE_THREADS)
211 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
212 {
213         threadobject *thread;
214         ucontext_t   *_uc;
215         scontext_t   *_sc;
216         u1           *pc;
217
218         thread = THREADOBJECT;
219
220         _uc = (ucontext_t*) _p;
221         _sc = &_uc->uc_mcontext;
222
223         pc = (u1 *) _sc->arm_pc;
224
225         thread->pc = pc;
226 }
227 #endif
228
229
230 /**
231  * Read the given context into an executionstate.
232  *
233  * @param es      execution state
234  * @param context machine context
235  */
236 void md_executionstate_read(executionstate_t *es, void *context)
237 {
238         vm_abort("md_executionstate_read: IMPLEMENT ME!");
239
240 #if 0
241         ucontext_t *_uc;
242         mcontext_t *_mc;
243         int         i;
244
245         _uc = (ucontext_t *) context;
246         _mc = &_uc->uc_mcontext;
247
248         /* read special registers */
249         es->pc = (u1 *) _mc->sc_pc;
250         es->sp = (u1 *) _mc->sc_regs[REG_SP];
251         es->pv = (u1 *) _mc->sc_regs[REG_PV];
252         es->ra = (u1 *) _mc->sc_regs[REG_RA];
253
254         /* read integer registers */
255         for (i = 0; i < INT_REG_CNT; i++)
256                 es->intregs[i] = _mc->sc_regs[i];
257
258         /* read float registers */
259         /* Do not use the assignment operator '=', as the type of
260          * the _mc->sc_fpregs[i] can cause invalid conversions. */
261
262         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
263         os_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
264 #endif
265 }
266
267
268 /**
269  * Write the given executionstate back to the context.
270  *
271  * @param es      execution state
272  * @param context machine context
273  */
274 void md_executionstate_write(executionstate_t *es, void *context)
275 {
276         vm_abort("md_executionstate_write: IMPLEMENT ME!");
277
278 #if 0
279         ucontext_t *_uc;
280         mcontext_t *_mc;
281         int         i;
282
283         _uc = (ucontext_t *) context;
284         _mc = &_uc->uc_mcontext;
285
286         /* write integer registers */
287         for (i = 0; i < INT_REG_CNT; i++)
288                 _mc->sc_regs[i] = es->intregs[i];
289
290         /* write float registers */
291         /* Do not use the assignment operator '=', as the type of
292          * the _mc->sc_fpregs[i] can cause invalid conversions. */
293
294         assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
295         os_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
296
297         /* write special registers */
298         _mc->sc_pc           = (ptrint) es->pc;
299         _mc->sc_regs[REG_SP] = (ptrint) es->sp;
300         _mc->sc_regs[REG_PV] = (ptrint) es->pv;
301         _mc->sc_regs[REG_RA] = (ptrint) es->ra;
302 #endif
303 }
304
305
306 /*
307  * These are local overrides for various environment variables in Emacs.
308  * Please do not remove this and leave it at the end of the file, where
309  * Emacs will automagically detect them.
310  * ---------------------------------------------------------------------
311  * Local variables:
312  * mode: c
313  * indent-tabs-mode: t
314  * c-basic-offset: 4
315  * tab-width: 4
316  * End:
317  */
318