| ... | @@ -2307,16 +2307,284 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_vo | ... | @@ -2307,16 +2307,284 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_vo |
| 2307 | } | 2307 | } |
| 2308 | | 2308 | |
| 2309 | fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(.Stdcall) c_long { | 2309 | fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(.Stdcall) c_long { |
| 2310 | const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress); | | |
| 2311 | switch (info.ExceptionRecord.ExceptionCode) { | 2310 | switch (info.ExceptionRecord.ExceptionCode) { |
| 2312 | windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access", .{}), | 2311 | windows.EXCEPTION_DATATYPE_MISALIGNMENT => handleSegfaultWindowsExtra(info, 0, "Unaligned Memory Access"), |
| 2313 | windows.EXCEPTION_ACCESS_VIOLATION => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", .{info.ExceptionRecord.ExceptionInformation[1]}), | 2312 | windows.EXCEPTION_ACCESS_VIOLATION => handleSegfaultWindowsExtra(info, 1, null), |
| 2314 | windows.EXCEPTION_ILLEGAL_INSTRUCTION => panicExtra(null, exception_address, "Illegal Instruction", .{}), | 2313 | windows.EXCEPTION_ILLEGAL_INSTRUCTION => handleSegfaultWindowsExtra(info, 2, null), |
| 2315 | windows.EXCEPTION_STACK_OVERFLOW => panicExtra(null, exception_address, "Stack Overflow", .{}), | 2314 | windows.EXCEPTION_STACK_OVERFLOW => handleSegfaultWindowsExtra(info, 0, "Stack Overflow"), |
| 2316 | else => return windows.EXCEPTION_CONTINUE_SEARCH, | 2315 | else => return windows.EXCEPTION_CONTINUE_SEARCH, |
| 2317 | } | 2316 | } |
| 2318 | } | 2317 | } |
| 2319 | | 2318 | |
| | 2319 | // zig won't let me use an anon enum here |
| | 2320 | fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, comptime msg: u8, comptime format: ?[]const u8) noreturn { |
| | 2321 | const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress); |
| | 2322 | if (comptime windows_exception_context.haveContext) { |
| | 2323 | const regs = windows_exception_context.getRegs(info.ContextRecord); |
| | 2324 | switch (msg) { |
| | 2325 | 0 => std.debug.warn("{}\n", .{format.?}), |
| | 2326 | 1 => std.debug.warn("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}), |
| | 2327 | 2 => std.debug.warn("Illegal instruction at address 0x{x}\n", .{regs.ip}), |
| | 2328 | else => unreachable, |
| | 2329 | } |
| | 2330 | |
| | 2331 | dumpStackTraceFromBase(regs.bp, regs.ip); |
| | 2332 | os.abort(); |
| | 2333 | } else { |
| | 2334 | switch (msg) { |
| | 2335 | 0 => panicExtra(null, exception_address, format.?, .{}), |
| | 2336 | 1 => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", .{info.ExceptionRecord.ExceptionInformation[1]}), |
| | 2337 | 2 => panicExtra(null, exception_address, "Illegal Instruction", .{}), |
| | 2338 | else => unreachable, |
| | 2339 | } |
| | 2340 | } |
| | 2341 | } |
| | 2342 | |
| | 2343 | pub const windows_exception_context = switch (builtin.arch) { |
| | 2344 | .i386 => struct { |
| | 2345 | pub const haveContext = true; |
| | 2346 | |
| | 2347 | pub fn getRegs(ptr: *c_void) struct {bp: usize, ip: usize} { |
| | 2348 | const ctx = @ptrCast(*const CONTEXT, @alignCast(@alignOf(CONTEXT), ptr)); |
| | 2349 | return .{.bp = @intCast(usize, ctx.Ebp), .ip = @intCast(usize, ctx.Eip)}; |
| | 2350 | } |
| | 2351 | |
| | 2352 | pub const CONTEXT = extern struct { |
| | 2353 | ContextFlags: DWORD, |
| | 2354 | Dr0: DWORD, |
| | 2355 | Dr1: DWORD, |
| | 2356 | Dr2: DWORD, |
| | 2357 | Dr3: DWORD, |
| | 2358 | Dr6: DWORD, |
| | 2359 | Dr7: DWORD, |
| | 2360 | FloatSave: FLOATING_SAVE_AREA, |
| | 2361 | SegGs: DWORD, |
| | 2362 | SegFs: DWORD, |
| | 2363 | SegEs: DWORD, |
| | 2364 | SegDs: DWORD, |
| | 2365 | Edi: DWORD, |
| | 2366 | Esi: DWORD, |
| | 2367 | Ebx: DWORD, |
| | 2368 | Edx: DWORD, |
| | 2369 | Ecx: DWORD, |
| | 2370 | Eax: DWORD, |
| | 2371 | Ebp: DWORD, |
| | 2372 | Eip: DWORD, |
| | 2373 | SegCs: DWORD, |
| | 2374 | EFlags: DWORD, |
| | 2375 | Esp: DWORD, |
| | 2376 | SegSs: DWORD, |
| | 2377 | ExtendedRegisters: [512]BYTE, |
| | 2378 | }; |
| | 2379 | |
| | 2380 | pub const FLOATING_SAVE_AREA = extern struct { |
| | 2381 | ControlWord: DWORD, |
| | 2382 | StatusWord: DWORD, |
| | 2383 | TagWord: DWORD, |
| | 2384 | ErrorOffset: DWORD, |
| | 2385 | ErrorSelector: DWORD, |
| | 2386 | DataOffset: DWORD, |
| | 2387 | DataSelector: DWORD, |
| | 2388 | RegisterArea: [80]BYTE, |
| | 2389 | Cr0NpxState: DWORD, |
| | 2390 | }; |
| | 2391 | |
| | 2392 | pub const BYTE = u8; |
| | 2393 | pub const DWORD = c_ulong; |
| | 2394 | }, |
| | 2395 | .x86_64 => struct { |
| | 2396 | pub const haveContext = true; |
| | 2397 | |
| | 2398 | pub fn getRegs(ptr: *c_void) struct {bp: usize, ip: usize} { |
| | 2399 | const ctx = @ptrCast(*const CONTEXT, @alignCast(@alignOf(CONTEXT), ptr)); |
| | 2400 | return .{.bp = @intCast(usize, ctx.Rbp), .ip = @intCast(usize, ctx.Rip)}; |
| | 2401 | } |
| | 2402 | |
| | 2403 | pub const CONTEXT = extern struct { |
| | 2404 | P1Home: DWORD64, |
| | 2405 | P2Home: DWORD64, |
| | 2406 | P3Home: DWORD64, |
| | 2407 | P4Home: DWORD64, |
| | 2408 | P5Home: DWORD64, |
| | 2409 | P6Home: DWORD64, |
| | 2410 | ContextFlags: DWORD, |
| | 2411 | MxCsr: DWORD, |
| | 2412 | SegCs: WORD, |
| | 2413 | SegDs: WORD, |
| | 2414 | SegEs: WORD, |
| | 2415 | SegFs: WORD, |
| | 2416 | SegGs: WORD, |
| | 2417 | SegSs: WORD, |
| | 2418 | EFlags: DWORD, |
| | 2419 | Dr0: DWORD64, |
| | 2420 | Dr1: DWORD64, |
| | 2421 | Dr2: DWORD64, |
| | 2422 | Dr3: DWORD64, |
| | 2423 | Dr6: DWORD64, |
| | 2424 | Dr7: DWORD64, |
| | 2425 | Rax: DWORD64, |
| | 2426 | Rcx: DWORD64, |
| | 2427 | Rdx: DWORD64, |
| | 2428 | Rbx: DWORD64, |
| | 2429 | Rsp: DWORD64, |
| | 2430 | Rbp: DWORD64, |
| | 2431 | Rsi: DWORD64, |
| | 2432 | Rdi: DWORD64, |
| | 2433 | R8: DWORD64, |
| | 2434 | R9: DWORD64, |
| | 2435 | R10: DWORD64, |
| | 2436 | R11: DWORD64, |
| | 2437 | R12: DWORD64, |
| | 2438 | R13: DWORD64, |
| | 2439 | R14: DWORD64, |
| | 2440 | R15: DWORD64, |
| | 2441 | Rip: DWORD64, |
| | 2442 | DUMMYUNIONNAME: extern union { |
| | 2443 | FltSave: XMM_SAVE_AREA32, |
| | 2444 | FloatSave: XMM_SAVE_AREA32, |
| | 2445 | DUMMYSTRUCTNAME: extern struct { |
| | 2446 | Header: [2]M128A, |
| | 2447 | Legacy: [8]M128A, |
| | 2448 | Xmm0: M128A, |
| | 2449 | Xmm1: M128A, |
| | 2450 | Xmm2: M128A, |
| | 2451 | Xmm3: M128A, |
| | 2452 | Xmm4: M128A, |
| | 2453 | Xmm5: M128A, |
| | 2454 | Xmm6: M128A, |
| | 2455 | Xmm7: M128A, |
| | 2456 | Xmm8: M128A, |
| | 2457 | Xmm9: M128A, |
| | 2458 | Xmm10: M128A, |
| | 2459 | Xmm11: M128A, |
| | 2460 | Xmm12: M128A, |
| | 2461 | Xmm13: M128A, |
| | 2462 | Xmm14: M128A, |
| | 2463 | Xmm15: M128A, |
| | 2464 | }, |
| | 2465 | }, |
| | 2466 | VectorRegister: [26]M128A, |
| | 2467 | VectorControl: DWORD64, |
| | 2468 | DebugControl: DWORD64, |
| | 2469 | LastBranchToRip: DWORD64, |
| | 2470 | LastBranchFromRip: DWORD64, |
| | 2471 | LastExceptionToRip: DWORD64, |
| | 2472 | LastExceptionFromRip: DWORD64, |
| | 2473 | }; |
| | 2474 | |
| | 2475 | pub const XMM_SAVE_AREA32 = extern struct { |
| | 2476 | ControlWord: WORD, |
| | 2477 | StatusWord: WORD, |
| | 2478 | TagWord: BYTE, |
| | 2479 | Reserved1: BYTE, |
| | 2480 | ErrorOpcode: WORD, |
| | 2481 | ErrorOffset: DWORD, |
| | 2482 | ErrorSelector: WORD, |
| | 2483 | Reserved2: WORD, |
| | 2484 | DataOffset: DWORD, |
| | 2485 | DataSelector: WORD, |
| | 2486 | Reserved3: WORD, |
| | 2487 | MxCsr: DWORD, |
| | 2488 | MxCsr_Mask: DWORD, |
| | 2489 | FloatRegisters: [8]M128A, |
| | 2490 | XmmRegisters: [16]M128A, |
| | 2491 | Reserved4: [96]BYTE, |
| | 2492 | }; |
| | 2493 | |
| | 2494 | pub const M128A = extern struct { |
| | 2495 | Low: ULONGLONG, |
| | 2496 | High: LONGLONG, |
| | 2497 | }; |
| | 2498 | |
| | 2499 | pub const BYTE = u8; |
| | 2500 | pub const WORD = u16; |
| | 2501 | pub const DWORD = u32; |
| | 2502 | pub const DWORD64 = u64; |
| | 2503 | pub const LONGLONG = c_longlong; |
| | 2504 | pub const ULONGLONG = c_ulonglong; |
| | 2505 | }, |
| | 2506 | .aarch64 => struct { |
| | 2507 | pub const haveContext = true; |
| | 2508 | |
| | 2509 | pub fn getRegs(ptr: *c_void) struct {bp: usize, ip: usize} { |
| | 2510 | const ctx = @ptrCast(*const CONTEXT, @alignCast(@alignOf(CONTEXT), ptr)); |
| | 2511 | return .{.bp = @intCast(usize, ctx.Fp), .ip = @intCast(usize, ctx.Pc)}; |
| | 2512 | } |
| | 2513 | |
| | 2514 | pub const CONTEXT = extern struct { |
| | 2515 | ContextFlags: ULONG, |
| | 2516 | Cpsr: ULONG, |
| | 2517 | DUMMYUNIONNAME: extern union { |
| | 2518 | DUMMYSTRUCTNAME: extern struct { |
| | 2519 | X0: DWORD64, |
| | 2520 | X1: DWORD64, |
| | 2521 | X2: DWORD64, |
| | 2522 | X3: DWORD64, |
| | 2523 | X4: DWORD64, |
| | 2524 | X5: DWORD64, |
| | 2525 | X6: DWORD64, |
| | 2526 | X7: DWORD64, |
| | 2527 | X8: DWORD64, |
| | 2528 | X9: DWORD64, |
| | 2529 | X10: DWORD64, |
| | 2530 | X11: DWORD64, |
| | 2531 | X12: DWORD64, |
| | 2532 | X13: DWORD64, |
| | 2533 | X14: DWORD64, |
| | 2534 | X15: DWORD64, |
| | 2535 | X16: DWORD64, |
| | 2536 | X17: DWORD64, |
| | 2537 | X18: DWORD64, |
| | 2538 | X19: DWORD64, |
| | 2539 | X20: DWORD64, |
| | 2540 | X21: DWORD64, |
| | 2541 | X22: DWORD64, |
| | 2542 | X23: DWORD64, |
| | 2543 | X24: DWORD64, |
| | 2544 | X25: DWORD64, |
| | 2545 | X26: DWORD64, |
| | 2546 | X27: DWORD64, |
| | 2547 | X28: DWORD64, |
| | 2548 | Fp: DWORD64, |
| | 2549 | Lr: DWORD64, |
| | 2550 | }, |
| | 2551 | X: [31]DWORD64, |
| | 2552 | }, |
| | 2553 | Sp: DWORD64, |
| | 2554 | Pc: DWORD64, |
| | 2555 | V: [32]NEON128, |
| | 2556 | Fpcr: DWORD, |
| | 2557 | Fpsr: DWORD, |
| | 2558 | Bcr: [8]DWORD, |
| | 2559 | Bvr: [8]DWORD64, |
| | 2560 | Wcr: [2]DWORD, |
| | 2561 | Wvr: [2]DWORD64, |
| | 2562 | }; |
| | 2563 | |
| | 2564 | pub const NEON128 = extern union { |
| | 2565 | DUMMYSTRUCTNAME: extern struct { |
| | 2566 | Low: ULONGLONG, |
| | 2567 | High: LONGLONG, |
| | 2568 | }, |
| | 2569 | D: [2]f64, |
| | 2570 | S: [4]f32, |
| | 2571 | H: [8]WORD, |
| | 2572 | B: [16]BYTE, |
| | 2573 | }; |
| | 2574 | |
| | 2575 | pub const ULONG = c_ulong; |
| | 2576 | pub const LONGLONG = c_longlong; |
| | 2577 | pub const ULONGLONG = c_ulonglong; |
| | 2578 | pub const BYTE = u8; |
| | 2579 | pub const WORD = c_ushort; |
| | 2580 | pub const DWORD = c_ulong; |
| | 2581 | pub const DWORD64 = c_ulonglong; |
| | 2582 | }, |
| | 2583 | else => struct { |
| | 2584 | pub const haveContext = false; |
| | 2585 | }, |
| | 2586 | }; |
| | 2587 | |
| 2320 | pub fn dumpStackPointerAddr(prefix: []const u8) void { | 2588 | pub fn dumpStackPointerAddr(prefix: []const u8) void { |
| 2321 | const sp = asm ("" | 2589 | const sp = asm ("" |
| 2322 | : [argc] "={rsp}" (-> usize) | 2590 | : [argc] "={rsp}" (-> usize) |