aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Coff/lld.zig2
-rw-r--r--src/link/Elf.zig2
-rw-r--r--src/link/MachO/dead_strip.zig52
-rw-r--r--src/link/MachO/zld.zig32
-rw-r--r--src/link/Wasm.zig4
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);