use std::io::{Read, Write};
use {Error, Header, SectionContent};
use types;
use num_traits::{FromPrimitive, ToPrimitive};
#[allow(non_camel_case_types)]
#[derive(Debug, Primitive, PartialEq, Clone)]
pub enum RelocationType {
R_X86_64_NONE = 0, R_X86_64_64 = 1, R_X86_64_PC32 = 2, R_X86_64_GOT32 = 3, R_X86_64_PLT32 = 4, R_X86_64_COPY = 5, R_X86_64_GLOB_DAT = 6, R_X86_64_JUMP_SLOT = 7, R_X86_64_RELATIVE = 8, R_X86_64_GOTPCREL = 9, R_X86_64_32 = 10, R_X86_64_32S = 11, R_X86_64_16 = 12, R_X86_64_PC16 = 13, R_X86_64_8 = 14, R_X86_64_PC8 = 15,
R_X86_64_DTPMOD64 = 16,
R_X86_64_DTPOFF64 = 17,
R_X86_64_TPOFF64 = 18,
R_X86_64_TLSGD = 19,
R_X86_64_TLSLD = 20,
R_X86_64_DTPOFF32 = 21,
R_X86_64_GOTTPOFF = 22,
R_X86_64_TPOFF32 = 23,
R_X86_64_PC64 = 24, R_X86_64_GOTOFF64 = 25, R_X86_64_GOTPC32 = 26, R_X86_64_SIZE32 = 32, R_X86_64_SIZE64 = 33, R_X86_64_GOTPC32_TLSDESC = 34, R_X86_64_TLSDESC_CALL = 35, R_X86_64_TLSDESC = 36, R_X86_64_IRELATIVE = 37, R_X86_64_RELATIVE64 = 38,
R_X86_64_GOTPCRELX = 41, R_X86_64_REX_GOTPCRELX = 42, }
impl Default for RelocationType {
fn default() -> Self {
RelocationType::R_X86_64_NONE
}
}
#[derive(Default, Debug, Clone)]
pub struct Relocation {
pub addr: u64,
pub sym: u32,
pub rtype: RelocationType,
pub addend: i64,
}
impl Relocation {
pub fn entsize(eh: &Header) -> usize {
match eh.machine {
types::Machine::X86_64 => 3 * 8,
_ => panic!("relocs for machine '{:?}' not implemented", eh.machine),
}
}
pub fn from_reader<R>(
mut io: R,
_: Option<&SectionContent>,
eh: &Header,
) -> Result<SectionContent, Error>
where
R: Read,
{
if eh.machine != types::Machine::X86_64 {
return Err(Error::UnsupportedMachineTypeForRelocation(
eh.machine.clone(),
));
}
let mut r = Vec::new();
while let Ok(addr) = elf_read_u64!(eh, io) {
let info = match elf_read_u64!(eh, io) {
Ok(v) => v,
_ => break,
};
let sym = (info >> 32) as u32;
let rtype = (info & 0xffffffff) as u32;
let rtype = match RelocationType::from_u32(rtype) {
Some(v) => v,
None => {
println!(
"warning: unknown relocation type {} skipped while reading",
rtype
);
elf_read_u64!(eh, io)?;
continue;
}
};
let addend = elf_read_u64!(eh, io)?;
r.push(Relocation {
addr: addr,
sym: sym,
rtype: rtype,
addend: addend as i64,
});
}
Ok(SectionContent::Relocations(r))
}
pub fn to_writer<W>(
&self,
mut io: W,
eh: &Header,
) -> Result<(usize), Error>
where
W: Write,
{
elf_write_u64!(eh, io, self.addr)?;
let info = (self.sym.to_u64().unwrap() << 32) + self.rtype.to_u64().unwrap();
elf_write_u64!(eh, io, info)?;
elf_write_u64!(eh, io, self.addend as u64)?;
Ok(8+8+8)
}
}