|
|
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.