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;...@@ -4,8 +4,6 @@ const mem = std.mem;
4const os = std.os;4const os = std.os;
5const File = std.fs.File;5const File = std.fs.File;
66
7const ArrayList = std.ArrayList;
8
9// CoffHeader.machine values7// CoffHeader.machine values
10// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx8// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx
11const IMAGE_FILE_MACHINE_I386 = 0x014c;9const IMAGE_FILE_MACHINE_I386 = 0x014c;
...@@ -117,7 +115,7 @@ pub const Coff = struct {...@@ -117,7 +115,7 @@ pub const Coff = struct {
117115
118 coff_header: CoffHeader,116 coff_header: CoffHeader,
119 pe_header: OptionalHeader,117 pe_header: OptionalHeader,
120 sections: ArrayList(Section),118 sections: std.ArrayListUnmanaged(Section) = .{},
121119
122 guid: [16]u8,120 guid: [16]u8,
123 age: u32,121 age: u32,
...@@ -128,12 +126,15 @@ pub const Coff = struct {...@@ -128,12 +126,15 @@ pub const Coff = struct {
128 .allocator = allocator,126 .allocator = allocator,
129 .coff_header = undefined,127 .coff_header = undefined,
130 .pe_header = undefined,128 .pe_header = undefined,
131 .sections = ArrayList(Section).init(allocator),
132 .guid = undefined,129 .guid = undefined,
133 .age = undefined,130 .age = undefined,
134 };131 };
135 }132 }
136133
134 pub fn deinit(self: *Coff) void {
135 self.sections.deinit(self.allocator);
136 }
137
137 pub fn loadHeader(self: *Coff) !void {138 pub fn loadHeader(self: *Coff) !void {
138 const pe_pointer_offset = 0x3C;139 const pe_pointer_offset = 0x3C;
139140
...@@ -291,7 +292,7 @@ pub const Coff = struct {...@@ -291,7 +292,7 @@ pub const Coff = struct {
291 if (self.sections.items.len == self.coff_header.number_of_sections)292 if (self.sections.items.len == self.coff_header.number_of_sections)
292 return;293 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
296 const in = self.in_file.reader();297 const in = self.in_file.reader();
297298
lib/std/debug.zig+34-12
...@@ -41,7 +41,7 @@ pub const SymbolInfo = struct {...@@ -41,7 +41,7 @@ pub const SymbolInfo = struct {
41 compile_unit_name: []const u8 = "???",41 compile_unit_name: []const u8 = "???",
42 line_info: ?LineInfo = null,42 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 {
45 if (self.line_info) |li| {45 if (self.line_info) |li| {
46 li.deinit(allocator);46 li.deinit(allocator);
47 }47 }
...@@ -50,6 +50,13 @@ pub const SymbolInfo = struct {...@@ -50,6 +50,13 @@ pub const SymbolInfo = struct {
50const PdbOrDwarf = union(enum) {50const PdbOrDwarf = union(enum) {
51 pdb: pdb.Pdb,51 pdb: pdb.Pdb,
52 dwarf: DW.DwarfInfo,52 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 }
53};60};
5461
55var stderr_mutex = std.Thread.Mutex{};62var stderr_mutex = std.Thread.Mutex{};
...@@ -793,6 +800,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo...@@ -793,6 +800,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo
793 errdefer coff_file.close();800 errdefer coff_file.close();
794801
795 const coff_obj = try allocator.create(coff.Coff);802 const coff_obj = try allocator.create(coff.Coff);
803 errdefer allocator.destroy(coff_obj);
796 coff_obj.* = coff.Coff.init(allocator, coff_file);804 coff_obj.* = coff.Coff.init(allocator, coff_file);
797805
798 var di = ModuleDebugInfo{806 var di = ModuleDebugInfo{
...@@ -1386,7 +1394,7 @@ pub const DebugInfo = struct {...@@ -1386,7 +1394,7 @@ pub const DebugInfo = struct {
1386pub const ModuleDebugInfo = switch (native_os) {1394pub const ModuleDebugInfo = switch (native_os) {
1387 .macos, .ios, .watchos, .tvos => struct {1395 .macos, .ios, .watchos, .tvos => struct {
1388 base_address: usize,1396 base_address: usize,
1389 mapped_memory: []const u8,1397 mapped_memory: []align(mem.page_size) const u8,
1390 symbols: []const MachoSymbol,1398 symbols: []const MachoSymbol,
1391 strings: [:0]const u8,1399 strings: [:0]const u8,
1392 ofiles: OFileTable,1400 ofiles: OFileTable,
...@@ -1406,6 +1414,7 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1406,6 +1414,7 @@ pub const ModuleDebugInfo = switch (native_os) {
1406 }1414 }
1407 self.ofiles.deinit();1415 self.ofiles.deinit();
1408 allocator.free(self.symbols);1416 allocator.free(self.symbols);
1417 os.munmap(self.mapped_memory);
1409 }1418 }
14101419
1411 fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo {1420 fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo {
...@@ -1609,18 +1618,20 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1609,18 +1618,20 @@ pub const ModuleDebugInfo = switch (native_os) {
1609 debug_data: PdbOrDwarf,1618 debug_data: PdbOrDwarf,
1610 coff: *coff.Coff,1619 coff: *coff.Coff,
16111620
1612 pub fn allocator(self: @This()) mem.Allocator {1621 fn deinit(self: *@This(), allocator: mem.Allocator) void {
1613 return self.coff.allocator;1622 self.debug_data.deinit(allocator);
1623 self.coff.deinit();
1624 allocator.destroy(self.coff);
1614 }1625 }
16151626
1616 pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {1627 pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo {
1617 // Translate the VA into an address into this object1628 // Translate the VA into an address into this object
1618 const relocated_address = address - self.base_address;1629 const relocated_address = address - self.base_address;
16191630
1620 switch (self.debug_data) {1631 switch (self.debug_data) {
1621 .dwarf => |*dwarf| {1632 .dwarf => |*dwarf| {
1622 const dwarf_address = relocated_address + self.coff.pe_header.image_base;1633 const dwarf_address = relocated_address + self.coff.pe_header.image_base;
1623 return getSymbolFromDwarf(dwarf_address, dwarf);1634 return getSymbolFromDwarf(allocator, dwarf_address, dwarf);
1624 },1635 },
1625 .pdb => {1636 .pdb => {
1626 // fallthrough to pdb handling1637 // fallthrough to pdb handling
...@@ -1666,17 +1677,28 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1666,17 +1677,28 @@ pub const ModuleDebugInfo = switch (native_os) {
1666 .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {1677 .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
1667 base_address: usize,1678 base_address: usize,
1668 dwarf: DW.DwarfInfo,1679 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 {
1672 // Translate the VA into an address into this object1688 // Translate the VA into an address into this object
1673 const relocated_address = address - self.base_address;1689 const relocated_address = address - self.base_address;
1674 return getSymbolFromDwarf(relocated_address, &self.dwarf);1690 return getSymbolFromDwarf(allocator, relocated_address, &self.dwarf);
1675 }1691 }
1676 },1692 },
1677 .wasi => struct {1693 .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 {
1679 _ = self;1700 _ = self;
1701 _ = allocator;
1680 _ = address;1702 _ = address;
1681 return SymbolInfo{};1703 return SymbolInfo{};
1682 }1704 }
...@@ -1684,14 +1706,14 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1684,14 +1706,14 @@ pub const ModuleDebugInfo = switch (native_os) {
1684 else => DW.DwarfInfo,1706 else => DW.DwarfInfo,
1685};1707};
16861708
1687fn getSymbolFromDwarf(address: u64, di: *DW.DwarfInfo) !SymbolInfo {1709fn getSymbolFromDwarf(allocator: mem.Allocator, address: u64, di: *DW.DwarfInfo) !SymbolInfo {
1688 if (nosuspend di.findCompileUnit(address)) |compile_unit| {1710 if (nosuspend di.findCompileUnit(address)) |compile_unit| {
1689 return SymbolInfo{1711 return SymbolInfo{
1690 .symbol_name = nosuspend di.getSymbolName(address) orelse "???",1712 .symbol_name = nosuspend di.getSymbolName(address) orelse "???",
1691 .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name) catch |err| switch (err) {1713 .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name) catch |err| switch (err) {
1692 error.MissingDebugInfo, error.InvalidDebugInfo => "???",1714 error.MissingDebugInfo, error.InvalidDebugInfo => "???",
1693 },1715 },
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) {
1695 error.MissingDebugInfo, error.InvalidDebugInfo => null,1717 error.MissingDebugInfo, error.InvalidDebugInfo => null,
1696 else => return err,1718 else => return err,
1697 },1719 },
lib/std/pdb.zig-1
...@@ -764,7 +764,6 @@ pub const Pdb = struct {...@@ -764,7 +764,6 @@ pub const Pdb = struct {
764 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);764 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
765765
766 return debug.LineInfo{766 return debug.LineInfo{
767 .allocator = self.allocator,
768 .file_name = source_file_name,767 .file_name = source_file_name,
769 .line = flags.Start,768 .line = flags.Start,
770 .column = column,769 .column = column,