Implement Mach-O TLS access for x64 newBE
This commit is contained in:
@@ -3016,6 +3016,19 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
sink.put4(0); // offset
|
sink.put4(0); // offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Inst::MachOTlsGetAddr { ref symbol } => {
|
||||||
|
// movq gv@tlv(%rip), %rdi
|
||||||
|
sink.put1(0x48); // REX.w
|
||||||
|
sink.put1(0x8b); // MOV
|
||||||
|
sink.put1(0x3d); // ModRM byte
|
||||||
|
emit_reloc(sink, state, Reloc::MachOX86_64Tlv, symbol, -4);
|
||||||
|
sink.put4(0); // offset
|
||||||
|
|
||||||
|
// callq *(%rdi)
|
||||||
|
sink.put1(0xff);
|
||||||
|
sink.put1(0x17);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.clear_post_insn();
|
state.clear_post_insn();
|
||||||
|
|||||||
@@ -3915,6 +3915,17 @@ fn test_x64_emit() {
|
|||||||
"elf_tls_get_addr User { namespace: 0, index: 0 }",
|
"elf_tls_get_addr User { namespace: 0, index: 0 }",
|
||||||
));
|
));
|
||||||
|
|
||||||
|
insns.push((
|
||||||
|
Inst::MachOTlsGetAddr {
|
||||||
|
symbol: ExternalName::User {
|
||||||
|
namespace: 0,
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"488B3D00000000FF17",
|
||||||
|
"macho_tls_get_addr User { namespace: 0, index: 0 }",
|
||||||
|
));
|
||||||
|
|
||||||
// ========================================================
|
// ========================================================
|
||||||
// Actually run the tests!
|
// Actually run the tests!
|
||||||
let mut flag_builder = settings::builder();
|
let mut flag_builder = settings::builder();
|
||||||
|
|||||||
@@ -480,6 +480,10 @@ pub enum Inst {
|
|||||||
/// A call to the `ElfTlsGetAddr` libcall. Returns address
|
/// A call to the `ElfTlsGetAddr` libcall. Returns address
|
||||||
/// of TLS symbol in rax.
|
/// of TLS symbol in rax.
|
||||||
ElfTlsGetAddr { symbol: ExternalName },
|
ElfTlsGetAddr { symbol: ExternalName },
|
||||||
|
|
||||||
|
/// A Mach-O TLS symbol access. Returns address of the TLS
|
||||||
|
/// symbol in rax.
|
||||||
|
MachOTlsGetAddr { symbol: ExternalName },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool {
|
pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool {
|
||||||
@@ -539,7 +543,8 @@ impl Inst {
|
|||||||
| Inst::XmmLoadConst { .. }
|
| Inst::XmmLoadConst { .. }
|
||||||
| Inst::XmmMinMaxSeq { .. }
|
| Inst::XmmMinMaxSeq { .. }
|
||||||
| Inst::XmmUninitializedValue { .. }
|
| Inst::XmmUninitializedValue { .. }
|
||||||
| Inst::ElfTlsGetAddr { .. } => None,
|
| Inst::ElfTlsGetAddr { .. }
|
||||||
|
| Inst::MachOTlsGetAddr { .. } => None,
|
||||||
|
|
||||||
// These use dynamic SSE opcodes.
|
// These use dynamic SSE opcodes.
|
||||||
Inst::GprToXmm { op, .. }
|
Inst::GprToXmm { op, .. }
|
||||||
@@ -1791,6 +1796,10 @@ impl PrettyPrint for Inst {
|
|||||||
Inst::ElfTlsGetAddr { ref symbol } => {
|
Inst::ElfTlsGetAddr { ref symbol } => {
|
||||||
format!("elf_tls_get_addr {:?}", symbol)
|
format!("elf_tls_get_addr {:?}", symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Inst::MachOTlsGetAddr { ref symbol } => {
|
||||||
|
format!("macho_tls_get_addr {:?}", symbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2051,7 +2060,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
|||||||
// No registers are used.
|
// No registers are used.
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::ElfTlsGetAddr { .. } => {
|
Inst::ElfTlsGetAddr { .. } | Inst::MachOTlsGetAddr { .. } => {
|
||||||
// All caller-saves are clobbered.
|
// All caller-saves are clobbered.
|
||||||
//
|
//
|
||||||
// We use the SysV calling convention here because the
|
// We use the SysV calling convention here because the
|
||||||
@@ -2449,6 +2458,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
|||||||
| Inst::Hlt
|
| Inst::Hlt
|
||||||
| Inst::AtomicRmwSeq { .. }
|
| Inst::AtomicRmwSeq { .. }
|
||||||
| Inst::ElfTlsGetAddr { .. }
|
| Inst::ElfTlsGetAddr { .. }
|
||||||
|
| Inst::MachOTlsGetAddr { .. }
|
||||||
| Inst::Fence { .. } => {
|
| Inst::Fence { .. } => {
|
||||||
// Instruction doesn't explicitly mention any regs, so it can't have any virtual
|
// Instruction doesn't explicitly mention any regs, so it can't have any virtual
|
||||||
// regs that we'd need to remap. Hence no action required.
|
// regs that we'd need to remap. Hence no action required.
|
||||||
|
|||||||
@@ -5333,6 +5333,13 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
ctx.emit(Inst::ElfTlsGetAddr { symbol });
|
ctx.emit(Inst::ElfTlsGetAddr { symbol });
|
||||||
ctx.emit(Inst::gen_move(dst, regs::rax(), types::I64));
|
ctx.emit(Inst::gen_move(dst, regs::rax(), types::I64));
|
||||||
}
|
}
|
||||||
|
TlsModel::Macho => {
|
||||||
|
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
|
||||||
|
let (name, _, _) = ctx.symbol_value(insn).unwrap();
|
||||||
|
let symbol = name.clone();
|
||||||
|
ctx.emit(Inst::MachOTlsGetAddr { symbol });
|
||||||
|
ctx.emit(Inst::gen_move(dst, regs::rax(), types::I64));
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
todo!(
|
todo!(
|
||||||
"Unimplemented TLS model in x64 backend: {:?}",
|
"Unimplemented TLS model in x64 backend: {:?}",
|
||||||
|
|||||||
Reference in New Issue
Block a user