| 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 | 578 | "os/windows/error.zig" |
| 579 | 579 | "os/windows/index.zig" |
| 580 | 580 | "os/windows/kernel32.zig" |
| 581 | "os/windows/ntdll.zig" | |
| 581 | 582 | "os/windows/ole32.zig" |
| 582 | 583 | "os/windows/shell32.zig" |
| 583 | 584 | "os/windows/shlwapi.zig" |
std/debug/index.zig+23-1| ... | ... | @@ -195,6 +195,10 @@ pub inline fn getReturnAddress(frame_count: usize) usize { |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 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 | 202 | const AddressState = union(enum) { |
| 199 | 203 | NotLookingForStartAddress, |
| 200 | 204 | LookingForStartAddress: usize, |
| ... | ... | @@ -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 | 252 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { |
| 231 | 253 | switch (builtin.os) { |
| 232 | 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 | 259 | } |
| 238 | 260 | |
| 239 | 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 | 263 | const relative_address = address - base_address; |
| 242 | 264 | std.debug.warn("{x} - {x} => {x}\n", address, base_address, relative_address); |
| 243 | 265 | try di.pdb.getSourceLine(relative_address); |
std/os/file.zig+1| ... | ... | @@ -271,6 +271,7 @@ pub const File = struct { |
| 271 | 271 | const err = windows.GetLastError(); |
| 272 | 272 | return switch (err) { |
| 273 | 273 | windows.ERROR.INVALID_PARAMETER => unreachable, |
| 274 | windows.ERROR.INVALID_HANDLE => unreachable, | |
| 274 | 275 | else => os.unexpectedErrorWindows(err), |
| 275 | 276 | }; |
| 276 | 277 | } |
std/os/index.zig+4-2| ... | ... | @@ -661,6 +661,7 @@ pub fn getBaseAddress() usize { |
| 661 | 661 | return phdr - @sizeOf(ElfHeader); |
| 662 | 662 | }, |
| 663 | 663 | builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header), |
| 664 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), | |
| 664 | 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 | 2070 | } |
| 2070 | 2071 | |
| 2071 | 2072 | // TODO make this a build variable that you can set |
| 2072 | const unexpected_error_tracing = false; | |
| 2073 | const unexpected_error_tracing = true; | |
| 2073 | 2074 | const UnexpectedError = error{ |
| 2074 | 2075 | /// The Operating System returned an undocumented error code. |
| 2075 | 2076 | Unexpected, |
| ... | ... | @@ -2088,8 +2089,9 @@ pub fn unexpectedErrorPosix(errno: usize) UnexpectedError { |
| 2088 | 2089 | /// Call this when you made a windows DLL call or something that does SetLastError |
| 2089 | 2090 | /// and you get an unexpected error. |
| 2090 | 2091 | pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { |
| 2091 | if (true) { | |
| 2092 | if (unexpected_error_tracing) { | |
| 2092 | 2093 | debug.warn("unexpected GetLastError(): {}\n", err); |
| 2094 | @breakpoint(); | |
| 2093 | 2095 | debug.dumpCurrentStackTrace(null); |
| 2094 | 2096 | } |
| 2095 | 2097 | return error.Unexpected; |
std/os/windows/index.zig+1| ... | ... | @@ -3,6 +3,7 @@ const assert = std.debug.assert; |
| 3 | 3 | |
| 4 | 4 | pub use @import("advapi32.zig"); |
| 5 | 5 | pub use @import("kernel32.zig"); |
| 6 | pub use @import("ntdll.zig"); | |
| 6 | 7 | pub use @import("ole32.zig"); |
| 7 | 8 | pub use @import("shell32.zig"); |
| 8 | 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; |