| ... | ... | @@ -73,44 +73,26 @@ pub fn deinit(self: *SelfInfo) void { |
| 73 | 73 | |
| 74 | 74 | pub fn unwindFrame(self: *SelfInfo, gpa: Allocator, context: *UnwindContext) !usize { |
| 75 | 75 | comptime assert(target_supported); |
| 76 | | const module: Module = try .lookup(&self.lookup_cache, gpa, context.pc); // MLUGG TODO: don't take gpa |
| 76 | const module: Module = try .lookup(&self.lookup_cache, gpa, context.pc); |
| 77 | 77 | const gop = try self.modules.getOrPut(gpa, module.load_offset); |
| 78 | 78 | if (!gop.found_existing) gop.value_ptr.* = .init; |
| 79 | 79 | if (!gop.value_ptr.loaded_unwind) { |
| 80 | 80 | try module.loadUnwindInfo(gpa, &gop.value_ptr.di); |
| 81 | 81 | gop.value_ptr.loaded_unwind = true; |
| 82 | 82 | } |
| 83 | | // MLUGG TODO: the stuff below is impl! |
| 84 | | if (native_os.isDarwin()) { |
| 85 | | // __unwind_info is a requirement for unwinding on Darwin. It may fall back to DWARF, but unwinding |
| 86 | | // via DWARF before attempting to use the compact unwind info will produce incorrect results. |
| 87 | | if (gop.value_ptr.di.unwind_info) |unwind_info| { |
| 88 | | if (unwindFrameMachO( |
| 89 | | module.text_base, |
| 90 | | module.load_offset, |
| 91 | | context, |
| 92 | | unwind_info, |
| 93 | | gop.value_ptr.di.eh_frame, |
| 94 | | )) |return_address| { |
| 95 | | return return_address; |
| 96 | | } else |err| { |
| 97 | | if (err != error.RequiresDWARFUnwind) return err; |
| 98 | | } |
| 99 | | } |
| 100 | | return error.MissingUnwindInfo; |
| 101 | | } |
| 102 | | return unwindFrameDwarf(&gop.value_ptr.di.unwind, module.load_offset, context, null); |
| 83 | return module.unwindFrame(gpa, &gop.value_ptr.di, context); |
| 103 | 84 | } |
| 104 | 85 | |
| 105 | 86 | pub fn getSymbolAtAddress(self: *SelfInfo, gpa: Allocator, address: usize) !std.debug.Symbol { |
| 106 | 87 | comptime assert(target_supported); |
| 107 | | const module: Module = try .lookup(&self.lookup_cache, gpa, address); // MLUGG TODO: don't take gpa |
| 88 | const module: Module = try .lookup(&self.lookup_cache, gpa, address); |
| 108 | 89 | const gop = try self.modules.getOrPut(gpa, module.key()); |
| 109 | 90 | if (!gop.found_existing) gop.value_ptr.* = .init; |
| 110 | 91 | if (!gop.value_ptr.loaded_debug) { |
| 111 | 92 | // MLUGG TODO: this overloads the name 'debug info' with including vs excluding unwind info |
| 112 | 93 | // figure out a better name for one or the other (i think the inner one is maybe 'symbol info' or something idk) |
| 113 | 94 | try module.loadDebugInfo(gpa, &gop.value_ptr.di); |
| 95 | gop.value_ptr.loaded_debug = true; |
| 114 | 96 | } |
| 115 | 97 | return module.getSymbolAtAddress(gpa, &gop.value_ptr.di, address); |
| 116 | 98 | } |
| ... | ... | @@ -120,7 +102,7 @@ pub fn getSymbolAtAddress(self: *SelfInfo, gpa: Allocator, address: usize) !std. |
| 120 | 102 | /// a path that doesn't rely on any side-effects of a prior successful module lookup. |
| 121 | 103 | pub fn getModuleNameForAddress(self: *SelfInfo, gpa: Allocator, address: usize) error{ Unexpected, OutOfMemory, MissingDebugInfo }![]const u8 { |
| 122 | 104 | comptime assert(target_supported); |
| 123 | | const module: Module = try .lookup(&self.lookup_cache, gpa, address); // MLUGG TODO: don't take gpa |
| 105 | const module: Module = try .lookup(&self.lookup_cache, gpa, address); |
| 124 | 106 | return module.name; |
| 125 | 107 | } |
| 126 | 108 | |
| ... | ... | @@ -251,6 +233,18 @@ const Module = switch (native_os) { |
| 251 | 233 | }, |
| 252 | 234 | }; |
| 253 | 235 | } |
| 236 | fn unwindFrame(module: *const Module, gpa: Allocator, di: *DebugInfo, context: *UnwindContext) !usize { |
| 237 | _ = gpa; |
| 238 | const unwind_info = di.unwind_info orelse return error.MissingUnwindInfo; |
| 239 | // MLUGG TODO: inline |
| 240 | return unwindFrameMachO( |
| 241 | module.text_base, |
| 242 | module.load_offset, |
| 243 | context, |
| 244 | unwind_info, |
| 245 | di.eh_frame, |
| 246 | ); |
| 247 | } |
| 254 | 248 | const LookupCache = void; |
| 255 | 249 | const DebugInfo = struct { |
| 256 | 250 | mapped_memory: []align(std.heap.page_size_min) const u8, |
| ... | ... | @@ -499,12 +493,16 @@ const Module = switch (native_os) { |
| 499 | 493 | const section_bytes = module.gnu_eh_frame orelse return error.MissingUnwindInfo; // MLUGG TODO: load from file |
| 500 | 494 | const section_vaddr: u64 = @intFromPtr(section_bytes.ptr) - module.load_offset; |
| 501 | 495 | const header: Dwarf.Unwind.EhFrameHeader = try .parse(section_vaddr, section_bytes, @sizeOf(usize), native_endian); |
| 502 | | try di.unwind.loadFromEhFrameHdr(header, section_vaddr, @ptrFromInt(module.load_offset + header.eh_frame_vaddr)); |
| 496 | di.unwind = .initEhFrameHdr(header, section_vaddr, @ptrFromInt(module.load_offset + header.eh_frame_vaddr)); |
| 503 | 497 | try di.unwind.prepareLookup(gpa, @sizeOf(usize), native_endian); |
| 504 | 498 | } |
| 505 | 499 | fn getSymbolAtAddress(module: *const Module, gpa: Allocator, di: *DebugInfo, address: usize) !std.debug.Symbol { |
| 506 | 500 | return di.em.getSymbolAtAddress(gpa, native_endian, module.load_offset, address); |
| 507 | 501 | } |
| 502 | fn unwindFrame(module: *const Module, gpa: Allocator, di: *DebugInfo, context: *UnwindContext) !usize { |
| 503 | _ = gpa; |
| 504 | return unwindFrameDwarf(&di.unwind, module.load_offset, context, null); |
| 505 | } |
| 508 | 506 | }, |
| 509 | 507 | .uefi, .windows => struct { |
| 510 | 508 | base_address: usize, |
| ... | ... | @@ -1507,9 +1505,12 @@ fn unwindFrameMachO( |
| 1507 | 1505 | .DWARF => { |
| 1508 | 1506 | const eh_frame = opt_eh_frame orelse return error.MissingEhFrame; |
| 1509 | 1507 | const eh_frame_vaddr = @intFromPtr(eh_frame.ptr) - load_offset; |
| 1510 | | var dwarf_unwind: Dwarf.Unwind = .init; |
| 1511 | | dwarf_unwind.loadFromSection(.eh_frame, eh_frame_vaddr, eh_frame); |
| 1512 | | return unwindFrameDwarf(&dwarf_unwind, load_offset, context, @intCast(encoding.value.x86_64.dwarf)); |
| 1508 | return unwindFrameDwarf( |
| 1509 | &.initSection(.eh_frame, eh_frame_vaddr, eh_frame), |
| 1510 | load_offset, |
| 1511 | context, |
| 1512 | @intCast(encoding.value.x86_64.dwarf), |
| 1513 | ); |
| 1513 | 1514 | }, |
| 1514 | 1515 | }, |
| 1515 | 1516 | .aarch64, .aarch64_be => switch (encoding.mode.arm64) { |
| ... | ... | @@ -1524,9 +1525,12 @@ fn unwindFrameMachO( |
| 1524 | 1525 | .DWARF => { |
| 1525 | 1526 | const eh_frame = opt_eh_frame orelse return error.MissingEhFrame; |
| 1526 | 1527 | const eh_frame_vaddr = @intFromPtr(eh_frame.ptr) - load_offset; |
| 1527 | | var dwarf_unwind: Dwarf.Unwind = .init; |
| 1528 | | dwarf_unwind.loadFromSection(.eh_frame, eh_frame_vaddr, eh_frame); |
| 1529 | | return unwindFrameDwarf(dwarf_unwind, load_offset, context, @intCast(encoding.value.arm64.dwarf)); |
| 1528 | return unwindFrameDwarf( |
| 1529 | &.initSection(.eh_frame, eh_frame_vaddr, eh_frame), |
| 1530 | load_offset, |
| 1531 | context, |
| 1532 | @intCast(encoding.value.x86_64.dwarf), |
| 1533 | ); |
| 1530 | 1534 | }, |
| 1531 | 1535 | .FRAME => ip: { |
| 1532 | 1536 | const frame = encoding.value.arm64.frame; |