~taiite/protodump

56119d31aa5b91263f323ee5067a848c2994307b — Hubert Hirtz 10 days ago 90395ec
Do not group by files by default
1 files changed, 26 insertions(+), 95 deletions(-)

M src/main.rs
M src/main.rs => src/main.rs +26 -95
@@ 9,8 9,9 @@ use std::env;
use std::fs;
use std::process;

type Sources = HashMap<String, HashMap<String, Prototype>>;
type SortedSources = Vec<(String, Vec<(String, Prototype)>)>;
// key=symbol name
type Sources = HashMap<String, Prototype>;
type SortedSources = Vec<(String, Prototype)>;

struct Prototype {
    return_type: String,


@@ 22,56 23,6 @@ struct Parameter {
    typ: String,
}

fn entry_attr_file<R>(
    dwarf: &gimli::Dwarf<R>,
    unit: &gimli::Unit<R>,
    entry: &gimli::DebuggingInformationEntry<R>,
    attr_name: gimli::DwAt,
) -> gimli::Result<Option<String>>
where
    R: gimli::Reader,
{
    entry
        .attr(attr_name)?
        .and_then(|attr| {
            let file = match attr.value() {
                gimli::AttributeValue::FileIndex(file) => file,
                av => panic!("unexpected attribute value: {:?}", av),
            };
            let header = unit.line_program.as_ref()?.header();
            let file = header.file(file)?;
            Some(resolve_file(dwarf, unit, header, file))
        })
        .transpose()
}

fn resolve_file<R>(
    dwarf: &gimli::Dwarf<R>,
    unit: &gimli::Unit<R>,
    header: &gimli::LineProgramHeader<R>,
    file: &gimli::FileEntry<R>,
) -> gimli::Result<String>
where
    R: gimli::Reader,
{
    let mut path = String::new();
    if let Some(directory) = file.directory(header) {
        let directory = dwarf.attr_string(unit, directory)?;
        let directory = directory.to_string_lossy()?;
        if !directory.starts_with('/') {
            if let Some(ref comp_dir) = unit.comp_dir {
                path.push_str(&comp_dir.to_string_lossy()?);
                path.push('/');
            }
        }
        path.push_str(&directory);
        path.push('/');
    }
    let basename = dwarf.attr_string(unit, file.path_name())?;
    path.push_str(&basename.to_string_lossy()?);
    Ok(path)
}

fn entry_attr_type<R>(
    dwarf: &gimli::Dwarf<R>,
    unit: &gimli::Unit<R>,


@@ 190,7 141,7 @@ fn read_prototypes(data: &[u8]) -> Result<Sources> {
    let dwarf_cow = gimli::Dwarf::load(&load_section)?;
    let dwarf = dwarf_cow.borrow(|section| gimli::EndianSlice::new(section, endian));

    let mut files = Sources::new();
    let mut prototypes = Sources::new();

    let mut it = dwarf.units();
    while let Some(header) = it.next()? {


@@ 208,13 159,11 @@ fn read_prototypes(data: &[u8]) -> Result<Sources> {

            let name = entry_attr_str(&dwarf, &unit, entry, gimli::DW_AT_name)?;
            let typ = entry_attr_type(&dwarf, &unit, entry, gimli::DW_AT_type)?;
            let loc = entry_attr_file(&dwarf, &unit, entry, gimli::DW_AT_decl_file)?;
            if name.is_none() || typ.is_none() || loc.is_none() {
            if name.is_none() || typ.is_none() {
                continue;
            }
            let name = name.unwrap();
            let typ = typ.unwrap();
            let loc = loc.unwrap();
            let mut parameters = Vec::new();

            if entry.has_children() {


@@ 236,7 185,7 @@ fn read_prototypes(data: &[u8]) -> Result<Sources> {
                }
            }

            files.entry(loc).or_default().insert(
            prototypes.insert(
                name,
                Prototype {
                    return_type: typ,


@@ 246,7 195,7 @@ fn read_prototypes(data: &[u8]) -> Result<Sources> {
        }
    }

    Ok(files)
    Ok(prototypes)
}

#[derive(Debug)]


@@ 321,51 270,36 @@ fn read_object_info(data: &[u8], filter: SymbolFilter) -> Result<ObjectInfo<'_>>
    })
}

fn sort_prototypes(files: Sources) -> SortedSources {
    let mut sorted: Vec<_> = files
        .into_iter()
        .map(|(filename, prototypes)| {
            let mut prototypes: Vec<_> = prototypes.into_iter().collect();
            prototypes.sort_unstable_by(|(name1, _), (name2, _)| String::cmp(name1, name2));
            (filename, prototypes)
        })
        .collect();
fn sort_prototypes(prototypes: Sources) -> SortedSources {
    let mut sorted: Vec<_> = prototypes.into_iter().collect();
    sorted.sort_unstable_by(|(name1, _), (name2, _)| String::cmp(name1, name2));
    sorted
}

fn show_prototypes(files: SortedSources) {
fn show_prototypes(prototypes: SortedSources) {
    let color = atty::is(atty::Stream::Stdout);
    for (file, ps) in files {
    for (name, p) in prototypes {
        if color {
            println!("{}", ansi_term::Color::Green.paint(&file))
            print!("{}", ansi_term::Style::new().bold().paint(p.return_type));
        } else {
            println!("{}", file)
            print!("{}", p.return_type);
        }
        for (name, p) in ps {
            if color {
                print!("{}", ansi_term::Style::new().bold().paint(p.return_type));
        print!("{}(", name);
        let mut first = true;
        for param in p.parameters {
            if first {
                first = false;
            } else {
                print!("{}", p.return_type);
                print!(", ");
            }
            print!("{}(", name);
            let mut first = true;
            for param in p.parameters {
                if first {
                    first = false;
                } else {
                    print!(", ");
                }
                if color {
                    print!("{}", ansi_term::Style::new().bold().paint(param.typ));
                } else {
                    print!("{}", param.typ);
                }
                print!("{}", param.name);
            if color {
                print!("{}", ansi_term::Style::new().bold().paint(param.typ));
            } else {
                print!("{}", param.typ);
            }
            println!(");");
            print!("{}", param.name);
        }
        println!()
        println!(");");
    }
}



@@ 403,10 337,7 @@ fn main() -> Result<()> {
        },
    )?;

    sources.retain(|_, file| {
        file.retain(|func, _| object_info.symbol_whitelist.contains(func.as_str()));
        !file.is_empty()
    });
    sources.retain(|func, _| object_info.symbol_whitelist.contains(func.as_str()));

    println!("OBJECT FILE {}", path);
    println!("Container type: {:?}", object_info.container_type);