|
|
1.1 root 1: /*************************************************************************
2: * Handling mistaken direct memory access *
3: *************************************************************************/
4:
5: #ifdef NATMEM_OFFSET
6: #ifdef _WIN32 // %%% BRIAN KING WAS HERE %%%
7: #include <winbase.h>
8: #else
9: #ifndef __USE_GNU
10: #define __USE_GNU
11: #endif
12: #include <sys/ucontext.h>
13: #endif
14: #include <signal.h>
15:
16: #define SIG_READ 1
17: #define SIG_WRITE 2
18:
19: static int in_handler = 0;
20: static uae_u8 *veccode;
21:
22: #if defined(JIT_DEBUG)
23: #define DEBUG_ACCESS
24: #elif defined(CPU_x86_64)
25: #define DEBUG_ACCESS
26: #endif
27:
28: #if defined(_WIN32) && defined(CPU_x86_64)
29:
30: typedef LPEXCEPTION_POINTERS CONTEXT_T;
31: #define HAVE_CONTEXT_T 1
32: #define CONTEXT_RIP(context) (context->ContextRecord->Rip)
33: #define CONTEXT_RAX(context) (context->ContextRecord->Rax)
34: #define CONTEXT_RCX(context) (context->ContextRecord->Rcx)
35: #define CONTEXT_RDX(context) (context->ContextRecord->Rdx)
36: #define CONTEXT_RBX(context) (context->ContextRecord->Rbx)
37: #define CONTEXT_RSP(context) (context->ContextRecord->Rsp)
38: #define CONTEXT_RBP(context) (context->ContextRecord->Rbp)
39: #define CONTEXT_RSI(context) (context->ContextRecord->Rsi)
40: #define CONTEXT_RDI(context) (context->ContextRecord->Rdi)
41: #define CONTEXT_R8(context) (context->ContextRecord->R8)
42: #define CONTEXT_R9(context) (context->ContextRecord->R9)
43: #define CONTEXT_R10(context) (context->ContextRecord->R10)
44: #define CONTEXT_R11(context) (context->ContextRecord->R11)
45: #define CONTEXT_R12(context) (context->ContextRecord->R12)
46: #define CONTEXT_R13(context) (context->ContextRecord->R13)
47: #define CONTEXT_R14(context) (context->ContextRecord->R14)
48: #define CONTEXT_R15(context) (context->ContextRecord->R15)
49:
50: #elif defined(_WIN32) && defined(CPU_i386)
51:
52: typedef LPEXCEPTION_POINTERS CONTEXT_T;
53: #define HAVE_CONTEXT_T 1
54: #define CONTEXT_RIP(context) (context->ContextRecord->Eip)
55: #define CONTEXT_RAX(context) (context->ContextRecord->Eax)
56: #define CONTEXT_RCX(context) (context->ContextRecord->Ecx)
57: #define CONTEXT_RDX(context) (context->ContextRecord->Edx)
58: #define CONTEXT_RBX(context) (context->ContextRecord->Ebx)
59: #define CONTEXT_RSP(context) (context->ContextRecord->Esp)
60: #define CONTEXT_RBP(context) (context->ContextRecord->Ebp)
61: #define CONTEXT_RSI(context) (context->ContextRecord->Esi)
62: #define CONTEXT_RDI(context) (context->ContextRecord->Edi)
63:
64: #elif defined(HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS) && defined(CPU_x86_64)
65:
66: typedef void *CONTEXT_T;
67: #define HAVE_CONTEXT_T 1
68: #define CONTEXT_RIP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RIP])
69: #define CONTEXT_RAX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RAX])
70: #define CONTEXT_RCX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RCX])
71: #define CONTEXT_RDX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RDX])
72: #define CONTEXT_RBX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RBX])
73: #define CONTEXT_RSP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RSP])
74: #define CONTEXT_RBP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RBP])
75: #define CONTEXT_RSI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RSI])
76: #define CONTEXT_RDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RDI])
77: #define CONTEXT_R8(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R8])
78: #define CONTEXT_R9(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R9])
79: #define CONTEXT_R10(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R10])
80: #define CONTEXT_R11(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R11])
81: #define CONTEXT_R12(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R12])
82: #define CONTEXT_R13(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R13])
83: #define CONTEXT_R14(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R14])
84: #define CONTEXT_R15(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R15])
85:
86: #elif defined(HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS) && defined(CPU_i386)
87:
88: typedef void *CONTEXT_T;
89: #define HAVE_CONTEXT_T 1
90: #define CONTEXT_RIP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EIP])
91: #define CONTEXT_RAX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EAX])
92: #define CONTEXT_RCX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ECX])
93: #define CONTEXT_RDX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDX])
94: #define CONTEXT_RBX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBX])
95: #define CONTEXT_RSP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESP])
96: #define CONTEXT_RBP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBP])
97: #define CONTEXT_RSI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESI])
98: #define CONTEXT_RDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDI])
99:
100: #elif defined(__DARWIN_UNIX03) && defined(CPU_x86_64)
101:
102: typedef void *CONTEXT_T;
103: #define HAVE_CONTEXT_T 1
104: #define CONTEXT_RIP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__rip))
105: #define CONTEXT_RAX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rax)
106: #define CONTEXT_RCX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rcx)
107: #define CONTEXT_RDX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rdx)
108: #define CONTEXT_RBX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rbx)
109: #define CONTEXT_RSP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__rsp))
110: #define CONTEXT_RBP(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rbp)
111: #define CONTEXT_RSI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rsi)
112: #define CONTEXT_RDI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rdi)
113: #define CONTEXT_R8(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r8)
114: #define CONTEXT_R9(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r9)
115: #define CONTEXT_R10(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r10)
116: #define CONTEXT_R11(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r11)
117: #define CONTEXT_R12(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r12)
118: #define CONTEXT_R13(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r13)
119: #define CONTEXT_R14(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r14)
120: #define CONTEXT_R15(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r15)
121:
122: #elif defined(__DARWIN_UNIX03) && defined(CPU_i386)
123:
124: typedef void *CONTEXT_T;
125: #define HAVE_CONTEXT_T 1
126: #define CONTEXT_RIP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__eip))
127: #define CONTEXT_RAX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__eax)
128: #define CONTEXT_RCX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ecx)
129: #define CONTEXT_RDX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edx)
130: #define CONTEXT_RBX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebx)
131: #define CONTEXT_RSP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__esp))
132: #define CONTEXT_RBP(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebp)
133: #define CONTEXT_RSI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__esi)
134: #define CONTEXT_RDI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edi)
135:
136: #endif
137:
138: #define CONTEXT_PC(context) CONTEXT_RIP(context)
139:
140: /* FIXME: replace usage with bswap16, move fallback defition to header */
141: static inline uae_u16 swap16(uae_u16 x)
142: {
143: return ((x & 0xff00) >> 8) | ((x & 0x00ff) << 8);
144: }
145:
146: /* FIXME: replace usage with bswap32, move fallback defition to header */
147: static inline uae_u32 swap32(uae_u32 x)
148: {
149: return ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) << 24) |
150: ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
151: }
152:
153: static int delete_trigger(blockinfo *bi, void *pc)
154: {
155: while (bi) {
156: if (bi->handler && (uae_u8*)bi->direct_handler <= pc &&
157: (uae_u8*)bi->nexthandler > pc) {
158: #ifdef DEBUG_ACCESS
159: write_log(_T("JIT: Deleted trigger (%p < %p < %p) %p\n"),
160: bi->handler, pc, bi->nexthandler, bi->pc_p);
161: #endif
162: invalidate_block(bi);
163: raise_in_cl_list(bi);
164: set_special(0);
165: return 1;
166: }
167: bi = bi->next;
168: }
169: return 0;
170: }
171:
172: /* Opcode register id list:
173: *
174: * 8 Bit: 16 Bit: 32 Bit:
175: *
176: * 0: AL 0: AX 0: EAX
177: * 1: CL 1: CX 1: ECX
178: * 2: DL 2: DX 2: EDX
179: * 3: BL 3: BX 3: EBX
180: * 4: AH (SPL, if REX) 4: SP 4: ESP
181: * 5: CH (BPL, if REX) 5: BP 5: EBP
182: * 6: DH (SIL, if REX) 6: SI 6: ESI
183: * 7: BH (DIL, if REX) 7: DI 7: EDI
184: * 8: R8L 8: R8W 8: R8D
185: * 9: R9L 9: R9W 9: R9D
186: * 10: R10L 10: R10W 10: R10D
187: * 11: R11L 11: R11W 11: R11D
188: * 12: R12L 12: R12W 12: R12D
189: * 13: R13L 13: R13W 13: R13D
190: * 14: R14L 14: R14W 14: R14D
191: * 15: R15L 15: R15W 15: R15D
192: */
193:
194: static bool decode_instruction(
195: uae_u8 *pc, int *r, int *dir, int *size, int *len, int *rex)
196: {
197: *r = -1;
198: *size = 4;
199: *dir = -1;
200: *len = 0;
201: *rex = 0;
202:
203: #ifdef CPU_x86_64
204: /* Skip address-size override prefix. */
205: if (*pc == 0x67) {
206: pc += 1;
207: *len += 1;
208: }
209: #endif
210: /* Operand size override prefix. */
211: if (*pc == 0x66) {
212: pc += 1;
213: *size = 2;
214: *len += 1;
215: }
216: #ifdef CPU_x86_64
217: /* Handle x86-64 REX prefix. */
218: if ((pc[0] & 0xf0) == 0x40) {
219: *rex = pc[0];
220: pc += 1;
221: *len += 1;
222: if (*rex & (1 << 3)) {
223: *size = 8;
224: /* 64-bit operand size not supported. */
225: return 0;
226: }
227: }
228: #endif
229:
230: switch (pc[0]) {
231: case 0x8a: /* MOV r8, m8 */
232: if ((pc[1] & 0xc0) == 0x80) {
233: *r = (pc[1] >> 3) & 7;
234: *dir = SIG_READ;
235: *size = 1;
236: *len += 6;
237: break;
238: }
239: break;
240: case 0x88: /* MOV m8, r8 */
241: if ((pc[1] & 0xc0) == 0x80) {
242: *r = (pc[1] >> 3) & 7;
243: *dir = SIG_WRITE;
244: *size = 1;
245: *len += 6;
246: break;
247: }
248: break;
249: case 0x8b: /* MOV r32, m32 */
250: switch (pc[1] & 0xc0) {
251: case 0x80:
252: *r = (pc[1] >> 3) & 7;
253: *dir = SIG_READ;
254: *len += 6;
255: break;
256: case 0x40:
257: *r = (pc[1] >> 3) & 7;
258: *dir = SIG_READ;
259: *len += 3;
260: break;
261: case 0x00:
262: *r = (pc[1] >> 3) & 7;
263: *dir = SIG_READ;
264: *len += 2;
265: break;
266: default:
267: break;
268: }
269: break;
270: case 0x89: /* MOV m32, r32 */
271: switch (pc[1] & 0xc0) {
272: case 0x80:
273: *r = (pc[1] >> 3) & 7;
274: *dir = SIG_WRITE;
275: *len += 6;
276: break;
277: case 0x40:
278: *r = (pc[1] >> 3) & 7;
279: *dir = SIG_WRITE;
280: *len += 3;
281: break;
282: case 0x00:
283: *r = (pc[1] >> 3) & 7;
284: *dir = SIG_WRITE;
285: *len += 2;
286: break;
287: }
288: break;
289: }
290: #ifdef CPU_x86_64
291: if (*rex & (1 << 2)) {
292: /* Use x86-64 extended registers R8..R15. */
293: *r += 8;
294: }
295: #endif
296: return *r != -1;
297: }
298:
299: #ifdef HAVE_CONTEXT_T
300:
301: static void *get_pr_from_context(CONTEXT_T context, int r, int size, int rex)
302: {
303: switch (r) {
304: case 0:
305: return &(CONTEXT_RAX(context));
306: case 1:
307: return &(CONTEXT_RCX(context));
308: case 2:
309: return &(CONTEXT_RDX(context));
310: case 3:
311: return &(CONTEXT_RBX(context));
312: case 4:
313: if (size > 1 || rex) {
314: return NULL;
315: } else {
316: return (((uae_u8 *) &(CONTEXT_RAX(context))) + 1); /* AH */
317: }
318: case 5:
319: if (size > 1 || rex) {
320: return &(CONTEXT_RBP(context));
321: } else {
322: return (((uae_u8 *) &(CONTEXT_RCX(context))) + 1); /* CH */
323: }
324: case 6:
325: if (size > 1 || rex) {
326: return &(CONTEXT_RSI(context));
327: } else {
328: return (((uae_u8 *) &(CONTEXT_RDX(context))) + 1); /* DH */
329: }
330: case 7:
331: if (size > 1 || rex) {
332: return &(CONTEXT_RDI(context));
333: } else {
334: return (((uae_u8 *) &(CONTEXT_RBX(context))) + 1); /* BH */
335: }
336: #ifdef CPU_x86_64
337: case 8:
338: return &(CONTEXT_R8(context));
339: case 9:
340: return &(CONTEXT_R9(context));
341: case 10:
342: return &(CONTEXT_R10(context));
343: case 11:
344: return &(CONTEXT_R11(context));
345: case 12:
346: return &(CONTEXT_R12(context));
347: case 13:
348: return &(CONTEXT_R13(context));
349: case 14:
350: return &(CONTEXT_R14(context));
351: case 15:
352: return &(CONTEXT_R15(context));
353: #endif
354: default:
355: abort ();
356: }
357: }
358:
359: static void log_unhandled_access(uae_u8 *fault_pc)
360: {
361: write_log(_T("JIT: Can't handle access PC=%p!\n"), fault_pc);
362: if (fault_pc) {
363: write_log(_T("JIT: Instruction bytes"));
364: for (int j = 0; j < 10; j++) {
365: write_log(_T(" %02x"), fault_pc[j]);
366: }
367: write_log(_T("\n"));
368: }
369: }
370:
371: /*
372: * Try to handle faulted memory access in compiled code
373: *
374: * Returns 1 if handled, 0 otherwise
375: */
376: static int handle_access(uintptr_t fault_addr, CONTEXT_T context)
377: {
378: uae_u8 *fault_pc = (uae_u8 *) CONTEXT_PC(context);
379: #ifdef CPU_64_BIT
380: #if 0
381: if ((fault_addr & 0xffffffff00000000) == 0xffffffff00000000) {
382: fault_addr &= 0xffffffff;
383: }
384: #endif
385: if (fault_addr > (uintptr_t) 0xffffffff) {
386: return 0;
387: }
388: #endif
389:
390: #ifdef DEBUG_ACCESS
391: write_log(_T("JIT: Fault address is 0x%lx at PC=%p\n"), fault_addr, fault_pc);
392: #endif
393: if (!canbang || !currprefs.cachesize)
394: return 0;
395:
396: if (in_handler)
397: write_log(_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n"));
398:
399: if (fault_pc < compiled_code || fault_pc > current_compile_p) {
400: return 0;
401: }
402:
403: int r = -1, size = 4, dir = -1, len = 0, rex = 0;
404: decode_instruction(fault_pc, &r, &dir, &size, &len, &rex);
405: if (r == -1) {
406: log_unhandled_access(fault_pc);
407: return 0;
408: }
409:
410: #ifdef DEBUG_ACCESS
411: write_log (_T("JIT: Register was %d, direction was %d, size was %d\n"),
412: r, dir, size);
413: #endif
414:
415: void *pr = get_pr_from_context(context, r, size, rex);
416: if (pr == NULL) {
417: log_unhandled_access(fault_pc);
418: return 0;
419: }
420:
421: uae_u32 addr = uae_p32(fault_addr) - uae_p32(NATMEM_OFFSET);
422: #ifdef DEBUG_ACCESS
423: if ((addr >= 0x10000000 && addr < 0x40000000) ||
424: (addr >= 0x50000000)) {
425: write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"), addr);
426: }
427: addrbank *ab = &get_mem_bank(addr);
428: if (ab)
429: write_log(_T("JIT: Address bank: %s, address %08x\n"), ab->name ? ab->name : _T("NONE"), addr);
430: #endif
431:
432: uae_u8* original_target = target;
433: target = (uae_u8*) CONTEXT_PC(context);
434:
435: uae_u8 vecbuf[5];
436: for (int i = 0; i < 5; i++) {
437: vecbuf[i] = target[i];
438: }
439: raw_jmp(uae_p32(veccode));
440:
441: #ifdef DEBUG_ACCESS
442: write_log(_T("JIT: Create jump to %p\n"), veccode);
443: write_log(_T("JIT: Handled one access!\n"));
444: #endif
445: segvcount++;
446:
447: target = veccode;
448: if (dir == SIG_READ) {
449: switch (size) {
450: case 1:
451: raw_mov_b_ri(r, get_byte(addr));
452: break;
453: case 2:
454: raw_mov_w_ri(r, swap16(get_word(addr)));
455: break;
456: case 4:
457: raw_mov_l_ri(r, swap32(get_long(addr)));
458: break;
459: default:
460: abort();
461: }
462: } else {
463: switch (size) {
464: case 1:
465: put_byte(addr, *((uae_u8 *) pr));
466: break;
467: case 2:
468: put_word(addr, swap16(*((uae_u16 *) pr)));
469: break;
470: case 4:
471: put_long(addr, swap32(*((uae_u32 *) pr)));
472: break;
473: default: abort();
474: }
475: }
476: for (int i = 0; i < 5; i++) {
477: raw_mov_b_mi(CONTEXT_PC(context) + i, vecbuf[i]);
478: }
479: raw_mov_l_mi(uae_p32(&in_handler), 0);
480: raw_jmp(uae_p32(CONTEXT_PC(context)) + len);
481:
482: in_handler = 1;
483: target = original_target;
484: if (delete_trigger(active, fault_pc)) {
485: return 1;
486: }
487: /* Not found in the active list. Might be a rom routine that
488: * is in the dormant list */
489: if (delete_trigger(dormant, fault_pc)) {
490: return 1;
491: }
492: #ifdef DEBUG_ACCESS
493: write_log (_T("JIT: Huh? Could not find trigger!\n"));
494: #endif
495: return 1;
496: }
497:
498: #endif /* CONTEXT_T */
499:
500: #ifdef _WIN32
501:
502: LONG WINAPI EvalException(LPEXCEPTION_POINTERS info)
503: {
504: DWORD code = info->ExceptionRecord->ExceptionCode;
505: if (code != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0)
506: return EXCEPTION_CONTINUE_SEARCH;
507:
508: uintptr_t address = info->ExceptionRecord->ExceptionInformation[1];
509: if (handle_access(address, info)) {
510: return EXCEPTION_CONTINUE_EXECUTION;
511: }
512: return EXCEPTION_CONTINUE_SEARCH;
513: }
514:
515: static void *installed_vector_handler;
516:
517: static LONG CALLBACK JITVectoredHandler(PEXCEPTION_POINTERS info)
518: {
519: // write_log(_T("JitVectoredHandler\n"));
520: return EvalException(info);
521: }
522:
523: #elif defined(HAVE_CONTEXT_T)
524:
525: static void sigsegv_handler(int signum, siginfo_t *info, void *context)
526: {
527: uae_u8 *i = (uae_u8 *) CONTEXT_PC(context);
528: uintptr_t address = (uintptr_t) info->si_addr;
529:
530: if (i >= compiled_code) {
531: if (handle_access(address, context)) {
532: return;
533: }
534: } else {
535: write_log ("Caught illegal access to %08lx at eip=%p\n", address, i);
536: }
537:
538: exit (EXIT_FAILURE);
539: }
540:
541: #endif
542:
543: // #define TEST_EXCEPTION_HANDLER
544:
545: #ifdef TEST_EXCEPTION_HANDLER
546: #include "test_exception_handler.cpp"
547: #endif
548:
549: static void install_exception_handler(void)
550: {
551: #ifdef TEST_EXCEPTION_HANDLER
552: test_exception_handler();
553: #endif
554:
555: #ifdef JIT_EXCEPTION_HANDLER
556: if (veccode == NULL) {
557: veccode = (uae_u8 *) uae_vm_alloc(256, UAE_VM_32BIT, UAE_VM_READ_WRITE_EXECUTE);
558: }
559: #endif
560: #ifdef USE_STRUCTURED_EXCEPTION_HANDLING
561: /* Structured exception handler is installed in main.cpp */
562: #elif defined(_WIN32)
563: #if 1
564: write_log(_T("JIT: Installing vectored exception handler\n"));
565: installed_vector_handler = AddVectoredExceptionHandler(
566: 0, JITVectoredHandler);
567: #else
568: write_log(_T("JIT: Installing unhandled exception filter\n"));
569: SetUnhandledExceptionFilter(EvalException);
570: #endif
571: #elif defined(HAVE_CONTEXT_T)
572: write_log (_T("JIT: Installing segfault handler\n"));
573: struct sigaction act;
574: act.sa_sigaction = (void (*)(int, siginfo_t*, void*)) sigsegv_handler;
575: sigemptyset (&act.sa_mask);
576: act.sa_flags = SA_SIGINFO;
577: sigaction(SIGSEGV, &act, NULL);
578: #ifdef MACOSX
579: sigaction(SIGBUS, &act, NULL);
580: #endif
581: #else
582: write_log (_T("JIT: No segfault handler installed\n"));
583: #endif
584: }
585:
586: #endif /* NATMEM_OFFSET */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.