mirror of
https://github.com/Noratrieb/elven-forest.git
synced 2026-01-16 19:35:02 +01:00
options!
This commit is contained in:
parent
d849e07c58
commit
e8195f32f6
3 changed files with 149 additions and 111 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
|
@ -66,9 +66,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.1.4"
|
version = "4.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
|
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
|
@ -106,6 +106,7 @@ name = "elven-forest"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"clap",
|
||||||
"elven-parser",
|
"elven-parser",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"tabled",
|
"tabled",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.69"
|
anyhow = "1.0.69"
|
||||||
|
clap = { version = "4.1.6", features = ["derive"] }
|
||||||
elven-parser = { path = "../elven-parser" }
|
elven-parser = { path = "../elven-parser" }
|
||||||
memmap2 = "0.5.8"
|
memmap2 = "0.5.8"
|
||||||
tabled = "0.10.0"
|
tabled = "0.10.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
use std::{fmt::Display, fs::File};
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
fs::File,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use clap::Parser;
|
||||||
use elven_parser::{
|
use elven_parser::{
|
||||||
consts::{self as c, DynamicTag, PhFlags, PhType, ShFlags, ShType, SymbolVisibility, RX86_64},
|
consts::{self as c, DynamicTag, PhFlags, PhType, ShFlags, ShType, SymbolVisibility, RX86_64},
|
||||||
read::{ElfReadError, ElfReader, Sym, SymInfo},
|
read::{ElfReadError, ElfReader, Sym, SymInfo},
|
||||||
|
|
@ -9,11 +14,29 @@ use elven_parser::{
|
||||||
use memmap2::Mmap;
|
use memmap2::Mmap;
|
||||||
use tabled::{object::Rows, Disable, Style, Table, Tabled};
|
use tabled::{object::Rows, Disable, Style, Table, Tabled};
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
#[derive(Parser)]
|
||||||
let objs = std::env::args().skip(1);
|
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 {
|
fn main() -> anyhow::Result<()> {
|
||||||
print_file(&obj).with_context(|| format!("Failed to print {obj}"))?;
|
let opts = Opts::parse();
|
||||||
|
|
||||||
|
for obj in &opts.files {
|
||||||
|
print_file(&opts, obj).with_context(|| format!("Failed to print {}", obj.display()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -76,142 +99,155 @@ struct DynTable {
|
||||||
value: Addr,
|
value: Addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_file(path: &str) -> anyhow::Result<()> {
|
fn print_file(opts: &Opts, path: &Path) -> anyhow::Result<()> {
|
||||||
println!("{path}");
|
println!("{}", path.display());
|
||||||
|
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
let mmap = unsafe { Mmap::map(&file) }?;
|
let mmap = unsafe { Mmap::map(&file) }?;
|
||||||
|
|
||||||
let elf = ElfReader::new(&mmap)?;
|
let elf = ElfReader::new(&mmap)?;
|
||||||
|
|
||||||
println!("\nHeader");
|
if opts.header {
|
||||||
|
println!("\nHeader");
|
||||||
|
|
||||||
let header = elf.header()?;
|
let header = elf.header()?;
|
||||||
let ident = header.ident;
|
let ident = header.ident;
|
||||||
let header_tab = vec![
|
let header_tab = vec![
|
||||||
HeaderTable("class", &ident.class),
|
HeaderTable("class", &ident.class),
|
||||||
HeaderTable("data", &ident.data),
|
HeaderTable("data", &ident.data),
|
||||||
HeaderTable("version", &ident.version),
|
HeaderTable("version", &ident.version),
|
||||||
HeaderTable("osabi", &ident.osabi),
|
HeaderTable("osabi", &ident.osabi),
|
||||||
HeaderTable("type", &header.r#type),
|
HeaderTable("type", &header.r#type),
|
||||||
HeaderTable("machine", &header.machine),
|
HeaderTable("machine", &header.machine),
|
||||||
HeaderTable("entrypoint", &header.entry),
|
HeaderTable("entrypoint", &header.entry),
|
||||||
HeaderTable("header size", &header.ehsize),
|
HeaderTable("header size", &header.ehsize),
|
||||||
HeaderTable("program header size", &header.phentsize),
|
HeaderTable("program header size", &header.phentsize),
|
||||||
HeaderTable("section header size", &header.shentsize),
|
HeaderTable("section header size", &header.shentsize),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut table = Table::new(header_tab);
|
let mut table = Table::new(header_tab);
|
||||||
// No header
|
// No header
|
||||||
table.with(Disable::row(Rows::first()));
|
table.with(Disable::row(Rows::first()));
|
||||||
print_table(table);
|
print_table(table);
|
||||||
|
}
|
||||||
|
|
||||||
println!("\nSections");
|
if opts.section_headers {
|
||||||
|
println!("\nSections");
|
||||||
|
|
||||||
let sections = elf
|
let sections = elf
|
||||||
.section_headers()?
|
.section_headers()?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|sh| {
|
.map(|sh| {
|
||||||
let name = elf.sh_string(sh.name)?.to_string();
|
let name = elf.sh_string(sh.name)?.to_string();
|
||||||
Ok(SectionTable {
|
Ok(SectionTable {
|
||||||
name,
|
name,
|
||||||
r#type: sh.r#type,
|
r#type: sh.r#type,
|
||||||
size: Addr(sh.size),
|
size: Addr(sh.size),
|
||||||
offset: sh.offset,
|
offset: sh.offset,
|
||||||
flags: sh.flags,
|
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
|
let sections = elf
|
||||||
.program_headers()?
|
.program_headers()?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ph| {
|
.map(|ph| {
|
||||||
let (inside_section, inside_section_offset) = section_name_of_offset(elf, ph.offset)?;
|
let (inside_section, inside_section_offset) =
|
||||||
|
section_name_of_offset(elf, ph.offset)?;
|
||||||
|
|
||||||
Ok(ProgramHeaderTable {
|
Ok(ProgramHeaderTable {
|
||||||
r#type: ph.r#type,
|
r#type: ph.r#type,
|
||||||
flags: ph.flags,
|
flags: ph.flags,
|
||||||
offset: ph.offset,
|
offset: ph.offset,
|
||||||
virtual_addr: ph.vaddr,
|
virtual_addr: ph.vaddr,
|
||||||
phys_addr: ph.paddr,
|
phys_addr: ph.paddr,
|
||||||
file_size: Addr(ph.filesz),
|
file_size: Addr(ph.filesz),
|
||||||
mem_size: Addr(ph.memsz),
|
mem_size: Addr(ph.memsz),
|
||||||
align: Addr(ph.align),
|
align: Addr(ph.align),
|
||||||
inside_section,
|
inside_section,
|
||||||
inside_section_offset,
|
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
|
let symbols = elf
|
||||||
.symbols()?
|
.symbols()?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|sym| {
|
.map(|sym| {
|
||||||
let name = sym_display_name(elf, sym)?;
|
let name = sym_display_name(elf, sym)?;
|
||||||
let section = match sym.shndx.0 {
|
let section = match sym.shndx.0 {
|
||||||
c::SHN_ABS | c::SHN_COMMON => String::new(),
|
c::SHN_ABS | c::SHN_COMMON => String::new(),
|
||||||
_ => elf
|
_ => elf
|
||||||
.sh_string(elf.section_header(sym.shndx)?.name)?
|
.sh_string(elf.section_header(sym.shndx)?.name)?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(SymbolTable {
|
Ok(SymbolTable {
|
||||||
name,
|
name,
|
||||||
info: sym.info,
|
info: sym.info,
|
||||||
other: sym.other,
|
other: sym.other,
|
||||||
section,
|
section,
|
||||||
size: sym.size,
|
size: sym.size,
|
||||||
value: sym.value,
|
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
|
let relas = elf
|
||||||
.relas()?
|
.relas()?
|
||||||
.map(|(sh, rela)| {
|
.map(|(sh, rela)| {
|
||||||
let section = elf.sh_string(sh.name)?.to_string();
|
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 offset = rela.offset;
|
||||||
let r#type = c::RX86_64(rela.info.r#type());
|
let r#type = c::RX86_64(rela.info.r#type());
|
||||||
let addend = rela.addend;
|
let addend = rela.addend;
|
||||||
|
|
||||||
Ok(RelaTable {
|
Ok(RelaTable {
|
||||||
section,
|
section,
|
||||||
symbol,
|
symbol,
|
||||||
offset,
|
offset,
|
||||||
r#type,
|
r#type,
|
||||||
addend,
|
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() {
|
if opts.dyns {
|
||||||
println!("\nDynamic entries");
|
if let Ok(dyns) = elf.dyn_entries() {
|
||||||
|
println!("\nDynamic entries");
|
||||||
|
|
||||||
let dyns = dyns.iter().map(|dy| DynTable {
|
let dyns = dyns.iter().map(|dy| DynTable {
|
||||||
tag: dy.tag,
|
tag: dy.tag,
|
||||||
value: Addr(dy.val),
|
value: Addr(dy.val),
|
||||||
});
|
});
|
||||||
print_table(Table::new(dyns));
|
print_table(Table::new(dyns));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue