etk-analyze 0.3.0

EVM Toolkit analysis tools
Documentation
#[path = "ecfg/opts.rs"]
mod opts;

use crate::opts::Opts;

use etk_analyze::cfg::ControlFlowGraph;

use etk_asm::disasm::Disassembler;

use etk_cli::errors::WithSources;

use etk_dasm::blocks::basic::Separator;
use etk_dasm::blocks::AnnotatedBlock;

use snafu::{Backtrace, Snafu};

use std::fs::File;
use std::io::Write;

#[derive(Debug, Snafu)]
enum Error {
    #[snafu(context(false))]
    Io {
        source: std::io::Error,
        backtrace: Backtrace,
    },
}

fn main() {
    let result = run();

    let root = match result {
        Ok(_) => return,
        Err(e) => e,
    };

    eprintln!("{}", WithSources(root));
    std::process::exit(1);
}

fn run() -> Result<(), Error> {
    let opts: Opts = clap::Parser::parse();

    let mut input = opts.src.open()?;
    let mut disasm = Disassembler::new();

    std::io::copy(&mut input, &mut disasm)?;

    let mut out: Box<dyn Write> = match opts.out_file {
        Some(path) => Box::new(File::create(path)?),
        None => Box::new(std::io::stdout()),
    };

    let mut separator = Separator::new();

    separator.push_all(disasm.ops());

    let blocks = separator
        .take()
        .into_iter()
        .chain(separator.finish().into_iter())
        .map(|x| AnnotatedBlock::annotate(&x));

    let mut cfg = ControlFlowGraph::new(blocks);
    cfg.refine_shallow();

    writeln!(out, "{}", cfg.render()).unwrap();

    Ok(())
}