| author | |
| committer | |
| log | 8950831d3c4af4dd169e0a404e25e8aa9b045caa |
| tree | 50d8df70cffdd5d42b5bd73737356a44b1936501 |
| parent | 156cd8f678ebdcccc48382d093a3ef7e45c85a45 |
| signature |
Apparently the `__eh_frame` in Mach-O binaries doesn't include the
terminator entry, but in all other respects it acts like `.eh_frame`
rather than `.debug_frame`. I have no idea.3 files changed, 12 insertions(+), 6 deletions(-)
lib/std/debug/Dwarf/Unwind.zig+10-4| ... | ... | @@ -475,10 +475,15 @@ pub fn prepare( |
| 475 | 475 | addr_size_bytes: u8, |
| 476 | 476 | endian: Endian, |
| 477 | 477 | need_lookup: bool, |
| 478 | /// The `__eh_frame` section in Mach-O binaries deviates from the standard `.eh_frame` section | |
| 479 | /// in one way which this function needs to be aware of. | |
| 480 | is_macho: bool, | |
| 478 | 481 | ) !void { |
| 479 | 482 | if (unwind.cie_list.len > 0 and (!need_lookup or unwind.lookup != null)) return; |
| 480 | 483 | unwind.cie_list.clearRetainingCapacity(); |
| 481 | 484 | |
| 485 | if (is_macho) assert(unwind.lookup == null or unwind.lookup.? != .eh_frame_hdr); | |
| 486 | ||
| 482 | 487 | const section = unwind.frame_section; |
| 483 | 488 | |
| 484 | 489 | var r: Reader = .fixed(section.bytes); |
| ... | ... | @@ -519,10 +524,11 @@ pub fn prepare( |
| 519 | 524 | .terminator => break true, |
| 520 | 525 | } |
| 521 | 526 | } else false; |
| 522 | switch (section.id) { | |
| 523 | .eh_frame => if (!saw_terminator) return bad(), // `.eh_frame` indicates the end of the CIE/FDE list with a sentinel entry | |
| 524 | .debug_frame => if (saw_terminator) return bad(), // `.debug_frame` uses the section bounds and does not specify a sentinel entry | |
| 525 | } | |
| 527 | const expect_terminator = switch (section.id) { | |
| 528 | .eh_frame => !is_macho, // `.eh_frame` indicates the end of the CIE/FDE list with a sentinel entry, though macOS omits this | |
| 529 | .debug_frame => false, // `.debug_frame` uses the section bounds and does not specify a sentinel entry | |
| 530 | }; | |
| 531 | if (saw_terminator != expect_terminator) return bad(); | |
| 526 | 532 | |
| 527 | 533 | std.mem.sortUnstable(SortedFdeEntry, fde_list.items, {}, struct { |
| 528 | 534 | fn lessThan(ctx: void, a: SortedFdeEntry, b: SortedFdeEntry) bool { |
lib/std/debug/SelfInfo/DarwinModule.zig+1-1| ... | ... | @@ -59,7 +59,7 @@ fn loadUnwindInfo(module: *const DarwinModule, gpa: Allocator, out: *DebugInfo) |
| 59 | 59 | var dwarf: Dwarf.Unwind = .initSection(.eh_frame, @intFromPtr(eh_frame.ptr) - vmaddr_slide, eh_frame); |
| 60 | 60 | errdefer dwarf.deinit(gpa); |
| 61 | 61 | // We don't need lookups, so this call is just for scanning CIEs. |
| 62 | dwarf.prepare(gpa, @sizeOf(usize), native_endian, false) catch |err| switch (err) { | |
| 62 | dwarf.prepare(gpa, @sizeOf(usize), native_endian, false, true) catch |err| switch (err) { | |
| 63 | 63 | error.ReadFailed => unreachable, // it's all fixed buffers |
| 64 | 64 | error.InvalidDebugInfo, |
| 65 | 65 | error.MissingDebugInfo, |
lib/std/debug/SelfInfo/ElfModule.zig+1-1| ... | ... | @@ -228,7 +228,7 @@ pub fn getSymbolAtAddress(module: *const ElfModule, gpa: Allocator, di: *DebugIn |
| 228 | 228 | }; |
| 229 | 229 | } |
| 230 | 230 | fn prepareUnwindLookup(unwind: *Dwarf.Unwind, gpa: Allocator) Error!void { |
| 231 | unwind.prepare(gpa, @sizeOf(usize), native_endian, true) catch |err| switch (err) { | |
| 231 | unwind.prepare(gpa, @sizeOf(usize), native_endian, true, false) catch |err| switch (err) { | |
| 232 | 232 | error.ReadFailed => unreachable, // it's all fixed buffers |
| 233 | 233 | error.InvalidDebugInfo, |
| 234 | 234 | error.MissingDebugInfo, |