diff options
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Coff/lld.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO/dead_strip.zig | 52 | ||||
| -rw-r--r-- | src/link/MachO/zld.zig | 32 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 4 |
5 files changed, 55 insertions, 37 deletions
diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 358c905b2c..01f724ed41 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -63,7 +63,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man = comp.cache_parent.obtain(); self.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 7); + comptime assert(Compilation.link_hash_implementation_version == 8); for (self.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index fcab34bf5e..95104ec2e8 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1305,7 +1305,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We are about to obtain this lock, so here we give other processes a chance first. self.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 7); + comptime assert(Compilation.link_hash_implementation_version == 8); try man.addOptionalFile(self.base.options.linker_script); try man.addOptionalFile(self.base.options.version_script); diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index 66c644ec04..ca0d961e2d 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -12,6 +12,7 @@ const Allocator = mem.Allocator; const AtomIndex = @import("zld.zig").AtomIndex; const Atom = @import("ZldAtom.zig"); const SymbolWithLoc = @import("zld.zig").SymbolWithLoc; +const SymbolResolver = @import("zld.zig").SymbolResolver; const UnwindInfo = @import("UnwindInfo.zig"); const Zld = @import("zld.zig").Zld; @@ -19,7 +20,7 @@ const N_DEAD = @import("zld.zig").N_DEAD; const AtomTable = std.AutoHashMap(AtomIndex, void); -pub fn gcAtoms(zld: *Zld) !void { +pub fn gcAtoms(zld: *Zld, resolver: *const SymbolResolver) !void { const gpa = zld.gpa; var arena = std.heap.ArenaAllocator.init(gpa); @@ -31,12 +32,25 @@ pub fn gcAtoms(zld: *Zld) !void { var alive = AtomTable.init(arena.allocator()); try alive.ensureTotalCapacity(@intCast(u32, zld.atoms.items.len)); - try collectRoots(zld, &roots); + try collectRoots(zld, &roots, resolver); try mark(zld, roots, &alive); prune(zld, alive); } -fn collectRoots(zld: *Zld, roots: *AtomTable) !void { +fn addRoot(zld: *Zld, roots: *AtomTable, file: u32, sym_loc: SymbolWithLoc) !void { + const sym = zld.getSymbol(sym_loc); + assert(!sym.undf()); + const object = &zld.objects.items[file]; + const atom_index = object.getAtomIndexForSymbol(sym_loc.sym_index).?; // panic here means fatal error + log.debug("root(ATOM({d}, %{d}, {d}))", .{ + atom_index, + zld.getAtom(atom_index).sym_index, + file, + }); + _ = try roots.getOrPut(atom_index); +} + +fn collectRoots(zld: *Zld, roots: *AtomTable, resolver: *const SymbolResolver) !void { log.debug("collecting roots", .{}); switch (zld.options.output_mode) { @@ -44,15 +58,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void { // Add entrypoint as GC root const global: SymbolWithLoc = zld.getEntryPoint(); if (global.getFile()) |file| { - const object = zld.objects.items[file]; - const atom_index = object.getAtomIndexForSymbol(global.sym_index).?; // panic here means fatal error - _ = try roots.getOrPut(atom_index); - - log.debug("root(ATOM({d}, %{d}, {?d}))", .{ - atom_index, - zld.getAtom(atom_index).sym_index, - zld.getAtom(atom_index).getFile(), - }); + try addRoot(zld, roots, file, global); } else { assert(zld.getSymbol(global).undf()); // Stub as our entrypoint is in a dylib. } @@ -64,20 +70,22 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void { const sym = zld.getSymbol(global); if (sym.undf()) continue; - const file = global.getFile() orelse continue; // synthetic globals are atomless - const object = zld.objects.items[file]; - const atom_index = object.getAtomIndexForSymbol(global.sym_index).?; // panic here means fatal error - _ = try roots.getOrPut(atom_index); - - log.debug("root(ATOM({d}, %{d}, {?d}))", .{ - atom_index, - zld.getAtom(atom_index).sym_index, - zld.getAtom(atom_index).getFile(), - }); + if (global.getFile()) |file| { + try addRoot(zld, roots, file, global); + } } }, } + // Add all symbols force-defined by the user. + for (zld.options.force_undefined_symbols.keys()) |sym_name| { + const global_index = resolver.table.get(sym_name).?; + const global = zld.globals.items[global_index]; + const sym = zld.getSymbol(global); + assert(!sym.undf()); + try addRoot(zld, roots, global.getFile().?, global); + } + for (zld.objects.items) |object| { const has_subsections = object.header.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0; diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 2e2b215698..47dd4dd54f 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -932,20 +932,29 @@ pub const Zld = struct { } } + fn forceSymbolDefined(self: *Zld, name: []const u8, resolver: *SymbolResolver) !void { + const sym_index = try self.allocateSymbol(); + const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; + const sym = self.getSymbolPtr(sym_loc); + sym.n_strx = try self.strtab.insert(self.gpa, name); + sym.n_type = macho.N_UNDF | macho.N_EXT; + const global_index = try self.addGlobal(sym_loc); + try resolver.table.putNoClobber(name, global_index); + try resolver.unresolved.putNoClobber(global_index, {}); + } + fn resolveSymbols(self: *Zld, resolver: *SymbolResolver) !void { // We add the specified entrypoint as the first unresolved symbols so that // we search for it in libraries should there be no object files specified // on the linker line. if (self.options.output_mode == .Exe) { const entry_name = self.options.entry orelse load_commands.default_entry_point; - const sym_index = try self.allocateSymbol(); - const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; - const sym = self.getSymbolPtr(sym_loc); - sym.n_strx = try self.strtab.insert(self.gpa, entry_name); - sym.n_type = macho.N_UNDF | macho.N_EXT; - const global_index = try self.addGlobal(sym_loc); - try resolver.table.putNoClobber(entry_name, global_index); - try resolver.unresolved.putNoClobber(global_index, {}); + try self.forceSymbolDefined(entry_name, resolver); + } + + // Force resolution of any symbols requested by the user. + for (self.options.force_undefined_symbols.keys()) |sym_name| { + try self.forceSymbolDefined(sym_name, resolver); } for (self.objects.items, 0..) |_, object_id| { @@ -3539,7 +3548,7 @@ pub const SymbolWithLoc = extern struct { } }; -const SymbolResolver = struct { +pub const SymbolResolver = struct { arena: Allocator, table: std.StringHashMap(u32), unresolved: std.AutoArrayHashMap(u32, void), @@ -3600,7 +3609,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr // We are about to obtain this lock, so here we give other processes a chance first. macho_file.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 7); + comptime assert(Compilation.link_hash_implementation_version == 8); for (options.objects) |obj| { _ = try man.addFile(obj.path, null); @@ -3630,6 +3639,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr } link.hashAddSystemLibs(&man.hash, options.system_libs); man.hash.addOptionalBytes(options.sysroot); + man.hash.addListOfBytes(options.force_undefined_symbols.keys()); try man.addOptionalFile(options.entitlements); // We don't actually care whether it's a cache hit or miss; we just @@ -4035,7 +4045,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr } if (gc_sections) { - try dead_strip.gcAtoms(&zld); + try dead_strip.gcAtoms(&zld, &resolver); } try zld.createDyldPrivateAtom(); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index e59b83176c..b1fc25bf26 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3059,7 +3059,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l // We are about to obtain this lock, so here we give other processes a chance first. wasm.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 7); + comptime assert(Compilation.link_hash_implementation_version == 8); for (options.objects) |obj| { _ = try man.addFile(obj.path, null); @@ -4086,7 +4086,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // We are about to obtain this lock, so here we give other processes a chance first. wasm.base.releaseLock(); - comptime assert(Compilation.link_hash_implementation_version == 7); + comptime assert(Compilation.link_hash_implementation_version == 8); for (wasm.base.options.objects) |obj| { _ = try man.addFile(obj.path, null); |
