x64: support PC-rel symbol references using the GOT when in PIC mode.
This commit is contained in:
@@ -2690,16 +2690,41 @@ pub(crate) fn emit(
|
||||
}
|
||||
|
||||
Inst::LoadExtName { dst, name, offset } => {
|
||||
// The full address can be encoded in the register, with a relocation.
|
||||
// Generates: movabsq $name, %dst
|
||||
let enc_dst = int_reg_enc(dst.to_reg());
|
||||
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
||||
sink.put1(0xB8 | (enc_dst & 7));
|
||||
emit_reloc(sink, state, Reloc::Abs8, name, *offset);
|
||||
if info.flags().emit_all_ones_funcaddrs() {
|
||||
sink.put8(u64::max_value());
|
||||
if info.flags().is_pic() {
|
||||
// Generates: movq symbol@GOTPCREL(%rip), %dst
|
||||
let enc_dst = int_reg_enc(dst.to_reg());
|
||||
sink.put1(0x48 | ((enc_dst >> 3) & 1) << 2);
|
||||
sink.put1(0x8B);
|
||||
sink.put1(0x05 | ((enc_dst & 7) << 3));
|
||||
emit_reloc(sink, state, Reloc::X86GOTPCRel4, name, -4);
|
||||
sink.put4(0);
|
||||
// Offset in the relocation above applies to the address of the *GOT entry*, not
|
||||
// the loaded address; so we emit a separate add or sub instruction if needed.
|
||||
if *offset < 0 {
|
||||
assert!(*offset >= -i32::MAX as i64);
|
||||
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
||||
sink.put1(0x81);
|
||||
sink.put1(0xe8 | (enc_dst & 7));
|
||||
sink.put4((-*offset) as u32);
|
||||
} else if *offset > 0 {
|
||||
assert!(*offset <= i32::MAX as i64);
|
||||
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
||||
sink.put1(0x81);
|
||||
sink.put1(0xc0 | (enc_dst & 7));
|
||||
sink.put4(*offset as u32);
|
||||
}
|
||||
} else {
|
||||
sink.put8(0);
|
||||
// The full address can be encoded in the register, with a relocation.
|
||||
// Generates: movabsq $name, %dst
|
||||
let enc_dst = int_reg_enc(dst.to_reg());
|
||||
sink.put1(0x48 | ((enc_dst >> 3) & 1));
|
||||
sink.put1(0xB8 | (enc_dst & 7));
|
||||
emit_reloc(sink, state, Reloc::Abs8, name, *offset);
|
||||
if info.flags().emit_all_ones_funcaddrs() {
|
||||
sink.put8(u64::max_value());
|
||||
} else {
|
||||
sink.put8(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user