diff --git a/elven-forest/src/main.rs b/elven-forest/src/main.rs index a64cf01..64604ab 100644 --- a/elven-forest/src/main.rs +++ b/elven-forest/src/main.rs @@ -1,3 +1,5 @@ +mod size; + use std::{ fmt::Display, fs::File, @@ -29,6 +31,8 @@ struct Opts { /// Not in readelf. #[arg(short('d'), long("dyns"))] dyns: bool, + #[arg(long("text-bloat"))] + text_bloat: bool, files: Vec, } @@ -252,6 +256,10 @@ fn print_file(opts: &Opts, path: &Path) -> anyhow::Result<()> { } } + if opts.text_bloat { + size::analyze_text_bloat(elf)?; + } + println!(); Ok(()) diff --git a/elven-forest/src/size.rs b/elven-forest/src/size.rs new file mode 100644 index 0000000..0943144 --- /dev/null +++ b/elven-forest/src/size.rs @@ -0,0 +1,42 @@ +use anyhow::{Context, Result}; +use elven_parser::read::ElfReader; + +pub fn analyze_text_bloat(elf: ElfReader<'_>) -> Result<()> { + let text = elf + .section_header_by_name(b".text") + .context(".text not found")?; + dbg!(text.size); + + let syms = elf.symbols().context("symbols not found")?; + + let text_range = text.addr..(text.addr + text.size); + + let mut symbols_sorted = syms + .into_iter() + .filter(|sym| text_range.contains(&sym.value)) + .collect::>(); + + symbols_sorted.sort_by_key(|s| s.value); + + let mut symbol_sizes = Vec::new(); + + for syms in symbols_sorted.windows(2) { + let [first, second] = syms else { + unreachable!() + }; + let first_size = second.value.u64() - first.value.u64(); + + let sym_name = elf.string(first.name)?; + + symbol_sizes.push((sym_name, first_size)); + } + + symbol_sizes.sort_by_key(|&(_, size)| size); + symbol_sizes.reverse(); + + for (sym, size) in symbol_sizes { + println!("{size} {sym}"); + } + + Ok(()) +} diff --git a/elven-parser/src/addrs.rs b/elven-parser/src/addrs.rs index 3e0157a..acb1072 100644 --- a/elven-parser/src/addrs.rs +++ b/elven-parser/src/addrs.rs @@ -18,6 +18,16 @@ pub const fn Addr(value: u64) -> Addr { Addr { value } } +impl Addr { + pub fn usize(self) -> usize { + self.value.try_into().unwrap() + } + + pub fn u64(self) -> u64 { + self.value + } +} + impl Debug for Addr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "0x{:x}", self.value)