use std::fs::File;
use std::io::Seek;
use std::io::SeekFrom::Start;
use std::io;
use std::fmt;
use std::slice;
pub const R_X86_64_NONE: u64 = 0; pub const R_X86_64_64: u64 = 1; pub const R_X86_64_PC32: u64 = 2; pub const R_X86_64_GOT32: u64 = 3; pub const R_X86_64_PLT32: u64 = 4; pub const R_X86_64_COPY: u64 = 5; pub const R_X86_64_GLOB_DAT: u64 = 6; pub const R_X86_64_JUMP_SLOT: u64 = 7; pub const R_X86_64_RELATIVE: u64 = 8; pub const R_X86_64_GOTPCREL: u64 = 9; pub const R_X86_64_32: u64 = 10; pub const R_X86_64_32S: u64 = 11; pub const R_X86_64_16: u64 = 12; pub const R_X86_64_PC16: u64 = 13; pub const R_X86_64_8: u64 = 14; pub const R_X86_64_PC8: u64 = 15; pub const R_X86_64_DTPMOD64: u64 = 16; pub const R_X86_64_DTPOFF64: u64 = 17; pub const R_X86_64_TPOFF64: u64 = 18; pub const R_X86_64_TLSGD: u64 = 19; pub const R_X86_64_TLSLD: u64 = 20; pub const R_X86_64_DTPOFF32: u64 = 21; pub const R_X86_64_GOTTPOFF: u64 = 22; pub const R_X86_64_TPOFF32: u64 = 23; pub const R_X86_64_PC64: u64 = 24; pub const R_X86_64_GOTOFF64: u64 = 25; pub const R_X86_64_GOTPC32: u64 = 26; pub const R_X86_64_GOT64: u64 = 27; pub const R_X86_64_GOTPCREL64: u64 = 28; pub const R_X86_64_GOTPC64: u64 = 29; pub const R_X86_64_GOTPLT64: u64 = 30; pub const R_X86_64_PLTOFF64: u64 = 31; pub const R_X86_64_SIZE32: u64 = 32; pub const R_X86_64_SIZE64: u64 = 33; pub const R_X86_64_GOTPC32_TLSDESC: u64 = 34; pub const R_X86_64_TLSDESC_CALL: u64 = 35; pub const R_X86_64_TLSDESC: u64 = 36; pub const R_X86_64_IRELATIVE: u64 = 37; pub const R_X86_64_RELATIVE64: u64 = 38; pub const R_X86_64_NUM: u64 = 39;
#[inline]
pub fn type_to_str(typ: u64) -> &'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",
}
}
#[repr(C)]
#[derive(Clone, PartialEq,Default)]
pub struct Rela {
pub r_offset: u64, pub r_info: u64, pub r_addend: i64, }
pub const SIZEOF_RELA: usize = 8 + 8 + 8;
#[inline(always)]
pub fn r_sym(info: u64) -> u64 {
info >> 32
}
#[inline(always)]
pub fn r_type(info: u64) -> u64 {
info & 0xffffffff
}
#[inline(always)]
pub fn r_info(sym: u64, typ: u64) -> u64 {
(sym << 32) + typ
}
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,
type_to_str(typ),
sym,
self.r_addend)
}
}
pub unsafe fn from_raw<'a>(ptr: *const Rela, size: usize) -> &'a [Rela] {
slice::from_raw_parts(ptr, size / SIZEOF_RELA)
}
#[cfg(not(feature = "no_endian_fd"))]
pub fn from_fd(fd: &mut File, offset: usize, size: usize, is_lsb: bool) -> io::Result<Vec<Rela>> {
use byteorder::{LittleEndian,BigEndian,ReadBytesExt};
let count = size / SIZEOF_RELA;
let mut res = Vec::with_capacity(count);
try!(fd.seek(Start(offset as u64)));
for _ in 0..count {
let mut rela = Rela::default();
if is_lsb {
rela.r_offset = try!(fd.read_u64::<LittleEndian>());
rela.r_info = try!(fd.read_u64::<LittleEndian>());
rela.r_addend = try!(fd.read_i64::<LittleEndian>());
} else {
rela.r_offset = try!(fd.read_u64::<BigEndian>());
rela.r_info = try!(fd.read_u64::<BigEndian>());
rela.r_addend = try!(fd.read_i64::<BigEndian>());
}
res.push(rela);
}
res.dedup();
Ok(res)
}
#[cfg(feature = "no_endian_fd")]
pub fn from_fd(fd: &mut File, offset: usize, size: usize, _: bool) -> io::Result<Vec<Rela>> {
use std::io::Read;
let count = size / SIZEOF_RELA;
let mut bytes = vec![0u8; size];
try!(fd.seek(Start(offset as u64)));
try!(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)
}