diff options
Diffstat (limited to 'lib/std/debug.zig')
| -rw-r--r-- | lib/std/debug.zig | 113 |
1 files changed, 80 insertions, 33 deletions
diff --git a/lib/std/debug.zig b/lib/std/debug.zig index b600f7245a..683219c78d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -30,10 +30,8 @@ pub const LineInfo = struct { line: u64, column: u64, file_name: []const u8, - allocator: ?mem.Allocator, - pub fn deinit(self: LineInfo) void { - const allocator = self.allocator orelse return; + pub fn deinit(self: LineInfo, allocator: mem.Allocator) void { allocator.free(self.file_name); } }; @@ -43,15 +41,22 @@ pub const SymbolInfo = struct { compile_unit_name: []const u8 = "???", line_info: ?LineInfo = null, - pub fn deinit(self: @This()) void { + pub fn deinit(self: SymbolInfo, allocator: mem.Allocator) void { if (self.line_info) |li| { - li.deinit(); + li.deinit(allocator); } } }; 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{}; @@ -677,7 +682,6 @@ test "machoSearchSymbols" { try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?); } -/// TODO resources https://github.com/ziglang/zig/issues/4353 pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void { const module = debug_info.getModuleForAddress(address) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => { @@ -694,8 +698,8 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address else => return err, }; - const symbol_info = try module.getSymbolAtAddress(address); - defer symbol_info.deinit(); + const symbol_info = try module.getSymbolAtAddress(debug_info.allocator, address); + defer symbol_info.deinit(debug_info.allocator); return printLineInfo( out_stream, @@ -763,7 +767,6 @@ pub const OpenSelfDebugInfoError = error{ UnsupportedOperatingSystem, }; -/// TODO resources https://github.com/ziglang/zig/issues/4353 pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo { nosuspend { if (builtin.strip_debug_info) @@ -788,13 +791,13 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo { /// This takes ownership of coff_file: users of this function should not close /// it themselves, even on error. -/// TODO resources https://github.com/ziglang/zig/issues/4353 /// TODO it's weird to take ownership even on error, rework this code. fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo { nosuspend { 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{ @@ -857,7 +860,6 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 { /// This takes ownership of elf_file: users of this function should not close /// it themselves, even on error. -/// TODO resources https://github.com/ziglang/zig/issues/4353 /// TODO it's weird to take ownership even on error, rework this code. pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugInfo { nosuspend { @@ -931,7 +933,6 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn } } -/// TODO resources https://github.com/ziglang/zig/issues/4353 /// This takes ownership of macho_file: users of this function should not close /// it themselves, even on error. /// TODO it's weird to take ownership even on error, rework this code. @@ -1144,7 +1145,12 @@ pub const DebugInfo = struct { } pub fn deinit(self: *DebugInfo) void { - // TODO: resources https://github.com/ziglang/zig/issues/4353 + var it = self.address_map.iterator(); + while (it.next()) |entry| { + const mdi = entry.value_ptr.*; + mdi.deinit(self.allocator); + self.allocator.destroy(mdi); + } self.address_map.deinit(); } @@ -1383,7 +1389,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, @@ -1394,11 +1400,19 @@ pub const ModuleDebugInfo = switch (native_os) { addr_table: std.StringHashMap(u64), }; - pub fn allocator(self: @This()) mem.Allocator { - return self.ofiles.allocator; + fn deinit(self: *@This(), allocator: mem.Allocator) void { + var it = self.ofiles.iterator(); + while (it.next()) |entry| { + const ofile = entry.value_ptr; + ofile.di.deinit(allocator); + ofile.addr_table.deinit(); + } + self.ofiles.deinit(); + allocator.free(self.symbols); + os.munmap(self.mapped_memory); } - fn loadOFile(self: *@This(), o_file_path: []const u8) !OFileInfo { + fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !OFileInfo { const o_file = try fs.cwd().openFile(o_file_path, .{ .intended_io_mode = .blocking }); const mapped_mem = try mapWholeFile(o_file); @@ -1450,7 +1464,7 @@ pub const ModuleDebugInfo = switch (native_os) { )[0..symtabcmd.?.nsyms]; // TODO handle tentative (common) symbols - var addr_table = std.StringHashMap(u64).init(self.allocator()); + var addr_table = std.StringHashMap(u64).init(allocator); try addr_table.ensureTotalCapacity(@intCast(u32, symtab.len)); for (symtab) |sym| { if (sym.n_strx == 0) continue; @@ -1519,7 +1533,7 @@ pub const ModuleDebugInfo = switch (native_os) { null, }; - try DW.openDwarfDebugInfo(&di, self.allocator()); + try DW.openDwarfDebugInfo(&di, allocator); var info = OFileInfo{ .di = di, .addr_table = addr_table, @@ -1531,7 +1545,7 @@ pub const ModuleDebugInfo = switch (native_os) { return info; } - pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { + pub fn getSymbolAtAddress(self: *@This(), allocator: mem.Allocator, address: usize) !SymbolInfo { nosuspend { // Translate the VA into an address into this object const relocated_address = address - self.base_address; @@ -1548,7 +1562,7 @@ pub const ModuleDebugInfo = switch (native_os) { // Check if its debug infos are already in the cache var o_file_info = self.ofiles.get(o_file_path) orelse - (self.loadOFile(o_file_path) catch |err| switch (err) { + (self.loadOFile(allocator, o_file_path) catch |err| switch (err) { error.FileNotFound, error.MissingDebugInfo, error.InvalidDebugInfo, @@ -1568,10 +1582,17 @@ pub const ModuleDebugInfo = switch (native_os) { if (o_file_di.findCompileUnit(relocated_address_o)) |compile_unit| { return SymbolInfo{ .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???", - .compile_unit_name = compile_unit.die.getAttrString(o_file_di, DW.AT.name) catch |err| switch (err) { + .compile_unit_name = compile_unit.die.getAttrString( + o_file_di, + DW.AT.name, + ) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => "???", }, - .line_info = o_file_di.getLineNumberInfo(compile_unit.*, relocated_address_o + addr_off) catch |err| switch (err) { + .line_info = o_file_di.getLineNumberInfo( + allocator, + compile_unit.*, + relocated_address_o + addr_off, + ) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => null, else => return err, }, @@ -1592,18 +1613,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 @@ -1649,17 +1672,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{}; } @@ -1667,14 +1701,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, }, @@ -1895,3 +1929,16 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void { ); std.debug.print("{} sp = 0x{x}\n", .{ prefix, sp }); } + +test "#4353: std.debug should manage resources correctly" { + if (builtin.os.tag == .wasi) return error.SkipZigTest; + + const writer = std.io.null_writer; + var di = try openSelfDebugInfo(testing.allocator); + defer di.deinit(); + try printSourceAtAddress(&di, writer, showMyTrace(), detectTTYConfig()); +} + +noinline fn showMyTrace() usize { + return @returnAddress(); +} |
