Skip to content

Commit

Permalink
macho: encode FDE offsets and personalities
Browse files Browse the repository at this point in the history
  • Loading branch information
kubkon committed Dec 3, 2023
1 parent c11e97a commit 8050ca1
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 27 deletions.
8 changes: 3 additions & 5 deletions src/MachO/Object.zig
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,6 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {
gop.value_ptr[1] = @intCast(fde_index);
}

const cpu_arch = macho_file.options.cpu_arch.?;

for (superposition.values()) |meta| {
self.has_unwind = true;

Expand All @@ -603,7 +601,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void {

if (meta[0]) |rec_index| {
const rec = macho_file.getUnwindRecord(rec_index);
if (!rec.enc.isDwarf(cpu_arch)) {
if (!rec.enc.isDwarf(macho_file)) {
// Mark FDE dead
fde.alive = false;
} else {
Expand Down Expand Up @@ -768,10 +766,10 @@ pub fn scanRelocs(self: Object, macho_file: *MachO) !void {
const rec = macho_file.getUnwindRecord(rec_index);
if (!rec.alive) continue;
if (rec.getFde(macho_file)) |fde| {
if (fde.getCie(macho_file).getPersonalityTarget(macho_file)) |sym| {
if (fde.getCie(macho_file).getPersonality(macho_file)) |sym| {
sym.flags.got = true;
}
} else if (rec.getPersonalityTarget(macho_file)) |sym| {
} else if (rec.getPersonality(macho_file)) |sym| {
sym.flags.got = true;
}
}
Expand Down
53 changes: 32 additions & 21 deletions src/MachO/UnwindInfo.zig
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ fn canFold(macho_file: *MachO, lhs_index: Record.Index, rhs_index: Record.Index)

pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
const gpa = macho_file.base.allocator;
const cpu_arch = macho_file.options.cpu_arch.?;

// Collect all unwind records
for (macho_file.sections.items(.atoms)) |atoms| {
Expand All @@ -62,6 +61,17 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
}
}

// Encode records
for (info.records.items) |index| {
const rec = macho_file.getUnwindRecord(index);
if (rec.getFde(macho_file)) |fde| {
rec.enc.setDwarfSectionOffset(@intCast(fde.out_offset));
} else if (rec.getPersonality(macho_file)) |_| {
const personality_index = try info.getOrPutPersonalityFunction(rec.personality.?); // TODO handle error
rec.enc.setPersonalityIndex(personality_index + 1);
}
}

// Sort by assigned relative address within each output section
const sortFn = struct {
fn sortFn(ctx: *MachO, lhs_index: Record.Index, rhs_index: Record.Index) bool {
Expand Down Expand Up @@ -138,7 +148,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {

for (info.records.items) |rec_index| {
const rec = macho_file.getUnwindRecord(rec_index);
if (rec.enc.isDwarf(cpu_arch)) continue;
if (rec.enc.isDwarf(macho_file)) continue;
const gop = try common_encodings_counts.getOrPut(rec.enc);
if (!gop.found_existing) {
gop.value_ptr.* = .{
Expand Down Expand Up @@ -460,16 +470,19 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
// return null;
// }

// fn getPersonalityFunction(info: UnwindInfo, global_index: MachO.SymbolWithLoc) ?u2 {
// comptime var index: u2 = 0;
// inline while (index < max_personalities) : (index += 1) {
// if (index >= info.personalities_count) return null;
// if (info.personalities[index].eql(global_index)) {
// return index;
// }
// }
// return null;
// }
fn getOrPutPersonalityFunction(info: *UnwindInfo, sym_index: Symbol.Index) error{TooManyPersonalities}!u2 {
comptime var index: u2 = 0;
inline while (index < max_personalities) : (index += 1) {
if (info.personalities[index] == sym_index) {
return index;
} else if (index == info.personalities_count) {
info.personalities[index] = sym_index;
info.personalities_count += 1;
return index;
}
}
return error.TooManyPersonalities;
}

// fn isLsda(record_id: usize, rel: macho.relocation_info) bool {
// const base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry)));
Expand Down Expand Up @@ -510,9 +523,9 @@ pub const Encoding = extern struct {
return @as(u4, @truncate((enc.enc & macho.UNWIND_ARM64_MODE_MASK) >> 24));
}

pub fn isDwarf(enc: Encoding, cpu_arch: std.Target.Cpu.Arch) bool {
pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool {
const mode = enc.getMode();
return switch (cpu_arch) {
return switch (macho_file.options.cpu_arch.?) {
.aarch64 => @as(macho.UNWIND_ARM64_MODE, @enumFromInt(mode)) == .DWARF,
.x86_64 => @as(macho.UNWIND_X86_64_MODE, @enumFromInt(mode)) == .DWARF,
else => unreachable,
Expand Down Expand Up @@ -543,14 +556,12 @@ pub const Encoding = extern struct {
enc.enc |= mask;
}

pub fn getDwarfSectionOffset(enc: Encoding, cpu_arch: std.Target.Cpu.Arch) u24 {
assert(enc.isDwarf(cpu_arch));
pub fn getDwarfSectionOffset(enc: Encoding) u24 {
const offset = @as(u24, @truncate(enc.enc));
return offset;
}

pub fn setDwarfSectionOffset(enc: *Encoding, cpu_arch: std.Target.Cpu.Arch, offset: u24) void {
assert(enc.isDwarf(cpu_arch));
pub fn setDwarfSectionOffset(enc: *Encoding, offset: u24) void {
enc.enc |= offset;
}

Expand Down Expand Up @@ -594,13 +605,13 @@ pub const Record = struct {
return macho_file.getAtom(rec.lsda);
}

pub fn getPersonalityTarget(rec: Record, macho_file: *MachO) ?*Symbol {
pub fn getPersonality(rec: Record, macho_file: *MachO) ?*Symbol {
const personality = rec.personality orelse return null;
return macho_file.getSymbol(personality);
}

pub fn getFde(rec: Record, macho_file: *MachO) ?Fde {
if (!rec.enc.isDwarf(macho_file.options.cpu_arch.?)) return null;
if (!rec.enc.isDwarf(macho_file)) return null;
return rec.getObject(macho_file).fdes.items[rec.fde];
}

Expand Down Expand Up @@ -647,7 +658,7 @@ pub const Record = struct {
try writer.print("{x} : len({x})", .{
rec.enc.enc, rec.length,
});
if (rec.enc.isDwarf(macho_file.options.cpu_arch.?)) try writer.print(" : fde({d})", .{rec.fde});
if (rec.enc.isDwarf(macho_file)) try writer.print(" : fde({d})", .{rec.fde});
try writer.print(" : {s}", .{rec.getAtom(macho_file).getName(macho_file)});
if (!rec.alive) try writer.writeAll(" : [*]");
}
Expand Down
2 changes: 1 addition & 1 deletion src/MachO/eh_frame.zig
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub const Cie = struct {
return data[cie.offset..][0..cie.getSize()];
}

pub fn getPersonalityTarget(cie: Cie, macho_file: *MachO) ?*Symbol {
pub fn getPersonality(cie: Cie, macho_file: *MachO) ?*Symbol {
const personality = cie.personality orelse return null;
return macho_file.getSymbol(personality.index);
}
Expand Down

0 comments on commit 8050ca1

Please sign in to comment.