| author | |
| committer | |
| log | f1b71053de6c5e71e2e1f73daeaff29280b69350 |
| tree | 6e27b78ebc073622dec68d49f809fe5ceb5fe674 |
| parent | 833477abf5a7df2c8861a2df11fae2105016e087 |
6 files changed, 33 insertions(+), 3 deletions(-)
CMakeLists.txt+1| ... | @@ -578,6 +578,7 @@ set(ZIG_STD_FILES | ... | @@ -578,6 +578,7 @@ set(ZIG_STD_FILES |
| 578 | "os/windows/error.zig" | 578 | "os/windows/error.zig" |
| 579 | "os/windows/index.zig" | 579 | "os/windows/index.zig" |
| 580 | "os/windows/kernel32.zig" | 580 | "os/windows/kernel32.zig" |
| 581 | "os/windows/ntdll.zig" | ||
| 581 | "os/windows/ole32.zig" | 582 | "os/windows/ole32.zig" |
| 582 | "os/windows/shell32.zig" | 583 | "os/windows/shell32.zig" |
| 583 | "os/windows/shlwapi.zig" | 584 | "os/windows/shlwapi.zig" |
std/debug/index.zig+23-1| ... | @@ -195,6 +195,10 @@ pub inline fn getReturnAddress(frame_count: usize) usize { | ... | @@ -195,6 +195,10 @@ pub inline fn getReturnAddress(frame_count: usize) usize { |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { | 197 | pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { |
| 198 | switch (builtin.os) { | ||
| 199 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, allocator, debug_info, tty_color, start_addr), | ||
| 200 | else => {}, | ||
| 201 | } | ||
| 198 | const AddressState = union(enum) { | 202 | const AddressState = union(enum) { |
| 199 | NotLookingForStartAddress, | 203 | NotLookingForStartAddress, |
| 200 | LookingForStartAddress: usize, | 204 | LookingForStartAddress: usize, |
| ... | @@ -227,6 +231,24 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_ | ... | @@ -227,6 +231,24 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_ |
| 227 | } | 231 | } |
| 228 | } | 232 | } |
| 229 | 233 | ||
| 234 | pub fn writeCurrentStackTraceWindows(out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, | ||
| 235 | tty_color: bool, start_addr: ?usize) !void | ||
| 236 | { | ||
| 237 | var addr_buf: [1024]usize = undefined; | ||
| 238 | const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast | ||
| 239 | const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null); | ||
| 240 | const addrs = addr_buf[0..n]; | ||
| 241 | var start_i: usize = if (start_addr) |saddr| blk: { | ||
| 242 | for (addrs) |addr, i| { | ||
| 243 | if (addr == saddr) break :blk i; | ||
| 244 | } | ||
| 245 | return; | ||
| 246 | } else 0; | ||
| 247 | for (addrs[start_i..]) |addr| { | ||
| 248 | try printSourceAtAddress(debug_info, out_stream, addr, tty_color); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 230 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { | 252 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { |
| 231 | switch (builtin.os) { | 253 | switch (builtin.os) { |
| 232 | builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color), | 254 | builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color), |
| ... | @@ -237,7 +259,7 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us | ... | @@ -237,7 +259,7 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us |
| 237 | } | 259 | } |
| 238 | 260 | ||
| 239 | fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { | 261 | fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { |
| 240 | const base_address = @ptrToInt(windows.GetModuleHandleW(null)); // returned HMODULE points to our executable file in memory | 262 | const base_address = os.getBaseAddress(); |
| 241 | const relative_address = address - base_address; | 263 | const relative_address = address - base_address; |
| 242 | std.debug.warn("{x} - {x} => {x}\n", address, base_address, relative_address); | 264 | std.debug.warn("{x} - {x} => {x}\n", address, base_address, relative_address); |
| 243 | try di.pdb.getSourceLine(relative_address); | 265 | try di.pdb.getSourceLine(relative_address); |
std/os/file.zig+1| ... | @@ -271,6 +271,7 @@ pub const File = struct { | ... | @@ -271,6 +271,7 @@ pub const File = struct { |
| 271 | const err = windows.GetLastError(); | 271 | const err = windows.GetLastError(); |
| 272 | return switch (err) { | 272 | return switch (err) { |
| 273 | windows.ERROR.INVALID_PARAMETER => unreachable, | 273 | windows.ERROR.INVALID_PARAMETER => unreachable, |
| 274 | windows.ERROR.INVALID_HANDLE => unreachable, | ||
| 274 | else => os.unexpectedErrorWindows(err), | 275 | else => os.unexpectedErrorWindows(err), |
| 275 | }; | 276 | }; |
| 276 | } | 277 | } |
std/os/index.zig+4-2| ... | @@ -661,6 +661,7 @@ pub fn getBaseAddress() usize { | ... | @@ -661,6 +661,7 @@ pub fn getBaseAddress() usize { |
| 661 | return phdr - @sizeOf(ElfHeader); | 661 | return phdr - @sizeOf(ElfHeader); |
| 662 | }, | 662 | }, |
| 663 | builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header), | 663 | builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header), |
| 664 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), | ||
| 664 | else => @compileError("Unsupported OS"), | 665 | else => @compileError("Unsupported OS"), |
| 665 | } | 666 | } |
| 666 | } | 667 | } |
| ... | @@ -2069,7 +2070,7 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons | ... | @@ -2069,7 +2070,7 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons |
| 2069 | } | 2070 | } |
| 2070 | 2071 | ||
| 2071 | // TODO make this a build variable that you can set | 2072 | // TODO make this a build variable that you can set |
| 2072 | const unexpected_error_tracing = false; | 2073 | const unexpected_error_tracing = true; |
| 2073 | const UnexpectedError = error{ | 2074 | const UnexpectedError = error{ |
| 2074 | /// The Operating System returned an undocumented error code. | 2075 | /// The Operating System returned an undocumented error code. |
| 2075 | Unexpected, | 2076 | Unexpected, |
| ... | @@ -2088,8 +2089,9 @@ pub fn unexpectedErrorPosix(errno: usize) UnexpectedError { | ... | @@ -2088,8 +2089,9 @@ pub fn unexpectedErrorPosix(errno: usize) UnexpectedError { |
| 2088 | /// Call this when you made a windows DLL call or something that does SetLastError | 2089 | /// Call this when you made a windows DLL call or something that does SetLastError |
| 2089 | /// and you get an unexpected error. | 2090 | /// and you get an unexpected error. |
| 2090 | pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { | 2091 | pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { |
| 2091 | if (true) { | 2092 | if (unexpected_error_tracing) { |
| 2092 | debug.warn("unexpected GetLastError(): {}\n", err); | 2093 | debug.warn("unexpected GetLastError(): {}\n", err); |
| 2094 | @breakpoint(); | ||
| 2093 | debug.dumpCurrentStackTrace(null); | 2095 | debug.dumpCurrentStackTrace(null); |
| 2094 | } | 2096 | } |
| 2095 | return error.Unexpected; | 2097 | return error.Unexpected; |
std/os/windows/index.zig+1| ... | @@ -3,6 +3,7 @@ const assert = std.debug.assert; | ... | @@ -3,6 +3,7 @@ const assert = std.debug.assert; |
| 3 | 3 | ||
| 4 | pub use @import("advapi32.zig"); | 4 | pub use @import("advapi32.zig"); |
| 5 | pub use @import("kernel32.zig"); | 5 | pub use @import("kernel32.zig"); |
| 6 | pub use @import("ntdll.zig"); | ||
| 6 | pub use @import("ole32.zig"); | 7 | pub use @import("ole32.zig"); |
| 7 | pub use @import("shell32.zig"); | 8 | pub use @import("shell32.zig"); |
| 8 | pub use @import("shlwapi.zig"); | 9 | pub use @import("shlwapi.zig"); |
std/os/windows/ntdll.zig created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | use @import("index.zig"); | ||
| 2 | |||
| 3 | pub extern "NtDll" stdcallcc fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) WORD; | ||