diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index f82b4829de..0cd2a608e9 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -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 diff --git a/lib/std/debug/Pdb.zig b/lib/std/debug/Pdb.zig index 198e815346..b76ed9e47c 100644 --- a/lib/std/debug/Pdb.zig +++ b/lib/std/debug/Pdb.zig @@ -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; diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 7955dd32c6..8a0535c487 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -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) { diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index 710b13c122..c3d72d4558 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -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 => {}, } } };