aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/UnwindInfo.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-08-27 09:55:24 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-08-29 11:40:18 +0200
commit2c68fb3d7ce077fba711747ee7b05b2fa0df6bcc (patch)
tree291b3aec840358c08a36c78c468c54fdc34727f0 /src/link/MachO/UnwindInfo.zig
parent42e0850d78e63fcc602dd0e167ac90dfb3cfec02 (diff)
downloadzig-2c68fb3d7ce077fba711747ee7b05b2fa0df6bcc.tar.gz
zig-2c68fb3d7ce077fba711747ee7b05b2fa0df6bcc.zip
macho: merge Zld state with MachO state
Diffstat (limited to 'src/link/MachO/UnwindInfo.zig')
-rw-r--r--src/link/MachO/UnwindInfo.zig140
1 files changed, 69 insertions, 71 deletions
diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig
index 3cd72fd64e..e3612c6948 100644
--- a/src/link/MachO/UnwindInfo.zig
+++ b/src/link/MachO/UnwindInfo.zig
@@ -1,25 +1,3 @@
-const UnwindInfo = @This();
-
-const std = @import("std");
-const assert = std.debug.assert;
-const eh_frame = @import("eh_frame.zig");
-const fs = std.fs;
-const leb = std.leb;
-const log = std.log.scoped(.unwind_info);
-const macho = std.macho;
-const math = std.math;
-const mem = std.mem;
-const trace = @import("../../tracy.zig").trace;
-
-const Allocator = mem.Allocator;
-const Atom = @import("Atom.zig");
-const AtomIndex = @import("zld.zig").AtomIndex;
-const EhFrameRecord = eh_frame.EhFrameRecord;
-const MachO = @import("../MachO.zig");
-const Object = @import("Object.zig");
-const SymbolWithLoc = MachO.SymbolWithLoc;
-const Zld = @import("zld.zig").Zld;
-
gpa: Allocator,
/// List of all unwind records gathered from all objects and sorted
@@ -203,28 +181,28 @@ pub fn deinit(info: *UnwindInfo) void {
info.lsdas_lookup.deinit(info.gpa);
}
-pub fn scanRelocs(zld: *Zld) !void {
- if (zld.unwind_info_section_index == null) return;
+pub fn scanRelocs(macho_file: *MachO) !void {
+ if (macho_file.unwind_info_section_index == null) return;
- const cpu_arch = zld.options.target.cpu.arch;
- for (zld.objects.items, 0..) |*object, object_id| {
+ const cpu_arch = macho_file.base.options.target.cpu.arch;
+ for (macho_file.objects.items, 0..) |*object, object_id| {
const unwind_records = object.getUnwindRecords();
for (object.exec_atoms.items) |atom_index| {
- var inner_syms_it = Atom.getInnerSymbolsIterator(zld, atom_index);
+ var inner_syms_it = Atom.getInnerSymbolsIterator(macho_file, atom_index);
while (inner_syms_it.next()) |sym| {
const record_id = object.unwind_records_lookup.get(sym) orelse continue;
if (object.unwind_relocs_lookup[record_id].dead) continue;
const record = unwind_records[record_id];
if (!UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) {
- if (getPersonalityFunctionReloc(zld, @as(u32, @intCast(object_id)), record_id)) |rel| {
+ if (getPersonalityFunctionReloc(macho_file, @as(u32, @intCast(object_id)), record_id)) |rel| {
// Personality function; add GOT pointer.
- const target = Atom.parseRelocTarget(zld, .{
+ const target = Atom.parseRelocTarget(macho_file, .{
.object_id = @as(u32, @intCast(object_id)),
.rel = rel,
.code = mem.asBytes(&record),
.base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))),
});
- try zld.addGotEntry(target);
+ try macho_file.addGotEntry(target);
}
}
}
@@ -232,10 +210,10 @@ pub fn scanRelocs(zld: *Zld) !void {
}
}
-pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
- if (zld.unwind_info_section_index == null) return;
+pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void {
+ if (macho_file.unwind_info_section_index == null) return;
- const cpu_arch = zld.options.target.cpu.arch;
+ const cpu_arch = macho_file.base.options.target.cpu.arch;
var records = std.ArrayList(macho.compact_unwind_entry).init(info.gpa);
defer records.deinit();
@@ -244,7 +222,7 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
defer sym_indexes.deinit();
// TODO handle dead stripping
- for (zld.objects.items, 0..) |*object, object_id| {
+ for (macho_file.objects.items, 0..) |*object, object_id| {
log.debug("collecting unwind records in {s} ({d})", .{ object.name, object_id });
const unwind_records = object.getUnwindRecords();
@@ -254,7 +232,7 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
try sym_indexes.ensureUnusedCapacity(object.exec_atoms.items.len);
for (object.exec_atoms.items) |atom_index| {
- var inner_syms_it = Atom.getInnerSymbolsIterator(zld, atom_index);
+ var inner_syms_it = Atom.getInnerSymbolsIterator(macho_file, atom_index);
var prev_symbol: ?SymbolWithLoc = null;
while (inner_syms_it.next()) |symbol| {
var record = if (object.unwind_records_lookup.get(symbol)) |record_id| blk: {
@@ -262,14 +240,14 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
var record = unwind_records[record_id];
if (UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) {
- try info.collectPersonalityFromDwarf(zld, @as(u32, @intCast(object_id)), symbol, &record);
+ try info.collectPersonalityFromDwarf(macho_file, @as(u32, @intCast(object_id)), symbol, &record);
} else {
if (getPersonalityFunctionReloc(
- zld,
+ macho_file,
@as(u32, @intCast(object_id)),
record_id,
)) |rel| {
- const target = Atom.parseRelocTarget(zld, .{
+ const target = Atom.parseRelocTarget(macho_file, .{
.object_id = @as(u32, @intCast(object_id)),
.rel = rel,
.code = mem.asBytes(&record),
@@ -286,8 +264,8 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
UnwindEncoding.setPersonalityIndex(&record.compactUnwindEncoding, personality_index + 1);
}
- if (getLsdaReloc(zld, @as(u32, @intCast(object_id)), record_id)) |rel| {
- const target = Atom.parseRelocTarget(zld, .{
+ if (getLsdaReloc(macho_file, @as(u32, @intCast(object_id)), record_id)) |rel| {
+ const target = Atom.parseRelocTarget(macho_file, .{
.object_id = @as(u32, @intCast(object_id)),
.rel = rel,
.code = mem.asBytes(&record),
@@ -298,7 +276,7 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
}
break :blk record;
} else blk: {
- const sym = zld.getSymbol(symbol);
+ const sym = macho_file.getSymbol(symbol);
if (sym.n_desc == MachO.N_DEAD) continue;
if (prev_symbol) |prev_sym| {
const prev_addr = object.getSourceSymbol(prev_sym.sym_index).?.n_value;
@@ -310,7 +288,7 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
if (object.eh_frame_records_lookup.get(symbol)) |fde_offset| {
if (object.eh_frame_relocs_lookup.get(fde_offset).?.dead) continue;
var record = nullRecord();
- try info.collectPersonalityFromDwarf(zld, @as(u32, @intCast(object_id)), symbol, &record);
+ try info.collectPersonalityFromDwarf(macho_file, @as(u32, @intCast(object_id)), symbol, &record);
switch (cpu_arch) {
.aarch64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_ARM64_MODE.DWARF),
.x86_64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_X86_64_MODE.DWARF),
@@ -323,8 +301,8 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
break :blk nullRecord();
};
- const atom = zld.getAtom(atom_index);
- const sym = zld.getSymbol(symbol);
+ const atom = macho_file.getAtom(atom_index);
+ const sym = macho_file.getSymbol(symbol);
assert(sym.n_desc != MachO.N_DEAD);
const size = if (inner_syms_it.next()) |next_sym| blk: {
// All this trouble to account for symbol aliases.
@@ -336,8 +314,8 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
const curr_addr = object.getSourceSymbol(symbol.sym_index).?.n_value;
const next_addr = object.getSourceSymbol(next_sym.sym_index).?.n_value;
if (next_addr > curr_addr) break :blk next_addr - curr_addr;
- break :blk zld.getSymbol(atom.getSymbolWithLoc()).n_value + atom.size - sym.n_value;
- } else zld.getSymbol(atom.getSymbolWithLoc()).n_value + atom.size - sym.n_value;
+ break :blk macho_file.getSymbol(atom.getSymbolWithLoc()).n_value + atom.size - sym.n_value;
+ } else macho_file.getSymbol(atom.getSymbolWithLoc()).n_value + atom.size - sym.n_value;
record.rangeStart = sym.n_value;
record.rangeLength = @as(u32, @intCast(size));
@@ -518,23 +496,23 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
fn collectPersonalityFromDwarf(
info: *UnwindInfo,
- zld: *Zld,
+ macho_file: *MachO,
object_id: u32,
sym_loc: SymbolWithLoc,
record: *macho.compact_unwind_entry,
) !void {
- const object = &zld.objects.items[object_id];
+ const object = &macho_file.objects.items[object_id];
var it = object.getEhFrameRecordsIterator();
const fde_offset = object.eh_frame_records_lookup.get(sym_loc).?;
it.seekTo(fde_offset);
const fde = (try it.next()).?;
- const cie_ptr = fde.getCiePointerSource(object_id, zld, fde_offset);
+ const cie_ptr = fde.getCiePointerSource(object_id, macho_file, fde_offset);
const cie_offset = fde_offset + 4 - cie_ptr;
it.seekTo(cie_offset);
const cie = (try it.next()).?;
if (cie.getPersonalityPointerReloc(
- zld,
+ macho_file,
@as(u32, @intCast(object_id)),
cie_offset,
)) |target| {
@@ -550,9 +528,9 @@ fn collectPersonalityFromDwarf(
}
}
-pub fn calcSectionSize(info: UnwindInfo, zld: *Zld) !void {
- const sect_id = zld.unwind_info_section_index orelse return;
- const sect = &zld.sections.items(.header)[sect_id];
+pub fn calcSectionSize(info: UnwindInfo, macho_file: *MachO) !void {
+ const sect_id = macho_file.unwind_info_section_index orelse return;
+ const sect = &macho_file.sections.items(.header)[sect_id];
sect.@"align" = 2;
sect.size = info.calcRequiredSize();
}
@@ -569,23 +547,23 @@ fn calcRequiredSize(info: UnwindInfo) usize {
return total_size;
}
-pub fn write(info: *UnwindInfo, zld: *Zld) !void {
- const sect_id = zld.unwind_info_section_index orelse return;
- const sect = &zld.sections.items(.header)[sect_id];
- const seg_id = zld.sections.items(.segment_index)[sect_id];
- const seg = zld.segments.items[seg_id];
+pub fn write(info: *UnwindInfo, macho_file: *MachO) !void {
+ const sect_id = macho_file.unwind_info_section_index orelse return;
+ const sect = &macho_file.sections.items(.header)[sect_id];
+ const seg_id = macho_file.sections.items(.segment_index)[sect_id];
+ const seg = macho_file.segments.items[seg_id];
- const text_sect_id = zld.text_section_index.?;
- const text_sect = zld.sections.items(.header)[text_sect_id];
+ const text_sect_id = macho_file.text_section_index.?;
+ const text_sect = macho_file.sections.items(.header)[text_sect_id];
var personalities: [max_personalities]u32 = undefined;
- const cpu_arch = zld.options.target.cpu.arch;
+ const cpu_arch = macho_file.base.options.target.cpu.arch;
log.debug("Personalities:", .{});
for (info.personalities[0..info.personalities_count], 0..) |target, i| {
- const addr = zld.getGotEntryAddress(target).?;
+ const addr = macho_file.getGotEntryAddress(target).?;
personalities[i] = @as(u32, @intCast(addr - seg.vmaddr));
- log.debug(" {d}: 0x{x} ({s})", .{ i, personalities[i], zld.getSymbolName(target) });
+ log.debug(" {d}: 0x{x} ({s})", .{ i, personalities[i], macho_file.getSymbolName(target) });
}
for (info.records.items) |*rec| {
@@ -599,7 +577,7 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void {
if (rec.compactUnwindEncoding > 0 and !UnwindEncoding.isDwarf(rec.compactUnwindEncoding, cpu_arch)) {
const lsda_target = @as(SymbolWithLoc, @bitCast(rec.lsda));
if (lsda_target.getFile()) |_| {
- const sym = zld.getSymbol(lsda_target);
+ const sym = macho_file.getSymbol(lsda_target);
rec.lsda = sym.n_value - seg.vmaddr;
}
}
@@ -689,11 +667,11 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void {
@memset(buffer.items[offset..], 0);
}
- try zld.file.pwriteAll(buffer.items, sect.offset);
+ try macho_file.base.file.?.pwriteAll(buffer.items, sect.offset);
}
-fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info {
- const object = &zld.objects.items[object_id];
+fn getRelocs(macho_file: *MachO, object_id: u32, record_id: usize) []const macho.relocation_info {
+ const object = &macho_file.objects.items[object_id];
assert(object.hasUnwindRecords());
const rel_pos = object.unwind_relocs_lookup[record_id].reloc;
const relocs = object.getRelocs(object.unwind_info_sect_id.?);
@@ -707,11 +685,11 @@ fn isPersonalityFunction(record_id: usize, rel: macho.relocation_info) bool {
}
pub fn getPersonalityFunctionReloc(
- zld: *Zld,
+ macho_file: *MachO,
object_id: u32,
record_id: usize,
) ?macho.relocation_info {
- const relocs = getRelocs(zld, object_id, record_id);
+ const relocs = getRelocs(macho_file, object_id, record_id);
for (relocs) |rel| {
if (isPersonalityFunction(record_id, rel)) return rel;
}
@@ -735,8 +713,8 @@ fn isLsda(record_id: usize, rel: macho.relocation_info) bool {
return rel_offset == 24;
}
-pub fn getLsdaReloc(zld: *Zld, object_id: u32, record_id: usize) ?macho.relocation_info {
- const relocs = getRelocs(zld, object_id, record_id);
+pub fn getLsdaReloc(macho_file: *MachO, object_id: u32, record_id: usize) ?macho.relocation_info {
+ const relocs = getRelocs(macho_file, object_id, record_id);
for (relocs) |rel| {
if (isLsda(record_id, rel)) return rel;
}
@@ -828,3 +806,23 @@ pub const UnwindEncoding = struct {
enc.* |= offset;
}
};
+
+const UnwindInfo = @This();
+
+const std = @import("std");
+const assert = std.debug.assert;
+const eh_frame = @import("eh_frame.zig");
+const fs = std.fs;
+const leb = std.leb;
+const log = std.log.scoped(.unwind_info);
+const macho = std.macho;
+const math = std.math;
+const mem = std.mem;
+const trace = @import("../../tracy.zig").trace;
+
+const Allocator = mem.Allocator;
+const Atom = @import("Atom.zig");
+const EhFrameRecord = eh_frame.EhFrameRecord;
+const MachO = @import("../MachO.zig");
+const Object = @import("Object.zig");
+const SymbolWithLoc = MachO.SymbolWithLoc;