diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-04-21 10:46:04 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-04-21 11:48:15 +0200 |
| commit | 28ca203b7132ba0513a3854bd3bcbd0ee9bca067 (patch) | |
| tree | eabc9d3522d89fe8d050197bd6dc1c8a14c349a5 /lib/std/debug.zig | |
| parent | 96c1314443bdf26442a2c9fdffa03f2afffbcb8e (diff) | |
| download | zig-28ca203b7132ba0513a3854bd3bcbd0ee9bca067.tar.gz zig-28ca203b7132ba0513a3854bd3bcbd0ee9bca067.zip | |
debug: fix resource (de)allocation for Elf and Coff targets
With this change, it is now possible to safely call
`var di = std.debug.openSelfDebugInfo(gpa)`. Calling then
`di.deinit()` on the object will correctly free all allocated
resources.
Ensure we store the result of `mmap` with correct alignment.
Diffstat (limited to 'lib/std/debug.zig')
| -rw-r--r-- | lib/std/debug.zig | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 58038ef522..5ee4973c1a 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -41,7 +41,7 @@ pub const SymbolInfo = struct { compile_unit_name: []const u8 = "???", line_info: ?LineInfo = null, - pub fn deinit(self: @This(), allocator: mem.Allocator) void { + pub fn deinit(self: SymbolInfo, allocator: mem.Allocator) void { if (self.line_info) |li| { li.deinit(allocator); } @@ -50,6 +50,13 @@ pub const SymbolInfo = struct { const PdbOrDwarf = union(enum) { pdb: pdb.Pdb, dwarf: DW.DwarfInfo, + + fn deinit(self: *PdbOrDwarf, allocator: mem.Allocator) void { + switch (self.*) { + .pdb => |*inner| inner.deinit(), + .dwarf => |*inner| inner.deinit(allocator), + } + } }; var stderr_mutex = std.Thread.Mutex{}; @@ -793,6 +800,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo errdefer coff_file.close(); const coff_obj = try allocator.create(coff.Coff); + errdefer allocator.destroy(coff_obj); coff_obj.* = coff.Coff.init(allocator, coff_file); var di = ModuleDebugInfo{ @@ -1386,7 +1394,7 @@ pub const DebugInfo = struct { pub const ModuleDebugInfo = switch (native_os) { .macos, .ios, .watchos, .tvos => struct { base_address: usize, - mapped_memory: []const u8, + mapped_memory: []align(mem.page_size) const u8, symbols: []const MachoSymbol, strings: [:0]const u8, ofiles: OFileTable, @@ -1406,6 +1414,7 @@ pub const ModuleDebugInfo = switch (native_os) { } self.ofiles.deinit(); allocator.free(self.symbols); + os.munmap(self.mapped_memory); } fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo { @@ -1609,18 +1618,20 @@ pub const ModuleDebugInfo = switch (native_os) { debug_data: PdbOrDwarf, coff: *coff.Coff, - pub fn allocator(self: @This()) mem.Allocator { - return self.coff.allocator; + fn deinit(self: *@This(), allocator: mem.Allocator) void { + self.debug_data.deinit(allocator); + self.coff.deinit(); + allocator.destroy(self.coff); } - pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { + pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo { // Translate the VA into an address into this object const relocated_address = address - self.base_address; switch (self.debug_data) { .dwarf => |*dwarf| { const dwarf_address = relocated_address + self.coff.pe_header.image_base; - return getSymbolFromDwarf(dwarf_address, dwarf); + return getSymbolFromDwarf(allocator, dwarf_address, dwarf); }, .pdb => { // fallthrough to pdb handling @@ -1666,17 +1677,28 @@ pub const ModuleDebugInfo = switch (native_os) { .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct { base_address: usize, dwarf: DW.DwarfInfo, - mapped_memory: []const u8, + mapped_memory: []align(mem.page_size) const u8, + + fn deinit(self: *@This(), allocator: mem.Allocator) void { + self.dwarf.deinit(allocator); + os.munmap(self.mapped_memory); + } - pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { + pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo { // Translate the VA into an address into this object const relocated_address = address - self.base_address; - return getSymbolFromDwarf(relocated_address, &self.dwarf); + return getSymbolFromDwarf(allocator, relocated_address, &self.dwarf); } }, .wasi => struct { - pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { + fn deinit(self: *@This(), allocator: mem.Allocator) void { + _ = self; + _ = allocator; + } + + pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo { _ = self; + _ = allocator; _ = address; return SymbolInfo{}; } @@ -1684,14 +1706,14 @@ pub const ModuleDebugInfo = switch (native_os) { else => DW.DwarfInfo, }; -fn getSymbolFromDwarf(address: u64, di: *DW.DwarfInfo) !SymbolInfo { +fn getSymbolFromDwarf(allocator: mem.Allocator, address: u64, di: *DW.DwarfInfo) !SymbolInfo { if (nosuspend di.findCompileUnit(address)) |compile_unit| { return SymbolInfo{ .symbol_name = nosuspend di.getSymbolName(address) orelse "???", .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => "???", }, - .line_info = nosuspend di.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) { + .line_info = nosuspend di.getLineNumberInfo(allocator, compile_unit.*, address) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => null, else => return err, }, |
