diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-22 13:29:53 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-24 12:34:42 +0100 |
| commit | 82628dd151c15241cffd17884ed5124808dc4ed2 (patch) | |
| tree | 75a7da2bdf55c2c0f0863cb1e61c54b5857c2e46 | |
| parent | fe19d1e09b283c8f09afa49abb0f3835fdc40aaa (diff) | |
| download | zig-82628dd151c15241cffd17884ed5124808dc4ed2.tar.gz zig-82628dd151c15241cffd17884ed5124808dc4ed2.zip | |
macho: synthesise unwind records from __eh_frame even if no __compact_unwind
| -rw-r--r-- | src/link/MachO.zig | 4 | ||||
| -rw-r--r-- | src/link/MachO/Object.zig | 70 | ||||
| -rw-r--r-- | src/link/MachO/relocatable.zig | 4 |
3 files changed, 43 insertions, 35 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 8c6f0f9d0e..3ffee5ad73 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1862,14 +1862,14 @@ fn initSyntheticSections(self: *MachO) !void { } const needs_unwind_info = for (self.objects.items) |index| { - if (self.getFile(index).?.object.compact_unwind_sect_index != null) break true; + if (self.getFile(index).?.object.hasUnwindRecords()) break true; } else false; if (needs_unwind_info) { self.unwind_info_sect_index = try self.addSection("__TEXT", "__unwind_info", .{}); } const needs_eh_frame = for (self.objects.items) |index| { - if (self.getFile(index).?.object.eh_frame_sect_index != null) break true; + if (self.getFile(index).?.object.hasEhFrameRecords()) break true; } else false; if (needs_eh_frame) { assert(needs_unwind_info); diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 3d1984e43f..850120b64b 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -164,6 +164,10 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { try self.initUnwindRecords(index, macho_file); } + if (self.hasUnwindRecords() or self.hasEhFrameRecords()) { + try self.parseUnwindRecords(macho_file); + } + self.initPlatform(); if (self.platform) |platform| { @@ -816,36 +820,9 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { } } } - - if (!macho_file.base.isObject()) try self.synthesiseNullUnwindRecords(macho_file); - - const sortFn = struct { - fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { - const lhs = ctx.getUnwindRecord(lhs_index); - const rhs = ctx.getUnwindRecord(rhs_index); - const lhsa = lhs.getAtom(ctx); - const rhsa = rhs.getAtom(ctx); - return lhsa.getInputAddress(ctx) + lhs.atom_offset < rhsa.getInputAddress(ctx) + rhs.atom_offset; - } - }.sortFn; - mem.sort(UnwindInfo.Record.Index, self.unwind_records.items, macho_file, sortFn); - - // Associate unwind records to atoms - var next_cu: u32 = 0; - while (next_cu < self.unwind_records.items.len) { - const start = next_cu; - const rec_index = self.unwind_records.items[start]; - const rec = macho_file.getUnwindRecord(rec_index); - while (next_cu < self.unwind_records.items.len and - macho_file.getUnwindRecord(self.unwind_records.items[next_cu]).atom == rec.atom) : (next_cu += 1) - {} - - const atom = rec.getAtom(macho_file); - atom.unwind_records = .{ .pos = start, .len = next_cu - start }; - } } -fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { +fn parseUnwindRecords(self: *Object, macho_file: *MachO) !void { // Synthesise missing unwind records. // The logic here is as follows: // 1. if an atom has unwind info record that is not DWARF, FDE is marked dead @@ -902,12 +879,10 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { } } else { // Synthesise new unwind info record - const fde_data = fde.getData(macho_file); - const atom_size = mem.readInt(u64, fde_data[16..][0..8], .little); const rec_index = try macho_file.addUnwindRecord(); const rec = macho_file.getUnwindRecord(rec_index); try self.unwind_records.append(gpa, rec_index); - rec.length = @intCast(atom_size); + rec.length = @intCast(meta.size); rec.atom = fde.atom; rec.atom_offset = fde.atom_offset; rec.fde = fde_index; @@ -930,6 +905,31 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { rec.file = self.index; } } + + const sortFn = struct { + fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { + const lhs = ctx.getUnwindRecord(lhs_index); + const rhs = ctx.getUnwindRecord(rhs_index); + const lhsa = lhs.getAtom(ctx); + const rhsa = rhs.getAtom(ctx); + return lhsa.getInputAddress(ctx) + lhs.atom_offset < rhsa.getInputAddress(ctx) + rhs.atom_offset; + } + }.sortFn; + mem.sort(UnwindInfo.Record.Index, self.unwind_records.items, macho_file, sortFn); + + // Associate unwind records to atoms + var next_cu: u32 = 0; + while (next_cu < self.unwind_records.items.len) { + const start = next_cu; + const rec_index = self.unwind_records.items[start]; + const rec = macho_file.getUnwindRecord(rec_index); + while (next_cu < self.unwind_records.items.len and + macho_file.getUnwindRecord(self.unwind_records.items[next_cu]).atom == rec.atom) : (next_cu += 1) + {} + + const atom = rec.getAtom(macho_file); + atom.unwind_records = .{ .pos = start, .len = next_cu - start }; + } } fn initPlatform(self: *Object) void { @@ -1566,6 +1566,14 @@ fn getString(self: Object, off: u32) [:0]const u8 { return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.ptr + off)), 0); } +pub fn hasUnwindRecords(self: Object) bool { + return self.unwind_records.items.len > 0; +} + +pub fn hasEhFrameRecords(self: Object) bool { + return self.cies.items.len > 0; +} + /// TODO handle multiple CUs pub fn hasDebugInfo(self: Object) bool { if (self.dwarf_info) |dw| { diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index ecd1d6220b..dcda59d607 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -143,7 +143,7 @@ fn initOutputSections(macho_file: *MachO) !void { } const needs_unwind_info = for (macho_file.objects.items) |index| { - if (macho_file.getFile(index).?.object.compact_unwind_sect_index != null) break true; + if (macho_file.getFile(index).?.object.hasUnwindRecords()) break true; } else false; if (needs_unwind_info) { macho_file.unwind_info_sect_index = try macho_file.addSection("__LD", "__compact_unwind", .{ @@ -152,7 +152,7 @@ fn initOutputSections(macho_file: *MachO) !void { } const needs_eh_frame = for (macho_file.objects.items) |index| { - if (macho_file.getFile(index).?.object.eh_frame_sect_index != null) break true; + if (macho_file.getFile(index).?.object.hasEhFrameRecords()) break true; } else false; if (needs_eh_frame) { assert(needs_unwind_info); |
