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