Uses dwarf iterator if dwarf symbols found for windows executable

This commit is contained in:
Mason Remaley
2026-04-10 13:53:41 -07:00
parent 825ba5a350
commit 5a4b5c8b94
4 changed files with 41 additions and 71 deletions
+28 -7
View File
@@ -22,7 +22,9 @@ const cast = std.math.cast;
const maxInt = std.math.maxInt;
const ArrayList = std.ArrayList;
const Endian = std.builtin.Endian;
const Reader = std.Io.Reader;
const Io = std.Io;
const Reader = Io.Reader;
const Error = std.debug.SelfInfoError;
const Dwarf = @This();
@@ -1543,21 +1545,40 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {
return str[casted_offset..last :0];
}
pub fn getSymbol(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64) !std.debug.Symbol {
pub const SymbolIterator = struct {
curr: ?std.debug.SelfInfoError!std.debug.Symbol,
pub fn deinit(self: *SymbolIterator, _: Io) void {
self.* = undefined;
}
pub fn next(self: *SymbolIterator) ?Error!std.debug.Symbol {
const result = self.curr;
self.curr = null;
return result;
}
};
pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64) SymbolIterator {
const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => return .unknown,
else => return err,
error.EndOfStream, error.Overflow => return .{ .curr = error.InvalidDebugInfo },
else => |e| return .{ .curr = e },
};
return .{
return .{ .curr = .{
.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,
},
.source_location = di.getLineNumberInfo(gpa, endian, compile_unit, address) catch |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => null,
else => return err,
error.ReadFailed,
error.EndOfStream,
error.Overflow,
error.StreamTooLong,
=> return .{ .curr = error.InvalidDebugInfo },
else => |e| return .{ .curr = e },
},
};
} };
}
/// DWARF5 7.4: "In the 32-bit DWARF format, all values that represent lengths of DWARF sections and
+1 -1
View File
@@ -358,7 +358,7 @@ pub const BinaryAnnotation = union(enum) {
self.curr.file_id = file_id;
},
// LLVM never emits this opcode, but it's clear enough how to interpret it so we
// may as well in case they use it in the future
// may as well handle it in case they emit it in the future
.change_code_length_and_code_offset => |info| {
self.curr.code_length = info.length;
self.curr.code_offset += info.delta;
+2 -28
View File
@@ -30,19 +30,7 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
if (si.unwind_cache) |cache| gpa.free(cache);
}
pub const SymbolIterator = struct {
curr: ?Error!std.debug.Symbol,
pub fn deinit(self: *SymbolIterator, _: Io) void {
self.* = undefined;
}
pub fn next(self: *SymbolIterator) ?Error!std.debug.Symbol {
const result = self.curr;
self.curr = null;
return result;
}
};
pub const SymbolIterator = std.debug.Dwarf.SymbolIterator;
pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {
const gpa = std.debug.getDebugInfoAllocator();
@@ -67,21 +55,7 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {
};
loaded_elf.scanned_dwarf = true;
}
if (dwarf.getSymbol(gpa, native_endian, vaddr)) |sym| {
return .{ .curr = sym };
} else |err| switch (err) {
error.MissingDebugInfo => {},
error.InvalidDebugInfo,
error.OutOfMemory,
=> |e| return .{ .curr = e },
error.ReadFailed,
error.EndOfStream,
error.Overflow,
error.StreamTooLong,
=> return .{ .curr = error.InvalidDebugInfo },
}
return dwarf.getSymbols(gpa, native_endian, vaddr);
}
// When DWARF is unavailable, fall back to searching the symtab.
const symbol = loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {
+10 -35
View File
@@ -33,7 +33,7 @@ pub const SymbolIterator = struct {
pub fn deinit(self: *SymbolIterator, io: Io) void {
if (self.lock) |lock| lock.unlockShared(io);
self.symbols.deinit();
self.symbols.deinit(io);
self.* = undefined;
}
@@ -105,29 +105,7 @@ pub const SymbolIterator = struct {
.source_location = pdb.getLineNumberInfo(info.module, info.addr) catch null,
};
},
.dwarf => |info| {
// The failure cases are unreachable because we only set the dwarf field if these
// are set
const di = if (self.module.di.?) |*di| di else |_| unreachable;
const dwarf = if (di.dwarf) |*dwarf| dwarf else unreachable;
// Return the main symbol and then return the iterator
defer self.symbols = .none;
const gpa = std.debug.getDebugInfoAllocator();
return dwarf.getSymbol(gpa, native_endian, info.addr) catch |err| switch (err) {
error.MissingDebugInfo => return null,
error.InvalidDebugInfo,
error.OutOfMemory,
=> |e| return e,
error.ReadFailed,
error.EndOfStream,
error.Overflow,
error.StreamTooLong,
=> return error.InvalidDebugInfo,
};
},
.dwarf => |*info| return info.next(),
.none => return null,
}
}
@@ -368,7 +346,7 @@ const Module = struct {
/// iteration, e.g. because they only wanted the topmost call.
inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym),
},
dwarf: struct { addr: u64 },
dwarf: std.debug.Dwarf.SymbolIterator,
none: void,
fn init(di: *DebugInfo, vaddr: usize) Error!Symbols {
@@ -425,23 +403,20 @@ const Module = struct {
// Dwarf
dwarf: {
if (di.dwarf == null) break :dwarf;
const dwarf = &(di.dwarf orelse break :dwarf);
const addr = vaddr + di.coff_image_base;
return .{ .dwarf = .{
.addr = addr,
} };
return .{ .dwarf = dwarf.getSymbols(gpa, native_endian, addr) };
}
return error.MissingDebugInfo;
}
fn deinit(self: *Symbols) void {
fn deinit(self: *Symbols, io: Io) void {
const gpa = std.debug.getDebugInfoAllocator();
switch (self.*) {
.pdb => |*info| {
const gpa = std.debug.getDebugInfoAllocator();
info.inline_sites.deinit(gpa);
},
.dwarf, .none => {},
.pdb => |*info| info.inline_sites.deinit(gpa),
.dwarf => |*info| info.deinit(io),
.none => {},
}
}
};