aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-09-15 13:15:15 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-09-15 16:51:56 +0200
commit25416d8121d14ec6a2a94943cfa4e2fb944e215b (patch)
treeb257177adba5bf20807c6f687e96d2da91bcdf82 /src
parent0395b35cee8d4082cc40b0dcd0298f797f42309d (diff)
downloadzig-25416d8121d14ec6a2a94943cfa4e2fb944e215b.tar.gz
zig-25416d8121d14ec6a2a94943cfa4e2fb944e215b.zip
macho: when adding extern fn, check if already resolved
This way, we will generate valid relocation info in the codegen.
Diffstat (limited to 'src')
-rw-r--r--src/codegen.zig9
-rw-r--r--src/link/MachO.zig33
2 files changed, 31 insertions, 11 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 511d4c2301..e79003f728 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -2840,7 +2840,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
}
} else if (func_value.castTag(.extern_fn)) |func_payload| {
const decl = func_payload.data;
- const where_index = try macho_file.addExternFn(mem.spanZ(decl.name));
+ const resolv = try macho_file.addExternFn(mem.spanZ(decl.name));
const offset = blk: {
switch (arch) {
.x86_64 => {
@@ -2861,8 +2861,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
// Add relocation to the decl.
try macho_file.active_decl.?.link.macho.relocs.append(self.bin_file.allocator, .{
.offset = offset,
- .where = .undef,
- .where_index = where_index,
+ .where = switch (resolv.where) {
+ .local => .local,
+ .undef => .undef,
+ },
+ .where_index = resolv.where_index,
.payload = .{ .branch = .{
.arch = arch,
} },
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index ce00c85dea..8037c5e9a0 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -4228,20 +4228,34 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m
return vaddr;
}
-pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
+const AddExternFnRes = struct {
+ where: enum {
+ local,
+ undef,
+ },
+ where_index: u32,
+};
+
+pub fn addExternFn(self: *MachO, name: []const u8) !AddExternFnRes {
const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});
defer self.base.allocator.free(sym_name);
+ const n_strx = try self.makeString(sym_name);
- if (self.strtab_dir.getKeyAdapted(@as([]const u8, sym_name), StringIndexAdapter{
- .bytes = &self.strtab,
- })) |n_strx| {
- const resolv = self.symbol_resolver.get(n_strx) orelse unreachable;
- return resolv.where_index;
+ if (self.symbol_resolver.get(n_strx)) |resolv| {
+ return switch (resolv.where) {
+ .global => AddExternFnRes{
+ .where = .local,
+ .where_index = resolv.local_sym_index,
+ },
+ .undef => AddExternFnRes{
+ .where = .undef,
+ .where_index = resolv.where_index,
+ },
+ };
}
log.debug("adding new extern function '{s}'", .{sym_name});
const sym_index = @intCast(u32, self.undefs.items.len);
- const n_strx = try self.makeString(sym_name);
try self.undefs.append(self.base.allocator, .{
.n_strx = n_strx,
.n_type = macho.N_UNDF,
@@ -4255,7 +4269,10 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
});
try self.unresolved.putNoClobber(self.base.allocator, sym_index, .stub);
- return sym_index;
+ return AddExternFnRes{
+ .where = .undef,
+ .where_index = sym_index,
+ };
}
const NextSegmentAddressAndOffset = struct {