authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-02 12:22:59+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-30 13:44:49+01:00
logfb88dab4c9c7d89ec7b5842dafdefe93ed939b3c
tree7cb044b7a85e9c8f2931ee31cfff220f78596e46
parented6ed62c42dfad18facde164785a62faa305cb6c
signaturelock-open Commit is signed but in an unrecognized format.

more still


2 files changed, 30 insertions(+), 44 deletions(-)

lib/std/debug/Dwarf.zig+22-36
...@@ -1451,18 +1451,10 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {...@@ -1451,18 +1451,10 @@ fn getStringGeneric(opt_str: ?[]const u8, offset: u64) ![:0]const u8 {
14511451
1452// MLUGG TODO: i am dubious of this whole thing being here atp. look closely and see if it depends on being the self process1452// MLUGG TODO: i am dubious of this whole thing being here atp. look closely and see if it depends on being the self process
1453pub const ElfModule = struct {1453pub const ElfModule = struct {
1454 unwind: Dwarf.Unwind,
1455 dwarf: Dwarf,1454 dwarf: Dwarf,
1456 mapped_memory: ?[]align(std.heap.page_size_min) const u8,1455 mapped_memory: []align(std.heap.page_size_min) const u8,
1457 external_mapped_memory: ?[]align(std.heap.page_size_min) const u8,1456 external_mapped_memory: ?[]align(std.heap.page_size_min) const u8,
14581457
1459 pub const init: ElfModule = .{
1460 .unwind = .init,
1461 .dwarf = .{},
1462 .mapped_memory = null,
1463 .external_mapped_memory = null,
1464 };
1465
1466 pub fn deinit(self: *@This(), allocator: Allocator) void {1458 pub fn deinit(self: *@This(), allocator: Allocator) void {
1467 self.dwarf.deinit(allocator);1459 self.dwarf.deinit(allocator);
1468 std.posix.munmap(self.mapped_memory);1460 std.posix.munmap(self.mapped_memory);
...@@ -1476,12 +1468,6 @@ pub const ElfModule = struct {...@@ -1476,12 +1468,6 @@ pub const ElfModule = struct {
1476 return self.dwarf.getSymbol(allocator, endian, vaddr);1468 return self.dwarf.getSymbol(allocator, endian, vaddr);
1477 }1469 }
14781470
1479 pub fn getDwarfUnwindForAddress(self: *@This(), allocator: Allocator, address: usize) !?*Dwarf.Unwind {
1480 _ = allocator;
1481 _ = address;
1482 return &self.unwind;
1483 }
1484
1485 pub const LoadError = error{1471 pub const LoadError = error{
1486 InvalidDebugInfo,1472 InvalidDebugInfo,
1487 MissingDebugInfo,1473 MissingDebugInfo,
...@@ -1506,10 +1492,7 @@ pub const ElfModule = struct {...@@ -1506,10 +1492,7 @@ pub const ElfModule = struct {
1506 /// If the required sections aren't present but a reference to external debug1492 /// If the required sections aren't present but a reference to external debug
1507 /// info is, then this this function will recurse to attempt to load the debug1493 /// info is, then this this function will recurse to attempt to load the debug
1508 /// sections from an external file.1494 /// sections from an external file.
1509 ///
1510 /// MLUGG TODO: this should *return* a thing
1511 pub fn load(1495 pub fn load(
1512 em: *ElfModule,
1513 gpa: Allocator,1496 gpa: Allocator,
1514 mapped_mem: []align(std.heap.page_size_min) const u8,1497 mapped_mem: []align(std.heap.page_size_min) const u8,
1515 build_id: ?[]const u8,1498 build_id: ?[]const u8,
...@@ -1517,9 +1500,7 @@ pub const ElfModule = struct {...@@ -1517,9 +1500,7 @@ pub const ElfModule = struct {
1517 parent_sections: ?*Dwarf.SectionArray,1500 parent_sections: ?*Dwarf.SectionArray,
1518 parent_mapped_mem: ?[]align(std.heap.page_size_min) const u8,1501 parent_mapped_mem: ?[]align(std.heap.page_size_min) const u8,
1519 elf_filename: ?[]const u8,1502 elf_filename: ?[]const u8,
1520 ) LoadError!void {1503 ) LoadError!ElfModule {
1521 assert(em.mapped_memory == null);
1522
1523 if (expected_crc) |crc| if (crc != std.hash.crc.Crc32.hash(mapped_mem)) return error.InvalidDebugInfo;1504 if (expected_crc) |crc| if (crc != std.hash.crc.Crc32.hash(mapped_mem)) return error.InvalidDebugInfo;
15241505
1525 const hdr: *const elf.Ehdr = @ptrCast(&mapped_mem[0]);1506 const hdr: *const elf.Ehdr = @ptrCast(&mapped_mem[0]);
...@@ -1657,7 +1638,7 @@ pub const ElfModule = struct {...@@ -1657,7 +1638,7 @@ pub const ElfModule = struct {
1657 .sub_path = filename,1638 .sub_path = filename,
1658 };1639 };
16591640
1660 return em.loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem) catch break :blk;1641 return loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem) catch break :blk;
1661 }1642 }
16621643
1663 const global_debug_directories = [_][]const u8{1644 const global_debug_directories = [_][]const u8{
...@@ -1685,7 +1666,7 @@ pub const ElfModule = struct {...@@ -1685,7 +1666,7 @@ pub const ElfModule = struct {
1685 };1666 };
1686 defer gpa.free(path.sub_path);1667 defer gpa.free(path.sub_path);
16871668
1688 return em.loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem) catch continue;1669 return loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem) catch continue;
1689 }1670 }
1690 }1671 }
16911672
...@@ -1701,7 +1682,7 @@ pub const ElfModule = struct {...@@ -1701,7 +1682,7 @@ pub const ElfModule = struct {
1701 defer exe_dir.close();1682 defer exe_dir.close();
17021683
1703 // <exe_dir>/<gnu_debuglink>1684 // <exe_dir>/<gnu_debuglink>
1704 if (em.loadPath(1685 if (loadPath(
1705 gpa,1686 gpa,
1706 .{1687 .{
1707 .root_dir = .{ .path = null, .handle = exe_dir },1688 .root_dir = .{ .path = null, .handle = exe_dir },
...@@ -1711,9 +1692,8 @@ pub const ElfModule = struct {...@@ -1711,9 +1692,8 @@ pub const ElfModule = struct {
1711 separate_debug_crc,1692 separate_debug_crc,
1712 &sections,1693 &sections,
1713 mapped_mem,1694 mapped_mem,
1714 )) |v| {1695 )) |em| {
1715 v;1696 return em;
1716 return;
1717 } else |_| {}1697 } else |_| {}
17181698
1719 // <exe_dir>/.debug/<gnu_debuglink>1699 // <exe_dir>/.debug/<gnu_debuglink>
...@@ -1723,7 +1703,9 @@ pub const ElfModule = struct {...@@ -1723,7 +1703,9 @@ pub const ElfModule = struct {
1723 };1703 };
1724 defer gpa.free(path.sub_path);1704 defer gpa.free(path.sub_path);
17251705
1726 if (em.loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem)) |debug_info| return debug_info else |_| {}1706 if (loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem)) |em| {
1707 return em;
1708 } else |_| {}
1727 }1709 }
17281710
1729 var cwd_buf: [std.fs.max_path_bytes]u8 = undefined;1711 var cwd_buf: [std.fs.max_path_bytes]u8 = undefined;
...@@ -1736,28 +1718,32 @@ pub const ElfModule = struct {...@@ -1736,28 +1718,32 @@ pub const ElfModule = struct {
1736 .sub_path = try std.fs.path.join(gpa, &.{ global_directory, cwd_path, separate_filename }),1718 .sub_path = try std.fs.path.join(gpa, &.{ global_directory, cwd_path, separate_filename }),
1737 };1719 };
1738 defer gpa.free(path.sub_path);1720 defer gpa.free(path.sub_path);
1739 if (em.loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem)) |debug_info| return debug_info else |_| {}1721 if (loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem)) |em| {
1722 return em;
1723 } else |_| {}
1740 }1724 }
1741 }1725 }
17421726
1743 return error.MissingDebugInfo;1727 return error.MissingDebugInfo;
1744 }1728 }
17451729
1746 em.mapped_memory = parent_mapped_mem orelse mapped_mem;1730 var dwarf: Dwarf = .{ .sections = sections };
1747 em.external_mapped_memory = if (parent_mapped_mem != null) mapped_mem else null;1731 try dwarf.open(gpa, endian);
1748 em.dwarf.sections = sections;1732 return .{
1749 try em.dwarf.open(gpa, endian);1733 .mapped_memory = parent_mapped_mem orelse mapped_mem,
1734 .external_mapped_memory = if (parent_mapped_mem != null) mapped_mem else null,
1735 .dwarf = dwarf,
1736 };
1750 }1737 }
17511738
1752 pub fn loadPath(1739 pub fn loadPath(
1753 em: *ElfModule,
1754 gpa: Allocator,1740 gpa: Allocator,
1755 elf_file_path: Path,1741 elf_file_path: Path,
1756 build_id: ?[]const u8,1742 build_id: ?[]const u8,
1757 expected_crc: ?u32,1743 expected_crc: ?u32,
1758 parent_sections: *Dwarf.SectionArray,1744 parent_sections: *Dwarf.SectionArray,
1759 parent_mapped_mem: ?[]align(std.heap.page_size_min) const u8,1745 parent_mapped_mem: ?[]align(std.heap.page_size_min) const u8,
1760 ) LoadError!void {1746 ) LoadError!ElfModule {
1761 const elf_file = elf_file_path.root_dir.handle.openFile(elf_file_path.sub_path, .{}) catch |err| switch (err) {1747 const elf_file = elf_file_path.root_dir.handle.openFile(elf_file_path.sub_path, .{}) catch |err| switch (err) {
1762 error.FileNotFound => return missing(),1748 error.FileNotFound => return missing(),
1763 else => return err,1749 else => return err,
...@@ -1780,7 +1766,7 @@ pub const ElfModule = struct {...@@ -1780,7 +1766,7 @@ pub const ElfModule = struct {
1780 };1766 };
1781 errdefer std.posix.munmap(mapped_mem);1767 errdefer std.posix.munmap(mapped_mem);
17821768
1783 return em.load(1769 return load(
1784 gpa,1770 gpa,
1785 mapped_mem,1771 mapped_mem,
1786 build_id,1772 build_id,
lib/std/debug/SelfInfo.zig+8-8
...@@ -99,10 +99,7 @@ pub fn unwindFrame(self: *SelfInfo, gpa: Allocator, context: *UnwindContext) !us...@@ -99,10 +99,7 @@ pub fn unwindFrame(self: *SelfInfo, gpa: Allocator, context: *UnwindContext) !us
99 }99 }
100 return error.MissingUnwindInfo;100 return error.MissingUnwindInfo;
101 }101 }
102 if (try gop.value_ptr.di.getDwarfUnwindForAddress(gpa, context.pc)) |unwind| {102 return unwindFrameDwarf(&gop.value_ptr.di.unwind, module.load_offset, context, null);
103 return unwindFrameDwarf(unwind, module.load_offset, context, null);
104 }
105 return error.MissingDebugInfo;
106}103}
107104
108pub fn getSymbolAtAddress(self: *SelfInfo, gpa: Allocator, address: usize) !std.debug.Symbol {105pub fn getSymbolAtAddress(self: *SelfInfo, gpa: Allocator, address: usize) !std.debug.Symbol {
...@@ -409,7 +406,11 @@ const Module = switch (native_os) {...@@ -409,7 +406,11 @@ const Module = switch (native_os) {
409 build_id: ?[]const u8,406 build_id: ?[]const u8,
410 gnu_eh_frame: ?[]const u8,407 gnu_eh_frame: ?[]const u8,
411 const LookupCache = void;408 const LookupCache = void;
412 const DebugInfo = Dwarf.ElfModule;409 const DebugInfo = struct {
410 const init: DebugInfo = undefined; // MLUGG TODO: this makes me sad
411 em: Dwarf.ElfModule, // MLUGG TODO: bad field name (and, frankly, type)
412 unwind: Dwarf.Unwind,
413 };
413 fn key(m: Module) usize {414 fn key(m: Module) usize {
414 return m.load_offset; // MLUGG TODO: is this technically valid? idk415 return m.load_offset; // MLUGG TODO: is this technically valid? idk
415 }416 }
...@@ -492,8 +493,7 @@ const Module = switch (native_os) {...@@ -492,8 +493,7 @@ const Module = switch (native_os) {
492 else => |e| return e,493 else => |e| return e,
493 };494 };
494 errdefer posix.munmap(mapped_mem);495 errdefer posix.munmap(mapped_mem);
495 try di.load(gpa, mapped_mem, module.build_id, null, null, null, filename);496 di.em = try .load(gpa, mapped_mem, module.build_id, null, null, null, filename);
496 assert(di.mapped_memory != null);
497 }497 }
498 fn loadUnwindInfo(module: *const Module, gpa: Allocator, di: *Module.DebugInfo) !void {498 fn loadUnwindInfo(module: *const Module, gpa: Allocator, di: *Module.DebugInfo) !void {
499 const section_bytes = module.gnu_eh_frame orelse return error.MissingUnwindInfo; // MLUGG TODO: load from file499 const section_bytes = module.gnu_eh_frame orelse return error.MissingUnwindInfo; // MLUGG TODO: load from file
...@@ -503,7 +503,7 @@ const Module = switch (native_os) {...@@ -503,7 +503,7 @@ const Module = switch (native_os) {
503 try di.unwind.prepareLookup(gpa, @sizeOf(usize), native_endian);503 try di.unwind.prepareLookup(gpa, @sizeOf(usize), native_endian);
504 }504 }
505 fn getSymbolAtAddress(module: *const Module, gpa: Allocator, di: *DebugInfo, address: usize) !std.debug.Symbol {505 fn getSymbolAtAddress(module: *const Module, gpa: Allocator, di: *DebugInfo, address: usize) !std.debug.Symbol {
506 return di.getSymbolAtAddress(gpa, native_endian, module.load_offset, address);506 return di.em.getSymbolAtAddress(gpa, native_endian, module.load_offset, address);
507 }507 }
508 },508 },
509 .uefi, .windows => struct {509 .uefi, .windows => struct {