| ... | @@ -102,9 +102,9 @@ pub fn getStderrMutex() *std.Thread.Mutex { | ... | @@ -102,9 +102,9 @@ pub fn getStderrMutex() *std.Thread.Mutex { |
| 102 | } | 102 | } |
| 103 | | 103 | |
| 104 | /// TODO multithreaded awareness | 104 | /// TODO multithreaded awareness |
| 105 | var self_debug_info: ?DebugInfo = null; | 105 | var self_debug_info: ?Info = null; |
| 106 | | 106 | |
| 107 | pub fn getSelfDebugInfo() !*DebugInfo { | 107 | pub fn getSelfDebugInfo() !*Info { |
| 108 | if (self_debug_info) |*info| { | 108 | if (self_debug_info) |*info| { |
| 109 | return info; | 109 | return info; |
| 110 | } else { | 110 | } else { |
| ... | @@ -346,7 +346,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT | ... | @@ -346,7 +346,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT |
| 346 | stack_trace.index = slice.len; | 346 | stack_trace.index = slice.len; |
| 347 | } else { | 347 | } else { |
| 348 | // TODO: This should use the DWARF unwinder if .eh_frame_hdr is available (so that full debug info parsing isn't required). | 348 | // TODO: This should use the DWARF unwinder if .eh_frame_hdr is available (so that full debug info parsing isn't required). |
| 349 | // A new path for loading DebugInfo needs to be created which will only attempt to parse in-memory sections, because | 349 | // A new path for loading Info needs to be created which will only attempt to parse in-memory sections, because |
| 350 | // stopping to load other debug info (ie. source line info) from disk here is not required for unwinding. | 350 | // stopping to load other debug info (ie. source line info) from disk here is not required for unwinding. |
| 351 | var it = StackIterator.init(first_address, null); | 351 | var it = StackIterator.init(first_address, null); |
| 352 | defer it.deinit(); | 352 | defer it.deinit(); |
| ... | @@ -524,7 +524,7 @@ pub fn writeStackTrace( | ... | @@ -524,7 +524,7 @@ pub fn writeStackTrace( |
| 524 | stack_trace: std.builtin.StackTrace, | 524 | stack_trace: std.builtin.StackTrace, |
| 525 | out_stream: anytype, | 525 | out_stream: anytype, |
| 526 | allocator: mem.Allocator, | 526 | allocator: mem.Allocator, |
| 527 | debug_info: *DebugInfo, | 527 | debug_info: *Info, |
| 528 | tty_config: io.tty.Config, | 528 | tty_config: io.tty.Config, |
| 529 | ) !void { | 529 | ) !void { |
| 530 | _ = allocator; | 530 | _ = allocator; |
| ... | @@ -561,11 +561,11 @@ pub const StackIterator = struct { | ... | @@ -561,11 +561,11 @@ pub const StackIterator = struct { |
| 561 | fp: usize, | 561 | fp: usize, |
| 562 | ma: MemoryAccessor = MemoryAccessor.init, | 562 | ma: MemoryAccessor = MemoryAccessor.init, |
| 563 | | 563 | |
| 564 | // When DebugInfo and a register context is available, this iterator can unwind | 564 | // When Info and a register context is available, this iterator can unwind |
| 565 | // stacks with frames that don't use a frame pointer (ie. -fomit-frame-pointer), | 565 | // stacks with frames that don't use a frame pointer (ie. -fomit-frame-pointer), |
| 566 | // using DWARF and MachO unwind info. | 566 | // using DWARF and MachO unwind info. |
| 567 | unwind_state: if (have_ucontext) ?struct { | 567 | unwind_state: if (have_ucontext) ?struct { |
| 568 | debug_info: *DebugInfo, | 568 | debug_info: *Info, |
| 569 | dwarf_context: DW.UnwindContext, | 569 | dwarf_context: DW.UnwindContext, |
| 570 | last_error: ?UnwindError = null, | 570 | last_error: ?UnwindError = null, |
| 571 | failed: bool = false, | 571 | failed: bool = false, |
| ... | @@ -590,7 +590,7 @@ pub const StackIterator = struct { | ... | @@ -590,7 +590,7 @@ pub const StackIterator = struct { |
| 590 | }; | 590 | }; |
| 591 | } | 591 | } |
| 592 | | 592 | |
| 593 | pub fn initWithContext(first_address: ?usize, debug_info: *DebugInfo, context: *const posix.ucontext_t) !StackIterator { | 593 | pub fn initWithContext(first_address: ?usize, debug_info: *Info, context: *const posix.ucontext_t) !StackIterator { |
| 594 | // The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that | 594 | // The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that |
| 595 | // the frame pointer register is always used, so on this platform we can safely use the FP-based unwinder. | 595 | // the frame pointer register is always used, so on this platform we can safely use the FP-based unwinder. |
| 596 | if (comptime builtin.target.isDarwin() and native_arch == .aarch64) { | 596 | if (comptime builtin.target.isDarwin() and native_arch == .aarch64) { |
| ... | @@ -850,7 +850,7 @@ const have_msync = switch (native_os) { | ... | @@ -850,7 +850,7 @@ const have_msync = switch (native_os) { |
| 850 | | 850 | |
| 851 | pub fn writeCurrentStackTrace( | 851 | pub fn writeCurrentStackTrace( |
| 852 | out_stream: anytype, | 852 | out_stream: anytype, |
| 853 | debug_info: *DebugInfo, | 853 | debug_info: *Info, |
| 854 | tty_config: io.tty.Config, | 854 | tty_config: io.tty.Config, |
| 855 | start_addr: ?usize, | 855 | start_addr: ?usize, |
| 856 | ) !void { | 856 | ) !void { |
| ... | @@ -936,7 +936,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w | ... | @@ -936,7 +936,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w |
| 936 | | 936 | |
| 937 | pub fn writeStackTraceWindows( | 937 | pub fn writeStackTraceWindows( |
| 938 | out_stream: anytype, | 938 | out_stream: anytype, |
| 939 | debug_info: *DebugInfo, | 939 | debug_info: *Info, |
| 940 | tty_config: io.tty.Config, | 940 | tty_config: io.tty.Config, |
| 941 | context: *const windows.CONTEXT, | 941 | context: *const windows.CONTEXT, |
| 942 | start_addr: ?usize, | 942 | start_addr: ?usize, |
| ... | @@ -1000,7 +1000,7 @@ test machoSearchSymbols { | ... | @@ -1000,7 +1000,7 @@ test machoSearchSymbols { |
| 1000 | try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?); | 1000 | try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?); |
| 1001 | } | 1001 | } |
| 1002 | | 1002 | |
| 1003 | fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void { | 1003 | fn printUnknownSource(debug_info: *Info, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void { |
| 1004 | const module_name = debug_info.getModuleNameForAddress(address); | 1004 | const module_name = debug_info.getModuleNameForAddress(address); |
| 1005 | return printLineInfo( | 1005 | return printLineInfo( |
| 1006 | out_stream, | 1006 | out_stream, |
| ... | @@ -1013,14 +1013,14 @@ fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usiz | ... | @@ -1013,14 +1013,14 @@ fn printUnknownSource(debug_info: *DebugInfo, out_stream: anytype, address: usiz |
| 1013 | ); | 1013 | ); |
| 1014 | } | 1014 | } |
| 1015 | | 1015 | |
| 1016 | fn printLastUnwindError(it: *StackIterator, debug_info: *DebugInfo, out_stream: anytype, tty_config: io.tty.Config) void { | 1016 | fn printLastUnwindError(it: *StackIterator, debug_info: *Info, out_stream: anytype, tty_config: io.tty.Config) void { |
| 1017 | if (!have_ucontext) return; | 1017 | if (!have_ucontext) return; |
| 1018 | if (it.getLastError()) |unwind_error| { | 1018 | if (it.getLastError()) |unwind_error| { |
| 1019 | printUnwindError(debug_info, out_stream, unwind_error.address, unwind_error.err, tty_config) catch {}; | 1019 | printUnwindError(debug_info, out_stream, unwind_error.address, unwind_error.err, tty_config) catch {}; |
| 1020 | } | 1020 | } |
| 1021 | } | 1021 | } |
| 1022 | | 1022 | |
| 1023 | fn printUnwindError(debug_info: *DebugInfo, out_stream: anytype, address: usize, err: UnwindError, tty_config: io.tty.Config) !void { | 1023 | fn printUnwindError(debug_info: *Info, out_stream: anytype, address: usize, err: UnwindError, tty_config: io.tty.Config) !void { |
| 1024 | const module_name = debug_info.getModuleNameForAddress(address) orelse "???"; | 1024 | const module_name = debug_info.getModuleNameForAddress(address) orelse "???"; |
| 1025 | try tty_config.setColor(out_stream, .dim); | 1025 | try tty_config.setColor(out_stream, .dim); |
| 1026 | if (err == error.MissingDebugInfo) { | 1026 | if (err == error.MissingDebugInfo) { |
| ... | @@ -1031,7 +1031,7 @@ fn printUnwindError(debug_info: *DebugInfo, out_stream: anytype, address: usize, | ... | @@ -1031,7 +1031,7 @@ fn printUnwindError(debug_info: *DebugInfo, out_stream: anytype, address: usize, |
| 1031 | try tty_config.setColor(out_stream, .reset); | 1031 | try tty_config.setColor(out_stream, .reset); |
| 1032 | } | 1032 | } |
| 1033 | | 1033 | |
| 1034 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void { | 1034 | pub fn printSourceAtAddress(debug_info: *Info, out_stream: anytype, address: usize, tty_config: io.tty.Config) !void { |
| 1035 | const module = debug_info.getModuleForAddress(address) catch |err| switch (err) { | 1035 | const module = debug_info.getModuleForAddress(address) catch |err| switch (err) { |
| 1036 | error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config), | 1036 | error.MissingDebugInfo, error.InvalidDebugInfo => return printUnknownSource(debug_info, out_stream, address, tty_config), |
| 1037 | else => return err, | 1037 | else => return err, |
| ... | @@ -1105,9 +1105,9 @@ fn printLineInfo( | ... | @@ -1105,9 +1105,9 @@ fn printLineInfo( |
| 1105 | pub const OpenSelfDebugInfoError = error{ | 1105 | pub const OpenSelfDebugInfoError = error{ |
| 1106 | MissingDebugInfo, | 1106 | MissingDebugInfo, |
| 1107 | UnsupportedOperatingSystem, | 1107 | UnsupportedOperatingSystem, |
| 1108 | } || @typeInfo(@typeInfo(@TypeOf(DebugInfo.init)).Fn.return_type.?).ErrorUnion.error_set; | 1108 | } || @typeInfo(@typeInfo(@TypeOf(Info.init)).Fn.return_type.?).ErrorUnion.error_set; |
| 1109 | | 1109 | |
| 1110 | pub fn openSelfDebugInfo(allocator: mem.Allocator) OpenSelfDebugInfoError!DebugInfo { | 1110 | pub fn openSelfDebugInfo(allocator: mem.Allocator) OpenSelfDebugInfoError!Info { |
| 1111 | nosuspend { | 1111 | nosuspend { |
| 1112 | if (builtin.strip_debug_info) | 1112 | if (builtin.strip_debug_info) |
| 1113 | return error.MissingDebugInfo; | 1113 | return error.MissingDebugInfo; |
| ... | @@ -1124,7 +1124,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) OpenSelfDebugInfoError!DebugI | ... | @@ -1124,7 +1124,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) OpenSelfDebugInfoError!DebugI |
| 1124 | .solaris, | 1124 | .solaris, |
| 1125 | .illumos, | 1125 | .illumos, |
| 1126 | .windows, | 1126 | .windows, |
| 1127 | => return try DebugInfo.init(allocator), | 1127 | => return try Info.init(allocator), |
| 1128 | else => return error.UnsupportedOperatingSystem, | 1128 | else => return error.UnsupportedOperatingSystem, |
| 1129 | } | 1129 | } |
| 1130 | } | 1130 | } |
| ... | @@ -1759,13 +1759,13 @@ pub const WindowsModuleInfo = struct { | ... | @@ -1759,13 +1759,13 @@ pub const WindowsModuleInfo = struct { |
| 1759 | } = null, | 1759 | } = null, |
| 1760 | }; | 1760 | }; |
| 1761 | | 1761 | |
| 1762 | pub const DebugInfo = struct { | 1762 | pub const Info = struct { |
| 1763 | allocator: mem.Allocator, | 1763 | allocator: mem.Allocator, |
| 1764 | address_map: std.AutoHashMap(usize, *ModuleDebugInfo), | 1764 | address_map: std.AutoHashMap(usize, *ModuleDebugInfo), |
| 1765 | modules: if (native_os == .windows) std.ArrayListUnmanaged(WindowsModuleInfo) else void, | 1765 | modules: if (native_os == .windows) std.ArrayListUnmanaged(WindowsModuleInfo) else void, |
| 1766 | | 1766 | |
| 1767 | pub fn init(allocator: mem.Allocator) !DebugInfo { | 1767 | pub fn init(allocator: mem.Allocator) !Info { |
| 1768 | var debug_info = DebugInfo{ | 1768 | var debug_info = Info{ |
| 1769 | .allocator = allocator, | 1769 | .allocator = allocator, |
| 1770 | .address_map = std.AutoHashMap(usize, *ModuleDebugInfo).init(allocator), | 1770 | .address_map = std.AutoHashMap(usize, *ModuleDebugInfo).init(allocator), |
| 1771 | .modules = if (native_os == .windows) .{} else {}, | 1771 | .modules = if (native_os == .windows) .{} else {}, |
| ... | @@ -1808,7 +1808,7 @@ pub const DebugInfo = struct { | ... | @@ -1808,7 +1808,7 @@ pub const DebugInfo = struct { |
| 1808 | return debug_info; | 1808 | return debug_info; |
| 1809 | } | 1809 | } |
| 1810 | | 1810 | |
| 1811 | pub fn deinit(self: *DebugInfo) void { | 1811 | pub fn deinit(self: *Info) void { |
| 1812 | var it = self.address_map.iterator(); | 1812 | var it = self.address_map.iterator(); |
| 1813 | while (it.next()) |entry| { | 1813 | while (it.next()) |entry| { |
| 1814 | const mdi = entry.value_ptr.*; | 1814 | const mdi = entry.value_ptr.*; |
| ... | @@ -1825,7 +1825,7 @@ pub const DebugInfo = struct { | ... | @@ -1825,7 +1825,7 @@ pub const DebugInfo = struct { |
| 1825 | } | 1825 | } |
| 1826 | } | 1826 | } |
| 1827 | | 1827 | |
| 1828 | pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo { | 1828 | pub fn getModuleForAddress(self: *Info, address: usize) !*ModuleDebugInfo { |
| 1829 | if (comptime builtin.target.isDarwin()) { | 1829 | if (comptime builtin.target.isDarwin()) { |
| 1830 | return self.lookupModuleDyld(address); | 1830 | return self.lookupModuleDyld(address); |
| 1831 | } else if (native_os == .windows) { | 1831 | } else if (native_os == .windows) { |
| ... | @@ -1842,7 +1842,7 @@ pub const DebugInfo = struct { | ... | @@ -1842,7 +1842,7 @@ pub const DebugInfo = struct { |
| 1842 | // Returns the module name for a given address. | 1842 | // Returns the module name for a given address. |
| 1843 | // This can be called when getModuleForAddress fails, so implementations should provide | 1843 | // This can be called when getModuleForAddress fails, so implementations should provide |
| 1844 | // a path that doesn't rely on any side-effects of a prior successful module lookup. | 1844 | // a path that doesn't rely on any side-effects of a prior successful module lookup. |
| 1845 | pub fn getModuleNameForAddress(self: *DebugInfo, address: usize) ?[]const u8 { | 1845 | pub fn getModuleNameForAddress(self: *Info, address: usize) ?[]const u8 { |
| 1846 | if (comptime builtin.target.isDarwin()) { | 1846 | if (comptime builtin.target.isDarwin()) { |
| 1847 | return self.lookupModuleNameDyld(address); | 1847 | return self.lookupModuleNameDyld(address); |
| 1848 | } else if (native_os == .windows) { | 1848 | } else if (native_os == .windows) { |
| ... | @@ -1856,7 +1856,7 @@ pub const DebugInfo = struct { | ... | @@ -1856,7 +1856,7 @@ pub const DebugInfo = struct { |
| 1856 | } | 1856 | } |
| 1857 | } | 1857 | } |
| 1858 | | 1858 | |
| 1859 | fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ModuleDebugInfo { | 1859 | fn lookupModuleDyld(self: *Info, address: usize) !*ModuleDebugInfo { |
| 1860 | const image_count = std.c._dyld_image_count(); | 1860 | const image_count = std.c._dyld_image_count(); |
| 1861 | | 1861 | |
| 1862 | var i: u32 = 0; | 1862 | var i: u32 = 0; |
| ... | @@ -1922,7 +1922,7 @@ pub const DebugInfo = struct { | ... | @@ -1922,7 +1922,7 @@ pub const DebugInfo = struct { |
| 1922 | return error.MissingDebugInfo; | 1922 | return error.MissingDebugInfo; |
| 1923 | } | 1923 | } |
| 1924 | | 1924 | |
| 1925 | fn lookupModuleNameDyld(self: *DebugInfo, address: usize) ?[]const u8 { | 1925 | fn lookupModuleNameDyld(self: *Info, address: usize) ?[]const u8 { |
| 1926 | _ = self; | 1926 | _ = self; |
| 1927 | const image_count = std.c._dyld_image_count(); | 1927 | const image_count = std.c._dyld_image_count(); |
| 1928 | | 1928 | |
| ... | @@ -1960,7 +1960,7 @@ pub const DebugInfo = struct { | ... | @@ -1960,7 +1960,7 @@ pub const DebugInfo = struct { |
| 1960 | return null; | 1960 | return null; |
| 1961 | } | 1961 | } |
| 1962 | | 1962 | |
| 1963 | fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ModuleDebugInfo { | 1963 | fn lookupModuleWin32(self: *Info, address: usize) !*ModuleDebugInfo { |
| 1964 | for (self.modules.items) |*module| { | 1964 | for (self.modules.items) |*module| { |
| 1965 | if (address >= module.base_address and address < module.base_address + module.size) { | 1965 | if (address >= module.base_address and address < module.base_address + module.size) { |
| 1966 | if (self.address_map.get(module.base_address)) |obj_di| { | 1966 | if (self.address_map.get(module.base_address)) |obj_di| { |
| ... | @@ -2050,7 +2050,7 @@ pub const DebugInfo = struct { | ... | @@ -2050,7 +2050,7 @@ pub const DebugInfo = struct { |
| 2050 | return error.MissingDebugInfo; | 2050 | return error.MissingDebugInfo; |
| 2051 | } | 2051 | } |
| 2052 | | 2052 | |
| 2053 | fn lookupModuleNameWin32(self: *DebugInfo, address: usize) ?[]const u8 { | 2053 | fn lookupModuleNameWin32(self: *Info, address: usize) ?[]const u8 { |
| 2054 | for (self.modules.items) |module| { | 2054 | for (self.modules.items) |module| { |
| 2055 | if (address >= module.base_address and address < module.base_address + module.size) { | 2055 | if (address >= module.base_address and address < module.base_address + module.size) { |
| 2056 | return module.name; | 2056 | return module.name; |
| ... | @@ -2059,7 +2059,7 @@ pub const DebugInfo = struct { | ... | @@ -2059,7 +2059,7 @@ pub const DebugInfo = struct { |
| 2059 | return null; | 2059 | return null; |
| 2060 | } | 2060 | } |
| 2061 | | 2061 | |
| 2062 | fn lookupModuleNameDl(self: *DebugInfo, address: usize) ?[]const u8 { | 2062 | fn lookupModuleNameDl(self: *Info, address: usize) ?[]const u8 { |
| 2063 | _ = self; | 2063 | _ = self; |
| 2064 | | 2064 | |
| 2065 | var ctx: struct { | 2065 | var ctx: struct { |
| ... | @@ -2097,7 +2097,7 @@ pub const DebugInfo = struct { | ... | @@ -2097,7 +2097,7 @@ pub const DebugInfo = struct { |
| 2097 | return null; | 2097 | return null; |
| 2098 | } | 2098 | } |
| 2099 | | 2099 | |
| 2100 | fn lookupModuleDl(self: *DebugInfo, address: usize) !*ModuleDebugInfo { | 2100 | fn lookupModuleDl(self: *Info, address: usize) !*ModuleDebugInfo { |
| 2101 | var ctx: struct { | 2101 | var ctx: struct { |
| 2102 | // Input | 2102 | // Input |
| 2103 | address: usize, | 2103 | address: usize, |
| ... | @@ -2191,13 +2191,13 @@ pub const DebugInfo = struct { | ... | @@ -2191,13 +2191,13 @@ pub const DebugInfo = struct { |
| 2191 | return obj_di; | 2191 | return obj_di; |
| 2192 | } | 2192 | } |
| 2193 | | 2193 | |
| 2194 | fn lookupModuleHaiku(self: *DebugInfo, address: usize) !*ModuleDebugInfo { | 2194 | fn lookupModuleHaiku(self: *Info, address: usize) !*ModuleDebugInfo { |
| 2195 | _ = self; | 2195 | _ = self; |
| 2196 | _ = address; | 2196 | _ = address; |
| 2197 | @panic("TODO implement lookup module for Haiku"); | 2197 | @panic("TODO implement lookup module for Haiku"); |
| 2198 | } | 2198 | } |
| 2199 | | 2199 | |
| 2200 | fn lookupModuleWasm(self: *DebugInfo, address: usize) !*ModuleDebugInfo { | 2200 | fn lookupModuleWasm(self: *Info, address: usize) !*ModuleDebugInfo { |
| 2201 | _ = self; | 2201 | _ = self; |
| 2202 | _ = address; | 2202 | _ = address; |
| 2203 | @panic("TODO implement lookup module for Wasm"); | 2203 | @panic("TODO implement lookup module for Wasm"); |