authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-09 20:26:34+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
logf8b5466aef4131821b259aa5f0d6b9654a5595ce
treea0b037225a7a256913ed861c61cd152b480bd513
parent882ff3ae31a39edf23db00b558db60ee574d9859

macho: migrate UnwindInfo


3 files changed, 64 insertions(+), 37 deletions(-)

src/link/MachO.zig+2-2
...@@ -354,8 +354,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -354,8 +354,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
354 if (comp.verbose_link) try self.dumpArgv(comp);354 if (comp.verbose_link) try self.dumpArgv(comp);
355355
356 if (self.getZigObject()) |zo| try zo.flushModule(self, tid);356 if (self.getZigObject()) |zo| try zo.flushModule(self, tid);
357 if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);357 // if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
358 if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);358 // if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
359359
360 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);360 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
361 defer positionals.deinit();361 defer positionals.deinit();
src/link/MachO/UnwindInfo.zig+22-11
...@@ -4,7 +4,7 @@ records: std.ArrayListUnmanaged(Record.Ref) = .{},...@@ -4,7 +4,7 @@ records: std.ArrayListUnmanaged(Record.Ref) = .{},
44
5/// List of all personalities referenced by either unwind info entries5/// List of all personalities referenced by either unwind info entries
6/// or __eh_frame entries.6/// or __eh_frame entries.
7personalities: [max_personalities]Symbol.Index = undefined,7personalities: [max_personalities]MachO.Ref = undefined,
8personalities_count: u2 = 0,8personalities_count: u2 = 0,
99
10/// List of common encodings sorted in descending order with the most common first.10/// 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 {...@@ -42,14 +42,17 @@ fn canFold(macho_file: *MachO, lhs_ref: Record.Ref, rhs_ref: Record.Ref) bool {
42}42}
4343
44pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {44pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
45 const tracy = trace(@src());
46 defer tracy.end();
47
45 const gpa = macho_file.base.comp.gpa;48 const gpa = macho_file.base.comp.gpa;
4649
47 log.debug("generating unwind info", .{});50 log.debug("generating unwind info", .{});
4851
49 // Collect all unwind records52 // Collect all unwind records
50 for (macho_file.sections.items(.atoms)) |atoms| {53 for (macho_file.sections.items(.atoms)) |atoms| {
51 for (atoms.items) |atom_index| {54 for (atoms.items) |ref| {
52 const atom = macho_file.getAtom(atom_index) orelse continue;55 const atom = ref.getAtom(macho_file) orelse continue;
53 if (!atom.flags.alive) continue;56 if (!atom.flags.alive) continue;
54 const recs = atom.getUnwindRecords(macho_file);57 const recs = atom.getUnwindRecords(macho_file);
55 const file = atom.getFile(macho_file);58 const file = atom.getFile(macho_file);
...@@ -73,11 +76,15 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -73,11 +76,15 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
73 }76 }
74 const cie = fde.getCie(macho_file);77 const cie = fde.getCie(macho_file);
75 if (cie.getPersonality(macho_file)) |_| {78 if (cie.getPersonality(macho_file)) |_| {
76 const personality_index = try info.getOrPutPersonalityFunction(cie.personality.?.index); // TODO handle error79 const object = cie.getObject(macho_file);
80 const sym_ref = object.getSymbolRef(cie.personality.?.index, macho_file);
81 const personality_index = try info.getOrPutPersonalityFunction(sym_ref); // TODO handle error
77 rec.enc.setPersonalityIndex(personality_index + 1);82 rec.enc.setPersonalityIndex(personality_index + 1);
78 }83 }
79 } else if (rec.getPersonality(macho_file)) |_| {84 } else if (rec.getPersonality(macho_file)) |_| {
80 const personality_index = try info.getOrPutPersonalityFunction(rec.personality.?); // TODO handle error85 const object = rec.getObject(macho_file);
86 const sym_ref = object.getSymbolRef(rec.personality.?, macho_file);
87 const personality_index = try info.getOrPutPersonalityFunction(sym_ref); // TODO handle error
81 rec.enc.setPersonalityIndex(personality_index + 1);88 rec.enc.setPersonalityIndex(personality_index + 1);
82 }89 }
83 }90 }
...@@ -257,6 +264,9 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -257,6 +264,9 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
257}264}
258265
259pub fn calcSize(info: UnwindInfo) usize {266pub fn calcSize(info: UnwindInfo) usize {
267 const tracy = trace(@src());
268 defer tracy.end();
269
260 var total_size: usize = 0;270 var total_size: usize = 0;
261 total_size += @sizeOf(macho.unwind_info_section_header);271 total_size += @sizeOf(macho.unwind_info_section_header);
262 total_size +=272 total_size +=
...@@ -293,8 +303,8 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -293,8 +303,8 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
293303
294 try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));304 try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));
295305
296 for (info.personalities[0..info.personalities_count]) |sym_index| {306 for (info.personalities[0..info.personalities_count]) |ref| {
297 const sym = macho_file.getSymbol(sym_index);307 const sym = ref.getSymbol(macho_file).?;
298 try writer.writeInt(u32, @intCast(sym.getGotAddress(macho_file) - seg.vmaddr), .little);308 try writer.writeInt(u32, @intCast(sym.getGotAddress(macho_file) - seg.vmaddr), .little);
299 }309 }
300310
...@@ -342,13 +352,13 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -342,13 +352,13 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
342 @memset(buffer[stream.pos..], 0);352 @memset(buffer[stream.pos..], 0);
343}353}
344354
345fn getOrPutPersonalityFunction(info: *UnwindInfo, sym_index: Symbol.Index) error{TooManyPersonalities}!u2 {355fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 {
346 comptime var index: u2 = 0;356 comptime var index: u2 = 0;
347 inline while (index < max_personalities) : (index += 1) {357 inline while (index < max_personalities) : (index += 1) {
348 if (info.personalities[index] == sym_index) {358 if (info.personalities[index].eql(ref)) {
349 return index;359 return index;
350 } else if (index == info.personalities_count) {360 } else if (index == info.personalities_count) {
351 info.personalities[index] = sym_index;361 info.personalities[index] = ref;
352 info.personalities_count += 1;362 info.personalities_count += 1;
353 return index;363 return index;
354 }364 }
...@@ -472,7 +482,8 @@ pub const Record = struct {...@@ -472,7 +482,8 @@ pub const Record = struct {
472482
473 pub fn getPersonality(rec: Record, macho_file: *MachO) ?*Symbol {483 pub fn getPersonality(rec: Record, macho_file: *MachO) ?*Symbol {
474 const personality = rec.personality orelse return null;484 const personality = rec.personality orelse return null;
475 return macho_file.getSymbol(personality);485 const object = rec.getObject(macho_file);
486 return object.getSymbolRef(personality, macho_file).getSymbol(macho_file);
476 }487 }
477488
478 pub fn getFde(rec: Record, macho_file: *MachO) ?Fde {489 pub fn getFde(rec: Record, macho_file: *MachO) ?Fde {
src/link/MachO/dead_strip.zig+40-24
...@@ -17,16 +17,16 @@ pub fn gcAtoms(macho_file: *MachO) !void {...@@ -17,16 +17,16 @@ pub fn gcAtoms(macho_file: *MachO) !void {
17fn collectRoots(roots: *std.ArrayList(*Atom), objects: []const File.Index, macho_file: *MachO) !void {17fn collectRoots(roots: *std.ArrayList(*Atom), objects: []const File.Index, macho_file: *MachO) !void {
18 for (objects) |index| {18 for (objects) |index| {
19 const object = macho_file.getFile(index).?;19 const object = macho_file.getFile(index).?;
20 for (object.getSymbols()) |sym_index| {20 for (object.getSymbols(), 0..) |*sym, i| {
21 const sym = macho_file.getSymbol(sym_index);21 const ref = object.getSymbolRef(@intCast(i), macho_file);
22 const file = sym.getFile(macho_file) orelse continue;22 const file = ref.getFile(macho_file) orelse continue;
23 if (file.getIndex() != index) continue;23 if (file.getIndex() != index) continue;
24 if (sym.flags.no_dead_strip or (macho_file.base.isDynLib() and sym.visibility == .global))24 if (sym.flags.no_dead_strip or (macho_file.base.isDynLib() and sym.visibility == .global))
25 try markSymbol(sym, roots, macho_file);25 try markSymbol(sym, roots, macho_file);
26 }26 }
2727
28 for (object.getAtoms()) |atom_index| {28 for (object.getAtoms()) |atom_index| {
29 const atom = macho_file.getAtom(atom_index).?;29 const atom = object.getAtom(atom_index) orelse continue;
30 const isec = atom.getInputSection(macho_file);30 const isec = atom.getInputSection(macho_file);
31 switch (isec.type()) {31 switch (isec.type()) {
32 macho.S_MOD_INIT_FUNC_POINTERS,32 macho.S_MOD_INIT_FUNC_POINTERS,
...@@ -51,19 +51,27 @@ fn collectRoots(roots: *std.ArrayList(*Atom), objects: []const File.Index, macho...@@ -51,19 +51,27 @@ fn collectRoots(roots: *std.ArrayList(*Atom), objects: []const File.Index, macho
51 }51 }
52 }52 }
5353
54 for (macho_file.undefined_symbols.items) |sym_index| {54 if (macho_file.getInternalObject()) |obj| {
55 const sym = macho_file.getSymbol(sym_index);55 for (obj.force_undefined.items) |sym_index| {
56 try markSymbol(sym, roots, macho_file);56 const ref = obj.getSymbolRef(sym_index, macho_file);
57 }57 if (ref.getFile(macho_file) != null) {
58 const sym = ref.getSymbol(macho_file).?;
59 try markSymbol(sym, roots, macho_file);
60 }
61 }
5862
59 for (&[_]?Symbol.Index{63 for (&[_]?Symbol.Index{
60 macho_file.entry_index,64 obj.entry_index,
61 macho_file.dyld_stub_binder_index,65 obj.dyld_stub_binder_index,
62 macho_file.objc_msg_send_index,66 obj.objc_msg_send_index,
63 }) |index| {67 }) |index| {
64 if (index) |idx| {68 if (index) |idx| {
65 const sym = macho_file.getSymbol(idx);69 const ref = obj.getSymbolRef(idx, macho_file);
66 try markSymbol(sym, roots, macho_file);70 if (ref.getFile(macho_file) != null) {
71 const sym = ref.getSymbol(macho_file).?;
72 try markSymbol(sym, roots, macho_file);
73 }
74 }
67 }75 }
68 }76 }
69}77}
...@@ -89,8 +97,9 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {...@@ -89,8 +97,9 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
89 loop = false;97 loop = false;
9098
91 for (objects) |index| {99 for (objects) |index| {
92 for (macho_file.getFile(index).?.getAtoms()) |atom_index| {100 const file = macho_file.getFile(index).?;
93 const atom = macho_file.getAtom(atom_index).?;101 for (file.getAtoms()) |atom_index| {
102 const atom = file.getAtom(atom_index) orelse continue;
94 const isec = atom.getInputSection(macho_file);103 const isec = atom.getInputSection(macho_file);
95 if (isec.isDontDeadStripIfReferencesLive() and104 if (isec.isDontDeadStripIfReferencesLive() and
96 !(mem.eql(u8, isec.sectName(), "__eh_frame") or105 !(mem.eql(u8, isec.sectName(), "__eh_frame") or
...@@ -120,8 +129,11 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {...@@ -120,8 +129,11 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {
120129
121 for (atom.getRelocs(macho_file)) |rel| {130 for (atom.getRelocs(macho_file)) |rel| {
122 const target_atom = switch (rel.tag) {131 const target_atom = switch (rel.tag) {
123 .local => rel.getTargetAtom(macho_file),132 .local => rel.getTargetAtom(atom.*, macho_file),
124 .@"extern" => rel.getTargetSymbol(macho_file).getAtom(macho_file),133 .@"extern" => blk: {
134 const ref = rel.getTargetSymbolRef(atom.*, macho_file);
135 break :blk if (ref.getSymbol(macho_file)) |sym| sym.getAtom(macho_file) else null;
136 },
125 };137 };
126 if (target_atom) |ta| {138 if (target_atom) |ta| {
127 if (markAtom(ta)) markLive(ta, macho_file);139 if (markAtom(ta)) markLive(ta, macho_file);
...@@ -151,8 +163,11 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {...@@ -151,8 +163,11 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {
151fn refersLive(atom: *Atom, macho_file: *MachO) bool {163fn refersLive(atom: *Atom, macho_file: *MachO) bool {
152 for (atom.getRelocs(macho_file)) |rel| {164 for (atom.getRelocs(macho_file)) |rel| {
153 const target_atom = switch (rel.tag) {165 const target_atom = switch (rel.tag) {
154 .local => rel.getTargetAtom(macho_file),166 .local => rel.getTargetAtom(atom.*, macho_file),
155 .@"extern" => rel.getTargetSymbol(macho_file).getAtom(macho_file),167 .@"extern" => blk: {
168 const ref = rel.getTargetSymbolRef(atom.*, macho_file);
169 break :blk if (ref.getSymbol(macho_file)) |sym| sym.getAtom(macho_file) else null;
170 },
156 };171 };
157 if (target_atom) |ta| {172 if (target_atom) |ta| {
158 if (ta.flags.alive) return true;173 if (ta.flags.alive) return true;
...@@ -163,8 +178,9 @@ fn refersLive(atom: *Atom, macho_file: *MachO) bool {...@@ -163,8 +178,9 @@ fn refersLive(atom: *Atom, macho_file: *MachO) bool {
163178
164fn prune(objects: []const File.Index, macho_file: *MachO) void {179fn prune(objects: []const File.Index, macho_file: *MachO) void {
165 for (objects) |index| {180 for (objects) |index| {
166 for (macho_file.getFile(index).?.getAtoms()) |atom_index| {181 const file = macho_file.getFile(index).?;
167 const atom = macho_file.getAtom(atom_index).?;182 for (file.getAtoms()) |atom_index| {
183 const atom = file.getAtom(atom_index) orelse continue;
168 if (atom.flags.alive and !atom.flags.visited) {184 if (atom.flags.alive and !atom.flags.visited) {
169 atom.flags.alive = false;185 atom.flags.alive = false;
170 atom.markUnwindRecordsDead(macho_file);186 atom.markUnwindRecordsDead(macho_file);