Object file support for s390x (#2872)

Add support for s390x binary format object files.  In particular,
add support for s390x ELF relocation types (currently only
S390xPCRel32Dbl).
This commit is contained in:
Ulrich Weigand
2021-05-03 18:50:00 +02:00
committed by GitHub
parent 7a3791f9e9
commit e1cc1a67d5
7 changed files with 34 additions and 0 deletions

View File

@@ -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"),

View File

@@ -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!(),
}
}

View File

@@ -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"),
};

View File

@@ -120,6 +120,7 @@ fn ensure_supported_elf_format(bytes: &mut Vec<u8>) -> Result<Endianness, Error>
match header.e_machine.get(e) {
EM_X86_64 => (),
EM_S390 => (),
machine => {
bail!("Unsupported ELF target machine: {:x}", machine);
}

View File

@@ -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;

View File

@@ -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,);
}

View File

@@ -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"),
}
}