This commit is contained in:
nora 2023-02-21 12:24:53 +01:00
parent d849e07c58
commit e8195f32f6
3 changed files with 149 additions and 111 deletions

5
Cargo.lock generated
View file

@ -66,9 +66,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.1.4"
version = "4.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
dependencies = [
"bitflags",
"clap_derive",
@ -106,6 +106,7 @@ name = "elven-forest"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"elven-parser",
"memmap2",
"tabled",

View file

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.69"
clap = { version = "4.1.6", features = ["derive"] }
elven-parser = { path = "../elven-parser" }
memmap2 = "0.5.8"
tabled = "0.10.0"

View file

@ -1,6 +1,11 @@
use std::{fmt::Display, fs::File};
use std::{
fmt::Display,
fs::File,
path::{Path, PathBuf},
};
use anyhow::Context;
use clap::Parser;
use elven_parser::{
consts::{self as c, DynamicTag, PhFlags, PhType, ShFlags, ShType, SymbolVisibility, RX86_64},
read::{ElfReadError, ElfReader, Sym, SymInfo},
@ -9,11 +14,29 @@ use elven_parser::{
use memmap2::Mmap;
use tabled::{object::Rows, Disable, Style, Table, Tabled};
fn main() -> anyhow::Result<()> {
let objs = std::env::args().skip(1);
#[derive(Parser)]
struct Opts {
#[arg(long("file-header"), long("header"))]
header: bool,
#[arg(short('l'), long("program-headers"), long("segments"))]
program_headers: bool,
#[arg(short('S'), long("section-headers"), long("sections"))]
section_headers: bool,
#[arg(short('s'), long("symbols"), long("syms"))]
symbols: bool,
#[arg(short('r'), long("relocs"))]
relocs: bool,
/// Not in readelf.
#[arg(short('d'), long("dyns"))]
dyns: bool,
files: Vec<PathBuf>,
}
for obj in objs {
print_file(&obj).with_context(|| format!("Failed to print {obj}"))?;
fn main() -> anyhow::Result<()> {
let opts = Opts::parse();
for obj in &opts.files {
print_file(&opts, obj).with_context(|| format!("Failed to print {}", obj.display()))?;
}
Ok(())
@ -76,142 +99,155 @@ struct DynTable {
value: Addr,
}
fn print_file(path: &str) -> anyhow::Result<()> {
println!("{path}");
fn print_file(opts: &Opts, path: &Path) -> anyhow::Result<()> {
println!("{}", path.display());
let file = File::open(path)?;
let mmap = unsafe { Mmap::map(&file) }?;
let elf = ElfReader::new(&mmap)?;
println!("\nHeader");
if opts.header {
println!("\nHeader");
let header = elf.header()?;
let ident = header.ident;
let header_tab = vec![
HeaderTable("class", &ident.class),
HeaderTable("data", &ident.data),
HeaderTable("version", &ident.version),
HeaderTable("osabi", &ident.osabi),
HeaderTable("type", &header.r#type),
HeaderTable("machine", &header.machine),
HeaderTable("entrypoint", &header.entry),
HeaderTable("header size", &header.ehsize),
HeaderTable("program header size", &header.phentsize),
HeaderTable("section header size", &header.shentsize),
];
let header = elf.header()?;
let ident = header.ident;
let header_tab = vec![
HeaderTable("class", &ident.class),
HeaderTable("data", &ident.data),
HeaderTable("version", &ident.version),
HeaderTable("osabi", &ident.osabi),
HeaderTable("type", &header.r#type),
HeaderTable("machine", &header.machine),
HeaderTable("entrypoint", &header.entry),
HeaderTable("header size", &header.ehsize),
HeaderTable("program header size", &header.phentsize),
HeaderTable("section header size", &header.shentsize),
];
let mut table = Table::new(header_tab);
// No header
table.with(Disable::row(Rows::first()));
print_table(table);
let mut table = Table::new(header_tab);
// No header
table.with(Disable::row(Rows::first()));
print_table(table);
}
println!("\nSections");
if opts.section_headers {
println!("\nSections");
let sections = elf
.section_headers()?
.iter()
.map(|sh| {
let name = elf.sh_string(sh.name)?.to_string();
Ok(SectionTable {
name,
r#type: sh.r#type,
size: Addr(sh.size),
offset: sh.offset,
flags: sh.flags,
let sections = elf
.section_headers()?
.iter()
.map(|sh| {
let name = elf.sh_string(sh.name)?.to_string();
Ok(SectionTable {
name,
r#type: sh.r#type,
size: Addr(sh.size),
offset: sh.offset,
flags: sh.flags,
})
})
})
.collect::<Result<Vec<_>, ElfReadError>>()?;
.collect::<Result<Vec<_>, ElfReadError>>()?;
print_table(Table::new(sections));
print_table(Table::new(sections));
}
println!("\nProgram headers");
if opts.program_headers {
println!("\nProgram headers");
let sections = elf
.program_headers()?
.iter()
.map(|ph| {
let (inside_section, inside_section_offset) = section_name_of_offset(elf, ph.offset)?;
let sections = elf
.program_headers()?
.iter()
.map(|ph| {
let (inside_section, inside_section_offset) =
section_name_of_offset(elf, ph.offset)?;
Ok(ProgramHeaderTable {
r#type: ph.r#type,
flags: ph.flags,
offset: ph.offset,
virtual_addr: ph.vaddr,
phys_addr: ph.paddr,
file_size: Addr(ph.filesz),
mem_size: Addr(ph.memsz),
align: Addr(ph.align),
inside_section,
inside_section_offset,
Ok(ProgramHeaderTable {
r#type: ph.r#type,
flags: ph.flags,
offset: ph.offset,
virtual_addr: ph.vaddr,
phys_addr: ph.paddr,
file_size: Addr(ph.filesz),
mem_size: Addr(ph.memsz),
align: Addr(ph.align),
inside_section,
inside_section_offset,
})
})
})
.collect::<Result<Vec<_>, ElfReadError>>()?;
.collect::<Result<Vec<_>, ElfReadError>>()?;
print_table(Table::new(sections));
print_table(Table::new(sections));
}
println!("\nSymbols");
if opts.symbols {
println!("\nSymbols");
let symbols = elf
.symbols()?
.iter()
.map(|sym| {
let name = sym_display_name(elf, sym)?;
let section = match sym.shndx.0 {
c::SHN_ABS | c::SHN_COMMON => String::new(),
_ => elf
.sh_string(elf.section_header(sym.shndx)?.name)?
.to_string(),
};
let symbols = elf
.symbols()?
.iter()
.map(|sym| {
let name = sym_display_name(elf, sym)?;
let section = match sym.shndx.0 {
c::SHN_ABS | c::SHN_COMMON => String::new(),
_ => elf
.sh_string(elf.section_header(sym.shndx)?.name)?
.to_string(),
};
Ok(SymbolTable {
name,
info: sym.info,
other: sym.other,
section,
size: sym.size,
value: sym.value,
Ok(SymbolTable {
name,
info: sym.info,
other: sym.other,
section,
size: sym.size,
value: sym.value,
})
})
})
.collect::<Result<Vec<_>, ElfReadError>>()?;
.collect::<Result<Vec<_>, ElfReadError>>()?;
print_table(Table::new(symbols));
print_table(Table::new(symbols));
}
println!("\nRelocations");
if opts.relocs {
println!("\nRelocations");
let relas = elf
.relas()?
.map(|(sh, rela)| {
let section = elf.sh_string(sh.name)?.to_string();
let relas = elf
.relas()?
.map(|(sh, rela)| {
let section = elf.sh_string(sh.name)?.to_string();
let sym = elf.symbol(rela.info.sym())?;
let sym = elf.symbol(rela.info.sym())?;
let symbol = sym_display_name(elf, sym)?;
let symbol = sym_display_name(elf, sym)?;
let offset = rela.offset;
let r#type = c::RX86_64(rela.info.r#type());
let addend = rela.addend;
let offset = rela.offset;
let r#type = c::RX86_64(rela.info.r#type());
let addend = rela.addend;
Ok(RelaTable {
section,
symbol,
offset,
r#type,
addend,
Ok(RelaTable {
section,
symbol,
offset,
r#type,
addend,
})
})
})
.collect::<Result<Vec<_>, ElfReadError>>()?;
.collect::<Result<Vec<_>, ElfReadError>>()?;
print_table(Table::new(relas));
print_table(Table::new(relas));
}
if let Ok(dyns) = elf.dyn_entries() {
println!("\nDynamic entries");
if opts.dyns {
if let Ok(dyns) = elf.dyn_entries() {
println!("\nDynamic entries");
let dyns = dyns.iter().map(|dy| DynTable {
tag: dy.tag,
value: Addr(dy.val),
});
print_table(Table::new(dyns));
let dyns = dyns.iter().map(|dy| DynTable {
tag: dy.tag,
value: Addr(dy.val),
});
print_table(Table::new(dyns));
}
}
println!();