diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-09-15 13:15:15 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-09-15 16:51:56 +0200 |
| commit | 25416d8121d14ec6a2a94943cfa4e2fb944e215b (patch) | |
| tree | b257177adba5bf20807c6f687e96d2da91bcdf82 /src | |
| parent | 0395b35cee8d4082cc40b0dcd0298f797f42309d (diff) | |
| download | zig-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.zig | 9 | ||||
| -rw-r--r-- | src/link/MachO.zig | 33 |
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 { |
