| author | |
| committer | |
| log | 6707a5efeea1ab973c3274495bb0a5640e4f568b |
| tree | e3f815ac7949a0b33ad997e386ccb4cdd5a81bcc |
| parent | 4ad665d3c8cd6a9d4f6b0e2f065098436142b450 |
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 | }; |
| 238 | 233 | ||
| 239 | /// Deprecated because it returns the optimization mode of the standard | 234 | /// 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. |
| 700 | pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void { | 695 | pub 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 { |
| 1186 | 1188 | ||
| 1187 | fn printSourceAtAddress( | 1189 | fn 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 enough | 1196 | 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 | |
| 1202 | 1205 | 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 | }; |
| 1221 | 1230 | ||
| 1222 | // If we failed to get any symbols, append the unknown symbol. We initialized with a capacity of | 1231 | // 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); |
| 1225 | 1234 | ||
| 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 | } |
| 1238 | fn printLineInfo( | 1239 | fn 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 {}; |
| 1249 | 1248 | ||
| 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"); |
| 1270 | 1269 | ||
| 1271 | // Show the matching source code line if possible | 1270 | // 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 char | 1274 | // 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 |
| 1220 | pub fn getLineNumberInfo( | 1220 | pub 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 { |
| 1547 | 1548 | ||
| 1548 | pub fn getSymbols( | 1549 | pub 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(); | ||
| 1557 | 1560 | ||
| 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 |
| 617 | 617 | ||
| 618 | pub fn getInlineSiteSourceLocation( | 618 | pub 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; |
| 628 | 629 | ||
| 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); |
| 632 | 633 | ||
| 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 | } |
| 642 | 643 | ||
| 643 | pub fn getFileName(self: *Pdb, mod: *Module, file_id: u32) ![]const u8 { | 644 | pub 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 API | 654 | 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 | } |
| 718 | 719 | ||
| 719 | pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.SourceLocation { | 720 | pub 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; | ||
| 723 | 723 | ||
| 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 |
| 769 | 769 | ||
| 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); |
| 774 | 774 | ||
| 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 { |
| 33 | pub fn getSymbols( | 33 | pub 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); |
| 43 | 45 | ||
| ... | @@ -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 { |
| 25 | pub fn getSymbols( | 25 | pub 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(); | ||
| 34 | 36 | ||
| 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( |
| 51 | 53 | ||
| 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( |
| 60 | 62 | ||
| 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 | }; |
| 69 | 71 | ||
| 70 | try symbols.append(gpa, .{ | 72 | try symbols.append(symbol_allocator, .{ |
| 71 | .name = ofile_dwarf.getSymbolName(ofile_vaddr) orelse | 73 | .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 { |
| 28 | pub fn getSymbols( | 28 | pub 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 { |
| 254 | 257 | ||
| 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 | else | 338 | else |
| 334 | null; | 339 | null; |
| 335 | 340 | ||
| 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 { |
| 359 | 364 | ||
| 360 | // If there's room for another symbol, add the actual proc | 365 | // 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 | } |
| 368 | 373 | ||
| ... | @@ -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 | } |
| 377 | 389 | ||
| 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); |
| 14 | 14 | ||
| 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 | |
| 22 | 21 | 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]; | ||
| 25 | 35 | ||
| 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", .{}); |