|
|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
use std::{env, fs};
|
|
|
|
|
use core::fmt;
|
|
|
|
|
use std::{char, env, fs};
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut args = env::args().skip(1);
|
|
|
|
|
@ -6,11 +7,10 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
let bytes = fs::read(path).unwrap();
|
|
|
|
|
|
|
|
|
|
let elf = Elf::parse(InputBytes::new(&bytes)).unwrap();
|
|
|
|
|
|
|
|
|
|
println!("{:?}", elf);
|
|
|
|
|
let elf = Elf::parse(&bytes).unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
struct InputBytes<'a> {
|
|
|
|
|
bytes: &'a [u8],
|
|
|
|
|
offset: usize,
|
|
|
|
|
@ -21,13 +21,26 @@ impl<'a> InputBytes<'a> {
|
|
|
|
|
Self { bytes, offset: 0 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn offset(&self) -> usize {
|
|
|
|
|
self.offset
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn advance_offset(&self, n: usize) -> usize {
|
|
|
|
|
self.bytes.len().min(self.offset + n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn advance(&mut self, n: usize) -> &mut Self {
|
|
|
|
|
self.offset = self.advance_offset(n);
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn peek(&self, n: usize) -> Option<&'a [u8]> {
|
|
|
|
|
self.bytes.get(self.offset .. (self.offset + n))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn pop(&mut self, n: usize) -> Option<&'a [u8]> {
|
|
|
|
|
let res = self.peek(n);
|
|
|
|
|
self.offset = self.bytes.len().min(self.offset + n);
|
|
|
|
|
self.advance(n);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -46,16 +59,39 @@ impl<'a> InputBytes<'a> {
|
|
|
|
|
Some(endianness.read_u64(bytes))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn pop_width(&mut self, endianness: Endianness, width: Width) -> Option<u64> {
|
|
|
|
|
fn pop_word(&mut self, endianness: Endianness, width: Width) -> Option<u64> {
|
|
|
|
|
match width {
|
|
|
|
|
Width::Bits32 => self.pop_u32(endianness).map(u64::from),
|
|
|
|
|
Width::Bits64 => self.pop_u64(endianness),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn hexdump(&self, n: usize) {
|
|
|
|
|
print!("{: <8}", "");
|
|
|
|
|
for i in 0..16 {
|
|
|
|
|
print!(" {:x}", i);
|
|
|
|
|
}
|
|
|
|
|
println!();
|
|
|
|
|
for (i, chunk) in self.bytes[.. n.min(self.bytes.len())].chunks(16).enumerate() {
|
|
|
|
|
print!("{:08x}", i * 16);
|
|
|
|
|
for b in chunk {
|
|
|
|
|
print!(" {:02x}", b);
|
|
|
|
|
}
|
|
|
|
|
print!("{: <4}", "");
|
|
|
|
|
for b in chunk {
|
|
|
|
|
let c = match char::from(*b) {
|
|
|
|
|
c if c.is_ascii_graphic() => c,
|
|
|
|
|
_ => '.',
|
|
|
|
|
};
|
|
|
|
|
print!("{}", c);
|
|
|
|
|
}
|
|
|
|
|
println!();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
struct Elf {
|
|
|
|
|
struct Elf<'a> {
|
|
|
|
|
bytes: &'a [u8],
|
|
|
|
|
width: Width,
|
|
|
|
|
endianness: Endianness,
|
|
|
|
|
header_version: u8,
|
|
|
|
|
@ -65,44 +101,48 @@ struct Elf {
|
|
|
|
|
elf_version: u32,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Elf {
|
|
|
|
|
fn parse(mut bytes: InputBytes) -> Result<Self, ElfError> {
|
|
|
|
|
let magic = bytes.pop(4).ok_or(ElfError::Invalid)?;
|
|
|
|
|
impl<'a> Elf<'a> {
|
|
|
|
|
fn parse(bytes: &'a [u8]) -> Result<Self, ElfError> {
|
|
|
|
|
let mut hdr = InputBytes::new(bytes);
|
|
|
|
|
|
|
|
|
|
hdr.hexdump(64);
|
|
|
|
|
|
|
|
|
|
let magic = hdr.pop(4).ok_or(ElfError)?;
|
|
|
|
|
if magic != &[0x7f, b'E', b'L', b'F'] {
|
|
|
|
|
return Err(ElfError::Invalid);
|
|
|
|
|
return Err(ElfError);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let width = match bytes.pop(1) {
|
|
|
|
|
let width = match hdr.pop(1) {
|
|
|
|
|
Some(&[1]) => Width::Bits32,
|
|
|
|
|
Some(&[2]) => Width::Bits64,
|
|
|
|
|
_ => return Err(ElfError::Invalid),
|
|
|
|
|
_ => return Err(ElfError),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let endianness = match bytes.pop(1) {
|
|
|
|
|
let endianness = match hdr.pop(1) {
|
|
|
|
|
Some(&[1]) => Endianness::Little,
|
|
|
|
|
Some(&[2]) => Endianness::Big,
|
|
|
|
|
_ => return Err(ElfError::Invalid),
|
|
|
|
|
_ => return Err(ElfError),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let Some(&[header_version]) = bytes.pop(1) else {
|
|
|
|
|
return Err(ElfError::Invalid)
|
|
|
|
|
let Some(&[header_version]) = hdr.pop(1) else {
|
|
|
|
|
return Err(ElfError)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let Some(&[abi]) = bytes.pop(1) else {
|
|
|
|
|
return Err(ElfError::Invalid)
|
|
|
|
|
let Some(&[abi]) = hdr.pop(1) else {
|
|
|
|
|
return Err(ElfError)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bytes.pop(8);
|
|
|
|
|
hdr.pop(8);
|
|
|
|
|
|
|
|
|
|
let ty = match bytes.pop_u16(endianness) {
|
|
|
|
|
let ty = match hdr.pop_u16(endianness) {
|
|
|
|
|
Some(1) => ElfType::Relocatable,
|
|
|
|
|
Some(2) => ElfType::Executable,
|
|
|
|
|
Some(3) => ElfType::Shared,
|
|
|
|
|
Some(4) => ElfType::Core,
|
|
|
|
|
_ => return Err(ElfError::Invalid),
|
|
|
|
|
_ => return Err(ElfError),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let instruction_set = match bytes.pop_u16(endianness) {
|
|
|
|
|
let instruction_set = match hdr.pop_u16(endianness) {
|
|
|
|
|
Some(0) => None,
|
|
|
|
|
Some(0x02) => Some(InstructionSet::Sparc),
|
|
|
|
|
Some(0x03) => Some(InstructionSet::I386),
|
|
|
|
|
@ -114,28 +154,36 @@ impl Elf {
|
|
|
|
|
Some(0x3e) => Some(InstructionSet::Amd64),
|
|
|
|
|
Some(0xb7) => Some(InstructionSet::Aarch64),
|
|
|
|
|
Some(0xf3) => Some(InstructionSet::RiscV),
|
|
|
|
|
_ => return Err(ElfError::Invalid),
|
|
|
|
|
_ => return Err(ElfError),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let elf_version = bytes.pop_u32(endianness).ok_or(ElfError::Invalid)?;
|
|
|
|
|
|
|
|
|
|
let entry_offset = bytes.pop_width(endianness, width).ok_or(ElfError::Invalid)?;
|
|
|
|
|
let program_header_table_offset = bytes.pop_width(endianness, width).ok_or(ElfError::Invalid)?;
|
|
|
|
|
let section_header_table_offset = bytes.pop_width(endianness, width).ok_or(ElfError::Invalid)?;
|
|
|
|
|
|
|
|
|
|
let flags = bytes.pop_u32(endianness).ok_or(ElfError::Invalid)?;
|
|
|
|
|
|
|
|
|
|
let header_size = bytes.pop_u16(endianness).ok_or(ElfError::Invalid)?;
|
|
|
|
|
let elf_version = hdr.pop_u32(endianness).ok_or(ElfError)?;
|
|
|
|
|
let entry_offset = hdr.pop_word(endianness, width).ok_or(ElfError)?;
|
|
|
|
|
let pht_offset = hdr.pop_word(endianness, width).ok_or(ElfError)?;
|
|
|
|
|
let sht_offset = hdr.pop_word(endianness, width).ok_or(ElfError)?;
|
|
|
|
|
let flags = hdr.pop_u32(endianness).ok_or(ElfError)?;
|
|
|
|
|
let header_size = hdr.pop_u16(endianness).ok_or(ElfError)?;
|
|
|
|
|
let pht_entry_size = hdr.pop_u16(endianness).ok_or(ElfError)?;
|
|
|
|
|
let pht_len = hdr.pop_u16(endianness).ok_or(ElfError)?;
|
|
|
|
|
let sht_entry_size = hdr.pop_u16(endianness).ok_or(ElfError)?;
|
|
|
|
|
let sht_len = hdr.pop_u16(endianness).ok_or(ElfError)?;
|
|
|
|
|
let string_table_idx = hdr.pop_u16(endianness).ok_or(ElfError)?;
|
|
|
|
|
|
|
|
|
|
dbg!(entry_offset);
|
|
|
|
|
dbg!(program_header_table_offset);
|
|
|
|
|
dbg!(section_header_table_offset);
|
|
|
|
|
dbg!(pht_offset);
|
|
|
|
|
dbg!(sht_offset);
|
|
|
|
|
dbg!(flags);
|
|
|
|
|
dbg!(header_size);
|
|
|
|
|
dbg!(pht_entry_size);
|
|
|
|
|
dbg!(pht_len);
|
|
|
|
|
dbg!(sht_entry_size);
|
|
|
|
|
dbg!(sht_len);
|
|
|
|
|
dbg!(string_table_idx);
|
|
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
|
bytes,
|
|
|
|
|
width,
|
|
|
|
|
endianness,
|
|
|
|
|
header_version,
|
|
|
|
|
@ -205,7 +253,4 @@ enum InstructionSet {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
enum ElfError {
|
|
|
|
|
Invalid,
|
|
|
|
|
Unsupported,
|
|
|
|
|
}
|
|
|
|
|
struct ElfError;
|
|
|
|
|
|