mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Don't bother resolving symbol names that won't be used
Also fixes some memory management issues
This commit is contained in:
+13
-9
@@ -38,12 +38,8 @@ pub const cpu_context = @import("debug/cpu_context.zig");
|
||||
/// pub const init: SelfInfo;
|
||||
/// pub fn deinit(si: *SelfInfo, io: Io) void;
|
||||
///
|
||||
/// /// Returns the the symbols and source locations of the instruction at `address`. Often this
|
||||
/// /// will return a single result, but in the case of inlines it may return multiple. When
|
||||
/// /// multiple results are returned, they are sorted from innermost to outermost.
|
||||
/// pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SelfInfoError![]const Symbol;
|
||||
/// /// Frees symbols returned from `getSymbols`.
|
||||
/// pub fn freeSymbols(si: *SelfInfo, symbols: []const Symbol) void;
|
||||
/// /// Returns the the symbols and source locations of the instruction at `address`.
|
||||
/// pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, include_inline_callers: bool) SelfInfoError![]Symbol;
|
||||
/// /// Returns a name for the "module" (e.g. shared library or executable image) containing `address`.
|
||||
/// pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) SelfInfoError![]const u8;
|
||||
/// pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) SelfInfoError!usize;
|
||||
@@ -233,6 +229,11 @@ pub const Symbol = struct {
|
||||
.compile_unit_name = null,
|
||||
.source_location = null,
|
||||
};
|
||||
|
||||
pub fn deinit(self: *Symbol, gpa: Allocator) void {
|
||||
if (self.source_location) |sl| gpa.free(sl.file_name);
|
||||
self.* = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/// Deprecated because it returns the optimization mode of the standard
|
||||
@@ -1192,7 +1193,8 @@ fn printSourceAtAddress(
|
||||
t: Io.Terminal,
|
||||
options: PrintSourceAddressOptions,
|
||||
) Writer.Error!void {
|
||||
const symbols: []const Symbol = debug_info.getSymbols(io, options.address) catch |err| {
|
||||
const gpa = getDebugInfoAllocator();
|
||||
const symbols: []Symbol = debug_info.getSymbols(io, options.address, options.resolve_inline_callers) catch |err| {
|
||||
t.setColor(.dim) catch {};
|
||||
defer t.setColor(.reset) catch {};
|
||||
switch (err) {
|
||||
@@ -1211,7 +1213,10 @@ fn printSourceAtAddress(
|
||||
}
|
||||
return printLineInfo(io, t, debug_info, null, options.address, null, null);
|
||||
};
|
||||
defer debug_info.freeSymbols(symbols);
|
||||
defer {
|
||||
for (symbols) |*symbol| symbol.deinit(gpa);
|
||||
gpa.free(symbols);
|
||||
}
|
||||
for (symbols) |symbol| {
|
||||
try printLineInfo(
|
||||
io,
|
||||
@@ -1222,7 +1227,6 @@ fn printSourceAtAddress(
|
||||
symbol.name,
|
||||
symbol.compile_unit_name,
|
||||
);
|
||||
if (!options.resolve_inline_callers) break;
|
||||
}
|
||||
}
|
||||
fn printLineInfo(
|
||||
|
||||
+13
-8
@@ -1545,17 +1545,22 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {
|
||||
return str[casted_offset..last :0];
|
||||
}
|
||||
|
||||
pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64) std.debug.SelfInfoError![]const std.debug.Symbol {
|
||||
const symbol = try gpa.create(std.debug.Symbol);
|
||||
errdefer gpa.destroy(symbol);
|
||||
pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64, resolve_inline_callers: bool) std.debug.SelfInfoError![]std.debug.Symbol {
|
||||
_ = resolve_inline_callers;
|
||||
|
||||
var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1);
|
||||
errdefer {
|
||||
for (symbols.items) |*symbol| symbol.deinit(gpa);
|
||||
symbols.deinit(gpa);
|
||||
}
|
||||
const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) {
|
||||
error.EndOfStream, error.Overflow => {
|
||||
symbol.* = .unknown;
|
||||
return symbol[0..1];
|
||||
symbols.appendAssumeCapacity(.unknown);
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
symbol.* = .{
|
||||
symbols.appendAssumeCapacity(.{
|
||||
.name = di.getSymbolName(address),
|
||||
.compile_unit_name = compile_unit.die.getAttrString(di, endian, std.dwarf.AT.name, di.section(.debug_str), compile_unit) catch |err| switch (err) {
|
||||
error.MissingDebugInfo, error.InvalidDebugInfo => null,
|
||||
@@ -1569,8 +1574,8 @@ pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64) std.
|
||||
=> return error.InvalidDebugInfo,
|
||||
else => |e| return e,
|
||||
},
|
||||
};
|
||||
return symbol[0..1];
|
||||
});
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
}
|
||||
|
||||
/// DWARF5 7.4: "In the 32-bit DWARF format, all values that represent lengths of DWARF sections and
|
||||
|
||||
@@ -30,7 +30,7 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
|
||||
if (si.unwind_cache) |cache| gpa.free(cache);
|
||||
}
|
||||
|
||||
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) Error![]const std.debug.Symbol {
|
||||
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol {
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
const module = try si.findModule(gpa, io, address, .exclusive);
|
||||
defer si.rwlock.unlock(io);
|
||||
@@ -53,27 +53,20 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) Error![]const std.debug
|
||||
};
|
||||
loaded_elf.scanned_dwarf = true;
|
||||
}
|
||||
return dwarf.getSymbols(gpa, native_endian, vaddr);
|
||||
return dwarf.getSymbols(gpa, native_endian, vaddr, resolve_inline_callers);
|
||||
}
|
||||
// When DWARF is unavailable, fall back to searching the symtab.
|
||||
const symbol = try gpa.create(std.debug.Symbol);
|
||||
errdefer gpa.destroy(symbol);
|
||||
symbol.* = loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {
|
||||
var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1);
|
||||
errdefer {
|
||||
for (symbols.items) |*symbol| symbol.deinit(gpa);
|
||||
symbols.deinit(gpa);
|
||||
}
|
||||
symbols.appendAssumeCapacity(loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {
|
||||
error.NoSymtab, error.NoStrtab => return error.MissingDebugInfo,
|
||||
error.BadSymtab => return error.InvalidDebugInfo,
|
||||
error.OutOfMemory => |e| return e,
|
||||
};
|
||||
return symbol[0..1];
|
||||
}
|
||||
pub fn freeSymbols(si: *SelfInfo, symbols: []const std.debug.Symbol) void {
|
||||
_ = si;
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
for (symbols) |symbol| {
|
||||
if (symbol.source_location) |source_location| {
|
||||
gpa.free(source_location.file_name);
|
||||
}
|
||||
}
|
||||
gpa.free(symbols);
|
||||
});
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
}
|
||||
pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 {
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
|
||||
@@ -36,15 +36,20 @@ pub const SymbolIterator = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) Error![]const std.debug.Symbol {
|
||||
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol {
|
||||
_ = resolve_inline_callers;
|
||||
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
const module = try si.findModule(gpa, io, address);
|
||||
defer si.mutex.unlock(io);
|
||||
|
||||
const file = try module.getFile(gpa, io);
|
||||
|
||||
const symbol = try gpa.create(std.debug.Symbol);
|
||||
errdefer gpa.destroy(symbol);
|
||||
var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1);
|
||||
errdefer {
|
||||
for (symbols.items) |*symbol| symbol.deinit(gpa);
|
||||
symbols.deinit(gpa);
|
||||
}
|
||||
|
||||
// This is not necessarily the same as the vmaddr_slide that dyld would report. This is
|
||||
// because the segments in the file on disk might differ from the ones in memory. Normally
|
||||
@@ -60,25 +65,25 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) Error![]const std.debug
|
||||
|
||||
const ofile_dwarf, const ofile_vaddr = file.getDwarfForAddress(gpa, io, vaddr) catch {
|
||||
// Return at least the symbol name if available.
|
||||
symbol.* = .{
|
||||
symbols.appendAssumeCapacity(.{
|
||||
.name = try file.lookupSymbolName(vaddr),
|
||||
.compile_unit_name = null,
|
||||
.source_location = null,
|
||||
};
|
||||
return symbol[0..1];
|
||||
});
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
};
|
||||
|
||||
const compile_unit = ofile_dwarf.findCompileUnit(native_endian, ofile_vaddr) catch {
|
||||
// Return at least the symbol name if available.
|
||||
symbol.* = .{
|
||||
symbols.appendAssumeCapacity(.{
|
||||
.name = try file.lookupSymbolName(vaddr),
|
||||
.compile_unit_name = null,
|
||||
.source_location = null,
|
||||
};
|
||||
return symbol[0..1];
|
||||
});
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
};
|
||||
|
||||
symbol.* = .{
|
||||
symbols.appendAssumeCapacity(.{
|
||||
.name = ofile_dwarf.getSymbolName(ofile_vaddr) orelse
|
||||
try file.lookupSymbolName(vaddr),
|
||||
.compile_unit_name = compile_unit.die.getAttrString(
|
||||
@@ -96,18 +101,8 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) Error![]const std.debug
|
||||
compile_unit,
|
||||
ofile_vaddr,
|
||||
) catch null,
|
||||
};
|
||||
return symbol[0..1];
|
||||
}
|
||||
pub fn freeSymbols(si: *SelfInfo, symbols: []const std.debug.Symbol) void {
|
||||
_ = si;
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
for (symbols) |symbol| {
|
||||
if (symbol.source_location) |source_location| {
|
||||
gpa.free(source_location.file_name);
|
||||
}
|
||||
}
|
||||
gpa.free(symbols);
|
||||
});
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
}
|
||||
pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 {
|
||||
_ = si;
|
||||
|
||||
@@ -25,24 +25,13 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
|
||||
si.modules.deinit(gpa);
|
||||
}
|
||||
|
||||
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) Error![]const std.debug.Symbol {
|
||||
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol {
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
try si.lock.lockShared(io);
|
||||
defer si.lock.unlockShared(io);
|
||||
const module = try si.findModule(gpa, address);
|
||||
const di = try module.getDebugInfo(gpa, io);
|
||||
return di.getSymbols(gpa, address - @intFromPtr(module.entry.DllBase));
|
||||
}
|
||||
|
||||
pub fn freeSymbols(si: *SelfInfo, symbols: []const std.debug.Symbol) void {
|
||||
_ = si;
|
||||
const gpa = std.debug.getDebugInfoAllocator();
|
||||
for (symbols) |symbol| {
|
||||
if (symbol.source_location) |source_location| {
|
||||
gpa.free(source_location.file_name);
|
||||
}
|
||||
}
|
||||
gpa.free(symbols);
|
||||
return di.getSymbols(gpa, address - @intFromPtr(module.entry.DllBase), resolve_inline_callers);
|
||||
}
|
||||
|
||||
pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 {
|
||||
@@ -252,7 +241,7 @@ const Module = struct {
|
||||
arena.deinit();
|
||||
}
|
||||
|
||||
fn getSymbols(di: *DebugInfo, gpa: Allocator, vaddr: usize) Error![]const std.debug.Symbol {
|
||||
fn getSymbols(di: *DebugInfo, gpa: Allocator, vaddr: usize, resolve_inline_callers: bool) Error![]std.debug.Symbol {
|
||||
pdb: {
|
||||
const pdb = &(di.pdb orelse break :pdb);
|
||||
var coff_section: *align(1) const coff.SectionHeader = undefined;
|
||||
@@ -285,8 +274,12 @@ const Module = struct {
|
||||
|
||||
const addr = vaddr - coff_section.virtual_address;
|
||||
const maybe_proc = pdb.getProcSym(module, addr);
|
||||
var symbols: std.ArrayList(std.debug.Symbol) = .empty;
|
||||
errdefer symbols.deinit(gpa);
|
||||
const compile_unit_name = fs.path.basename(module.obj_file_name);
|
||||
var symbols: std.ArrayList(std.debug.Symbol) = try .initCapacity(gpa, 1);
|
||||
errdefer {
|
||||
for (symbols.items) |*symbol| symbol.deinit(gpa);
|
||||
symbols.deinit(gpa);
|
||||
}
|
||||
|
||||
if (maybe_proc) |proc| {
|
||||
const offset_in_func = addr - proc.code_offset;
|
||||
@@ -315,25 +308,43 @@ const Module = struct {
|
||||
if (inline_site.inlinee == last_inlinee) continue;
|
||||
last_inlinee = inline_site.inlinee;
|
||||
|
||||
// If we're appending this symbol, resolve the name. If we're replacing the
|
||||
// last symbol, clear the previous symbols and wait to resolve the name
|
||||
// until we've reached the last symbol to avoid doing work and then
|
||||
// throwing it out.
|
||||
const name = b: {
|
||||
if (resolve_inline_callers) break :b pdb.findInlineeName(inline_site.inlinee);
|
||||
symbols.items.len = 0;
|
||||
break :b null;
|
||||
};
|
||||
|
||||
try symbols.append(gpa, .{
|
||||
.name = pdb.findInlineeName(inline_site.inlinee),
|
||||
.compile_unit_name = fs.path.basename(module.obj_file_name),
|
||||
.name = name,
|
||||
.compile_unit_name = compile_unit_name,
|
||||
.source_location = loc,
|
||||
});
|
||||
}
|
||||
|
||||
// Inline sites are stored in the pdb in reverse order, so we reverse the
|
||||
// matching sites here. We could alternatively use the parent fields to
|
||||
// determine the order, but this would introduce seemingly unecessary
|
||||
// complexity.
|
||||
std.mem.reverse(std.debug.Symbol, symbols.items);
|
||||
if (resolve_inline_callers) {
|
||||
// Inline sites are stored in the pdb in reverse order, so we reverse the
|
||||
// matching sites here. We could alternatively use the parent fields to
|
||||
// determine the order, but this would introduce seemingly unecessary
|
||||
// complexity.
|
||||
std.mem.reverse(std.debug.Symbol, symbols.items);
|
||||
} else if (last_inlinee) |inlinee| {
|
||||
// If we haven't resolved the name yet, resolve it now
|
||||
symbols.items[symbols.items.len - 1].name = pdb.findInlineeName(inlinee);
|
||||
}
|
||||
}
|
||||
|
||||
try symbols.append(gpa, .{
|
||||
.name = if (maybe_proc) |proc| pdb.getSymbolName(proc) else null,
|
||||
.compile_unit_name = fs.path.basename(module.obj_file_name),
|
||||
.source_location = pdb.getLineNumberInfo(module, addr) catch null,
|
||||
});
|
||||
// If there's room for another symbol, add the actual proc
|
||||
if (resolve_inline_callers or symbols.items.len == 0) {
|
||||
try symbols.append(gpa, .{
|
||||
.name = if (maybe_proc) |proc| pdb.getSymbolName(proc) else null,
|
||||
.compile_unit_name = compile_unit_name,
|
||||
.source_location = pdb.getLineNumberInfo(module, addr) catch null,
|
||||
});
|
||||
}
|
||||
|
||||
return symbols.toOwnedSlice(gpa);
|
||||
}
|
||||
@@ -341,7 +352,7 @@ const Module = struct {
|
||||
dwarf: {
|
||||
const dwarf = &(di.dwarf orelse break :dwarf);
|
||||
const addr = vaddr + di.coff_image_base;
|
||||
return dwarf.getSymbols(gpa, native_endian, addr);
|
||||
return dwarf.getSymbols(gpa, native_endian, addr, resolve_inline_callers);
|
||||
}
|
||||
|
||||
return error.MissingDebugInfo;
|
||||
|
||||
Reference in New Issue
Block a user