aboutsummaryrefslogtreecommitdiff
path: root/lib/std/debug.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/debug.zig')
-rw-r--r--lib/std/debug.zig113
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();
+}