authorgravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-10 13:53:41-07:00
committergravatar for mason@gamesbymason.comMason Remaley <mason@gamesbymason.com> 2026-04-12 04:01:30-07:00
log5a4b5c8b94236429263ef25d9287b6c5cc829bde
tree52bc7eedf23bb607811581b04d1d5edfc3e27f66
parent825ba5a350cab21fff5531d645d18cd9d2facd8f

Uses dwarf iterator if dwarf symbols found for windows executable


4 files changed, 41 insertions(+), 71 deletions(-)

lib/std/debug/Dwarf.zig+28-7
...@@ -22,7 +22,9 @@ const cast = std.math.cast;...@@ -22,7 +22,9 @@ const cast = std.math.cast;
22const maxInt = std.math.maxInt;22const maxInt = std.math.maxInt;
23const ArrayList = std.ArrayList;23const ArrayList = std.ArrayList;
24const Endian = std.builtin.Endian;24const Endian = std.builtin.Endian;
25const Reader = std.Io.Reader;25const Io = std.Io;
26const Reader = Io.Reader;
27const Error = std.debug.SelfInfoError;
2628
27const Dwarf = @This();29const Dwarf = @This();
2830
...@@ -1543,21 +1545,40 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {...@@ -1543,21 +1545,40 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {
1543 return str[casted_offset..last :0];1545 return str[casted_offset..last :0];
1544}1546}
15451547
1546pub fn getSymbol(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64) !std.debug.Symbol {1548pub const SymbolIterator = struct {
1549 curr: ?std.debug.SelfInfoError!std.debug.Symbol,
1550
1551 pub fn deinit(self: *SymbolIterator, _: Io) void {
1552 self.* = undefined;
1553 }
1554
1555 pub fn next(self: *SymbolIterator) ?Error!std.debug.Symbol {
1556 const result = self.curr;
1557 self.curr = null;
1558 return result;
1559 }
1560};
1561
1562pub fn getSymbols(di: *Dwarf, gpa: Allocator, endian: Endian, address: u64) SymbolIterator {
1547 const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) {1563 const compile_unit = di.findCompileUnit(endian, address) catch |err| switch (err) {
1548 error.MissingDebugInfo, error.InvalidDebugInfo => return .unknown,1564 error.EndOfStream, error.Overflow => return .{ .curr = error.InvalidDebugInfo },
1549 else => return err,1565 else => |e| return .{ .curr = e },
1550 };1566 };
1551 return .{1567 return .{ .curr = .{
1552 .name = di.getSymbolName(address),1568 .name = di.getSymbolName(address),
1553 .compile_unit_name = compile_unit.die.getAttrString(di, endian, std.dwarf.AT.name, di.section(.debug_str), compile_unit) catch |err| switch (err) {1569 .compile_unit_name = compile_unit.die.getAttrString(di, endian, std.dwarf.AT.name, di.section(.debug_str), compile_unit) catch |err| switch (err) {
1554 error.MissingDebugInfo, error.InvalidDebugInfo => null,1570 error.MissingDebugInfo, error.InvalidDebugInfo => null,
1555 },1571 },
1556 .source_location = di.getLineNumberInfo(gpa, endian, compile_unit, address) catch |err| switch (err) {1572 .source_location = di.getLineNumberInfo(gpa, endian, compile_unit, address) catch |err| switch (err) {
1557 error.MissingDebugInfo, error.InvalidDebugInfo => null,1573 error.MissingDebugInfo, error.InvalidDebugInfo => null,
1558 else => return err,1574 error.ReadFailed,
1575 error.EndOfStream,
1576 error.Overflow,
1577 error.StreamTooLong,
1578 => return .{ .curr = error.InvalidDebugInfo },
1579 else => |e| return .{ .curr = e },
1559 },1580 },
1560 };1581 } };
1561}1582}
15621583
1563/// DWARF5 7.4: "In the 32-bit DWARF format, all values that represent lengths of DWARF sections and1584/// DWARF5 7.4: "In the 32-bit DWARF format, all values that represent lengths of DWARF sections and
lib/std/debug/Pdb.zig+1-1
...@@ -358,7 +358,7 @@ pub const BinaryAnnotation = union(enum) {...@@ -358,7 +358,7 @@ pub const BinaryAnnotation = union(enum) {
358 self.curr.file_id = file_id;358 self.curr.file_id = file_id;
359 },359 },
360 // LLVM never emits this opcode, but it's clear enough how to interpret it so we360 // LLVM never emits this opcode, but it's clear enough how to interpret it so we
361 // may as well in case they use it in the future361 // may as well handle it in case they emit it in the future
362 .change_code_length_and_code_offset => |info| {362 .change_code_length_and_code_offset => |info| {
363 self.curr.code_length = info.length;363 self.curr.code_length = info.length;
364 self.curr.code_offset += info.delta;364 self.curr.code_offset += info.delta;
lib/std/debug/SelfInfo/Elf.zig+2-28
...@@ -30,19 +30,7 @@ pub fn deinit(si: *SelfInfo, io: Io) void {...@@ -30,19 +30,7 @@ pub fn deinit(si: *SelfInfo, io: Io) void {
30 if (si.unwind_cache) |cache| gpa.free(cache);30 if (si.unwind_cache) |cache| gpa.free(cache);
31}31}
3232
33pub const SymbolIterator = struct {33pub const SymbolIterator = std.debug.Dwarf.SymbolIterator;
34 curr: ?Error!std.debug.Symbol,
35
36 pub fn deinit(self: *SymbolIterator, _: Io) void {
37 self.* = undefined;
38 }
39
40 pub fn next(self: *SymbolIterator) ?Error!std.debug.Symbol {
41 const result = self.curr;
42 self.curr = null;
43 return result;
44 }
45};
4634
47pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {35pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {
48 const gpa = std.debug.getDebugInfoAllocator();36 const gpa = std.debug.getDebugInfoAllocator();
...@@ -67,21 +55,7 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {...@@ -67,21 +55,7 @@ pub fn getSymbols(si: *SelfInfo, io: Io, address: usize) SymbolIterator {
67 };55 };
68 loaded_elf.scanned_dwarf = true;56 loaded_elf.scanned_dwarf = true;
69 }57 }
70 if (dwarf.getSymbol(gpa, native_endian, vaddr)) |sym| {58 return dwarf.getSymbols(gpa, native_endian, vaddr);
71 return .{ .curr = sym };
72 } else |err| switch (err) {
73 error.MissingDebugInfo => {},
74
75 error.InvalidDebugInfo,
76 error.OutOfMemory,
77 => |e| return .{ .curr = e },
78
79 error.ReadFailed,
80 error.EndOfStream,
81 error.Overflow,
82 error.StreamTooLong,
83 => return .{ .curr = error.InvalidDebugInfo },
84 }
85 }59 }
86 // When DWARF is unavailable, fall back to searching the symtab.60 // When DWARF is unavailable, fall back to searching the symtab.
87 const symbol = loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {61 const symbol = loaded_elf.file.searchSymtab(gpa, vaddr) catch |err| switch (err) {
lib/std/debug/SelfInfo/Windows.zig+10-35
...@@ -33,7 +33,7 @@ pub const SymbolIterator = struct {...@@ -33,7 +33,7 @@ pub const SymbolIterator = struct {
3333
34 pub fn deinit(self: *SymbolIterator, io: Io) void {34 pub fn deinit(self: *SymbolIterator, io: Io) void {
35 if (self.lock) |lock| lock.unlockShared(io);35 if (self.lock) |lock| lock.unlockShared(io);
36 self.symbols.deinit();36 self.symbols.deinit(io);
37 self.* = undefined;37 self.* = undefined;
38 }38 }
3939
...@@ -105,29 +105,7 @@ pub const SymbolIterator = struct {...@@ -105,29 +105,7 @@ pub const SymbolIterator = struct {
105 .source_location = pdb.getLineNumberInfo(info.module, info.addr) catch null,105 .source_location = pdb.getLineNumberInfo(info.module, info.addr) catch null,
106 };106 };
107 },107 },
108 .dwarf => |info| {108 .dwarf => |*info| return info.next(),
109 // The failure cases are unreachable because we only set the dwarf field if these
110 // are set
111 const di = if (self.module.di.?) |*di| di else |_| unreachable;
112 const dwarf = if (di.dwarf) |*dwarf| dwarf else unreachable;
113
114 // Return the main symbol and then return the iterator
115 defer self.symbols = .none;
116 const gpa = std.debug.getDebugInfoAllocator();
117 return dwarf.getSymbol(gpa, native_endian, info.addr) catch |err| switch (err) {
118 error.MissingDebugInfo => return null,
119
120 error.InvalidDebugInfo,
121 error.OutOfMemory,
122 => |e| return e,
123
124 error.ReadFailed,
125 error.EndOfStream,
126 error.Overflow,
127 error.StreamTooLong,
128 => return error.InvalidDebugInfo,
129 };
130 },
131 .none => return null,109 .none => return null,
132 }110 }
133 }111 }
...@@ -368,7 +346,7 @@ const Module = struct {...@@ -368,7 +346,7 @@ const Module = struct {
368 /// iteration, e.g. because they only wanted the topmost call.346 /// iteration, e.g. because they only wanted the topmost call.
369 inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym),347 inline_sites: std.ArrayList(*align(1) const std.pdb.InlineSiteSym),
370 },348 },
371 dwarf: struct { addr: u64 },349 dwarf: std.debug.Dwarf.SymbolIterator,
372 none: void,350 none: void,
373351
374 fn init(di: *DebugInfo, vaddr: usize) Error!Symbols {352 fn init(di: *DebugInfo, vaddr: usize) Error!Symbols {
...@@ -425,23 +403,20 @@ const Module = struct {...@@ -425,23 +403,20 @@ const Module = struct {
425403
426 // Dwarf404 // Dwarf
427 dwarf: {405 dwarf: {
428 if (di.dwarf == null) break :dwarf;406 const dwarf = &(di.dwarf orelse break :dwarf);
429 const addr = vaddr + di.coff_image_base;407 const addr = vaddr + di.coff_image_base;
430 return .{ .dwarf = .{408 return .{ .dwarf = dwarf.getSymbols(gpa, native_endian, addr) };
431 .addr = addr,
432 } };
433 }409 }
434410
435 return error.MissingDebugInfo;411 return error.MissingDebugInfo;
436 }412 }
437413
438 fn deinit(self: *Symbols) void {414 fn deinit(self: *Symbols, io: Io) void {
415 const gpa = std.debug.getDebugInfoAllocator();
439 switch (self.*) {416 switch (self.*) {
440 .pdb => |*info| {417 .pdb => |*info| info.inline_sites.deinit(gpa),
441 const gpa = std.debug.getDebugInfoAllocator();418 .dwarf => |*info| info.deinit(io),
442 info.inline_sites.deinit(gpa);419 .none => {},
443 },
444 .dwarf, .none => {},
445 }420 }
446 }421 }
447 };422 };