mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
Dwarf.Unwind: handle macOS deviation from standard
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.
This commit is contained in:
parent
156cd8f678
commit
8950831d3c
@ -475,10 +475,15 @@ pub fn prepare(
|
||||
addr_size_bytes: u8,
|
||||
endian: Endian,
|
||||
need_lookup: bool,
|
||||
/// The `__eh_frame` section in Mach-O binaries deviates from the standard `.eh_frame` section
|
||||
/// in one way which this function needs to be aware of.
|
||||
is_macho: bool,
|
||||
) !void {
|
||||
if (unwind.cie_list.len > 0 and (!need_lookup or unwind.lookup != null)) return;
|
||||
unwind.cie_list.clearRetainingCapacity();
|
||||
|
||||
if (is_macho) assert(unwind.lookup == null or unwind.lookup.? != .eh_frame_hdr);
|
||||
|
||||
const section = unwind.frame_section;
|
||||
|
||||
var r: Reader = .fixed(section.bytes);
|
||||
@ -519,10 +524,11 @@ pub fn prepare(
|
||||
.terminator => break true,
|
||||
}
|
||||
} else false;
|
||||
switch (section.id) {
|
||||
.eh_frame => if (!saw_terminator) return bad(), // `.eh_frame` indicates the end of the CIE/FDE list with a sentinel entry
|
||||
.debug_frame => if (saw_terminator) return bad(), // `.debug_frame` uses the section bounds and does not specify a sentinel entry
|
||||
}
|
||||
const expect_terminator = switch (section.id) {
|
||||
.eh_frame => !is_macho, // `.eh_frame` indicates the end of the CIE/FDE list with a sentinel entry, though macOS omits this
|
||||
.debug_frame => false, // `.debug_frame` uses the section bounds and does not specify a sentinel entry
|
||||
};
|
||||
if (saw_terminator != expect_terminator) return bad();
|
||||
|
||||
std.mem.sortUnstable(SortedFdeEntry, fde_list.items, {}, struct {
|
||||
fn lessThan(ctx: void, a: SortedFdeEntry, b: SortedFdeEntry) bool {
|
||||
|
||||
@ -59,7 +59,7 @@ fn loadUnwindInfo(module: *const DarwinModule, gpa: Allocator, out: *DebugInfo)
|
||||
var dwarf: Dwarf.Unwind = .initSection(.eh_frame, @intFromPtr(eh_frame.ptr) - vmaddr_slide, eh_frame);
|
||||
errdefer dwarf.deinit(gpa);
|
||||
// We don't need lookups, so this call is just for scanning CIEs.
|
||||
dwarf.prepare(gpa, @sizeOf(usize), native_endian, false) catch |err| switch (err) {
|
||||
dwarf.prepare(gpa, @sizeOf(usize), native_endian, false, true) catch |err| switch (err) {
|
||||
error.ReadFailed => unreachable, // it's all fixed buffers
|
||||
error.InvalidDebugInfo,
|
||||
error.MissingDebugInfo,
|
||||
|
||||
@ -228,7 +228,7 @@ pub fn getSymbolAtAddress(module: *const ElfModule, gpa: Allocator, di: *DebugIn
|
||||
};
|
||||
}
|
||||
fn prepareUnwindLookup(unwind: *Dwarf.Unwind, gpa: Allocator) Error!void {
|
||||
unwind.prepare(gpa, @sizeOf(usize), native_endian, true) catch |err| switch (err) {
|
||||
unwind.prepare(gpa, @sizeOf(usize), native_endian, true, false) catch |err| switch (err) {
|
||||
error.ReadFailed => unreachable, // it's all fixed buffers
|
||||
error.InvalidDebugInfo,
|
||||
error.MissingDebugInfo,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user