authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-30 09:26:39-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-30 09:26:39-05:00
log0303e7bd8e4fb245b4dfae51c7c1e34a66e0855c
tree28721c76baf99b6c07bafe3a797073a43a112f2a
parente77a102e24c351a56cdda5bad5a46dcd58101c23
parenta5f18c2b2ae86126e0fd0cba67676ae68ba0f1df
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4319 from Rocknest/windows-traces

Bring windows segfault handler on par with linux

2 files changed, 258 insertions(+), 8 deletions(-)

lib/std/debug.zig+31-6
......@@ -131,6 +131,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
131131 const tty_config = detectTTYConfig();
132132 printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return;
133133 const first_return_address = @intToPtr(*const usize, bp + @sizeOf(usize)).*;
134 if (first_return_address == 0) return; // The whole call stack may be optimized out
134135 printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_config) catch return;
135136 var it = StackIterator{
136137 .first_addr = null,
......@@ -325,6 +326,7 @@ pub const StackIterator = struct {
325326 }
326327
327328 const return_address = @intToPtr(*const usize, self.fp - fp_adjust_factor + @sizeOf(usize)).*;
329 if (return_address == 0) return null;
328330 return return_address;
329331 }
330332};
......@@ -470,7 +472,7 @@ fn printSourceAtAddressWindows(
470472 line_index += @sizeOf(pdb.LineNumberEntry);
471473
472474 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
473 if (relative_address <= vaddr_start) {
475 if (relative_address < vaddr_start) {
474476 break;
475477 }
476478 }
......@@ -2309,16 +2311,39 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_vo
23092311}
23102312
23112313fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(.Stdcall) c_long {
2312 const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
23132314 switch (info.ExceptionRecord.ExceptionCode) {
2314 windows.EXCEPTION_DATATYPE_MISALIGNMENT => panicExtra(null, exception_address, "Unaligned Memory Access", .{}),
2315 windows.EXCEPTION_ACCESS_VIOLATION => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", .{info.ExceptionRecord.ExceptionInformation[1]}),
2316 windows.EXCEPTION_ILLEGAL_INSTRUCTION => panicExtra(null, exception_address, "Illegal Instruction", .{}),
2317 windows.EXCEPTION_STACK_OVERFLOW => panicExtra(null, exception_address, "Stack Overflow", .{}),
2315 windows.EXCEPTION_DATATYPE_MISALIGNMENT => handleSegfaultWindowsExtra(info, 0, "Unaligned Memory Access"),
2316 windows.EXCEPTION_ACCESS_VIOLATION => handleSegfaultWindowsExtra(info, 1, null),
2317 windows.EXCEPTION_ILLEGAL_INSTRUCTION => handleSegfaultWindowsExtra(info, 2, null),
2318 windows.EXCEPTION_STACK_OVERFLOW => handleSegfaultWindowsExtra(info, 0, "Stack Overflow"),
23182319 else => return windows.EXCEPTION_CONTINUE_SEARCH,
23192320 }
23202321}
23212322
2323// zig won't let me use an anon enum here https://github.com/ziglang/zig/issues/3707
2324fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, comptime msg: u8, comptime format: ?[]const u8) noreturn {
2325 const exception_address = @ptrToInt(info.ExceptionRecord.ExceptionAddress);
2326 if (@hasDecl(windows, "CONTEXT")) {
2327 const regs = info.ContextRecord.getRegs();
2328 switch (msg) {
2329 0 => std.debug.warn("{}\n", .{format.?}),
2330 1 => std.debug.warn("Segmentation fault at address 0x{x}\n", .{info.ExceptionRecord.ExceptionInformation[1]}),
2331 2 => std.debug.warn("Illegal instruction at address 0x{x}\n", .{regs.ip}),
2332 else => unreachable,
2333 }
2334
2335 dumpStackTraceFromBase(regs.bp, regs.ip);
2336 os.abort();
2337 } else {
2338 switch (msg) {
2339 0 => panicExtra(null, exception_address, format.?, .{}),
2340 1 => panicExtra(null, exception_address, "Segmentation fault at address 0x{x}", .{info.ExceptionRecord.ExceptionInformation[1]}),
2341 2 => panicExtra(null, exception_address, "Illegal Instruction", .{}),
2342 else => unreachable,
2343 }
2344 }
2345}
2346
23222347pub fn dumpStackPointerAddr(prefix: []const u8) void {
23232348 const sp = asm (""
23242349 : [argc] "={rsp}" (-> usize)
lib/std/os/windows/bits.zig+227-2
......@@ -23,7 +23,6 @@ pub const BOOL = c_int;
2323pub const BOOLEAN = BYTE;
2424pub const BYTE = u8;
2525pub const CHAR = u8;
26pub const DWORD = u32;
2726pub const FLOAT = f32;
2827pub const HANDLE = *c_void;
2928pub const HCRYPTPROV = ULONG_PTR;
......@@ -52,6 +51,8 @@ pub const DWORD_PTR = ULONG_PTR;
5251pub const UNICODE = false;
5352pub const WCHAR = u16;
5453pub const WORD = u16;
54pub const DWORD = u32;
55pub const DWORD64 = u64;
5556pub const LARGE_INTEGER = i64;
5657pub const USHORT = u16;
5758pub const SHORT = i16;
......@@ -887,9 +888,233 @@ pub const EXCEPTION_RECORD = extern struct {
887888 ExceptionInformation: [15]usize,
888889};
889890
891pub usingnamespace switch (builtin.arch) {
892 .i386 => struct {
893 pub const FLOATING_SAVE_AREA = extern struct {
894 ControlWord: DWORD,
895 StatusWord: DWORD,
896 TagWord: DWORD,
897 ErrorOffset: DWORD,
898 ErrorSelector: DWORD,
899 DataOffset: DWORD,
900 DataSelector: DWORD,
901 RegisterArea: [80]BYTE,
902 Cr0NpxState: DWORD,
903 };
904
905 pub const CONTEXT = extern struct {
906 ContextFlags: DWORD,
907 Dr0: DWORD,
908 Dr1: DWORD,
909 Dr2: DWORD,
910 Dr3: DWORD,
911 Dr6: DWORD,
912 Dr7: DWORD,
913 FloatSave: FLOATING_SAVE_AREA,
914 SegGs: DWORD,
915 SegFs: DWORD,
916 SegEs: DWORD,
917 SegDs: DWORD,
918 Edi: DWORD,
919 Esi: DWORD,
920 Ebx: DWORD,
921 Edx: DWORD,
922 Ecx: DWORD,
923 Eax: DWORD,
924 Ebp: DWORD,
925 Eip: DWORD,
926 SegCs: DWORD,
927 EFlags: DWORD,
928 Esp: DWORD,
929 SegSs: DWORD,
930 ExtendedRegisters: [512]BYTE,
931
932 pub fn getRegs(ctx: *const CONTEXT) struct {bp: usize, ip: usize} {
933 return .{.bp = ctx.Ebp, .ip = ctx.Eip};
934 }
935 };
936
937 pub const PCONTEXT = *CONTEXT;
938 },
939 .x86_64 => struct {
940 pub const M128A = extern struct {
941 Low: ULONGLONG,
942 High: LONGLONG,
943 };
944
945 pub const XMM_SAVE_AREA32 = extern struct {
946 ControlWord: WORD,
947 StatusWord: WORD,
948 TagWord: BYTE,
949 Reserved1: BYTE,
950 ErrorOpcode: WORD,
951 ErrorOffset: DWORD,
952 ErrorSelector: WORD,
953 Reserved2: WORD,
954 DataOffset: DWORD,
955 DataSelector: WORD,
956 Reserved3: WORD,
957 MxCsr: DWORD,
958 MxCsr_Mask: DWORD,
959 FloatRegisters: [8]M128A,
960 XmmRegisters: [16]M128A,
961 Reserved4: [96]BYTE,
962 };
963
964 pub const CONTEXT = extern struct {
965 P1Home: DWORD64,
966 P2Home: DWORD64,
967 P3Home: DWORD64,
968 P4Home: DWORD64,
969 P5Home: DWORD64,
970 P6Home: DWORD64,
971 ContextFlags: DWORD,
972 MxCsr: DWORD,
973 SegCs: WORD,
974 SegDs: WORD,
975 SegEs: WORD,
976 SegFs: WORD,
977 SegGs: WORD,
978 SegSs: WORD,
979 EFlags: DWORD,
980 Dr0: DWORD64,
981 Dr1: DWORD64,
982 Dr2: DWORD64,
983 Dr3: DWORD64,
984 Dr6: DWORD64,
985 Dr7: DWORD64,
986 Rax: DWORD64,
987 Rcx: DWORD64,
988 Rdx: DWORD64,
989 Rbx: DWORD64,
990 Rsp: DWORD64,
991 Rbp: DWORD64,
992 Rsi: DWORD64,
993 Rdi: DWORD64,
994 R8: DWORD64,
995 R9: DWORD64,
996 R10: DWORD64,
997 R11: DWORD64,
998 R12: DWORD64,
999 R13: DWORD64,
1000 R14: DWORD64,
1001 R15: DWORD64,
1002 Rip: DWORD64,
1003 DUMMYUNIONNAME: extern union {
1004 FltSave: XMM_SAVE_AREA32,
1005 FloatSave: XMM_SAVE_AREA32,
1006 DUMMYSTRUCTNAME: extern struct {
1007 Header: [2]M128A,
1008 Legacy: [8]M128A,
1009 Xmm0: M128A,
1010 Xmm1: M128A,
1011 Xmm2: M128A,
1012 Xmm3: M128A,
1013 Xmm4: M128A,
1014 Xmm5: M128A,
1015 Xmm6: M128A,
1016 Xmm7: M128A,
1017 Xmm8: M128A,
1018 Xmm9: M128A,
1019 Xmm10: M128A,
1020 Xmm11: M128A,
1021 Xmm12: M128A,
1022 Xmm13: M128A,
1023 Xmm14: M128A,
1024 Xmm15: M128A,
1025 },
1026 },
1027 VectorRegister: [26]M128A,
1028 VectorControl: DWORD64,
1029 DebugControl: DWORD64,
1030 LastBranchToRip: DWORD64,
1031 LastBranchFromRip: DWORD64,
1032 LastExceptionToRip: DWORD64,
1033 LastExceptionFromRip: DWORD64,
1034
1035 pub fn getRegs(ctx: *const CONTEXT) struct {bp: usize, ip: usize} {
1036 return .{.bp = ctx.Rbp, .ip = ctx.Rip};
1037 }
1038 };
1039
1040 pub const PCONTEXT = *CONTEXT;
1041 },
1042 .aarch64 => struct {
1043 pub const NEON128 = extern union {
1044 DUMMYSTRUCTNAME: extern struct {
1045 Low: ULONGLONG,
1046 High: LONGLONG,
1047 },
1048 D: [2]f64,
1049 S: [4]f32,
1050 H: [8]WORD,
1051 B: [16]BYTE,
1052 };
1053
1054 pub const CONTEXT = extern struct {
1055 ContextFlags: ULONG,
1056 Cpsr: ULONG,
1057 DUMMYUNIONNAME: extern union {
1058 DUMMYSTRUCTNAME: extern struct {
1059 X0: DWORD64,
1060 X1: DWORD64,
1061 X2: DWORD64,
1062 X3: DWORD64,
1063 X4: DWORD64,
1064 X5: DWORD64,
1065 X6: DWORD64,
1066 X7: DWORD64,
1067 X8: DWORD64,
1068 X9: DWORD64,
1069 X10: DWORD64,
1070 X11: DWORD64,
1071 X12: DWORD64,
1072 X13: DWORD64,
1073 X14: DWORD64,
1074 X15: DWORD64,
1075 X16: DWORD64,
1076 X17: DWORD64,
1077 X18: DWORD64,
1078 X19: DWORD64,
1079 X20: DWORD64,
1080 X21: DWORD64,
1081 X22: DWORD64,
1082 X23: DWORD64,
1083 X24: DWORD64,
1084 X25: DWORD64,
1085 X26: DWORD64,
1086 X27: DWORD64,
1087 X28: DWORD64,
1088 Fp: DWORD64,
1089 Lr: DWORD64,
1090 },
1091 X: [31]DWORD64,
1092 },
1093 Sp: DWORD64,
1094 Pc: DWORD64,
1095 V: [32]NEON128,
1096 Fpcr: DWORD,
1097 Fpsr: DWORD,
1098 Bcr: [8]DWORD,
1099 Bvr: [8]DWORD64,
1100 Wcr: [2]DWORD,
1101 Wvr: [2]DWORD64,
1102
1103 pub fn getRegs(ctx: *const CONTEXT) struct {bp: usize, ip: usize} {
1104 return .{.bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp, .ip = ctx.Pc};
1105 }
1106 };
1107
1108 pub const PCONTEXT = *CONTEXT;
1109 },
1110 else => struct {
1111 pub const PCONTEXT = *c_void;
1112 },
1113};
1114
8901115pub const EXCEPTION_POINTERS = extern struct {
8911116 ExceptionRecord: *EXCEPTION_RECORD,
892 ContextRecord: *c_void,
1117 ContextRecord: PCONTEXT,
8931118};
8941119
8951120pub const VECTORED_EXCEPTION_HANDLER = fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(.Stdcall) c_long;