authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-21 10:46:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-21 11:48:15+02:00
log28ca203b7132ba0513a3854bd3bcbd0ee9bca067
treeeabc9d3522d89fe8d050197bd6dc1c8a14c349a5
parent96c1314443bdf26442a2c9fdffa03f2afffbcb8e

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.

3 files changed, 40 insertions(+), 18 deletions(-)

lib/std/coff.zig+6-5
......@@ -4,8 +4,6 @@ const mem = std.mem;
44const os = std.os;
55const File = std.fs.File;
66
7const ArrayList = std.ArrayList;
8
97// CoffHeader.machine values
108// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx
119const IMAGE_FILE_MACHINE_I386 = 0x014c;
......@@ -117,7 +115,7 @@ pub const Coff = struct {
117115
118116 coff_header: CoffHeader,
119117 pe_header: OptionalHeader,
120 sections: ArrayList(Section),
118 sections: std.ArrayListUnmanaged(Section) = .{},
121119
122120 guid: [16]u8,
123121 age: u32,
......@@ -128,12 +126,15 @@ pub const Coff = struct {
128126 .allocator = allocator,
129127 .coff_header = undefined,
130128 .pe_header = undefined,
131 .sections = ArrayList(Section).init(allocator),
132129 .guid = undefined,
133130 .age = undefined,
134131 };
135132 }
136133
134 pub fn deinit(self: *Coff) void {
135 self.sections.deinit(self.allocator);
136 }
137
137138 pub fn loadHeader(self: *Coff) !void {
138139 const pe_pointer_offset = 0x3C;
139140
......@@ -291,7 +292,7 @@ pub const Coff = struct {
291292 if (self.sections.items.len == self.coff_header.number_of_sections)
292293 return;
293294
294 try self.sections.ensureTotalCapacityPrecise(self.coff_header.number_of_sections);
295 try self.sections.ensureTotalCapacityPrecise(self.allocator, self.coff_header.number_of_sections);
295296
296297 const in = self.in_file.reader();
297298
lib/std/debug.zig+34-12
......@@ -41,7 +41,7 @@ pub const SymbolInfo = struct {
4141 compile_unit_name: []const u8 = "???",
4242 line_info: ?LineInfo = null,
4343
44 pub fn deinit(self: @This(), allocator: mem.Allocator) void {
44 pub fn deinit(self: SymbolInfo, allocator: mem.Allocator) void {
4545 if (self.line_info) |li| {
4646 li.deinit(allocator);
4747 }
......@@ -50,6 +50,13 @@ pub const SymbolInfo = struct {
5050const PdbOrDwarf = union(enum) {
5151 pdb: pdb.Pdb,
5252 dwarf: DW.DwarfInfo,
53
54 fn deinit(self: *PdbOrDwarf, allocator: mem.Allocator) void {
55 switch (self.*) {
56 .pdb => |*inner| inner.deinit(),
57 .dwarf => |*inner| inner.deinit(allocator),
58 }
59 }
5360};
5461
5562var stderr_mutex = std.Thread.Mutex{};
......@@ -793,6 +800,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo
793800 errdefer coff_file.close();
794801
795802 const coff_obj = try allocator.create(coff.Coff);
803 errdefer allocator.destroy(coff_obj);
796804 coff_obj.* = coff.Coff.init(allocator, coff_file);
797805
798806 var di = ModuleDebugInfo{
......@@ -1386,7 +1394,7 @@ pub const DebugInfo = struct {
13861394pub const ModuleDebugInfo = switch (native_os) {
13871395 .macos, .ios, .watchos, .tvos => struct {
13881396 base_address: usize,
1389 mapped_memory: []const u8,
1397 mapped_memory: []align(mem.page_size) const u8,
13901398 symbols: []const MachoSymbol,
13911399 strings: [:0]const u8,
13921400 ofiles: OFileTable,
......@@ -1406,6 +1414,7 @@ pub const ModuleDebugInfo = switch (native_os) {
14061414 }
14071415 self.ofiles.deinit();
14081416 allocator.free(self.symbols);
1417 os.munmap(self.mapped_memory);
14091418 }
14101419
14111420 fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo {
......@@ -1609,18 +1618,20 @@ pub const ModuleDebugInfo = switch (native_os) {
16091618 debug_data: PdbOrDwarf,
16101619 coff: *coff.Coff,
16111620
1612 pub fn allocator(self: @This()) mem.Allocator {
1613 return self.coff.allocator;
1621 fn deinit(self: *@This(), allocator: mem.Allocator) void {
1622 self.debug_data.deinit(allocator);
1623 self.coff.deinit();
1624 allocator.destroy(self.coff);
16141625 }
16151626
1616 pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
1627 pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
16171628 // Translate the VA into an address into this object
16181629 const relocated_address = address - self.base_address;
16191630
16201631 switch (self.debug_data) {
16211632 .dwarf => |*dwarf| {
16221633 const dwarf_address = relocated_address + self.coff.pe_header.image_base;
1623 return getSymbolFromDwarf(dwarf_address, dwarf);
1634 return getSymbolFromDwarf(allocator, dwarf_address, dwarf);
16241635 },
16251636 .pdb => {
16261637 // fallthrough to pdb handling
......@@ -1666,17 +1677,28 @@ pub const ModuleDebugInfo = switch (native_os) {
16661677 .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
16671678 base_address: usize,
16681679 dwarf: DW.DwarfInfo,
1669 mapped_memory: []const u8,
1680 mapped_memory: []align(mem.page_size) const u8,
1681
1682 fn deinit(self: *@This(), allocator: mem.Allocator) void {
1683 self.dwarf.deinit(allocator);
1684 os.munmap(self.mapped_memory);
1685 }
16701686
1671 pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
1687 pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
16721688 // Translate the VA into an address into this object
16731689 const relocated_address = address - self.base_address;
1674 return getSymbolFromDwarf(relocated_address, &self.dwarf);
1690 return getSymbolFromDwarf(allocator, relocated_address, &self.dwarf);
16751691 }
16761692 },
16771693 .wasi => struct {
1678 pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
1694 fn deinit(self: *@This(), allocator: mem.Allocator) void {
1695 _ = self;
1696 _ = allocator;
1697 }
1698
1699 pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
16791700 _ = self;
1701 _ = allocator;
16801702 _ = address;
16811703 return SymbolInfo{};
16821704 }
......@@ -1684,14 +1706,14 @@ pub const ModuleDebugInfo = switch (native_os) {
16841706 else => DW.DwarfInfo,
16851707};
16861708
1687fn getSymbolFromDwarf(address: u64, di: *DW.DwarfInfo) !SymbolInfo {
1709fn getSymbolFromDwarf(allocator: mem.Allocator, address: u64, di: *DW.DwarfInfo) !SymbolInfo {
16881710 if (nosuspend di.findCompileUnit(address)) |compile_unit| {
16891711 return SymbolInfo{
16901712 .symbol_name = nosuspend di.getSymbolName(address) orelse "???",
16911713 .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name) catch |err| switch (err) {
16921714 error.MissingDebugInfo, error.InvalidDebugInfo => "???",
16931715 },
1694 .line_info = nosuspend di.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) {
1716 .line_info = nosuspend di.getLineNumberInfo(allocator, compile_unit.*, address) catch |err| switch (err) {
16951717 error.MissingDebugInfo, error.InvalidDebugInfo => null,
16961718 else => return err,
16971719 },
lib/std/pdb.zig-1
......@@ -764,7 +764,6 @@ pub const Pdb = struct {
764764 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
765765
766766 return debug.LineInfo{
767 .allocator = self.allocator,
768767 .file_name = source_file_name,
769768 .line = flags.Start,
770769 .column = column,