// #![allow(incomplete_features)] // #![feature(unsized_locals)] mod structs; use crate::structs::{ ElfHeader, ElfProgramHeader, ElfProgramType, ElfSectionHeader, ElfSectionType, ElfSymbol, }; use std::io::Read; #[repr(C)] #[derive(Debug)] struct Elf { header: &'static ElfHeader, sections: &'static [ElfSectionHeader], symbols: &'static [ElfSymbol], programs: &'static [ElfProgramHeader], shstrtab: *const u8, start: *const u8, } impl Elf { pub fn new(bytes: &[u8]) -> Elf { let header = unsafe { &*(bytes.as_ptr() as *const ElfHeader) }; assert_eq!(&header.ident.magic, b"\x7fELF"); let sections = unsafe { std::slice::from_raw_parts( bytes.as_ptr().add(header.shoff as usize) as *const ElfSectionHeader, header.shnum as usize, ) }; let shstrtab = unsafe { bytes .as_ptr() .add((§ions[header.shstrndx as usize]).offset as usize) }; let programs = unsafe { std::slice::from_raw_parts( bytes.as_ptr().add(header.phoff as usize) as *const ElfProgramHeader, header.phnum as usize, ) }; // dbg!(program); let symtab = sections .iter() .find(|&&sec| sec.r#type == ElfSectionType::SymTab) .expect("No symbol table!"); // //dbg!(§ions[symtab.link as usize]); let symstrtab = §ions[symtab.link as usize]; let symbols = unsafe { std::slice::from_raw_parts( bytes.as_ptr().add(symtab.offset as usize) as *const ElfSymbol, (symtab.size / symtab.entsize) as usize, ) }; // dbg!(symbols.len()); // .iter() // .filter(|sym| sym.shndx != 0) // .filter_map(|sym| unsafe { // std::ffi::CStr::from_ptr(std::ptr::addr_of!(symstrtab).add(sym.name as usize) as *const i8).to_str().ok() // }) // .filter(|name| name.len() > 1) // .collect(); // dbg!(symbols); // for sym in symbols { // // // dbg!(sym); // let name = unsafe { // std::ffi::CStr::from_ptr(bytes.as_ptr().add(symstrtab.offset as usize).add(sym.name as usize) as *const i8) // .to_str() // .unwrap_or("") // }; // dbg!(name); // } Elf { header, sections, symbols, programs, shstrtab, start: bytes.as_ptr(), } } } // readelf behavior here impl std::fmt::Display for Elf { fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("ELF Header:\n")?; formatter.write_fmt(format_args!("{}\n", self.header))?; formatter.write_str("Section Headers:\n")?; formatter .write_str(" [Nr] Name Type Address Offset\n")?; formatter .write_str(" Size EntSize Flags Link Info Align\n")?; for (i, section) in self.sections.iter().enumerate() { let name = unsafe { std::ffi::CStr::from_ptr(self.shstrtab.add(section.name as usize) as *const i8) .to_str() .expect("Bad section name") }; formatter.write_fmt(format_args!(" [{: >2}] {: <17.17} {}\n", i, name, section))?; } formatter.write_str("Key to Flags:\n")?; formatter.write_str( " W (write), A (alloc), X (execute), M (merge), S (strings), I (info),\n", )?; formatter.write_str( " L (link order), O (extra OS processing required), G (group), T (TLS),\n", )?; formatter.write_str(" C (compressed), x (unknown), o (OS specific), E (exclude),\n")?; formatter.write_str(" D (mbind), l (large), p (processor specific)\n\n")?; formatter.write_str("Program Headers:\n")?; formatter.write_str(" Type Offset VirtAddr PhysAddr\n")?; formatter .write_str(" FileSiz MemSiz Flags Align\n")?; for program in self.programs { formatter.write_fmt(format_args!(" {}\n", program)); if program.r#type == ElfProgramType::Interp { let interpreter = unsafe { std::ffi::CStr::from_ptr(self.start.add(program.offset as usize) as *const i8) .to_str() .expect("Bad interpreter name") }; formatter.write_fmt(format_args!( " [Requesting program interpreter: {interpreter}]\n" )); } } // printing notes is a littlec complicated // for section in self.sections.iter().filter(|&&sec| sec.r#type == ElfSectionType::Note) { // let name = unsafe { // std::ffi::CStr::from_ptr(self.shstrtab.add(section.name as usize) as *const i8) // .to_str() // .expect("Bad section name") // }; // formatter.write_fmt(format_args!("Displaying notes found in: {}\n{}\n", name, section))?; // } Ok(()) } } fn main() { let args: Vec = std::env::args().collect(); let buffer = { let mut f = std::fs::File::open(&args[1]).expect("no file found"); let metadata = std::fs::metadata(&args[1]).expect("unable to read metadata"); let mut buffer = vec![0; metadata.len() as usize]; f.read(&mut buffer).expect("buffer overflow"); buffer }; let elf = Elf::new(&buffer[..]); println!("{}", elf); // dbg!(symtab); }