aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-03-31 22:36:10 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-04-01 14:22:44 +0200
commitf2587de4e915423d0224b8b6ef0cb3d9cb7e60e2 (patch)
treef03f33b4b1c0a80eea3e8cc10f1ae21186dceb40 /src
parent381dc2d9509ffeaf60a1775ee0983c7dd1b9e346 (diff)
downloadzig-f2587de4e915423d0224b8b6ef0cb3d9cb7e60e2.tar.gz
zig-f2587de4e915423d0224b8b6ef0cb3d9cb7e60e2.zip
macho: look for entry in archives/dylibs too
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO.zig2
-rw-r--r--src/link/MachO/load_commands.zig4
-rw-r--r--src/link/MachO/zld.zig67
3 files changed, 48 insertions, 25 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 3206b63fa3..4c3301a3b4 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -3981,7 +3981,7 @@ pub fn getStubsAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?At
/// Returns symbol location corresponding to the set entrypoint.
/// Asserts output mode is executable.
pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {
- const entry_name = self.base.options.entry orelse "_main";
+ const entry_name = self.base.options.entry orelse load_commands.default_entry_point;
const global = self.getGlobal(entry_name) orelse {
log.err("entrypoint '{s}' not found", .{entry_name});
return error.MissingMainEntrypoint;
diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig
index 43469ac435..228a1ccfaf 100644
--- a/src/link/MachO/load_commands.zig
+++ b/src/link/MachO/load_commands.zig
@@ -8,6 +8,10 @@ const mem = std.mem;
const Allocator = mem.Allocator;
const Dylib = @import("Dylib.zig");
+/// Default implicit entrypoint symbol name.
+pub const default_entry_point: []const u8 = "_main";
+
+/// Default path to dyld.
pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";
fn calcInstallNameLen(cmd_size: u64, name: []const u8, assume_max_path_len: bool) u64 {
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index 07241b54cd..196a437884 100644
--- a/src/link/MachO/zld.zig
+++ b/src/link/MachO/zld.zig
@@ -932,6 +932,34 @@ pub const Zld = struct {
}
}
+ 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, {});
+ }
+
+ for (self.objects.items, 0..) |_, object_id| {
+ try self.resolveSymbolsInObject(@intCast(u32, object_id), resolver);
+ }
+
+ try self.resolveSymbolsInArchives(resolver);
+ try self.resolveDyldStubBinder(resolver);
+ try self.resolveSymbolsInDylibs(resolver);
+ try self.createMhExecuteHeaderSymbol(resolver);
+ try self.createDsoHandleSymbol(resolver);
+ try self.resolveSymbolsAtLoading(resolver);
+ }
+
fn resolveSymbolsInObject(self: *Zld, object_id: u32, resolver: *SymbolResolver) !void {
const object = &self.objects.items[object_id];
const in_symtab = object.in_symtab orelse return;
@@ -975,9 +1003,7 @@ pub const Zld = struct {
const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };
const global_index = resolver.table.get(sym_name) orelse {
- const gpa = self.gpa;
- const global_index = @intCast(u32, self.globals.items.len);
- try self.globals.append(gpa, sym_loc);
+ const global_index = try self.addGlobal(sym_loc);
try resolver.table.putNoClobber(sym_name, global_index);
if (sym.undf() and !sym.tentative()) {
try resolver.unresolved.putNoClobber(global_index, {});
@@ -1034,8 +1060,10 @@ pub const Zld = struct {
};
if (update_global) {
- const global_object = &self.objects.items[global.getFile().?];
- global_object.globals_lookup[global.sym_index] = global_index;
+ if (global.getFile()) |file| {
+ const global_object = &self.objects.items[file];
+ global_object.globals_lookup[global.sym_index] = global_index;
+ }
_ = resolver.unresolved.swapRemove(resolver.table.get(sym_name).?);
global.* = sym_loc;
} else {
@@ -1180,9 +1208,7 @@ pub const Zld = struct {
global.* = sym_loc;
self.mh_execute_header_index = global_index;
} else {
- const global_index = @intCast(u32, self.globals.items.len);
- try self.globals.append(gpa, sym_loc);
- self.mh_execute_header_index = global_index;
+ self.mh_execute_header_index = try self.addGlobal(sym_loc);
}
}
@@ -1358,6 +1384,12 @@ pub const Zld = struct {
return index;
}
+ fn addGlobal(self: *Zld, sym_loc: SymbolWithLoc) !u32 {
+ const global_index = @intCast(u32, self.globals.items.len);
+ try self.globals.append(self.gpa, sym_loc);
+ return global_index;
+ }
+
fn allocateSpecialSymbols(self: *Zld) !void {
for (&[_]?u32{
self.dso_handle_index,
@@ -3980,17 +4012,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
.table = std.StringHashMap(u32).init(arena),
.unresolved = std.AutoArrayHashMap(u32, void).init(arena),
};
-
- for (zld.objects.items, 0..) |_, object_id| {
- try zld.resolveSymbolsInObject(@intCast(u32, object_id), &resolver);
- }
-
- try zld.resolveSymbolsInArchives(&resolver);
- try zld.resolveDyldStubBinder(&resolver);
- try zld.resolveSymbolsInDylibs(&resolver);
- try zld.createMhExecuteHeaderSymbol(&resolver);
- try zld.createDsoHandleSymbol(&resolver);
- try zld.resolveSymbolsAtLoading(&resolver);
+ try zld.resolveSymbols(&resolver);
if (resolver.unresolved.count() > 0) {
return error.UndefinedSymbolReference;
@@ -4003,11 +4025,8 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
}
if (options.output_mode == .Exe) {
- const entry_name = options.entry orelse "_main";
- const global_index = resolver.table.get(entry_name) orelse {
- log.err("entrypoint '{s}' not found", .{entry_name});
- return error.MissingMainEntrypoint;
- };
+ const entry_name = options.entry orelse load_commands.default_entry_point;
+ const global_index = resolver.table.get(entry_name).?; // Error was flagged earlier
zld.entry_index = global_index;
}