diff --git a/lib/compiler-llvm/src/object_file.rs b/lib/compiler-llvm/src/object_file.rs index 889ce8bcf1c..2807c36338e 100644 --- a/lib/compiler-llvm/src/object_file.rs +++ b/lib/compiler-llvm/src/object_file.rs @@ -172,6 +172,26 @@ where (object::Architecture::Aarch64, object::RelocationKind::PltRelative, 26) => { RelocationKind::Arm64Call } + ( + object::Architecture::Aarch64, + object::RelocationKind::Elf(object::elf::R_AARCH64_MOVW_UABS_G0_NC), + 0, + ) => RelocationKind::Arm64Movw0, + ( + object::Architecture::Aarch64, + object::RelocationKind::Elf(object::elf::R_AARCH64_MOVW_UABS_G1_NC), + 0, + ) => RelocationKind::Arm64Movw1, + ( + object::Architecture::Aarch64, + object::RelocationKind::Elf(object::elf::R_AARCH64_MOVW_UABS_G2_NC), + 0, + ) => RelocationKind::Arm64Movw2, + ( + object::Architecture::Aarch64, + object::RelocationKind::Elf(object::elf::R_AARCH64_MOVW_UABS_G3), + 0, + ) => RelocationKind::Arm64Movw3, _ => { return Err(CompileError::Codegen(format!( "unknown relocation {:?}", diff --git a/lib/compiler/src/engine/universal/link.rs b/lib/compiler/src/engine/universal/link.rs index 713908a22fc..153d581b446 100644 --- a/lib/compiler/src/engine/universal/link.rs +++ b/lib/compiler/src/engine/universal/link.rs @@ -69,6 +69,30 @@ fn apply_relocation( | (read_unaligned(reloc_address as *mut u32) & 0xfc00_0000); write_unaligned(reloc_address as *mut u32, reloc_delta); }, + RelocationKind::Arm64Movw0 => unsafe { + let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64); + let reloc_delta = + (((reloc_delta & 0xffff) as u32) << 5) | read_unaligned(reloc_address as *mut u32); + write_unaligned(reloc_address as *mut u32, reloc_delta); + }, + RelocationKind::Arm64Movw1 => unsafe { + let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64); + let reloc_delta = ((((reloc_delta >> 16) & 0xffff) as u32) << 5) + | read_unaligned(reloc_address as *mut u32); + write_unaligned(reloc_address as *mut u32, reloc_delta); + }, + RelocationKind::Arm64Movw2 => unsafe { + let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64); + let reloc_delta = ((((reloc_delta >> 32) & 0xffff) as u32) << 5) + | read_unaligned(reloc_address as *mut u32); + write_unaligned(reloc_address as *mut u32, reloc_delta); + }, + RelocationKind::Arm64Movw3 => unsafe { + let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64); + let reloc_delta = ((((reloc_delta >> 48) & 0xffff) as u32) << 5) + | read_unaligned(reloc_address as *mut u32); + write_unaligned(reloc_address as *mut u32, reloc_delta); + }, kind => panic!( "Relocation kind unsupported in the current architecture {}", kind diff --git a/lib/types/src/compilation/relocation.rs b/lib/types/src/compilation/relocation.rs index 6286e455727..1b6653e8685 100644 --- a/lib/types/src/compilation/relocation.rs +++ b/lib/types/src/compilation/relocation.rs @@ -41,6 +41,14 @@ pub enum RelocationKind { Arm32Call, /// Arm64 call target Arm64Call, + /// Arm64 movk/z part 0 + Arm64Movw0, + /// Arm64 movk/z part 1 + Arm64Movw1, + /// Arm64 movk/z part 2 + Arm64Movw2, + /// Arm64 movk/z part 3 + Arm64Movw3, // /// RISC-V call target // RiscvCall, /// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol. @@ -62,6 +70,10 @@ impl fmt::Display for RelocationKind { Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"), Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"), Self::Arm32Call | Self::Arm64Call => write!(f, "Call"), + Self::Arm64Movw0 => write!(f, "Arm64MovwG0"), + Self::Arm64Movw1 => write!(f, "Arm64MovwG1"), + Self::Arm64Movw2 => write!(f, "Arm64MovwG2"), + Self::Arm64Movw3 => write!(f, "Arm64MovwG3"), Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"), // Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"), } @@ -101,7 +113,11 @@ impl Relocation { /// The function returns the relocation address and the delta. pub fn for_address(&self, start: usize, target_func_address: u64) -> (usize, u64) { match self.kind { - RelocationKind::Abs8 => { + RelocationKind::Abs8 + | RelocationKind::Arm64Movw0 + | RelocationKind::Arm64Movw1 + | RelocationKind::Arm64Movw2 + | RelocationKind::Arm64Movw3 => { let reloc_address = start + self.offset as usize; let reloc_addend = self.addend as isize; let reloc_abs = target_func_address