| ... | ... | @@ -183,6 +183,11 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { |
| 183 | 183 | return; |
| 184 | 184 | }; |
| 185 | 185 | const tty_config = detectTTYConfig(io.getStdErr()); |
| 186 | if (native_os == .windows) { |
| 187 | writeCurrentStackTraceWindows(stderr, debug_info, tty_config, ip) catch return; |
| 188 | return; |
| 189 | } |
| 190 | |
| 186 | 191 | printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return; |
| 187 | 192 | var it = StackIterator.init(null, bp); |
| 188 | 193 | while (it.next()) |return_address| { |
| ... | ... | @@ -595,7 +600,16 @@ pub noinline fn walkStackWindows(addresses: []usize) usize { |
| 595 | 600 | if (windows.ntdll.RtlLookupFunctionEntry(current_regs.ip, &image_base, &history_table)) |runtime_function| { |
| 596 | 601 | var handler_data: ?*anyopaque = null; |
| 597 | 602 | var establisher_frame: u64 = undefined; |
| 598 | | _ = windows.ntdll.RtlVirtualUnwind(windows.UNW_FLAG_NHANDLER, image_base, current_regs.ip, runtime_function, &context, &handler_data, &establisher_frame, null); |
| 603 | _ = windows.ntdll.RtlVirtualUnwind( |
| 604 | windows.UNW_FLAG_NHANDLER, |
| 605 | image_base, |
| 606 | current_regs.ip, |
| 607 | runtime_function, |
| 608 | &context, |
| 609 | &handler_data, |
| 610 | &establisher_frame, |
| 611 | null, |
| 612 | ); |
| 599 | 613 | } else { |
| 600 | 614 | // leaf function |
| 601 | 615 | context.setIp(@intToPtr(*u64, current_regs.sp).*); |
| ... | ... | @@ -769,23 +783,29 @@ test "machoSearchSymbols" { |
| 769 | 783 | try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?); |
| 770 | 784 | } |
| 771 | 785 | |
| 786 | fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void { |
| 787 | const module_name = debug_info.getModuleNameForAddress(address); |
| 788 | return printLineInfo( |
| 789 | out_stream, |
| 790 | null, |
| 791 | address, |
| 792 | "???", |
| 793 | module_name orelse "???", |
| 794 | tty_config, |
| 795 | printLineFromFileAnyOs, |
| 796 | ); |
| 797 | } |
| 798 | |
| 772 | 799 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void { |
| 773 | 800 | const module = debug_info.getModuleForAddress(address) catch |err| switch (err) { |
| 774 | | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 775 | | return printLineInfo( |
| 776 | | out_stream, |
| 777 | | null, |
| 778 | | address, |
| 779 | | "???", |
| 780 | | "???", |
| 781 | | tty_config, |
| 782 | | printLineFromFileAnyOs, |
| 783 | | ); |
| 784 | | }, |
| 801 | error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config), |
| 785 | 802 | else => return err, |
| 786 | 803 | }; |
| 787 | 804 | |
| 788 | | const symbol_info = try module.getSymbolAtAddress(debug_info.allocator, address); |
| 805 | const symbol_info = module.getSymbolAtAddress(debug_info.allocator, address) catch |err| switch (err) { |
| 806 | error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config), |
| 807 | else => return err, |
| 808 | }; |
| 789 | 809 | defer symbol_info.deinit(debug_info.allocator); |
| 790 | 810 | |
| 791 | 811 | return printLineInfo( |
| ... | ... | @@ -1275,15 +1295,16 @@ fn mapWholeFile(file: File) ![]align(mem.page_size) const u8 { |
| 1275 | 1295 | } |
| 1276 | 1296 | } |
| 1277 | 1297 | |
| 1278 | | pub const ModuleInfo = struct { |
| 1298 | pub const WindowsModuleInfo = struct { |
| 1279 | 1299 | base_address: usize, |
| 1280 | 1300 | size: u32, |
| 1301 | name: []const u8, |
| 1281 | 1302 | }; |
| 1282 | 1303 | |
| 1283 | 1304 | pub const DebugInfo = struct { |
| 1284 | 1305 | allocator: mem.Allocator, |
| 1285 | 1306 | address_map: std.AutoHashMap(usize, *ModuleDebugInfo), |
| 1286 | | modules: if (native_os == .windows) std.ArrayListUnmanaged(ModuleInfo) else void, |
| 1307 | modules: if (native_os == .windows) std.ArrayListUnmanaged(WindowsModuleInfo) else void, |
| 1287 | 1308 | |
| 1288 | 1309 | pub fn init(allocator: mem.Allocator) !DebugInfo { |
| 1289 | 1310 | var debug_info = DebugInfo{ |
| ... | ... | @@ -1299,7 +1320,6 @@ pub const DebugInfo = struct { |
| 1299 | 1320 | else => |err| return windows.unexpectedError(err), |
| 1300 | 1321 | } |
| 1301 | 1322 | } |
| 1302 | | |
| 1303 | 1323 | defer windows.CloseHandle(handle); |
| 1304 | 1324 | |
| 1305 | 1325 | var module_entry: windows.MODULEENTRY32 = undefined; |
| ... | ... | @@ -1313,6 +1333,7 @@ pub const DebugInfo = struct { |
| 1313 | 1333 | const module_info = try debug_info.modules.addOne(allocator); |
| 1314 | 1334 | module_info.base_address = @ptrToInt(module_entry.modBaseAddr); |
| 1315 | 1335 | module_info.size = module_entry.modBaseSize; |
| 1336 | module_info.name = allocator.dupe(u8, mem.sliceTo(&module_entry.szModule, 0)) catch &.{}; |
| 1316 | 1337 | module_valid = windows.kernel32.Module32Next(handle, &module_entry) == 1; |
| 1317 | 1338 | } |
| 1318 | 1339 | } |
| ... | ... | @@ -1328,7 +1349,12 @@ pub const DebugInfo = struct { |
| 1328 | 1349 | self.allocator.destroy(mdi); |
| 1329 | 1350 | } |
| 1330 | 1351 | self.address_map.deinit(); |
| 1331 | | if (native_os == .windows) self.modules.deinit(self.allocator); |
| 1352 | if (native_os == .windows) { |
| 1353 | for (self.modules.items) |module| { |
| 1354 | self.allocator.free(module.name); |
| 1355 | } |
| 1356 | self.modules.deinit(self.allocator); |
| 1357 | } |
| 1332 | 1358 | } |
| 1333 | 1359 | |
| 1334 | 1360 | pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo { |
| ... | ... | @@ -1351,6 +1377,22 @@ pub const DebugInfo = struct { |
| 1351 | 1377 | } |
| 1352 | 1378 | } |
| 1353 | 1379 | |
| 1380 | pub fn getModuleNameForAddress(self: *DebugInfo, address: usize) ?[]const u8 { |
| 1381 | if (builtin.zig_backend == .stage2_c) { |
| 1382 | return null; |
| 1383 | } else if (comptime builtin.target.isDarwin()) { |
| 1384 | return null; |
| 1385 | } else if (native_os == .windows) { |
| 1386 | return self.lookupModuleNameWin32(address); |
| 1387 | } else if (native_os == .haiku) { |
| 1388 | return null; |
| 1389 | } else if (comptime builtin.target.isWasm()) { |
| 1390 | return null; |
| 1391 | } else { |
| 1392 | return null; |
| 1393 | } |
| 1394 | } |
| 1395 | |
| 1354 | 1396 | fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ModuleDebugInfo { |
| 1355 | 1397 | const image_count = std.c._dyld_image_count(); |
| 1356 | 1398 | |
| ... | ... | @@ -1428,6 +1470,15 @@ pub const DebugInfo = struct { |
| 1428 | 1470 | return error.MissingDebugInfo; |
| 1429 | 1471 | } |
| 1430 | 1472 | |
| 1473 | fn lookupModuleNameWin32(self: *DebugInfo, address: usize) ?[]const u8 { |
| 1474 | for (self.modules.items) |module| { |
| 1475 | if (address >= module.base_address and address < module.base_address + module.size) { |
| 1476 | return module.name; |
| 1477 | } |
| 1478 | } |
| 1479 | return null; |
| 1480 | } |
| 1481 | |
| 1431 | 1482 | fn lookupModuleDl(self: *DebugInfo, address: usize) !*ModuleDebugInfo { |
| 1432 | 1483 | var ctx: struct { |
| 1433 | 1484 | // Input |