diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index c2f7d8c436..50fa0c1ffd 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -85,14 +85,15 @@ pub fn emitMir(emit: *Emit) Error!void { @tagName(emit.lower.bin_file.tag), }), .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { + const is_obj = emit.lower.bin_file.options.effectiveOutputMode() == .Obj; const atom = elf_file.symbol(data.atom_index).atom(elf_file).?; const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index); const sym = elf_file.symbol(sym_index); - if (sym.flags.needs_zig_got and emit.lower.bin_file.options.effectiveOutputMode() != .Obj) { + if (sym.flags.needs_zig_got and !is_obj) { _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); } if (emit.lower.bin_file.options.pic) { - const r_type: u32 = if (sym.flags.needs_zig_got) + const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj) link.File.Elf.R_X86_64_ZIG_GOTPCREL else if (sym.flags.needs_got) std.elf.R_X86_64_GOTPCREL @@ -104,7 +105,7 @@ pub fn emitMir(emit: *Emit) Error!void { .r_addend = -4, }); } else { - const r_type: u32 = if (sym.flags.needs_zig_got) + const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj) link.File.Elf.R_X86_64_ZIG_GOT32 else if (sym.flags.needs_got) std.elf.R_X86_64_GOT32 diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig index fe735a3700..fb1d867384 100644 --- a/src/arch/x86_64/Lower.zig +++ b/src/arch/x86_64/Lower.zig @@ -319,6 +319,15 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { } fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { + const needsZigGot = struct { + fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool { + const elf_file = ctx.cast(link.File.Elf).?; + const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); + return elf_file.symbol(sym_index).flags.needs_zig_got; + } + }.needsZigGot; + + const is_obj = lower.bin_file.options.effectiveOutputMode() == .Obj; var emit_prefix = prefix; var emit_mnemonic = mnemonic; var emit_ops_storage: [4]Operand = undefined; @@ -334,7 +343,13 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) assert(mem_op.sib.scale_index.scale == 0); _ = lower.reloc(.{ .linker_reloc = sym }); break :op if (lower.bin_file.options.pic) switch (mnemonic) { - .mov, .lea => .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, + .lea => { + break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; + }, + .mov => { + if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; + break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; + }, else => unreachable, } else switch (mnemonic) { .call => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ @@ -344,9 +359,12 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) emit_mnemonic = .mov; break :op .{ .imm = Immediate.s(0) }; }, - .mov => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ - .base = .{ .reg = .ds }, - }) }, + .mov => { + if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; + break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ + .base = .{ .reg = .ds }, + }) }; + }, else => unreachable, }; },