authorgravatar for 35231115+Rocknest@users.noreply.github.comRocknest <35231115+Rocknest@users.noreply.github.com> 2020-01-29 16:57:43+02:00
committergravatar for 35231115+Rocknest@users.noreply.github.comRocknest <35231115+Rocknest@users.noreply.github.com> 2020-01-29 17:27:53+02:00
log3500b41bfed159b54b951b7cee5ff404ae5fbbda
tree6585589c29564e998bd63e45e5899c3c091245eb
parent13259acbc3a9bf87db7245daf8132a7194264c51

Add an advanced segfault handler on windows


1 files changed, 273 insertions(+), 5 deletions(-)

lib/std/debug.zig+273-5
......@@ -2307,16 +2307,284 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_vo
23072307}
23082308
23092309fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(.Stdcall) c_long {
2310 const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
23112310 switch (info.ExceptionRecord.ExceptionCode) {
2312 windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access", .{}),
2313 windows.EXCEPTION_ACCESS_VIOLATION => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", .{info.ExceptionRecord.ExceptionInformation[1]}),
2314 windows.EXCEPTION_ILLEGAL_INSTRUCTION => panicExtra(null, exception_address, "Illegal Instruction", .{}),
2315 windows.EXCEPTION_STACK_OVERFLOW => panicExtra(null, exception_address, "Stack Overflow", .{}),
2311 windows.EXCEPTION_DATATYPE_MISALIGNMENT => handleSegfaultWindowsExtra(info, 0, "Unaligned Memory Access"),
2312 windows.EXCEPTION_ACCESS_VIOLATION => handleSegfaultWindowsExtra(info, 1, null),
2313 windows.EXCEPTION_ILLEGAL_INSTRUCTION => handleSegfaultWindowsExtra(info, 2, null),
2314 windows.EXCEPTION_STACK_OVERFLOW => handleSegfaultWindowsExtra(info, 0, "Stack Overflow"),
23162315 else => return windows.EXCEPTION_CONTINUE_SEARCH,
23172316 }
23182317}
23192318
2319// zig won't let me use an anon enum here
2320fn 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
2343pub 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
23202588pub fn dumpStackPointerAddr(prefix: []const u8) void {
23212589 const sp = asm (""
23222590 : [argc] "={rsp}" (-> usize)