diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-11 18:42:35 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-24 12:34:39 +0100 |
| commit | 8a1311733b313a59afa2ea354ca9b342a935d869 (patch) | |
| tree | d4d8438c087a3bd4d19c6369214e8b7e9b06b7da /src | |
| parent | b8f67d79850b0be1f2384dca0a9a946bfa6a75a6 (diff) | |
| download | zig-8a1311733b313a59afa2ea354ca9b342a935d869.tar.gz zig-8a1311733b313a59afa2ea354ca9b342a935d869.zip | |
macho: resolve symbols and mark files live
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 82 | ||||
| -rw-r--r-- | src/link/MachO/Dylib.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO/Object.zig | 3 |
3 files changed, 73 insertions, 14 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 49e4ad525c..8a43526fab 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -497,6 +497,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node } try self.addUndefinedGlobals(); + try self.resolveSymbols(); state_log.debug("{}", .{self.dumpState()}); @@ -1157,6 +1158,63 @@ fn addUndefinedGlobals(self: *MachO) !void { } } +/// When resolving symbols, we approach the problem similarly to `mold`. +/// 1. Resolve symbols across all objects (including those preemptively extracted archives). +/// 2. Resolve symbols across all shared objects. +/// 3. Mark live objects (see `MachO.markLive`) +/// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. +/// 5. Remove references to dead objects/shared objects +/// 6. Re-run symbol resolution on pruned objects and shared objects sets. +pub fn resolveSymbols(self: *MachO) !void { + const tracy = trace(@src()); + defer tracy.end(); + + // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). + for (self.objects.items) |index| self.getFile(index).?.resolveSymbols(self); + for (self.dylibs.items) |index| self.getFile(index).?.resolveSymbols(self); + + // Mark live objects. + self.markLive(); + + // Reset state of all globals after marking live objects. + for (self.objects.items) |index| self.getFile(index).?.resetGlobals(self); + for (self.dylibs.items) |index| self.getFile(index).?.resetGlobals(self); + + // Prune dead objects. + var i: usize = 0; + while (i < self.objects.items.len) { + const index = self.objects.items[i]; + if (!self.getFile(index).?.object.alive) { + _ = self.objects.orderedRemove(i); + } else i += 1; + } + + // Re-resolve the symbols. + for (self.objects.items) |index| self.getFile(index).?.resolveSymbols(self); + for (self.dylibs.items) |index| self.getFile(index).?.resolveSymbols(self); +} + +fn markLive(self: *MachO) void { + const tracy = trace(@src()); + defer tracy.end(); + + for (self.undefined_symbols.items) |index| { + if (self.getSymbol(index).getFile(self)) |file| { + if (file == .object) file.object.alive = true; + } + } + if (self.entry_index) |index| { + const sym = self.getSymbol(index); + if (sym.getFile(self)) |file| { + if (file == .object) file.object.alive = true; + } + } + for (self.objects.items) |index| { + const object = self.getFile(index).?.object; + if (object.alive) object.markLive(self); + } +} + fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { _ = self; _ = atom_index; @@ -1791,18 +1849,18 @@ fn fmtDumpState( object.fmtSymtab(self), }); } - // for (self.dylibs.items) |index| { - // const dylib = self.getFile(index).?.dylib; - // try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{ - // index, - // dylib.path, - // dylib.needed, - // dylib.weak, - // }); - // if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])"); - // try writer.writeByte('\n'); - // try writer.print("{}\n", .{dylib.fmtSymtab(self)}); - // } + for (self.dylibs.items) |index| { + const dylib = self.getFile(index).?.dylib; + try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{ + index, + dylib.path, + dylib.needed, + dylib.weak, + }); + if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])"); + try writer.writeByte('\n'); + try writer.print("{}\n", .{dylib.fmtSymtab(self)}); + } if (self.getInternalObject()) |internal| { try writer.print("internal({d}) : internal\n", .{internal.index}); try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) }); diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 694f2214b7..0df66ffd71 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -530,7 +530,7 @@ pub fn resetGlobals(self: *Dylib, macho_file: *MachO) void { } pub fn isAlive(self: Dylib, macho_file: *MachO) bool { - if (!macho_file.options.dead_strip_dylibs) return self.explicit or self.referenced or self.needed; + if (!macho_file.dead_strip_dylibs) return self.explicit or self.referenced or self.needed; return self.referenced or self.needed; } diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index e28c23d4ad..9d39621d16 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -1021,7 +1021,8 @@ pub fn resolveSymbols(self: *Object, macho_file: *MachO) void { symbol.flags.weak_ref = false; symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0; symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip(); - symbol.flags.interposable = macho_file.options.dylib and macho_file.options.namespace == .flat and !nlist.pext(); + // TODO: symbol.flags.interposable = macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext(); + symbol.flags.interposable = false; if (nlist.sect() and self.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES) |
