use goblin::elf::Elf;
use goblin::Object;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;
pub struct ElfFile {
elf: Elf<'static>,
}
impl ElfFile {
pub fn parse(path: &Path) -> io::Result<Self> {
let mut file = File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
let buffer = Box::leak(buffer.into_boxed_slice());
match Object::parse(buffer) {
Ok(Object::Elf(elf)) => Ok(ElfFile { elf }),
_ => Err(io::Error::new(io::ErrorKind::Other, "Failed to parse ELF file")),
}
}
pub fn symbols(&self) -> Vec<String> {
self.elf.syms.iter().map(|sym| {
self.elf.strtab.get_at(sym.st_name).unwrap_or("").to_string()
}).collect()
}
pub fn resolve_got_plt(&self) -> Vec<(String, u64)> {
self.elf.dynsyms.iter().filter_map(|sym| {
self.elf.dynstrtab.get_at(sym.st_name).map(|name| {
(name.to_string(), sym.st_value)
})
}).collect()
}
pub fn find_symbol(&self, symbol: &str) -> Option<u64> {
self.elf.syms.iter().find_map(|sym| {
if let Some(name) = self.elf.strtab.get_at(sym.st_name) {
if name == symbol {
return Some(sym.st_value);
}
}
None
})
}
}