| author | |
| committer | |
| log | 4ad665d3c8cd6a9d4f6b0e2f065098436142b450 |
| tree | 26e3f51669fd2a2c44286f2d912e47d4001b3cf9 |
| parent | e968e6d00473a0fb9de86ae99400503e4e40f0ef |
5 files changed, 79 insertions(+), 61 deletions(-)
lib/std/debug.zig+19-10| ... | ... | @@ -38,8 +38,8 @@ pub const cpu_context = @import("debug/cpu_context.zig"); |
| 38 | 38 | /// pub const init: SelfInfo; |
| 39 | 39 | /// pub fn deinit(si: *SelfInfo, io: Io) void; |
| 40 | 40 | /// |
| 41 | /// /// Returns the the symbols and source locations of the instruction at `address`. | |
| 42 | /// pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, include_inline_callers: bool) SelfInfoError![]Symbol; | |
| 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; | |
| 43 | 43 | /// /// Returns a name for the "module" (e.g. shared library or executable image) containing `address`. |
| 44 | 44 | /// pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) SelfInfoError![]const u8; |
| 45 | 45 | /// pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) SelfInfoError!usize; |
| ... | ... | @@ -1190,8 +1190,17 @@ fn printSourceAtAddress( |
| 1190 | 1190 | t: Io.Terminal, |
| 1191 | 1191 | options: PrintSourceAddressOptions, |
| 1192 | 1192 | ) Writer.Error!void { |
| 1193 | const gpa = getDebugInfoAllocator(); | |
| 1194 | const symbols: []Symbol = debug_info.getSymbols(io, options.address, options.resolve_inline_callers) catch |err| { | |
| 1193 | // In the common case where there's only one symbol, allocate it on the stack. Reserve enough | |
| 1194 | // space for one item regardless of alignment. | |
| 1195 | var stack_fallback = std.heap.stackFallback(@sizeOf(Symbol) + @alignOf(Symbol) - 1, getDebugInfoAllocator()); | |
| 1196 | const sfa = stack_fallback.get(); | |
| 1197 | var symbols = std.ArrayList(Symbol).initCapacity(sfa, 1) catch unreachable; | |
| 1198 | defer { | |
| 1199 | for (symbols.items) |*symbol| symbol.deinit(sfa); | |
| 1200 | symbols.deinit(sfa); | |
| 1201 | } | |
| 1202 | ||
| 1203 | debug_info.getSymbols(io, sfa, options.address, options.resolve_inline_callers, &symbols) catch |err| { | |
| 1195 | 1204 | t.setColor(.dim) catch {}; |
| 1196 | 1205 | defer t.setColor(.reset) catch {}; |
| 1197 | 1206 | switch (err) { |
| ... | ... | @@ -1208,13 +1217,13 @@ fn printSourceAtAddress( |
| 1208 | 1217 | t.setColor(.reset) catch {}; |
| 1209 | 1218 | }, |
| 1210 | 1219 | } |
| 1211 | return printLineInfo(io, t, debug_info, null, options.address, null, null); | |
| 1212 | 1220 | }; |
| 1213 | defer { | |
| 1214 | for (symbols) |*symbol| symbol.deinit(gpa); | |
| 1215 | gpa.free(symbols); | |
| 1216 | } | |
| 1217 | for (symbols) |symbol| { | |
| 1221 | ||
| 1222 | // If we failed to get any symbols, append the unknown symbol. We initialized with a capacity of | |
| 1223 | // one using a stack fallback allocator so this can't fail. | |
| 1224 | if (symbols.items.len == 0) symbols.appendAssumeCapacity(.unknown); | |
| 1225 | ||
| 1226 | for (symbols.items) |symbol| { | |
| 1218 | 1227 | try printLineInfo( |
| 1219 | 1228 | io, |
| 1220 | 1229 | t, |
lib/std/debug/Dwarf.zig+12-13| ... | ... | @@ -1545,22 +1545,22 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 { |
| 1545 | 1545 | return str[casted_offset..last :0]; |
| 1546 | 1546 | } |
| 1547 | 1547 | |
| 1548 | pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64, resolve_inline_callers: bool) std.debug.SelfInfoError![]std.debug.Symbol { | |
| 1548 | pub fn getSymbols( | |
| 1549 | di: *Dwarf, | |
| 1550 | gpa: Allocator, | |
| 1551 | endian: Endian, | |
| 1552 | address: u64, | |
| 1553 | resolve_inline_callers: bool, | |
| 1554 | symbols: *std.ArrayList(std.debug.Symbol), | |
| 1555 | ) std.debug.SelfInfoError!void { | |
| 1549 | 1556 | _ = resolve_inline_callers; |
| 1550 | 1557 | |
| 1551 | var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1); | |
| 1552 | errdefer { | |
| 1553 | for (symbols.items) |*symbol| symbol.deinit(gpa); | |
| 1554 | symbols.deinit(gpa); | |
| 1555 | } | |
| 1556 | 1558 | const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) { |
| 1557 | error.EndOfStream, error.Overflow => { | |
| 1558 | symbols.appendAssumeCapacity(.unknown); | |
| 1559 | return symbols.toOwnedSlice(gpa); | |
| 1560 | }, | |
| 1561 | else => |e| return e, | |
| 1559 | error.EndOfStream => return error.MissingDebugInfo, | |
| 1560 | error.Overflow => return error.InvalidDebugInfo, | |
| 1561 | error.ReadFailed, error.InvalidDebugInfo, error.MissingDebugInfo => |e| return e, | |
| 1562 | 1562 | }; |
| 1563 | symbols.appendAssumeCapacity(.{ | |
| 1563 | try symbols.append(gpa, .{ | |
| 1564 | 1564 | .name = di.getSymbolName(address), |
| 1565 | 1565 | .compile_unit_name = compile_unit.die.getAttrString(di, endian, std.dwarf.AT.name, di.section(.debug_str), compile_unit) catch |err| switch (err) { |
| 1566 | 1566 | error.MissingDebugInfo, error.InvalidDebugInfo => null, |
| ... | ... | @@ -1575,7 +1575,6 @@ pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64, reso |
| 1575 | 1575 | else => |e| return e, |
| 1576 | 1576 | }, |
| 1577 | 1577 | }); |
| 1578 | return symbols.toOwnedSlice(gpa); | |
| 1579 | 1578 | } |
| 1580 | 1579 | |
| 1581 | 1580 | /// DWARF5 7.4: "In the 32-bit DWARF format, all values that represent lengths of DWARF sections and |
lib/std/debug/SelfInfo/Elf.zig+10-10| ... | ... | @@ -30,8 +30,14 @@ pub fn deinit(si: *SelfInfo, io: Io) void { |
| 30 | 30 | if (si.unwind_cache) |cache| gpa.free(cache); |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol { | |
| 34 | const gpa = std.debug.getDebugInfoAllocator(); | |
| 33 | pub fn getSymbols( | |
| 34 | si: *SelfInfo, | |
| 35 | io: Io, | |
| 36 | gpa: Allocator, | |
| 37 | address: usize, | |
| 38 | resolve_inline_callers: bool, | |
| 39 | symbols: *std.ArrayList(std.debug.Symbol), | |
| 40 | ) Error!void { | |
| 35 | 41 | const module = try si.findModule(gpa, io, address, .exclusive); |
| 36 | 42 | defer si.rwlock.unlock(io); |
| 37 | 43 | |
| ... | ... | @@ -53,20 +59,14 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: |
| 53 | 59 | }; |
| 54 | 60 | loaded_elf.scanned_dwarf = true; |
| 55 | 61 | } |
| 56 | return dwarf.getSymbols(gpa, native_endian, vaddr, resolve_inline_callers); | |
| 62 | return dwarf.getSymbols(gpa, native_endian, vaddr, resolve_inline_callers, symbols); | |
| 57 | 63 | } |
| 58 | 64 | // When DWARF is unavailable, fall back to searching the symtab. |
| 59 | var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1); | |
| 60 | errdefer { | |
| 61 | for (symbols.items) |*symbol| symbol.deinit(gpa); | |
| 62 | symbols.deinit(gpa); | |
| 63 | } | |
| 64 | symbols.appendAssumeCapacity(loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) { | |
| 65 | try symbols.append(gpa, loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) { | |
| 65 | 66 | error.NoSymtab, error.NoStrtab => return error.MissingDebugInfo, |
| 66 | 67 | error.BadSymtab => return error.InvalidDebugInfo, |
| 67 | 68 | error.OutOfMemory => |e| return e, |
| 68 | 69 | }); |
| 69 | return symbols.toOwnedSlice(gpa); | |
| 70 | 70 | } |
| 71 | 71 | pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 { |
| 72 | 72 | const gpa = std.debug.getDebugInfoAllocator(); |
lib/std/debug/SelfInfo/MachO.zig+11-14| ... | ... | @@ -22,21 +22,21 @@ pub fn deinit(si: *SelfInfo, io: Io) void { |
| 22 | 22 | si.modules.deinit(gpa); |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol { | |
| 25 | pub fn getSymbols( | |
| 26 | si: *SelfInfo, | |
| 27 | io: Io, | |
| 28 | gpa: Allocator, | |
| 29 | address: usize, | |
| 30 | resolve_inline_callers: bool, | |
| 31 | symbols: *std.ArrayList(std.debug.Symbol), | |
| 32 | ) Error!void { | |
| 26 | 33 | _ = resolve_inline_callers; |
| 27 | 34 | |
| 28 | const gpa = std.debug.getDebugInfoAllocator(); | |
| 29 | 35 | const module = try si.findModule(gpa, io, address); |
| 30 | 36 | defer si.mutex.unlock(io); |
| 31 | 37 | |
| 32 | 38 | const file = try module.getFile(gpa, io); |
| 33 | 39 | |
| 34 | var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1); | |
| 35 | errdefer { | |
| 36 | for (symbols.items) |*symbol| symbol.deinit(gpa); | |
| 37 | symbols.deinit(gpa); | |
| 38 | } | |
| 39 | ||
| 40 | 40 | // This is not necessarily the same as the vmaddr_slide that dyld would report. This is |
| 41 | 41 | // because the segments in the file on disk might differ from the ones in memory. Normally |
| 42 | 42 | // we wouldn't necessarily expect that to work, but /usr/lib/dyld is incredibly annoying: |
| ... | ... | @@ -51,25 +51,23 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: |
| 51 | 51 | |
| 52 | 52 | const ofile_dwarf, const ofile_vaddr = file.getDwarfForAddress(gpa, io, vaddr) catch { |
| 53 | 53 | // Return at least the symbol name if available. |
| 54 | symbols.appendAssumeCapacity(.{ | |
| 54 | return symbols.append(gpa, .{ | |
| 55 | 55 | .name = try file.lookupSymbolName(vaddr), |
| 56 | 56 | .compile_unit_name = null, |
| 57 | 57 | .source_location = null, |
| 58 | 58 | }); |
| 59 | return symbols.toOwnedSlice(gpa); | |
| 60 | 59 | }; |
| 61 | 60 | |
| 62 | 61 | const compile_unit = ofile_dwarf.findCompileUnit(native_endian, ofile_vaddr) catch { |
| 63 | 62 | // Return at least the symbol name if available. |
| 64 | symbols.appendAssumeCapacity(.{ | |
| 63 | return symbols.append(gpa, .{ | |
| 65 | 64 | .name = try file.lookupSymbolName(vaddr), |
| 66 | 65 | .compile_unit_name = null, |
| 67 | 66 | .source_location = null, |
| 68 | 67 | }); |
| 69 | return symbols.toOwnedSlice(gpa); | |
| 70 | 68 | }; |
| 71 | 69 | |
| 72 | symbols.appendAssumeCapacity(.{ | |
| 70 | try symbols.append(gpa, .{ | |
| 73 | 71 | .name = ofile_dwarf.getSymbolName(ofile_vaddr) orelse |
| 74 | 72 | try file.lookupSymbolName(vaddr), |
| 75 | 73 | .compile_unit_name = compile_unit.die.getAttrString( |
| ... | ... | @@ -88,7 +86,6 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: |
| 88 | 86 | ofile_vaddr, |
| 89 | 87 | ) catch null, |
| 90 | 88 | }); |
| 91 | return symbols.toOwnedSlice(gpa); | |
| 92 | 89 | } |
| 93 | 90 | pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 { |
| 94 | 91 | _ = si; |
lib/std/debug/SelfInfo/Windows.zig+27-14| ... | ... | @@ -25,13 +25,24 @@ pub fn deinit(si: *SelfInfo, io: Io) void { |
| 25 | 25 | si.modules.deinit(gpa); |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol { | |
| 29 | const gpa = std.debug.getDebugInfoAllocator(); | |
| 28 | pub fn getSymbols( | |
| 29 | si: *SelfInfo, | |
| 30 | io: Io, | |
| 31 | gpa: Allocator, | |
| 32 | address: usize, | |
| 33 | resolve_inline_callers: bool, | |
| 34 | symbols: *std.ArrayList(std.debug.Symbol), | |
| 35 | ) Error!void { | |
| 30 | 36 | try si.lock.lockShared(io); |
| 31 | 37 | defer si.lock.unlockShared(io); |
| 32 | 38 | const module = try si.findModule(gpa, address); |
| 33 | 39 | const di = try module.getDebugInfo(gpa, io); |
| 34 | return di.getSymbols(gpa, address - @intFromPtr(module.entry.DllBase), resolve_inline_callers); | |
| 40 | return di.getSymbols( | |
| 41 | gpa, | |
| 42 | address - @intFromPtr(module.entry.DllBase), | |
| 43 | resolve_inline_callers, | |
| 44 | symbols, | |
| 45 | ); | |
| 35 | 46 | } |
| 36 | 47 | |
| 37 | 48 | pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 { |
| ... | ... | @@ -241,7 +252,13 @@ const Module = struct { |
| 241 | 252 | arena.deinit(); |
| 242 | 253 | } |
| 243 | 254 | |
| 244 | fn getSymbols(di: *DebugInfo, gpa: Allocator, vaddr: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol { | |
| 255 | fn getSymbols( | |
| 256 | di: *DebugInfo, | |
| 257 | gpa: Allocator, | |
| 258 | vaddr: usize, | |
| 259 | resolve_inline_callers: bool, | |
| 260 | symbols: *std.ArrayList(std.debug.Symbol), | |
| 261 | ) Error!void { | |
| 245 | 262 | pdb: { |
| 246 | 263 | const pdb = &(di.pdb orelse break :pdb); |
| 247 | 264 | var coff_section: *align(1) const coff.SectionHeader = undefined; |
| ... | ... | @@ -275,12 +292,7 @@ const Module = struct { |
| 275 | 292 | const addr = vaddr - coff_section.virtual_address; |
| 276 | 293 | const maybe_proc = pdb.getProcSym(module, addr); |
| 277 | 294 | const compile_unit_name = fs.path.basename(module.obj_file_name); |
| 278 | var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1); | |
| 279 | errdefer { | |
| 280 | for (symbols.items) |*symbol| symbol.deinit(gpa); | |
| 281 | symbols.deinit(gpa); | |
| 282 | } | |
| 283 | ||
| 295 | const symbols_top = symbols.items.len; | |
| 284 | 296 | if (maybe_proc) |proc| { |
| 285 | 297 | const offset_in_func = addr - proc.code_offset; |
| 286 | 298 | var last_inlinee: ?u32 = null; |
| ... | ... | @@ -308,9 +320,10 @@ const Module = struct { |
| 308 | 320 | const loc = maybe_loc orelse continue; |
| 309 | 321 | |
| 310 | 322 | // If we aren't trying to resolve inline callers, and we've matched a |
| 311 | // new inline site, we want to overwrite the previous results. | |
| 323 | // new inline site, we want to overwrite the previously appended | |
| 324 | // results. | |
| 312 | 325 | if (!resolve_inline_callers and inline_site.inlinee != last_inlinee) { |
| 313 | symbols.items.len = 0; | |
| 326 | symbols.items.len = symbols_top; | |
| 314 | 327 | } |
| 315 | 328 | |
| 316 | 329 | // Only resolve the name if we're resolving inline callers, otherwise |
| ... | ... | @@ -353,13 +366,13 @@ const Module = struct { |
| 353 | 366 | }); |
| 354 | 367 | } |
| 355 | 368 | |
| 356 | return symbols.toOwnedSlice(gpa); | |
| 369 | return; | |
| 357 | 370 | } |
| 358 | 371 | |
| 359 | 372 | dwarf: { |
| 360 | 373 | const dwarf = &(di.dwarf orelse break :dwarf); |
| 361 | 374 | const addr = vaddr + di.coff_image_base; |
| 362 | return dwarf.getSymbols(gpa, native_endian, addr, resolve_inline_callers); | |
| 375 | return dwarf.getSymbols(gpa, native_endian, addr, resolve_inline_callers, symbols); | |
| 363 | 376 | } |
| 364 | 377 | |
| 365 | 378 | return error.MissingDebugInfo; |