From bb0515bf11e2e197cefb307eed55e3db5ca04355 Mon Sep 17 00:00:00 2001 From: Mrmaxmeier Date: Mon, 20 Nov 2023 15:19:43 +0000 Subject: [PATCH] cranelift-jit: implement GOT relocations for aarch64 --- cranelift/codegen/src/binemit/mod.rs | 2 +- cranelift/jit/src/compiled_blob.rs | 29 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs index 9eed2905c4cd..14509736e8b7 100644 --- a/cranelift/codegen/src/binemit/mod.rs +++ b/cranelift/codegen/src/binemit/mod.rs @@ -81,7 +81,7 @@ pub enum Reloc { Aarch64TlsDescCall, /// AArch64 GOT Page - /// Set the immediate value of an ADRP to bits 32:12 of X; check that –232 <= X < 232 + /// Set the immediate value of an ADRP to bits 32:12 of X; check that –2^32 <= X < 2^32 /// This is equivalent to `R_AARCH64_ADR_GOT_PAGE` (311) in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#static-aarch64-relocations) Aarch64AdrGotPage21, diff --git a/cranelift/jit/src/compiled_blob.rs b/cranelift/jit/src/compiled_blob.rs index f4f134023ea2..904cb79ae6a4 100644 --- a/cranelift/jit/src/compiled_blob.rs +++ b/cranelift/jit/src/compiled_blob.rs @@ -93,6 +93,35 @@ impl CompiledBlob { let imm26 = (diff as u32) << chop >> chop; unsafe { modify_inst32(iptr, |inst| inst | imm26) }; } + Reloc::Aarch64AdrGotPage21 => { + // Set the immediate value of an ADRP to bits [32:12] of X; check that –2^32 <= X < 2^32 + assert_eq!(addend, 0, "addend affects the address looked up in get_got_entry, which is currently only called with a symbol"); + let what = get_got_entry(name); + let what_page = (what as usize) & !0xfff; + let at_page = (at as usize) & !0xfff; + let pcrel = (what_page as isize).checked_sub(at_page as isize).unwrap(); + assert!( + (-1 << 32) <= pcrel && pcrel < (1 << 32), + "can't reach GOT page with ±4GB `adrp` instruction" + ); + let val = pcrel >> 12; + + let immlo = ((val as u32) & 0b11) << 29; + let immhi = (((val as u32) >> 2) & &0x7ffff) << 5; + let mask = !((0x7ffff << 5) | (0b11 << 29)); + unsafe { modify_inst32(at as *mut u32, |adrp| (adrp & mask) | immlo | immhi) }; + } + Reloc::Aarch64Ld64GotLo12Nc => { + // Set the LD/ST immediate field to bits 11:3 of X. No overflow check; check that X&7 = 0 + assert_eq!(addend, 0); + let base = get_got_entry(name); + let what = base as u32; + assert_eq!(what & 0b111, 0); + let val = what >> 3; + let imm9 = (val & 0x1ff) << 10; + let mask = !(0x1ff << 10); + unsafe { modify_inst32(at as *mut u32, |ldr| (ldr & mask) | imm9) }; + } Reloc::RiscvCallPlt => { // A R_RISCV_CALL_PLT relocation expects auipc+jalr instruction pair. // It is the equivalent of two relocations: