From ec9b6856e84ec84a8ef91fbd64df792ab7c267e0 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 3 May 2021 16:29:42 +0200 Subject: [PATCH] Object file support for s390x Add support for s390x binary format object files. In particular, add support for s390x ELF relocation types (currently only S390xPCRel32Dbl). --- cranelift/codegen/src/binemit/mod.rs | 3 +++ cranelift/jit/src/compiled_blob.rs | 9 +++++++++ cranelift/src/disasm.rs | 5 +++++ crates/debug/src/lib.rs | 1 + crates/jit/src/link.rs | 13 +++++++++++++ crates/obj/src/builder.rs | 2 ++ crates/profiling/src/jitdump_linux.rs | 1 + 7 files changed, 34 insertions(+) diff --git a/cranelift/codegen/src/binemit/mod.rs b/cranelift/codegen/src/binemit/mod.rs index b534ec97653d..aa3102797e42 100644 --- a/cranelift/codegen/src/binemit/mod.rs +++ b/cranelift/codegen/src/binemit/mod.rs @@ -60,6 +60,8 @@ pub enum Reloc { Arm64Call, /// RISC-V call target RiscvCall, + /// s390x PC-relative 4-byte offset + S390xPCRel32Dbl, /// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol. ElfX86_64TlsGd, @@ -75,6 +77,7 @@ impl fmt::Display for Reloc { match *self { Self::Abs4 => write!(f, "Abs4"), Self::Abs8 => write!(f, "Abs8"), + Self::S390xPCRel32Dbl => write!(f, "PCRel32Dbl"), Self::X86PCRel4 => write!(f, "PCRel4"), Self::X86PCRelRodata4 => write!(f, "PCRelRodata4"), Self::X86CallPCRel4 => write!(f, "CallPCRel4"), diff --git a/cranelift/jit/src/compiled_blob.rs b/cranelift/jit/src/compiled_blob.rs index d44497ae9ee6..f00165dbab72 100644 --- a/cranelift/jit/src/compiled_blob.rs +++ b/cranelift/jit/src/compiled_blob.rs @@ -72,6 +72,15 @@ impl CompiledBlob { write_unaligned(at as *mut i32, pcrel) }; } + Reloc::S390xPCRel32Dbl => { + let base = get_address(name); + let what = unsafe { base.offset(isize::try_from(addend).unwrap()) }; + let pcrel = i32::try_from(((what as isize) - (at as isize)) >> 1).unwrap(); + #[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_ptr_alignment))] + unsafe { + write_unaligned(at as *mut i32, pcrel) + }; + } _ => unimplemented!(), } } diff --git a/cranelift/src/disasm.rs b/cranelift/src/disasm.rs index a98e867380be..35a581d3445a 100644 --- a/cranelift/src/disasm.rs +++ b/cranelift/src/disasm.rs @@ -153,6 +153,11 @@ cfg_if! { cs.set_skipdata(true).map_err(map_caperr)?; cs } + Architecture::S390x {..} => Capstone::new() + .sysz() + .mode(arch::sysz::ArchMode::Default) + .build() + .map_err(map_caperr)?, _ => anyhow::bail!("Unknown ISA"), }; diff --git a/crates/debug/src/lib.rs b/crates/debug/src/lib.rs index b438051b4572..b6d6830d51be 100644 --- a/crates/debug/src/lib.rs +++ b/crates/debug/src/lib.rs @@ -120,6 +120,7 @@ fn ensure_supported_elf_format(bytes: &mut Vec) -> Result match header.e_machine.get(e) { EM_X86_64 => (), + EM_S390 => (), machine => { bail!("Unsupported ELF target machine: {:x}", machine); } diff --git a/crates/jit/src/link.rs b/crates/jit/src/link.rs index 9c58a138a5bb..fffd9ecca805 100644 --- a/crates/jit/src/link.rs +++ b/crates/jit/src/link.rs @@ -111,6 +111,19 @@ fn apply_reloc( ); write_unaligned(reloc_address as *mut u32, reloc_delta_u64 as u32); }, + #[cfg(target_pointer_width = "64")] + (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => unsafe { + let reloc_address = body.add(offset as usize) as usize; + let reloc_addend = r.addend() as isize; + let reloc_delta_u64 = (target_func_address as u64) + .wrapping_sub(reloc_address as u64) + .wrapping_add(reloc_addend as u64); + assert!( + (reloc_delta_u64 as isize) >> 1 <= i32::max_value() as isize, + "relocation too large to fit in i32" + ); + write_unaligned(reloc_address as *mut u32, (reloc_delta_u64 >> 1) as u32); + }, (RelocationKind::Elf(elf::R_AARCH64_CALL26), RelocationEncoding::Generic, 32) => unsafe { let reloc_address = body.add(offset as usize) as usize; let reloc_addend = r.addend() as isize; diff --git a/crates/obj/src/builder.rs b/crates/obj/src/builder.rs index 805adbb806e9..f606d720784d 100644 --- a/crates/obj/src/builder.rs +++ b/crates/obj/src/builder.rs @@ -80,6 +80,7 @@ fn to_object_relocations<'a>( RelocationEncoding::Generic, 32, ), + Reloc::S390xPCRel32Dbl => (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32), other => unimplemented!("Unimplemented relocation {:?}", other), }; Some(ObjectRelocation { @@ -102,6 +103,7 @@ fn to_object_architecture( X86_64 => Architecture::X86_64, Arm(_) => Architecture::Arm, Aarch64(_) => Architecture::Aarch64, + S390x => Architecture::S390x, architecture => { anyhow::bail!("target architecture {:?} is unsupported", architecture,); } diff --git a/crates/profiling/src/jitdump_linux.rs b/crates/profiling/src/jitdump_linux.rs index 0f3a4bb00d48..b43e8155afa5 100644 --- a/crates/profiling/src/jitdump_linux.rs +++ b/crates/profiling/src/jitdump_linux.rs @@ -241,6 +241,7 @@ impl State { Architecture::X86_32(_) => elf::EM_386 as u32, Architecture::Arm(_) => elf::EM_ARM as u32, Architecture::Aarch64(_) => elf::EM_AARCH64 as u32, + Architecture::S390x => elf::EM_S390 as u32, _ => unimplemented!("unrecognized architecture"), } }