authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-13 00:43:34-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-13 01:30:14-07:00
log6707a5efeea1ab973c3274495bb0a5640e4f568b
treee3f815ac7949a0b33ad997e386ccb4cdd5a81bcc
parent4ad665d3c8cd6a9d4f6b0e2f065098436142b450

Arena allocates text


7 files changed, 109 insertions(+), 71 deletions(-)

lib/std/debug.zig+39-38
...@@ -39,7 +39,7 @@ pub const cpu_context = @import("debug/cpu_context.zig");...@@ -39,7 +39,7 @@ pub const cpu_context = @import("debug/cpu_context.zig");
39/// pub fn deinit(si: *SelfInfo, io: Io) void;39/// pub fn deinit(si: *SelfInfo, io: Io) void;
40///40///
41/// /// Appends the symbols for the instruction at `address` to `symbols`.41/// /// Appends the symbols for the instruction at `address` to `symbols`.
42/// pub fn getSymbols(si: *SelfInfo, io: Io, gpa: Allocator, address: usize, include_inline_callers: bool, symbols: *std.ArrayList(Symbol)) SelfInfoError!void;42/// pub fn getSymbols(si: *SelfInfo, io: Io, symbol_allocator: Allocator, text_arena: Allocator, address: usize, include_inline_callers: bool, symbols: *std.ArrayList(Symbol)) SelfInfoError!void;
43/// /// Returns a name for the "module" (e.g. shared library or executable image) containing `address`.43/// /// Returns a name for the "module" (e.g. shared library or executable image) containing `address`.
44/// pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) SelfInfoError![]const u8;44/// pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) SelfInfoError![]const u8;
45/// pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) SelfInfoError!usize;45/// pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) SelfInfoError!usize;
...@@ -229,11 +229,6 @@ pub const Symbol = struct {...@@ -229,11 +229,6 @@ pub const Symbol = struct {
229 .compile_unit_name = null,229 .compile_unit_name = null,
230 .source_location = null,230 .source_location = null,
231 };231 };
232
233 pub fn deinit(self: *Symbol, gpa: Allocator) void {
234 if (self.source_location) |sl| gpa.free(sl.file_name);
235 self.* = undefined;
236 }
237};232};
238233
239/// Deprecated because it returns the optimization mode of the standard234/// Deprecated because it returns the optimization mode of the standard
...@@ -699,6 +694,10 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:...@@ -699,6 +694,10 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:
699/// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing.694/// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing.
700pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void {695pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void {
701 const writer = t.writer;696 const writer = t.writer;
697
698 var text_arena: std.heap.ArenaAllocator = .init(getDebugInfoAllocator());
699 defer text_arena.deinit();
700
702 if (!std.options.allow_stack_tracing) {701 if (!std.options.allow_stack_tracing) {
703 t.setColor(.dim) catch {};702 t.setColor(.dim) catch {};
704 try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{});703 try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{});
...@@ -776,7 +775,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin...@@ -776,7 +775,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin
776 }775 }
777 // `ret_addr` is the return address, which is *after* the function call.776 // `ret_addr` is the return address, which is *after* the function call.
778 // Subtract 1 to get an address *in* the function call for a better source location.777 // Subtract 1 to get an address *in* the function call for a better source location.
779 try printSourceAtAddress(io, di, t, .{778 try printSourceAtAddress(io, &text_arena, di, t, .{
780 .address = ret_addr -| StackIterator.ra_call_offset,779 .address = ret_addr -| StackIterator.ra_call_offset,
781 .resolve_inline_callers = true,780 .resolve_inline_callers = true,
782 });781 });
...@@ -832,6 +831,9 @@ fn writeTrace(...@@ -832,6 +831,9 @@ fn writeTrace(
832 t: Io.Terminal,831 t: Io.Terminal,
833 resolve_inline_callers: bool,832 resolve_inline_callers: bool,
834) Writer.Error!void {833) Writer.Error!void {
834 var text_arena: std.heap.ArenaAllocator = .init(getDebugInfoAllocator());
835 defer text_arena.deinit();
836
835 const writer = t.writer;837 const writer = t.writer;
836 if (!std.options.allow_stack_tracing) {838 if (!std.options.allow_stack_tracing) {
837 t.setColor(.dim) catch {};839 t.setColor(.dim) catch {};
...@@ -853,7 +855,7 @@ fn writeTrace(...@@ -853,7 +855,7 @@ fn writeTrace(
853 for (addresses) |addr| {855 for (addresses) |addr| {
854 // `addr` is the return address, which is *after* the function call.856 // `addr` is the return address, which is *after* the function call.
855 // Subtract 1 to get an address *in* the function call for a better source location.857 // Subtract 1 to get an address *in* the function call for a better source location.
856 try printSourceAtAddress(io, di, t, .{858 try printSourceAtAddress(io, &text_arena, di, t, .{
857 .address = addr -| StackIterator.ra_call_offset,859 .address = addr -| StackIterator.ra_call_offset,
858 .resolve_inline_callers = resolve_inline_callers,860 .resolve_inline_callers = resolve_inline_callers,
859 });861 });
...@@ -1186,21 +1188,28 @@ const PrintSourceAddressOptions = struct {...@@ -1186,21 +1188,28 @@ const PrintSourceAddressOptions = struct {
11861188
1187fn printSourceAtAddress(1189fn printSourceAtAddress(
1188 io: Io,1190 io: Io,
1191 text_arena: *std.heap.ArenaAllocator,
1189 debug_info: *SelfInfo,1192 debug_info: *SelfInfo,
1190 t: Io.Terminal,1193 t: Io.Terminal,
1191 options: PrintSourceAddressOptions,1194 options: PrintSourceAddressOptions,
1192) Writer.Error!void {1195) Writer.Error!void {
1193 // In the common case where there's only one symbol, allocate it on the stack. Reserve enough1196 defer _ = text_arena.reset(.retain_capacity);
1194 // space for one item regardless of alignment.1197
1195 var stack_fallback = std.heap.stackFallback(@sizeOf(Symbol) + @alignOf(Symbol) - 1, getDebugInfoAllocator());1198 // Initialize the symbol array with space for at least one element, allocating this on the stack
1196 const sfa = stack_fallback.get();1199 // in the common case where only one element is needed
1197 var symbols = std.ArrayList(Symbol).initCapacity(sfa, 1) catch unreachable;1200 var symbol_fallback_allocator = std.heap.stackFallback(@sizeOf(Symbol) + @alignOf(Symbol) - 1, getDebugInfoAllocator());
1198 defer {1201 const symbol_allocator = symbol_fallback_allocator.get();
1199 for (symbols.items) |*symbol| symbol.deinit(sfa);1202 var symbols = std.ArrayList(Symbol).initCapacity(symbol_allocator, 1) catch unreachable;
1200 symbols.deinit(sfa);1203 defer symbols.deinit(symbol_allocator);
1201 }1204
12021205 debug_info.getSymbols(
1203 debug_info.getSymbols(io, sfa, options.address, options.resolve_inline_callers, &symbols) catch |err| {1206 io,
1207 symbol_allocator,
1208 text_arena.allocator(),
1209 options.address,
1210 options.resolve_inline_callers,
1211 &symbols,
1212 ) catch |err| {
1204 t.setColor(.dim) catch {};1213 t.setColor(.dim) catch {};
1205 defer t.setColor(.reset) catch {};1214 defer t.setColor(.reset) catch {};
1206 switch (err) {1215 switch (err) {
...@@ -1219,35 +1228,25 @@ fn printSourceAtAddress(...@@ -1219,35 +1228,25 @@ fn printSourceAtAddress(
1219 }1228 }
1220 };1229 };
12211230
1222 // If we failed to get any symbols, append the unknown symbol. We initialized with a capacity of1231 // If we failed to write any symbols, at least write the unknown symbol. Can't fail since we
1223 // one using a stack fallback allocator so this can't fail.1232 // initialized with a capacity of 1.
1224 if (symbols.items.len == 0) symbols.appendAssumeCapacity(.unknown);1233 if (symbols.items.len == 0) symbols.appendAssumeCapacity(.unknown);
12251234
1226 for (symbols.items) |symbol| {1235 for (symbols.items) |symbol| {
1227 try printLineInfo(1236 try printLineInfo(io, t, debug_info, options.address, symbol);
1228 io,
1229 t,
1230 debug_info,
1231 symbol.source_location,
1232 options.address,
1233 symbol.name,
1234 symbol.compile_unit_name,
1235 );
1236 }1237 }
1237}1238}
1238fn printLineInfo(1239fn printLineInfo(
1239 io: Io,1240 io: Io,
1240 t: Io.Terminal,1241 t: Io.Terminal,
1241 debug_info: *SelfInfo,1242 debug_info: *SelfInfo,
1242 source_location: ?SourceLocation,
1243 address: usize,1243 address: usize,
1244 symbol_name: ?[]const u8,1244 symbol: Symbol,
1245 compile_unit_name: ?[]const u8,
1246) Writer.Error!void {1245) Writer.Error!void {
1247 const writer = t.writer;1246 const writer = t.writer;
1248 t.setColor(.bold) catch {};1247 t.setColor(.bold) catch {};
12491248
1250 if (source_location) |*sl| {1249 if (symbol.source_location) |*sl| {
1251 if (sl.column == 0) {1250 if (sl.column == 0) {
1252 try writer.print("{s}:{d}", .{ sl.file_name, sl.line });1251 try writer.print("{s}:{d}", .{ sl.file_name, sl.line });
1253 } else {1252 } else {
...@@ -1262,14 +1261,14 @@ fn printLineInfo(...@@ -1262,14 +1261,14 @@ fn printLineInfo(
1262 t.setColor(.dim) catch {};1261 t.setColor(.dim) catch {};
1263 try writer.print("0x{x} in {s} ({s})", .{1262 try writer.print("0x{x} in {s} ({s})", .{
1264 address,1263 address,
1265 symbol_name orelse "???",1264 symbol.name orelse "???",
1266 compile_unit_name orelse debug_info.getModuleName(io, address) catch "???",1265 symbol.compile_unit_name orelse debug_info.getModuleName(io, address) catch "???",
1267 });1266 });
1268 t.setColor(.reset) catch {};1267 t.setColor(.reset) catch {};
1269 try writer.writeAll("\n");1268 try writer.writeAll("\n");
12701269
1271 // Show the matching source code line if possible1270 // Show the matching source code line if possible
1272 if (source_location) |sl| {1271 if (symbol.source_location) |sl| {
1273 if (printLineFromFile(io, writer, sl)) {1272 if (printLineFromFile(io, writer, sl)) {
1274 if (sl.column > 0) {1273 if (sl.column > 0) {
1275 // The caret already takes one char1274 // The caret already takes one char
...@@ -1708,7 +1707,9 @@ test "manage resources correctly" {...@@ -1708,7 +1707,9 @@ test "manage resources correctly" {
1708 var di: SelfInfo = .init;1707 var di: SelfInfo = .init;
1709 defer di.deinit(io);1708 defer di.deinit(io);
1710 const t: Io.Terminal = .{ .writer = &discarding.writer, .mode = .no_color };1709 const t: Io.Terminal = .{ .writer = &discarding.writer, .mode = .no_color };
1711 try printSourceAtAddress(io, &di, t, .{1710 var text_arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
1711 defer text_arena.deinit();
1712 try printSourceAtAddress(io, &text_arena, &di, t, .{
1712 .address = S.showMyTrace(),1713 .address = S.showMyTrace(),
1713 .resolve_inline_callers = true,1714 .resolve_inline_callers = true,
1714 });1715 });
lib/std/debug/Dwarf.zig+7-4
...@@ -1220,6 +1220,7 @@ pub fn populateSrcLocCache(d: *Dwarf, gpa: Allocator, endian: Endian, cu: *Compi...@@ -1220,6 +1220,7 @@ pub fn populateSrcLocCache(d: *Dwarf, gpa: Allocator, endian: Endian, cu: *Compi
1220pub fn getLineNumberInfo(1220pub fn getLineNumberInfo(
1221 d: *Dwarf,1221 d: *Dwarf,
1222 gpa: Allocator,1222 gpa: Allocator,
1223 text_arena: Allocator,
1223 endian: Endian,1224 endian: Endian,
1224 compile_unit: *CompileUnit,1225 compile_unit: *CompileUnit,
1225 target_address: u64,1226 target_address: u64,
...@@ -1232,7 +1233,7 @@ pub fn getLineNumberInfo(...@@ -1232,7 +1233,7 @@ pub fn getLineNumberInfo(
1232 const file_entry = &slc.files[file_index];1233 const file_entry = &slc.files[file_index];
1233 if (file_entry.dir_index >= slc.directories.len) return bad();1234 if (file_entry.dir_index >= slc.directories.len) return bad();
1234 const dir_name = slc.directories[file_entry.dir_index].path;1235 const dir_name = slc.directories[file_entry.dir_index].path;
1235 const file_name = try std.fs.path.join(gpa, &.{ dir_name, file_entry.path });1236 const file_name = try std.fs.path.join(text_arena, &.{ dir_name, file_entry.path });
1236 return .{1237 return .{
1237 .line = entry.line,1238 .line = entry.line,
1238 .column = entry.column,1239 .column = entry.column,
...@@ -1547,25 +1548,27 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {...@@ -1547,25 +1548,27 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {
15471548
1548pub fn getSymbols(1549pub fn getSymbols(
1549 di: *Dwarf,1550 di: *Dwarf,
1550 gpa: Allocator,1551 symbol_allocator: Allocator,
1552 text_arena: Allocator,
1551 endian: Endian,1553 endian: Endian,
1552 address: u64,1554 address: u64,
1553 resolve_inline_callers: bool,1555 resolve_inline_callers: bool,
1554 symbols: *std.ArrayList(std.debug.Symbol),1556 symbols: *std.ArrayList(std.debug.Symbol),
1555) std.debug.SelfInfoError!void {1557) std.debug.SelfInfoError!void {
1556 _ = resolve_inline_callers;1558 _ = resolve_inline_callers;
1559 const gpa = std.debug.getDebugInfoAllocator();
15571560
1558 const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) {1561 const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) {
1559 error.EndOfStream => return error.MissingDebugInfo,1562 error.EndOfStream => return error.MissingDebugInfo,
1560 error.Overflow => return error.InvalidDebugInfo,1563 error.Overflow => return error.InvalidDebugInfo,
1561 error.ReadFailed, error.InvalidDebugInfo, error.MissingDebugInfo => |e| return e,1564 error.ReadFailed, error.InvalidDebugInfo, error.MissingDebugInfo => |e| return e,
1562 };1565 };
1563 try symbols.append(gpa, .{1566 try symbols.append(symbol_allocator, .{
1564 .name = di.getSymbolName(address),1567 .name = di.getSymbolName(address),
1565 .compile_unit_name = compile_unit.die.getAttrString(di, endian, std.dwarf.AT.name, di.section(.debug_str), compile_unit) catch |err| switch (err) {1568 .compile_unit_name = compile_unit.die.getAttrString(di, endian, std.dwarf.AT.name, di.section(.debug_str), compile_unit) catch |err| switch (err) {
1566 error.MissingDebugInfo, error.InvalidDebugInfo => null,1569 error.MissingDebugInfo, error.InvalidDebugInfo => null,
1567 },1570 },
1568 .source_location = di.getLineNumberInfo(gpa, endian, compile_unit, address) catch |err| switch (err) {1571 .source_location = di.getLineNumberInfo(gpa, text_arena, endian, compile_unit, address) catch |err| switch (err) {
1569 error.MissingDebugInfo, error.InvalidDebugInfo => null,1572 error.MissingDebugInfo, error.InvalidDebugInfo => null,
1570 error.ReadFailed,1573 error.ReadFailed,
1571 error.EndOfStream,1574 error.EndOfStream,
lib/std/debug/Pdb.zig+6-6
...@@ -617,6 +617,7 @@ pub fn getBinaryAnnotations(self: *Pdb, module: *Module, site: *align(1) const p...@@ -617,6 +617,7 @@ pub fn getBinaryAnnotations(self: *Pdb, module: *Module, site: *align(1) const p
617617
618pub fn getInlineSiteSourceLocation(618pub fn getInlineSiteSourceLocation(
619 self: *Pdb,619 self: *Pdb,
620 gpa: Allocator,
620 mod: *Module,621 mod: *Module,
621 site: *align(1) const pdb.InlineSiteSym,622 site: *align(1) const pdb.InlineSiteSym,
622 inlinee_src_line: *align(1) const pdb.InlineeSourceLine,623 inlinee_src_line: *align(1) const pdb.InlineeSourceLine,
...@@ -627,7 +628,7 @@ pub fn getInlineSiteSourceLocation(...@@ -627,7 +628,7 @@ pub fn getInlineSiteSourceLocation(
627 if (!range.contains(offset_in_func)) continue;628 if (!range.contains(offset_in_func)) continue;
628629
629 const file_id = range.file_id orelse inlinee_src_line.file_id;630 const file_id = range.file_id orelse inlinee_src_line.file_id;
630 const file_name = try self.getFileName(mod, file_id);631 const file_name = try self.getFileName(gpa, mod, file_id);
631 errdefer self.allocator.free(file_name);632 errdefer self.allocator.free(file_name);
632633
633 return .{634 return .{
...@@ -640,14 +641,14 @@ pub fn getInlineSiteSourceLocation(...@@ -640,14 +641,14 @@ pub fn getInlineSiteSourceLocation(
640 return null;641 return null;
641}642}
642643
643pub fn getFileName(self: *Pdb, mod: *Module, file_id: u32) ![]const u8 {644pub fn getFileName(self: *Pdb, gpa: Allocator, mod: *Module, file_id: u32) ![]const u8 {
644 const checksum_offset = mod.checksum_offset orelse return error.MissingDebugInfo;645 const checksum_offset = mod.checksum_offset orelse return error.MissingDebugInfo;
645 const subsect_index = checksum_offset + file_id;646 const subsect_index = checksum_offset + file_id;
646 const chksum_hdr: *align(1) pdb.FileChecksumEntryHeader = @ptrCast(&mod.subsect_info[subsect_index]);647 const chksum_hdr: *align(1) pdb.FileChecksumEntryHeader = @ptrCast(&mod.subsect_info[subsect_index]);
647 const strtab_offset = @sizeOf(pdb.StringTableHeader) + chksum_hdr.file_name_offset;648 const strtab_offset = @sizeOf(pdb.StringTableHeader) + chksum_hdr.file_name_offset;
648 self.string_table.?.seekTo(strtab_offset) catch return error.InvalidDebugInfo;649 self.string_table.?.seekTo(strtab_offset) catch return error.InvalidDebugInfo;
649 const string_reader = &self.string_table.?.interface;650 const string_reader = &self.string_table.?.interface;
650 var source_file_name: Io.Writer.Allocating = .init(self.allocator);651 var source_file_name: Io.Writer.Allocating = .init(gpa);
651 defer source_file_name.deinit();652 defer source_file_name.deinit();
652 _ = try string_reader.streamDelimiterLimit(&source_file_name.writer, 0, .limited(1024));653 _ = try string_reader.streamDelimiterLimit(&source_file_name.writer, 0, .limited(1024));
653 assert(string_reader.buffered()[0] == 0); // TODO change streamDelimiterLimit API654 assert(string_reader.buffered()[0] == 0); // TODO change streamDelimiterLimit API
...@@ -716,10 +717,9 @@ pub fn getInlineeSourceLines(...@@ -716,10 +717,9 @@ pub fn getInlineeSourceLines(
716 return mod.inlinee_source_lines[begin..end];717 return mod.inlinee_source_lines[begin..end];
717}718}
718719
719pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.SourceLocation {720pub fn getLineNumberInfo(self: *Pdb, gpa: Allocator, module: *Module, address: u64) !std.debug.SourceLocation {
720 std.debug.assert(module.populated);721 std.debug.assert(module.populated);
721 const subsect_info = module.subsect_info;722 const subsect_info = module.subsect_info;
722 const gpa = self.allocator;
723723
724 var sect_offset: usize = 0;724 var sect_offset: usize = 0;
725 var skip_len: usize = undefined;725 var skip_len: usize = undefined;
...@@ -769,7 +769,7 @@ pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.S...@@ -769,7 +769,7 @@ pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.S
769769
770 // line_i == 0 would mean that no matching pdb.LineNumberEntry was found.770 // line_i == 0 would mean that no matching pdb.LineNumberEntry was found.
771 if (line_i > 0) {771 if (line_i > 0) {
772 const file_name = try self.getFileName(module, block_hdr.name_index);772 const file_name = try self.getFileName(gpa, module, block_hdr.name_index);
773 errdefer gpa.free(file_name);773 errdefer gpa.free(file_name);
774774
775 const line_entry_idx = line_i - 1;775 const line_entry_idx = line_i - 1;
lib/std/debug/SelfInfo/Elf.zig+12-3
...@@ -33,11 +33,13 @@ pub fn deinit(si: *SelfInfo, io: Io) void {...@@ -33,11 +33,13 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
33pub fn getSymbols(33pub fn getSymbols(
34 si: *SelfInfo,34 si: *SelfInfo,
35 io: Io,35 io: Io,
36 gpa: Allocator,36 symbol_allocator: Allocator,
37 text_arena: Allocator,
37 address: usize,38 address: usize,
38 resolve_inline_callers: bool,39 resolve_inline_callers: bool,
39 symbols: *std.ArrayList(std.debug.Symbol),40 symbols: *std.ArrayList(std.debug.Symbol),
40) Error!void {41) Error!void {
42 const gpa = std.debug.getDebugInfoAllocator();
41 const module = try si.findModule(gpa, io, address, .exclusive);43 const module = try si.findModule(gpa, io, address, .exclusive);
42 defer si.rwlock.unlock(io);44 defer si.rwlock.unlock(io);
4345
...@@ -59,10 +61,17 @@ pub fn getSymbols(...@@ -59,10 +61,17 @@ pub fn getSymbols(
59 };61 };
60 loaded_elf.scanned_dwarf = true;62 loaded_elf.scanned_dwarf = true;
61 }63 }
62 return dwarf.getSymbols(gpa, native_endian, vaddr, resolve_inline_callers, symbols);64 return dwarf.getSymbols(
65 symbol_allocator,
66 text_arena,
67 native_endian,
68 vaddr,
69 resolve_inline_callers,
70 symbols,
71 );
63 }72 }
64 // When DWARF is unavailable, fall back to searching the symtab.73 // When DWARF is unavailable, fall back to searching the symtab.
65 try symbols.append(gpa, loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {74 try symbols.append(symbol_allocator, loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {
66 error.NoSymtab, error.NoStrtab => return error.MissingDebugInfo,75 error.NoSymtab, error.NoStrtab => return error.MissingDebugInfo,
67 error.BadSymtab => return error.InvalidDebugInfo,76 error.BadSymtab => return error.InvalidDebugInfo,
68 error.OutOfMemory => |e| return e,77 error.OutOfMemory => |e| return e,
lib/std/debug/SelfInfo/MachO.zig+7-4
...@@ -25,12 +25,14 @@ pub fn deinit(si: *SelfInfo, io: Io) void {...@@ -25,12 +25,14 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
25pub fn getSymbols(25pub fn getSymbols(
26 si: *SelfInfo,26 si: *SelfInfo,
27 io: Io,27 io: Io,
28 gpa: Allocator,28 symbol_allocator: Allocator,
29 text_arena: Allocator,
29 address: usize,30 address: usize,
30 resolve_inline_callers: bool,31 resolve_inline_callers: bool,
31 symbols: *std.ArrayList(std.debug.Symbol),32 symbols: *std.ArrayList(std.debug.Symbol),
32) Error!void {33) Error!void {
33 _ = resolve_inline_callers;34 _ = resolve_inline_callers;
35 const gpa = std.debug.getDebugInfoAllocator();
3436
35 const module = try si.findModule(gpa, io, address);37 const module = try si.findModule(gpa, io, address);
36 defer si.mutex.unlock(io);38 defer si.mutex.unlock(io);
...@@ -51,7 +53,7 @@ pub fn getSymbols(...@@ -51,7 +53,7 @@ pub fn getSymbols(
5153
52 const ofile_dwarf, const ofile_vaddr = file.getDwarfForAddress(gpa, io, vaddr) catch {54 const ofile_dwarf, const ofile_vaddr = file.getDwarfForAddress(gpa, io, vaddr) catch {
53 // Return at least the symbol name if available.55 // Return at least the symbol name if available.
54 return symbols.append(gpa, .{56 return symbols.append(symbol_allocator, .{
55 .name = try file.lookupSymbolName(vaddr),57 .name = try file.lookupSymbolName(vaddr),
56 .compile_unit_name = null,58 .compile_unit_name = null,
57 .source_location = null,59 .source_location = null,
...@@ -60,14 +62,14 @@ pub fn getSymbols(...@@ -60,14 +62,14 @@ pub fn getSymbols(
6062
61 const compile_unit = ofile_dwarf.findCompileUnit(native_endian, ofile_vaddr) catch {63 const compile_unit = ofile_dwarf.findCompileUnit(native_endian, ofile_vaddr) catch {
62 // Return at least the symbol name if available.64 // Return at least the symbol name if available.
63 return symbols.append(gpa, .{65 return symbols.append(symbol_allocator, .{
64 .name = try file.lookupSymbolName(vaddr),66 .name = try file.lookupSymbolName(vaddr),
65 .compile_unit_name = null,67 .compile_unit_name = null,
66 .source_location = null,68 .source_location = null,
67 });69 });
68 };70 };
6971
70 try symbols.append(gpa, .{72 try symbols.append(symbol_allocator, .{
71 .name = ofile_dwarf.getSymbolName(ofile_vaddr) orelse73 .name = ofile_dwarf.getSymbolName(ofile_vaddr) orelse
72 try file.lookupSymbolName(vaddr),74 try file.lookupSymbolName(vaddr),
73 .compile_unit_name = compile_unit.die.getAttrString(75 .compile_unit_name = compile_unit.die.getAttrString(
...@@ -81,6 +83,7 @@ pub fn getSymbols(...@@ -81,6 +83,7 @@ pub fn getSymbols(
81 },83 },
82 .source_location = ofile_dwarf.getLineNumberInfo(84 .source_location = ofile_dwarf.getLineNumberInfo(
83 gpa,85 gpa,
86 text_arena,
84 native_endian,87 native_endian,
85 compile_unit,88 compile_unit,
86 ofile_vaddr,89 ofile_vaddr,
lib/std/debug/SelfInfo/Windows.zig+19-7
...@@ -28,17 +28,20 @@ pub fn deinit(si: *SelfInfo, io: Io) void {...@@ -28,17 +28,20 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
28pub fn getSymbols(28pub fn getSymbols(
29 si: *SelfInfo,29 si: *SelfInfo,
30 io: Io,30 io: Io,
31 gpa: Allocator, 31 symbol_allocator: Allocator,
32 text_arena: Allocator,
32 address: usize,33 address: usize,
33 resolve_inline_callers: bool,34 resolve_inline_callers: bool,
34 symbols: *std.ArrayList(std.debug.Symbol),35 symbols: *std.ArrayList(std.debug.Symbol),
35) Error!void {36) Error!void {
37 const gpa = std.debug.getDebugInfoAllocator();
36 try si.lock.lockShared(io);38 try si.lock.lockShared(io);
37 defer si.lock.unlockShared(io);39 defer si.lock.unlockShared(io);
38 const module = try si.findModule(gpa, address);40 const module = try si.findModule(gpa, address);
39 const di = try module.getDebugInfo(gpa, io);41 const di = try module.getDebugInfo(gpa, io);
40 return di.getSymbols(42 return di.getSymbols(
41 gpa,43 symbol_allocator,
44 text_arena,
42 address - @intFromPtr(module.entry.DllBase),45 address - @intFromPtr(module.entry.DllBase),
43 resolve_inline_callers,46 resolve_inline_callers,
44 symbols,47 symbols,
...@@ -254,7 +257,8 @@ const Module = struct {...@@ -254,7 +257,8 @@ const Module = struct {
254257
255 fn getSymbols(258 fn getSymbols(
256 di: *DebugInfo,259 di: *DebugInfo,
257 gpa: Allocator,260 symbol_allocator: Allocator,
261 text_arena: Allocator,
258 vaddr: usize,262 vaddr: usize,
259 resolve_inline_callers: bool,263 resolve_inline_callers: bool,
260 symbols: *std.ArrayList(std.debug.Symbol),264 symbols: *std.ArrayList(std.debug.Symbol),
...@@ -312,6 +316,7 @@ const Module = struct {...@@ -312,6 +316,7 @@ const Module = struct {
312 inline_site.inlinee,316 inline_site.inlinee,
313 )) |inlinee_src_line| {317 )) |inlinee_src_line| {
314 const maybe_loc = pdb.getInlineSiteSourceLocation(318 const maybe_loc = pdb.getInlineSiteSourceLocation(
319 text_arena,
315 module,320 module,
316 inline_site,321 inline_site,
317 inlinee_src_line.info,322 inlinee_src_line.info,
...@@ -333,7 +338,7 @@ const Module = struct {...@@ -333,7 +338,7 @@ const Module = struct {
333 else338 else
334 null;339 null;
335340
336 try symbols.append(gpa, .{341 try symbols.append(symbol_allocator, .{
337 .name = name,342 .name = name,
338 .compile_unit_name = compile_unit_name,343 .compile_unit_name = compile_unit_name,
339 .source_location = loc,344 .source_location = loc,
...@@ -359,10 +364,10 @@ const Module = struct {...@@ -359,10 +364,10 @@ const Module = struct {
359364
360 // If there's room for another symbol, add the actual proc365 // If there's room for another symbol, add the actual proc
361 if (resolve_inline_callers or symbols.items.len == 0) {366 if (resolve_inline_callers or symbols.items.len == 0) {
362 try symbols.append(gpa, .{367 try symbols.append(symbol_allocator, .{
363 .name = if (maybe_proc) |proc| pdb.getSymbolName(proc) else null,368 .name = if (maybe_proc) |proc| pdb.getSymbolName(proc) else null,
364 .compile_unit_name = compile_unit_name,369 .compile_unit_name = compile_unit_name,
365 .source_location = pdb.getLineNumberInfo(module, addr) catch null,370 .source_location = pdb.getLineNumberInfo(text_arena, module, addr) catch null,
366 });371 });
367 }372 }
368373
...@@ -372,7 +377,14 @@ const Module = struct {...@@ -372,7 +377,14 @@ const Module = struct {
372 dwarf: {377 dwarf: {
373 const dwarf = &(di.dwarf orelse break :dwarf);378 const dwarf = &(di.dwarf orelse break :dwarf);
374 const addr = vaddr + di.coff_image_base;379 const addr = vaddr + di.coff_image_base;
375 return dwarf.getSymbols(gpa, native_endian, addr, resolve_inline_callers, symbols);380 return dwarf.getSymbols(
381 symbol_allocator,
382 text_arena,
383 native_endian,
384 addr,
385 resolve_inline_callers,
386 symbols,
387 );
376 }388 }
377389
378 return error.MissingDebugInfo;390 return error.MissingDebugInfo;
test/standalone/coff_dwarf/main.zig+19-9
...@@ -12,16 +12,26 @@ pub fn main(init: std.process.Init) void {...@@ -12,16 +12,26 @@ pub fn main(init: std.process.Init) void {
12 var add_addr: usize = undefined;12 var add_addr: usize = undefined;
13 _ = add(1, 2, &add_addr);13 _ = add(1, 2, &add_addr);
1414
15 const symbols = di.getSymbols(io, add_addr, false) catch |err| fatal("failed to get symbol: {t}", .{err});
16 const debug_gpa = std.debug.getDebugInfoAllocator();15 const debug_gpa = std.debug.getDebugInfoAllocator();
17 defer for (symbols) |symbol| {16 const symbol_allocator = debug_gpa;
18 if (symbol.source_location) |sl| {17
19 debug_gpa.free(sl.file_name);18 var symbols: std.ArrayList(std.debug.Symbol) = .empty;
20 }19 defer symbols.deinit(symbol_allocator);
21 };20
2221 var text_arena: std.heap.ArenaAllocator = .init(debug_gpa);
23 if (symbols.len != 1) fatal("expected 1 symbol, found {}", .{symbols.len});22 defer text_arena.deinit();
24 const symbol = symbols[0];23
24 di.getSymbols(
25 io,
26 symbol_allocator,
27 text_arena.allocator(),
28 add_addr,
29 false,
30 &symbols,
31 ) catch |err| fatal("failed to get symbol: {t}", .{err});
32
33 if (symbols.items.len != 1) fatal("expected 1 symbol, found {}", .{symbols.items.len});
34 const symbol = symbols.items[0];
2535
26 if (symbol.name == null) fatal("failed to resolve symbol name", .{});36 if (symbol.name == null) fatal("failed to resolve symbol name", .{});
27 if (symbol.compile_unit_name == null) fatal("failed to resolve compile unit", .{});37 if (symbol.compile_unit_name == null) fatal("failed to resolve compile unit", .{});