| ... | ... | @@ -319,6 +319,15 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { |
| 322 | const needsZigGot = struct { |
| 323 | fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool { |
| 324 | const elf_file = ctx.cast(link.File.Elf).?; |
| 325 | const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index); |
| 326 | return elf_file.symbol(sym_index).flags.needs_zig_got; |
| 327 | } |
| 328 | }.needsZigGot; |
| 329 | |
| 330 | const is_obj = lower.bin_file.options.effectiveOutputMode() == .Obj; |
| 322 | 331 | var emit_prefix = prefix; |
| 323 | 332 | var emit_mnemonic = mnemonic; |
| 324 | 333 | var emit_ops_storage: [4]Operand = undefined; |
| ... | ... | @@ -334,7 +343,13 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 334 | 343 | assert(mem_op.sib.scale_index.scale == 0); |
| 335 | 344 | _ = lower.reloc(.{ .linker_reloc = sym }); |
| 336 | 345 | break :op if (lower.bin_file.options.pic) switch (mnemonic) { |
| 337 | | .mov, .lea => .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, |
| 346 | .lea => { |
| 347 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; |
| 348 | }, |
| 349 | .mov => { |
| 350 | if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; |
| 351 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; |
| 352 | }, |
| 338 | 353 | else => unreachable, |
| 339 | 354 | } else switch (mnemonic) { |
| 340 | 355 | .call => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ |
| ... | ... | @@ -344,9 +359,12 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 344 | 359 | emit_mnemonic = .mov; |
| 345 | 360 | break :op .{ .imm = Immediate.s(0) }; |
| 346 | 361 | }, |
| 347 | | .mov => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ |
| 348 | | .base = .{ .reg = .ds }, |
| 349 | | }) }, |
| 362 | .mov => { |
| 363 | if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; |
| 364 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ |
| 365 | .base = .{ .reg = .ds }, |
| 366 | }) }; |
| 367 | }, |
| 350 | 368 | else => unreachable, |
| 351 | 369 | }; |
| 352 | 370 | }, |