| ... | @@ -319,6 +319,15 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { | ... | @@ -319,6 +319,15 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate { |
| 319 | } | 319 | } |
| 320 | | 320 | |
| 321 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { | 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 | var emit_prefix = prefix; | 331 | var emit_prefix = prefix; |
| 323 | var emit_mnemonic = mnemonic; | 332 | var emit_mnemonic = mnemonic; |
| 324 | var emit_ops_storage: [4]Operand = undefined; | 333 | var emit_ops_storage: [4]Operand = undefined; |
| ... | @@ -334,7 +343,13 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) | ... | @@ -334,7 +343,13 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 334 | assert(mem_op.sib.scale_index.scale == 0); | 343 | assert(mem_op.sib.scale_index.scale == 0); |
| 335 | _ = lower.reloc(.{ .linker_reloc = sym }); | 344 | _ = lower.reloc(.{ .linker_reloc = sym }); |
| 336 | break :op if (lower.bin_file.options.pic) switch (mnemonic) { | 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 | else => unreachable, | 353 | else => unreachable, |
| 339 | } else switch (mnemonic) { | 354 | } else switch (mnemonic) { |
| 340 | .call => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | 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,9 +359,12 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 344 | emit_mnemonic = .mov; | 359 | emit_mnemonic = .mov; |
| 345 | break :op .{ .imm = Immediate.s(0) }; | 360 | break :op .{ .imm = Immediate.s(0) }; |
| 346 | }, | 361 | }, |
| 347 | .mov => .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | 362 | .mov => { |
| 348 | .base = .{ .reg = .ds }, | 363 | if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea; |
| 349 | }) }, | 364 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ |
| | 365 | .base = .{ .reg = .ds }, |
| | 366 | }) }; |
| | 367 | }, |
| 350 | else => unreachable, | 368 | else => unreachable, |
| 351 | }; | 369 | }; |
| 352 | }, | 370 | }, |