mirror of
https://github.com/ziglang/zig.git
synced 2026-01-13 19:05:12 +00:00
macho: synthesise unwind records from __eh_frame even if no __compact_unwind
This commit is contained in:
parent
fe19d1e09b
commit
82628dd151
@ -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);
|
||||
|
||||
@ -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| {
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user