#![allow(non_camel_case_types)]
use nom::number;
use nom::IResult;
use serde::Serialize;
#[derive(Debug, Clone, Copy, Serialize)]
pub enum SymbolBinding {
STB_LOCAL, STB_GLOBAL, STB_WEAK, UNSPECIFIED(u8),
}
impl Into<u8> for SymbolBinding {
fn into(self) -> u8 {
match self {
Self::STB_LOCAL => 0,
Self::STB_GLOBAL => 1,
Self::STB_WEAK => 2,
Self::UNSPECIFIED(v) => v,
}
}
}
impl From<u8> for SymbolBinding {
fn from(value: u8) -> Self {
match value {
0 => Self::STB_LOCAL,
1 => Self::STB_GLOBAL,
2 => Self::STB_WEAK,
_ => Self::UNSPECIFIED(value),
}
}
}
#[derive(Debug, Clone, Copy, Serialize)]
pub enum SymbolType {
STT_NOTYPE, STT_OBJECT, STT_FUNC, STT_SECTION, STT_FILE, UNSPECIFIED(u8),
}
impl Into<u8> for SymbolType {
fn into(self) -> u8 {
match self {
Self::STT_NOTYPE => 0,
Self::STT_OBJECT => 1,
Self::STT_FUNC => 2,
Self::STT_SECTION => 3,
Self::STT_FILE => 4,
Self::UNSPECIFIED(v) => v,
}
}
}
impl From<u8> for SymbolType {
fn from(value: u8) -> Self {
match value {
0 => Self::STT_NOTYPE,
1 => Self::STT_OBJECT,
2 => Self::STT_FUNC,
3 => Self::STT_SECTION,
4 => Self::STT_FILE,
_ => Self::UNSPECIFIED(value),
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct Elf64_Sym {
pub st_name: u32,
pub st_info: u8,
pub st_other: u8,
pub st_shndx: u16,
pub st_value: u64,
pub st_size: u64,
pub symbol_type: SymbolType,
pub symbol_binding: SymbolBinding,
}
impl Into<Vec<u8>> for Elf64_Sym {
fn into(self) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend(self.st_name.to_le_bytes());
out.push(self.st_info);
out.push(self.st_other);
out.extend(self.st_shndx.to_le_bytes());
out.extend(self.st_value.to_le_bytes());
out.extend(self.st_size.to_le_bytes());
out
}
}
impl Into<Vec<u8>> for &Elf64_Sym {
fn into(self) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend(self.st_name.to_le_bytes());
out.push(self.st_info);
out.push(self.st_other);
out.extend(self.st_shndx.to_le_bytes());
out.extend(self.st_value.to_le_bytes());
out.extend(self.st_size.to_le_bytes());
out
}
}
impl Elf64_Sym {
pub fn parse(raw: &[u8]) -> IResult<&[u8], Self> {
let (remaining, st_name) = number::complete::le_u32(raw)?;
let (remaining, st_info) = number::complete::le_u8(remaining)?;
let (remaining, st_other) = number::complete::le_u8(remaining)?;
let (remaining, st_shndx) = number::complete::le_u16(remaining)?;
let (remaining, st_value) = number::complete::le_u64(remaining)?;
let (remaining, st_size) = number::complete::le_u64(remaining)?;
Ok((
remaining,
Self {
st_info,
st_name,
st_size,
st_other,
st_shndx,
st_value,
symbol_type: SymbolType::from(st_info << 4),
symbol_binding: SymbolBinding::from(st_info >> 4),
},
))
}
}
#[derive(Debug, Clone, Copy, Serialize)]
pub struct Elf64_Rel {
pub r_offset: u64,
pub r_info: u64,
}
impl Into<Vec<u8>> for Elf64_Rel {
fn into(self) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend(self.r_offset.to_le_bytes());
out.extend(self.r_info.to_le_bytes());
out
}
}
impl Into<Vec<u8>> for &Elf64_Rel {
fn into(self) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend(self.r_offset.to_le_bytes());
out.extend(self.r_info.to_le_bytes());
out
}
}
impl Elf64_Rel {
pub fn parse(raw: &[u8]) -> IResult<&[u8], Self> {
let (remaining, r_offset) = number::complete::le_u64(raw)?;
let (remaining, r_info) = number::complete::le_u64(remaining)?;
Ok((remaining, Self { r_info, r_offset }))
}
}
#[derive(Clone, Copy, Debug, Serialize)]
#[repr(u32)]
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, R_X86_64_CODE_4_GOTPCRELX = 43, R_X86_64_CODE_4_GOTTPOFF = 44, R_X86_64_CODE_4_GOTPC32_TLSDESC = 45, R_X86_64_CODE_5_GOTPCRELX = 46, R_X86_64_CODE_5_GOTTPOFF = 47, R_X86_64_CODE_5_GOTPC32_TLSDESC = 48, R_X86_64_CODE_6_GOTPCRELX = 49, R_X86_64_CODE_6_GOTTPOFF = 50, R_X86_64_CODE_6_GOTPC32_TLSDESC = 51,
UNSPECIFIED(u32),
}
impl From<u32> for RelocationType {
fn from(value: u32) -> Self {
match value {
0 => Self::R_X86_64_NONE,
1 => Self::R_X86_64_64,
2 => Self::R_X86_64_PC32,
3 => Self::R_X86_64_GOT32,
4 => Self::R_X86_64_PLT32,
5 => Self::R_X86_64_COPY,
6 => Self::R_X86_64_GLOB_DAT,
7 => Self::R_X86_64_JUMP_SLOT,
8 => Self::R_X86_64_RELATIVE,
9 => Self::R_X86_64_GOTPCREL,
10 => Self::R_X86_64_32,
11 => Self::R_X86_64_32S,
12 => Self::R_X86_64_16,
13 => Self::R_X86_64_PC16,
14 => Self::R_X86_64_8,
15 => Self::R_X86_64_PC8,
16 => Self::R_X86_64_DTPMOD64,
17 => Self::R_X86_64_DTPOFF64,
18 => Self::R_X86_64_TPOFF64,
19 => Self::R_X86_64_TLSGD,
20 => Self::R_X86_64_TLSLD,
21 => Self::R_X86_64_DTPOFF32,
22 => Self::R_X86_64_GOTTPOFF,
23 => Self::R_X86_64_TPOFF32,
24 => Self::R_X86_64_PC64,
25 => Self::R_X86_64_GOTOFF64,
26 => Self::R_X86_64_GOTPC32,
32 => Self::R_X86_64_SIZE32,
33 => Self::R_X86_64_SIZE64,
34 => Self::R_X86_64_GOTPC32_TLSDESC,
35 => Self::R_X86_64_TLSDESC_CALL,
36 => Self::R_X86_64_TLSDESC,
37 => Self::R_X86_64_IRELATIVE,
38 => Self::R_X86_64_RELATIVE64,
41 => Self::R_X86_64_GOTPCRELX,
42 => Self::R_X86_64_REX_GOTPCRELX,
43 => Self::R_X86_64_CODE_4_GOTPCRELX,
44 => Self::R_X86_64_CODE_4_GOTTPOFF,
45 => Self::R_X86_64_CODE_4_GOTPC32_TLSDESC,
46 => Self::R_X86_64_CODE_5_GOTPCRELX,
47 => Self::R_X86_64_CODE_5_GOTTPOFF,
48 => Self::R_X86_64_CODE_5_GOTPC32_TLSDESC,
49 => Self::R_X86_64_CODE_6_GOTPCRELX,
50 => Self::R_X86_64_CODE_6_GOTTPOFF,
51 => Self::R_X86_64_CODE_6_GOTPC32_TLSDESC,
_ => Self::UNSPECIFIED(value),
}
}
}
#[derive(Debug, Serialize)]
pub struct Elf64_Rela {
pub r_offset: u64,
pub r_info: u64,
pub r_addend: u64,
pub relocation_type: RelocationType,
pub symbol_index: u32,
}
impl Into<Vec<u8>> for Elf64_Rela {
fn into(self) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend(self.r_offset.to_le_bytes());
out.extend(self.r_info.to_le_bytes());
out.extend(self.r_addend.to_le_bytes());
out
}
}
impl Into<Vec<u8>> for &Elf64_Rela {
fn into(self) -> Vec<u8> {
let mut out: Vec<u8> = Vec::new();
out.extend(self.r_offset.to_le_bytes());
out.extend(self.r_info.to_le_bytes());
out.extend(self.r_addend.to_le_bytes());
out
}
}
impl Elf64_Rela {
pub fn parse(raw: &[u8]) -> IResult<&[u8], Self> {
let (remaining, r_offset) = number::complete::le_u64(raw)?;
let (remaining, r_info) = number::complete::le_u64(remaining)?;
let (remaining, r_addend) = number::complete::le_u64(remaining)?;
Ok((
remaining,
Self {
r_info,
r_offset,
r_addend,
relocation_type: ((r_info & 0xffffffff) as u32).into(),
symbol_index: (r_info >> 32) as u32,
},
))
}
}