mirror of
https://github.com/ziglang/zig.git
synced 2025-01-24 19:07:35 +00:00
macho: migrate UnwindInfo
This commit is contained in:
parent
882ff3ae31
commit
f8b5466aef
@ -354,8 +354,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
|
||||
if (comp.verbose_link) try self.dumpArgv(comp);
|
||||
|
||||
if (self.getZigObject()) |zo| try zo.flushModule(self, tid);
|
||||
if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
|
||||
if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
|
||||
// if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
|
||||
// if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
|
||||
|
||||
var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
|
||||
defer positionals.deinit();
|
||||
|
@ -4,7 +4,7 @@ records: std.ArrayListUnmanaged(Record.Ref) = .{},
|
||||
|
||||
/// List of all personalities referenced by either unwind info entries
|
||||
/// or __eh_frame entries.
|
||||
personalities: [max_personalities]Symbol.Index = undefined,
|
||||
personalities: [max_personalities]MachO.Ref = undefined,
|
||||
personalities_count: u2 = 0,
|
||||
|
||||
/// List of common encodings sorted in descending order with the most common first.
|
||||
@ -42,14 +42,17 @@ fn canFold(macho_file: *MachO, lhs_ref: Record.Ref, rhs_ref: Record.Ref) bool {
|
||||
}
|
||||
|
||||
pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
|
||||
log.debug("generating unwind info", .{});
|
||||
|
||||
// Collect all unwind records
|
||||
for (macho_file.sections.items(.atoms)) |atoms| {
|
||||
for (atoms.items) |atom_index| {
|
||||
const atom = macho_file.getAtom(atom_index) orelse continue;
|
||||
for (atoms.items) |ref| {
|
||||
const atom = ref.getAtom(macho_file) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const recs = atom.getUnwindRecords(macho_file);
|
||||
const file = atom.getFile(macho_file);
|
||||
@ -73,11 +76,15 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
|
||||
}
|
||||
const cie = fde.getCie(macho_file);
|
||||
if (cie.getPersonality(macho_file)) |_| {
|
||||
const personality_index = try info.getOrPutPersonalityFunction(cie.personality.?.index); // TODO handle error
|
||||
const object = cie.getObject(macho_file);
|
||||
const sym_ref = object.getSymbolRef(cie.personality.?.index, macho_file);
|
||||
const personality_index = try info.getOrPutPersonalityFunction(sym_ref); // TODO handle error
|
||||
rec.enc.setPersonalityIndex(personality_index + 1);
|
||||
}
|
||||
} else if (rec.getPersonality(macho_file)) |_| {
|
||||
const personality_index = try info.getOrPutPersonalityFunction(rec.personality.?); // TODO handle error
|
||||
const object = rec.getObject(macho_file);
|
||||
const sym_ref = object.getSymbolRef(rec.personality.?, macho_file);
|
||||
const personality_index = try info.getOrPutPersonalityFunction(sym_ref); // TODO handle error
|
||||
rec.enc.setPersonalityIndex(personality_index + 1);
|
||||
}
|
||||
}
|
||||
@ -257,6 +264,9 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
|
||||
}
|
||||
|
||||
pub fn calcSize(info: UnwindInfo) usize {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
var total_size: usize = 0;
|
||||
total_size += @sizeOf(macho.unwind_info_section_header);
|
||||
total_size +=
|
||||
@ -293,8 +303,8 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
|
||||
|
||||
try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));
|
||||
|
||||
for (info.personalities[0..info.personalities_count]) |sym_index| {
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
for (info.personalities[0..info.personalities_count]) |ref| {
|
||||
const sym = ref.getSymbol(macho_file).?;
|
||||
try writer.writeInt(u32, @intCast(sym.getGotAddress(macho_file) - seg.vmaddr), .little);
|
||||
}
|
||||
|
||||
@ -342,13 +352,13 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
|
||||
@memset(buffer[stream.pos..], 0);
|
||||
}
|
||||
|
||||
fn getOrPutPersonalityFunction(info: *UnwindInfo, sym_index: Symbol.Index) error{TooManyPersonalities}!u2 {
|
||||
fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 {
|
||||
comptime var index: u2 = 0;
|
||||
inline while (index < max_personalities) : (index += 1) {
|
||||
if (info.personalities[index] == sym_index) {
|
||||
if (info.personalities[index].eql(ref)) {
|
||||
return index;
|
||||
} else if (index == info.personalities_count) {
|
||||
info.personalities[index] = sym_index;
|
||||
info.personalities[index] = ref;
|
||||
info.personalities_count += 1;
|
||||
return index;
|
||||
}
|
||||
@ -472,7 +482,8 @@ pub const Record = struct {
|
||||
|
||||
pub fn getPersonality(rec: Record, macho_file: *MachO) ?*Symbol {
|
||||
const personality = rec.personality orelse return null;
|
||||
return macho_file.getSymbol(personality);
|
||||
const object = rec.getObject(macho_file);
|
||||
return object.getSymbolRef(personality, macho_file).getSymbol(macho_file);
|
||||
}
|
||||
|
||||
pub fn getFde(rec: Record, macho_file: *MachO) ?Fde {
|
||||
|
@ -17,16 +17,16 @@ pub fn gcAtoms(macho_file: *MachO) !void {
|
||||
fn collectRoots(roots: *std.ArrayList(*Atom), objects: []const File.Index, macho_file: *MachO) !void {
|
||||
for (objects) |index| {
|
||||
const object = macho_file.getFile(index).?;
|
||||
for (object.getSymbols()) |sym_index| {
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
const file = sym.getFile(macho_file) orelse continue;
|
||||
for (object.getSymbols(), 0..) |*sym, i| {
|
||||
const ref = object.getSymbolRef(@intCast(i), macho_file);
|
||||
const file = ref.getFile(macho_file) orelse continue;
|
||||
if (file.getIndex() != index) continue;
|
||||
if (sym.flags.no_dead_strip or (macho_file.base.isDynLib() and sym.visibility == .global))
|
||||
try markSymbol(sym, roots, macho_file);
|
||||
}
|
||||
|
||||
for (object.getAtoms()) |atom_index| {
|
||||
const atom = macho_file.getAtom(atom_index).?;
|
||||
const atom = object.getAtom(atom_index) orelse continue;
|
||||
const isec = atom.getInputSection(macho_file);
|
||||
switch (isec.type()) {
|
||||
macho.S_MOD_INIT_FUNC_POINTERS,
|
||||
@ -51,19 +51,27 @@ fn collectRoots(roots: *std.ArrayList(*Atom), objects: []const File.Index, macho
|
||||
}
|
||||
}
|
||||
|
||||
for (macho_file.undefined_symbols.items) |sym_index| {
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
try markSymbol(sym, roots, macho_file);
|
||||
}
|
||||
if (macho_file.getInternalObject()) |obj| {
|
||||
for (obj.force_undefined.items) |sym_index| {
|
||||
const ref = obj.getSymbolRef(sym_index, macho_file);
|
||||
if (ref.getFile(macho_file) != null) {
|
||||
const sym = ref.getSymbol(macho_file).?;
|
||||
try markSymbol(sym, roots, macho_file);
|
||||
}
|
||||
}
|
||||
|
||||
for (&[_]?Symbol.Index{
|
||||
macho_file.entry_index,
|
||||
macho_file.dyld_stub_binder_index,
|
||||
macho_file.objc_msg_send_index,
|
||||
}) |index| {
|
||||
if (index) |idx| {
|
||||
const sym = macho_file.getSymbol(idx);
|
||||
try markSymbol(sym, roots, macho_file);
|
||||
for (&[_]?Symbol.Index{
|
||||
obj.entry_index,
|
||||
obj.dyld_stub_binder_index,
|
||||
obj.objc_msg_send_index,
|
||||
}) |index| {
|
||||
if (index) |idx| {
|
||||
const ref = obj.getSymbolRef(idx, macho_file);
|
||||
if (ref.getFile(macho_file) != null) {
|
||||
const sym = ref.getSymbol(macho_file).?;
|
||||
try markSymbol(sym, roots, macho_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,8 +97,9 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
|
||||
loop = false;
|
||||
|
||||
for (objects) |index| {
|
||||
for (macho_file.getFile(index).?.getAtoms()) |atom_index| {
|
||||
const atom = macho_file.getAtom(atom_index).?;
|
||||
const file = macho_file.getFile(index).?;
|
||||
for (file.getAtoms()) |atom_index| {
|
||||
const atom = file.getAtom(atom_index) orelse continue;
|
||||
const isec = atom.getInputSection(macho_file);
|
||||
if (isec.isDontDeadStripIfReferencesLive() and
|
||||
!(mem.eql(u8, isec.sectName(), "__eh_frame") or
|
||||
@ -120,8 +129,11 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {
|
||||
|
||||
for (atom.getRelocs(macho_file)) |rel| {
|
||||
const target_atom = switch (rel.tag) {
|
||||
.local => rel.getTargetAtom(macho_file),
|
||||
.@"extern" => rel.getTargetSymbol(macho_file).getAtom(macho_file),
|
||||
.local => rel.getTargetAtom(atom.*, macho_file),
|
||||
.@"extern" => blk: {
|
||||
const ref = rel.getTargetSymbolRef(atom.*, macho_file);
|
||||
break :blk if (ref.getSymbol(macho_file)) |sym| sym.getAtom(macho_file) else null;
|
||||
},
|
||||
};
|
||||
if (target_atom) |ta| {
|
||||
if (markAtom(ta)) markLive(ta, macho_file);
|
||||
@ -151,8 +163,11 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {
|
||||
fn refersLive(atom: *Atom, macho_file: *MachO) bool {
|
||||
for (atom.getRelocs(macho_file)) |rel| {
|
||||
const target_atom = switch (rel.tag) {
|
||||
.local => rel.getTargetAtom(macho_file),
|
||||
.@"extern" => rel.getTargetSymbol(macho_file).getAtom(macho_file),
|
||||
.local => rel.getTargetAtom(atom.*, macho_file),
|
||||
.@"extern" => blk: {
|
||||
const ref = rel.getTargetSymbolRef(atom.*, macho_file);
|
||||
break :blk if (ref.getSymbol(macho_file)) |sym| sym.getAtom(macho_file) else null;
|
||||
},
|
||||
};
|
||||
if (target_atom) |ta| {
|
||||
if (ta.flags.alive) return true;
|
||||
@ -163,8 +178,9 @@ fn refersLive(atom: *Atom, macho_file: *MachO) bool {
|
||||
|
||||
fn prune(objects: []const File.Index, macho_file: *MachO) void {
|
||||
for (objects) |index| {
|
||||
for (macho_file.getFile(index).?.getAtoms()) |atom_index| {
|
||||
const atom = macho_file.getAtom(atom_index).?;
|
||||
const file = macho_file.getFile(index).?;
|
||||
for (file.getAtoms()) |atom_index| {
|
||||
const atom = file.getAtom(atom_index) orelse continue;
|
||||
if (atom.flags.alive and !atom.flags.visited) {
|
||||
atom.flags.alive = false;
|
||||
atom.markUnwindRecordsDead(macho_file);
|
||||
|
Loading…
Reference in New Issue
Block a user