From 25416d8121d14ec6a2a94943cfa4e2fb944e215b Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 15 Sep 2021 13:15:15 +0200 Subject: [PATCH] macho: when adding extern fn, check if already resolved This way, we will generate valid relocation info in the codegen. --- src/codegen.zig | 9 ++++++--- src/link/MachO.zig | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index 511d4c2301d49aa71495ec107394ecff0e8e396b..e79003f7287d368020e9c99380bc5aa60de18114 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 ce00c85deaee882e034b74ef0238658978ca46a9..8037c5e9a03582138e98aa7c67c769804e9bb304 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); - - 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; - } - - 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); + + 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); 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 { -- 2.54.0