use core::fmt;
#[derive(Clone, Copy, PartialEq, Default)]
pub struct Reloc {
pub r_offset: usize,
pub r_info: usize,
pub r_addend: isize,
pub r_sym: usize,
pub r_type: u32,
pub is_rela: bool
}
#[cfg(feature = "std")]
pub trait ElfReloc {
fn r_offset(&self) -> u64;
fn r_info(&self) -> u64;
fn r_addend(&self) -> i64;
fn r_sym(&self) -> usize;
fn r_type(&self) -> u32;
}
#[cfg(feature = "std")]
impl ElfReloc for Reloc {
fn r_offset(&self) -> u64 {
self.r_offset as u64
}
fn r_info(&self) -> u64 {
self.r_info as u64
}
fn r_addend(&self) -> i64 {
self.r_addend as i64
}
fn r_sym(&self) -> usize {
self.r_sym
}
fn r_type(&self) -> u32 {
self.r_type
}
}
impl fmt::Debug for Reloc {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"r_offset: {:x} {} @ {} r_addend: {:x} rela: {}",
self.r_offset,
self.r_type,
self.r_sym,
self.r_addend,
self.is_rela,
)
}
}
macro_rules! elf_reloc {
($size:ident, $isize:ty) => {
use core::convert::From;
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Default)]
#[cfg_attr(feature = "endian_fd", derive(Pread, Pwrite))]
pub struct Rela {
pub r_offset: $size,
pub r_info: $size,
pub r_addend: $isize,
}
#[repr(C)]
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(feature = "endian_fd", derive(Pread, Pwrite))]
pub struct Rel {
pub r_offset: $size,
pub r_info: $size,
}
impl From<Rela> for super::reloc::Reloc {
fn from(rela: Rela) -> Self {
Reloc {
r_offset: rela.r_offset as usize,
r_info: rela.r_info as usize,
r_addend: rela.r_addend as isize,
r_sym: r_sym(rela.r_info) as usize,
r_type: r_type(rela.r_info),
is_rela: true,
}
}
}
impl From<Rel> for super::reloc::Reloc {
fn from(rel: Rel) -> Self {
Reloc {
r_offset: rel.r_offset as usize,
r_info: rel.r_info as usize,
r_addend: 0,
r_sym: r_sym(rel.r_info) as usize,
r_type: r_type(rel.r_info),
is_rela: false,
}
}
}
impl From<super::reloc::Reloc> for Rela {
fn from(rela: super::reloc::Reloc) -> Self {
Rela {
r_offset: rela.r_offset as $size,
r_info: rela.r_info as $size,
r_addend: rela.r_addend as $isize,
}
}
}
impl From<super::reloc::Reloc> for Rel {
fn from(rel: super::reloc::Reloc) -> Self {
Rel {
r_offset: rel.r_offset as $size,
r_info: rel.r_info as $size,
}
}
}
};
}
include!("constants_relocation.rs");
#[inline]
pub fn type_to_str(typ: u32) -> &'static str {
match typ {
R_X86_64_NONE => "NONE",
R_X86_64_64 => "64",
R_X86_64_PC32 => "PC32",
R_X86_64_GOT32 => "GOT32",
R_X86_64_PLT32 => "PLT32",
R_X86_64_COPY => "COPY",
R_X86_64_GLOB_DAT => "GLOB_DAT",
R_X86_64_JUMP_SLOT => "JUMP_SLOT",
R_X86_64_RELATIVE => "RELATIVE",
R_X86_64_GOTPCREL => "GOTPCREL",
R_X86_64_32 => "32",
R_X86_64_32S => "32S",
R_X86_64_16 => "16",
R_X86_64_PC16 => "PC16",
R_X86_64_8 => "8",
R_X86_64_PC8 => "PC8",
R_X86_64_DTPMOD64 => "DTPMOD64",
R_X86_64_DTPOFF64 => "DTPOFF64",
R_X86_64_TPOFF64 => "TPOFF64",
R_X86_64_TLSGD => "TLSGD",
R_X86_64_TLSLD => "TLSLD",
R_X86_64_DTPOFF32 => "DTPOFF32",
R_X86_64_GOTTPOFF => "GOTTPOFF",
R_X86_64_TPOFF32 => "TPOFF32",
R_X86_64_PC64 => "PC64",
R_X86_64_GOTOFF64 => "GOTOFF64",
R_X86_64_GOTPC32 => "GOTPC32",
R_X86_64_GOT64 => "GOT64",
R_X86_64_GOTPCREL64 => "GOTPCREL64",
R_X86_64_GOTPC64 => "GOTPC64",
R_X86_64_GOTPLT64 => "GOTPLT64",
R_X86_64_PLTOFF64 => "PLTOFF64",
R_X86_64_SIZE32 => "SIZE32",
R_X86_64_SIZE64 => "SIZE64",
R_X86_64_GOTPC32_TLSDESC => "GOTPC32_TLSDESC",
R_X86_64_TLSDESC_CALL => "TLSDESC_CALL",
R_X86_64_TLSDESC => "TLSDESC",
R_X86_64_IRELATIVE => "IRELATIVE",
R_X86_64_RELATIVE64 => "RELATIVE64",
_ => "UNKNOWN_RELA_TYPE",
}
}
macro_rules! signed_from_unsigned {
(u32) => {i32};
(u64) => {i64}
}
macro_rules! elf_rela_impure_impl { ($size:ident) => {
#[cfg(feature = "std")]
pub use self::impure::*;
#[cfg(feature = "std")]
mod impure {
use super::*;
use core::fmt;
use core::slice;
use elf::error::*;
use scroll;
use std::fs::File;
use std::io::{Read, Seek};
use std::io::SeekFrom::Start;
impl fmt::Debug for Rela {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let sym = r_sym(self.r_info);
let typ = r_type(self.r_info);
write!(f,
"r_offset: {:x} {} @ {} r_addend: {:x}",
self.r_offset,
typ,
sym,
self.r_addend)
}
}
impl fmt::Debug for Rel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let sym = r_sym(self.r_info);
let typ = r_type(self.r_info);
write!(f,
"r_offset: {:x} {} @ {}",
self.r_offset,
typ,
sym
)
}
}
impl ElfReloc for Rela {
fn r_offset(&self) -> u64 {
self.r_offset as u64
}
fn r_info(&self) -> u64 {
self.r_info as u64
}
fn r_addend(&self) -> i64 {
self.r_addend as i64
}
fn r_sym(&self) -> usize {
r_sym(self.r_info) as usize
}
fn r_type(&self) -> u32 {
r_type(self.r_info)
}
}
impl ElfReloc for Rel {
fn r_offset(&self) -> u64 {
self.r_offset as u64
}
fn r_info(&self) -> u64 {
self.r_info as u64
}
fn r_addend(&self) -> i64 {
0
}
fn r_sym(&self) -> usize {
r_sym(self.r_info) as usize
}
fn r_type(&self) -> u32 {
r_type(self.r_info)
}
}
pub unsafe fn from_raw_rela<'a>(ptr: *const Rela, size: usize) -> &'a [Rela] {
slice::from_raw_parts(ptr, size / SIZEOF_RELA)
}
pub unsafe fn from_raw_rel<'a>(ptr: *const Rel, size: usize) -> &'a [Rel] {
slice::from_raw_parts(ptr, size / SIZEOF_REL)
}
pub fn from_fd(fd: &mut File, offset: usize, size: usize) -> Result<Vec<Rela>> {
let count = size / SIZEOF_RELA;
let mut bytes = vec![0u8; size];
fd.seek(Start(offset as u64))?;
fd.read(&mut bytes)?;
let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *mut Rela, count) };
let mut res = Vec::with_capacity(count);
res.extend_from_slice(bytes);
Ok(res)
}
#[cfg(feature = "endian_fd")]
pub fn parse<S: scroll::Gread>(fd: &S, offset: usize, size: usize, little_endian: scroll::Endian, is_rela: bool) -> Result<Vec<Reloc>> {
let sizeof_relocation = if is_rela { SIZEOF_RELA } else { SIZEOF_REL };
let count = size / sizeof_relocation;
let mut res = Vec::with_capacity(count);
let mut offset = offset;
for _ in 0..count {
let mut reloc = Reloc::default();
reloc.r_offset = fd.gread_with::<$size>(&mut offset, little_endian)? as usize;
let info = fd.gread_with::<$size>(&mut offset, little_endian)?;
reloc.r_info = info as usize;
if is_rela { reloc.r_addend = fd.gread_with::<signed_from_unsigned!($size)>(&mut offset, little_endian)? as isize; }
reloc.r_sym = r_sym(info) as usize;
reloc.r_type = r_type(info) as u32;
reloc.is_rela = is_rela;
res.push(reloc);
}
Ok(res)
}
}
};}