Merged with michi branch at rev 1684fe51cf3d.
[cacao.git] / src / vm / jit / i386 / solaris / md-os.c
1 /* src/vm/jit/i386/solaris/md-os.c - machine dependent i386 Solaris functions
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 #include <ucontext.h>
30
31 #include "vm/types.h"
32
33 #include "vm/jit/i386/codegen.h"
34 #include "vm/jit/i386/md.h"
35
36 #include "threads/thread.hpp"
37
38 #include "vm/jit/builtin.hpp"
39 #include "vm/signallocal.hpp"
40
41 #include "vm/jit/asmpart.h"
42 #include "vm/jit/executionstate.h"
43 #include "vm/jit/stacktrace.hpp"
44 #include "vm/jit/trap.hpp"
45
46
47 /* md_signal_handler_sigsegv ***************************************************
48
49    Signal handler for hardware exceptions.
50
51 *******************************************************************************/
52
53 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
54 {
55         ucontext_t     *_uc;
56         mcontext_t     *_mc;
57         u1             *pv;
58         u1             *sp;
59         u1             *ra;
60         u1             *xpc;
61         u1              opc;
62         u1              mod;
63         u1              rm;
64         s4              d;
65         s4              disp;
66         ptrint          val;
67         s4              type;
68         void           *p;
69
70         _uc = (ucontext_t *) _p;
71         _mc = &_uc->uc_mcontext;
72
73         pv  = NULL;                 /* is resolved during stackframeinfo creation */
74         sp  = (u1 *) _mc->gregs[ESP];
75         xpc = (u1 *) _mc->gregs[EIP];
76         ra  = xpc;                              /* return address is equal to XPC */
77
78         /* get exception-throwing instruction */
79
80         opc = M_ALD_MEM_GET_OPC(xpc);
81         mod = M_ALD_MEM_GET_MOD(xpc);
82         rm  = M_ALD_MEM_GET_RM(xpc);
83
84         /* for values see emit_mov_mem_reg and emit_mem */
85
86         if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
87                 /* this was a hardware-exception */
88
89                 d    = M_ALD_MEM_GET_REG(xpc);
90                 disp = M_ALD_MEM_GET_DISP(xpc);
91
92                 /* we use the exception type as load displacement */
93
94                 type = disp;
95
96                 /* ATTENTION: The _mc->gregs layout is completely crazy!  The
97                    registers are reversed starting with number 4 for REG_EDI
98                    (see /usr/include/sys/ucontext.h).  We have to convert that
99                    here. */
100
101                 val = _mc->gregs[EAX - d];
102
103                 if (type == TRAP_COMPILER) {
104                         /* The PV from the compiler stub is equal to the XPC. */
105
106                         pv = xpc;
107
108                         /* We use a framesize of zero here because the call pushed
109                            the return addres onto the stack. */
110
111                         ra = md_stacktrace_get_returnaddress(sp, 0);
112
113                         /* Skip the RA on the stack. */
114
115                         sp = sp + 1 * SIZEOF_VOID_P;
116
117                         /* The XPC is the RA minus 2, because the RA points to the
118                            instruction after the call. */
119
120                         xpc = ra - 2;
121                 }
122         }
123         else {
124                 /* this was a normal NPE */
125
126                 type = TRAP_NullPointerException;
127                 val  = 0;
128         }
129
130         /* Handle the trap. */
131
132         p = trap_handle(type, val, pv, sp, ra, xpc, _p);
133
134         /* Set registers. */
135
136         if (type == TRAP_COMPILER) {
137                 if (p == NULL) {
138                         _mc->gregs[ESP] = (uintptr_t) sp;    /* Remove RA from stack. */
139                 }
140         }
141 }
142
143
144 /* md_signal_handler_sigfpe ****************************************************
145
146    ArithmeticException signal handler for hardware divide by zero
147    check.
148
149 *******************************************************************************/
150
151 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
152 {
153         ucontext_t *_uc;
154         mcontext_t *_mc;
155         u1         *pv;
156         u1         *sp;
157         u1         *ra;
158         u1         *xpc;
159         s4          type;
160         ptrint      val;
161
162         _uc = (ucontext_t *) _p;
163         _mc = &_uc->uc_mcontext;
164
165         pv  = NULL;                 /* is resolved during stackframeinfo creation */
166         sp  = (u1 *) _mc->gregs[ESP];
167         xpc = (u1 *) _mc->gregs[EIP];
168         ra  = xpc;                          /* return address is equal to xpc     */
169
170         /* This is an ArithmeticException. */
171
172         type = TRAP_ArithmeticException;
173         val  = 0;
174
175         /* Handle the trap. */
176
177         trap_handle(type, val, pv, sp, ra, xpc, _p);
178 }
179
180
181 /* md_signal_handler_sigill ****************************************************
182
183    Signal handler for hardware patcher traps (ud2).
184
185 *******************************************************************************/
186
187 void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
188 {
189         ucontext_t *_uc;
190         mcontext_t *_mc;
191         u1         *pv;
192         u1         *sp;
193         u1         *ra;
194         u1         *xpc;
195         s4          type;
196         ptrint      val;
197
198         _uc = (ucontext_t *) _p;
199         _mc = &_uc->uc_mcontext;
200
201         pv  = NULL;                 /* is resolved during stackframeinfo creation */
202         sp  = (u1 *) _mc->gregs[ESP];
203         xpc = (u1 *) _mc->gregs[EIP];
204         ra  = xpc;                            /* return address is equal to xpc   */
205
206         // Check if the trap instruction is valid.
207         // TODO Move this into patcher_handler.
208         if (patcher_is_valid_trap_instruction_at(xpc) == false) {
209                 // Check if the PC has been patched during our way to this
210                 // signal handler (see PR85).
211                 if (patcher_is_patched_at(xpc) == true)
212                         return;
213
214                 // We have a problem...
215                 log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc);
216 #if defined(ENABLE_DISASSEMBLER)
217                 (void) disassinstr(xpc);
218 #endif
219                 vm_abort("Aborting...");
220         }
221
222         type = TRAP_PATCHER;
223         val  = 0;
224
225         /* Handle the trap. */
226
227         trap_handle(type, val, pv, sp, ra, xpc, _p);
228 }
229
230
231 /* md_signal_handler_sigusr1 ***************************************************
232
233    Signal handler for suspending threads.
234
235 *******************************************************************************/
236
237 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
238 void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
239 {
240         ucontext_t *_uc;
241         mcontext_t *_mc;
242         u1         *pc;
243         u1         *sp;
244
245         _uc = (ucontext_t *) _p;
246         _mc = &_uc->uc_mcontext;
247
248         /* get the PC and SP for this thread */
249         pc = (u1 *) _mc->gregs[EIP];
250         sp = (u1 *) _mc->gregs[ESP];
251
252         /* now suspend the current thread */
253         threads_suspend_ack(pc, sp);
254 }
255 #endif
256
257
258 /* md_signal_handler_sigusr2 ***************************************************
259
260    Signal handler for profiling sampling.
261
262 *******************************************************************************/
263
264 #if defined(ENABLE_THREADS)
265 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
266 {
267         threadobject *t;
268         ucontext_t   *_uc;
269         mcontext_t   *_mc;
270         u1           *pc;
271
272         t = THREADOBJECT;
273
274         _uc = (ucontext_t *) _p;
275         _mc = &_uc->uc_mcontext;
276
277         pc = (u1 *) _mc->gregs[EIP];
278
279         t->pc = pc;
280 }
281 #endif
282
283
284 /* md_executionstate_read ******************************************************
285
286    Read the given context into an executionstate for Replacement.
287
288 *******************************************************************************/
289
290 void md_executionstate_read(executionstate_t *es, void *context)
291 {
292         ucontext_t *_uc;
293         mcontext_t *_mc;
294         s4          i;
295
296         _uc = (ucontext_t *) context;
297         _mc = &_uc->uc_mcontext;
298
299         /* read special registers */
300         es->pc = (u1 *) _mc->gregs[EIP];
301         es->sp = (u1 *) _mc->gregs[ESP];
302         es->pv = NULL;                   /* pv must be looked up via AVL tree */
303
304         /* read integer registers */
305         for (i = 0; i < INT_REG_CNT; i++)
306                 es->intregs[i] = _mc->gregs[EAX - i];
307
308         /* read float registers */
309         for (i = 0; i < FLT_REG_CNT; i++)
310                 es->fltregs[i] = 0xdeadbeefdeadbeefULL;
311 }
312
313
314 /* md_executionstate_write *****************************************************
315
316    Write the given executionstate back to the context for Replacement.
317
318 *******************************************************************************/
319
320 void md_executionstate_write(executionstate_t *es, void *context)
321 {
322         ucontext_t *_uc;
323         mcontext_t *_mc;
324         s4          i;
325
326         _uc = (ucontext_t *) context;
327         _mc = &_uc->uc_mcontext;
328
329         /* write integer registers */
330         for (i = 0; i < INT_REG_CNT; i++)
331                 _mc->gregs[EAX - i] = es->intregs[i];
332
333         /* write special registers */
334         _mc->gregs[EIP] = (ptrint) es->pc;
335         _mc->gregs[ESP] = (ptrint) es->sp;
336 }
337
338
339 /*
340  * These are local overrides for various environment variables in Emacs.
341  * Please do not remove this and leave it at the end of the file, where
342  * Emacs will automagically detect them.
343  * ---------------------------------------------------------------------
344  * Local variables:
345  * mode: c
346  * indent-tabs-mode: t
347  * c-basic-offset: 4
348  * tab-width: 4
349  * End:
350  */