authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-02 18:47:31+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-30 13:44:50+01:00
log665f13b0cde4b9c2e69b139a87d272a67a9489e1
tree88598b5eb7d17a86ea15a93ca15dbab5be6594d2
parentba3f38959a31ace9af1816f16cda6c0717518b7f
signaturelock-open Commit is signed but in an unrecognized format.

SelfInfo deinit magic


4 files changed, 43 insertions(+), 38 deletions(-)

lib/std/debug/SelfInfo.zig+15-14
......@@ -18,7 +18,7 @@ const regValueNative = Dwarf.abi.regValueNative;
1818
1919const SelfInfo = @This();
2020
21modules: std.AutoHashMapUnmanaged(usize, Module.DebugInfo),
21modules: std.AutoArrayHashMapUnmanaged(usize, Module.DebugInfo),
2222lookup_cache: Module.LookupCache,
2323
2424/// Indicates whether the `SelfInfo` implementation has support for this target.
......@@ -68,18 +68,18 @@ comptime {
6868
6969pub const init: SelfInfo = .{
7070 .modules = .empty,
71 .lookup_cache = .init,
71 .lookup_cache = if (Module.LookupCache != void) .init,
7272};
7373
74pub fn deinit(self: *SelfInfo) void {
75 // MLUGG TODO: that's amusing, this function is straight-up unused. i... wonder if it even should be used anywhere? perhaps not... so perhaps it should not even exist...????
76 var it = self.modules.iterator();
77 while (it.next()) |entry| {
78 const mdi = entry.value_ptr.*;
79 mdi.deinit(self.allocator);
80 self.allocator.destroy(mdi);
81 }
82 self.modules.deinit(self.allocator);
74pub fn deinit(self: *SelfInfo, gpa: Allocator) void {
75 for (self.modules.values()) |*di| di.deinit(gpa);
76 self.modules.deinit(gpa);
77 if (Module.LookupCache != void) self.lookup_cache.deinit(gpa);
78}
79comptime {
80 // `std.debug` does not currently utilize `deinit`, as it keeps hold of debug info for the
81 // whole lifetime of the program. Let's try to avoid it bitrotting.
82 _ = &deinit;
8383}
8484
8585pub fn unwindFrame(self: *SelfInfo, gpa: Allocator, context: *UnwindContext) !usize {
......@@ -110,11 +110,12 @@ pub fn getModuleNameForAddress(self: *SelfInfo, gpa: Allocator, address: usize)
110110
111111/// This type contains the target-specific implementation. It must expose the following declarations:
112112///
113/// * `LookupCache: type`
114/// * `LookupCache.init: LookupCache`
113/// * `LookupCache: type`, with the following declarations unless `LookupCache == void`:
114/// * `init: LookupCache`
115/// * `deinit: fn (*LookupCache, Allocator) void`
115116/// * `lookup: fn (*LookupCache, Allocator, address: usize) !Module`
116117/// * `key: fn (*const Module) usize`
117/// * `DebugInfo: type`
118/// * `DebugInfo: type`, with the following declarations:
118119/// * `DebugInfo.init: DebugInfo`
119120/// * `getSymbolAtAddress: fn (*const Module, Allocator, *DebugInfo, address: usize) !std.debug.Symbol`
120121///
lib/std/debug/SelfInfo/DarwinModule.zig+13-13
......@@ -578,9 +578,7 @@ fn unwindFrameMachO(
578578 return new_ip;
579579}
580580/// No cache needed, because `_dyld_get_image_header` etc are already fast.
581pub const LookupCache = struct {
582 pub const init: LookupCache = .{};
583};
581pub const LookupCache = void;
584582pub const DebugInfo = struct {
585583 unwind: ?struct {
586584 // Backed by the in-memory sections mapped by the loader
......@@ -601,22 +599,24 @@ pub const DebugInfo = struct {
601599 .full = null,
602600 };
603601
602 pub fn deinit(di: *DebugInfo, gpa: Allocator) void {
603 if (di.full) |*full| {
604 for (full.ofiles.values()) |*ofile| {
605 ofile.dwarf.deinit(gpa);
606 ofile.addr_table.deinit(gpa);
607 }
608 full.ofiles.deinit(gpa);
609 gpa.free(full.symbols);
610 posix.munmap(full.mapped_memory);
611 }
612 }
613
604614 const OFile = struct {
605615 dwarf: Dwarf,
606616 // MLUGG TODO: this could use an adapter to just index straight into the strtab!
607617 addr_table: std.StringArrayHashMapUnmanaged(u64),
608618 };
609619
610 fn deinit(di: *DebugInfo, gpa: Allocator) void {
611 for (di.full.ofiles.values()) |*ofile| {
612 ofile.dwarf.deinit(gpa);
613 ofile.addr_table.deinit(gpa);
614 }
615 di.full.ofiles.deinit();
616 gpa.free(di.full.symbols);
617 posix.munmap(di.full.mapped_memory);
618 }
619
620620 fn loadOFile(gpa: Allocator, o_file_path: []const u8) !OFile {
621621 const mapped_mem = try mapDebugInfoFile(o_file_path);
622622 errdefer posix.munmap(mapped_mem);
lib/std/debug/SelfInfo/ElfModule.zig+4-3
......@@ -4,9 +4,7 @@ build_id: ?[]const u8,
44gnu_eh_frame: ?[]const u8,
55
66/// No cache needed, because `dl_iterate_phdr` is already fast.
7pub const LookupCache = struct {
8 pub const init: LookupCache = .{};
9};
7pub const LookupCache = void;
108
119pub const DebugInfo = struct {
1210 loaded_elf: ?Dwarf.ElfModule,
......@@ -15,6 +13,9 @@ pub const DebugInfo = struct {
1513 .loaded_elf = null,
1614 .unwind = null,
1715 };
16 pub fn deinit(di: *DebugInfo, gpa: Allocator) void {
17 if (di.loaded_elf) |*loaded_elf| loaded_elf.deinit(gpa);
18 }
1819};
1920
2021pub fn key(m: ElfModule) usize {
lib/std/debug/SelfInfo/WindowsModule.zig+11-8
......@@ -167,6 +167,9 @@ fn loadLocationInfo(module: *const WindowsModule, gpa: Allocator, di: *DebugInfo
167167pub const LookupCache = struct {
168168 modules: std.ArrayListUnmanaged(windows.MODULEENTRY32),
169169 pub const init: LookupCache = .{ .modules = .empty };
170 pub fn deinit(lc: *LookupCache, gpa: Allocator) void {
171 lc.modules.deinit(gpa);
172 }
170173};
171174pub const DebugInfo = struct {
172175 loaded: bool,
......@@ -176,12 +179,6 @@ pub const DebugInfo = struct {
176179 file: fs.File,
177180 section_handle: windows.HANDLE,
178181 section_view: []const u8,
179 fn deinit(mapped: @This()) void {
180 const process_handle = windows.GetCurrentProcess();
181 assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(mapped.section_view.ptr)) == .SUCCESS);
182 windows.CloseHandle(mapped.section_handle);
183 mapped.file.close();
184 }
185182 },
186183
187184 dwarf: ?Dwarf,
......@@ -199,11 +196,17 @@ pub const DebugInfo = struct {
199196 .coff_section_headers = &.{},
200197 };
201198
202 fn deinit(di: *DebugInfo, gpa: Allocator) void {
199 pub fn deinit(di: *DebugInfo, gpa: Allocator) void {
200 if (!di.loaded) return;
203201 if (di.dwarf) |*dwarf| dwarf.deinit(gpa);
204202 if (di.pdb) |*pdb| pdb.deinit();
205203 gpa.free(di.coff_section_headers);
206 if (di.mapped_file) |mapped| mapped.deinit();
204 if (di.mapped_file) |mapped| {
205 const process_handle = windows.GetCurrentProcess();
206 assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(mapped.section_view.ptr)) == .SUCCESS);
207 windows.CloseHandle(mapped.section_handle);
208 mapped.file.close();
209 }
207210 }
208211
209212 fn getSymbolFromPdb(di: *DebugInfo, relocated_address: usize) !?std.debug.Symbol {