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;...@@ -18,7 +18,7 @@ const regValueNative = Dwarf.abi.regValueNative;
1818
19const SelfInfo = @This();19const SelfInfo = @This();
2020
21modules: std.AutoHashMapUnmanaged(usize, Module.DebugInfo),21modules: std.AutoArrayHashMapUnmanaged(usize, Module.DebugInfo),
22lookup_cache: Module.LookupCache,22lookup_cache: Module.LookupCache,
2323
24/// Indicates whether the `SelfInfo` implementation has support for this target.24/// Indicates whether the `SelfInfo` implementation has support for this target.
...@@ -68,18 +68,18 @@ comptime {...@@ -68,18 +68,18 @@ comptime {
6868
69pub const init: SelfInfo = .{69pub const init: SelfInfo = .{
70 .modules = .empty,70 .modules = .empty,
71 .lookup_cache = .init,71 .lookup_cache = if (Module.LookupCache != void) .init,
72};72};
7373
74pub fn deinit(self: *SelfInfo) void {74pub fn deinit(self: *SelfInfo, gpa: Allocator) 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...????75 for (self.modules.values()) |*di| di.deinit(gpa);
76 var it = self.modules.iterator();76 self.modules.deinit(gpa);
77 while (it.next()) |entry| {77 if (Module.LookupCache != void) self.lookup_cache.deinit(gpa);
78 const mdi = entry.value_ptr.*;78}
79 mdi.deinit(self.allocator);79comptime {
80 self.allocator.destroy(mdi);80 // `std.debug` does not currently utilize `deinit`, as it keeps hold of debug info for the
81 }81 // whole lifetime of the program. Let's try to avoid it bitrotting.
82 self.modules.deinit(self.allocator);82 _ = &deinit;
83}83}
8484
85pub fn unwindFrame(self: *SelfInfo, gpa: Allocator, context: *UnwindContext) !usize {85pub fn unwindFrame(self: *SelfInfo, gpa: Allocator, context: *UnwindContext) !usize {
...@@ -110,11 +110,12 @@ pub fn getModuleNameForAddress(self: *SelfInfo, gpa: Allocator, address: usize)...@@ -110,11 +110,12 @@ pub fn getModuleNameForAddress(self: *SelfInfo, gpa: Allocator, address: usize)
110110
111/// This type contains the target-specific implementation. It must expose the following declarations:111/// This type contains the target-specific implementation. It must expose the following declarations:
112///112///
113/// * `LookupCache: type`113/// * `LookupCache: type`, with the following declarations unless `LookupCache == void`:
114/// * `LookupCache.init: LookupCache`114/// * `init: LookupCache`
115/// * `deinit: fn (*LookupCache, Allocator) void`
115/// * `lookup: fn (*LookupCache, Allocator, address: usize) !Module`116/// * `lookup: fn (*LookupCache, Allocator, address: usize) !Module`
116/// * `key: fn (*const Module) usize`117/// * `key: fn (*const Module) usize`
117/// * `DebugInfo: type`118/// * `DebugInfo: type`, with the following declarations:
118/// * `DebugInfo.init: DebugInfo`119/// * `DebugInfo.init: DebugInfo`
119/// * `getSymbolAtAddress: fn (*const Module, Allocator, *DebugInfo, address: usize) !std.debug.Symbol`120/// * `getSymbolAtAddress: fn (*const Module, Allocator, *DebugInfo, address: usize) !std.debug.Symbol`
120///121///
lib/std/debug/SelfInfo/DarwinModule.zig+13-13
...@@ -578,9 +578,7 @@ fn unwindFrameMachO(...@@ -578,9 +578,7 @@ fn unwindFrameMachO(
578 return new_ip;578 return new_ip;
579}579}
580/// No cache needed, because `_dyld_get_image_header` etc are already fast.580/// No cache needed, because `_dyld_get_image_header` etc are already fast.
581pub const LookupCache = struct {581pub const LookupCache = void;
582 pub const init: LookupCache = .{};
583};
584pub const DebugInfo = struct {582pub const DebugInfo = struct {
585 unwind: ?struct {583 unwind: ?struct {
586 // Backed by the in-memory sections mapped by the loader584 // Backed by the in-memory sections mapped by the loader
...@@ -601,22 +599,24 @@ pub const DebugInfo = struct {...@@ -601,22 +599,24 @@ pub const DebugInfo = struct {
601 .full = null,599 .full = null,
602 };600 };
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
604 const OFile = struct {614 const OFile = struct {
605 dwarf: Dwarf,615 dwarf: Dwarf,
606 // MLUGG TODO: this could use an adapter to just index straight into the strtab!616 // MLUGG TODO: this could use an adapter to just index straight into the strtab!
607 addr_table: std.StringArrayHashMapUnmanaged(u64),617 addr_table: std.StringArrayHashMapUnmanaged(u64),
608 };618 };
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
620 fn loadOFile(gpa: Allocator, o_file_path: []const u8) !OFile {620 fn loadOFile(gpa: Allocator, o_file_path: []const u8) !OFile {
621 const mapped_mem = try mapDebugInfoFile(o_file_path);621 const mapped_mem = try mapDebugInfoFile(o_file_path);
622 errdefer posix.munmap(mapped_mem);622 errdefer posix.munmap(mapped_mem);
lib/std/debug/SelfInfo/ElfModule.zig+4-3
...@@ -4,9 +4,7 @@ build_id: ?[]const u8,...@@ -4,9 +4,7 @@ build_id: ?[]const u8,
4gnu_eh_frame: ?[]const u8,4gnu_eh_frame: ?[]const u8,
55
6/// No cache needed, because `dl_iterate_phdr` is already fast.6/// No cache needed, because `dl_iterate_phdr` is already fast.
7pub const LookupCache = struct {7pub const LookupCache = void;
8 pub const init: LookupCache = .{};
9};
108
11pub const DebugInfo = struct {9pub const DebugInfo = struct {
12 loaded_elf: ?Dwarf.ElfModule,10 loaded_elf: ?Dwarf.ElfModule,
...@@ -15,6 +13,9 @@ pub const DebugInfo = struct {...@@ -15,6 +13,9 @@ pub const DebugInfo = struct {
15 .loaded_elf = null,13 .loaded_elf = null,
16 .unwind = null,14 .unwind = null,
17 };15 };
16 pub fn deinit(di: *DebugInfo, gpa: Allocator) void {
17 if (di.loaded_elf) |*loaded_elf| loaded_elf.deinit(gpa);
18 }
18};19};
1920
20pub fn key(m: ElfModule) usize {21pub 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...@@ -167,6 +167,9 @@ fn loadLocationInfo(module: *const WindowsModule, gpa: Allocator, di: *DebugInfo
167pub const LookupCache = struct {167pub const LookupCache = struct {
168 modules: std.ArrayListUnmanaged(windows.MODULEENTRY32),168 modules: std.ArrayListUnmanaged(windows.MODULEENTRY32),
169 pub const init: LookupCache = .{ .modules = .empty };169 pub const init: LookupCache = .{ .modules = .empty };
170 pub fn deinit(lc: *LookupCache, gpa: Allocator) void {
171 lc.modules.deinit(gpa);
172 }
170};173};
171pub const DebugInfo = struct {174pub const DebugInfo = struct {
172 loaded: bool,175 loaded: bool,
...@@ -176,12 +179,6 @@ pub const DebugInfo = struct {...@@ -176,12 +179,6 @@ pub const DebugInfo = struct {
176 file: fs.File,179 file: fs.File,
177 section_handle: windows.HANDLE,180 section_handle: windows.HANDLE,
178 section_view: []const u8,181 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 }
185 },182 },
186183
187 dwarf: ?Dwarf,184 dwarf: ?Dwarf,
...@@ -199,11 +196,17 @@ pub const DebugInfo = struct {...@@ -199,11 +196,17 @@ pub const DebugInfo = struct {
199 .coff_section_headers = &.{},196 .coff_section_headers = &.{},
200 };197 };
201198
202 fn deinit(di: *DebugInfo, gpa: Allocator) void {199 pub fn deinit(di: *DebugInfo, gpa: Allocator) void {
200 if (!di.loaded) return;
203 if (di.dwarf) |*dwarf| dwarf.deinit(gpa);201 if (di.dwarf) |*dwarf| dwarf.deinit(gpa);
204 if (di.pdb) |*pdb| pdb.deinit();202 if (di.pdb) |*pdb| pdb.deinit();
205 gpa.free(di.coff_section_headers);203 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 }
207 }210 }
208211
209 fn getSymbolFromPdb(di: *DebugInfo, relocated_address: usize) !?std.debug.Symbol {212 fn getSymbolFromPdb(di: *DebugInfo, relocated_address: usize) !?std.debug.Symbol {