Commit 25416d8121

Jakub Konka <kubkon@jakubkonka.com>
2021-09-15 13:15:15
macho: when adding extern fn, check if already resolved
This way, we will generate valid relocation info in the codegen.
1 parent 0395b35
Changed files (2)
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 {
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,
                             } },