70 lines
2.1 KiB
Rust
70 lines
2.1 KiB
Rust
use petgraph::dot::{Config as DotConfig, Dot};
|
|
|
|
use ppc750cl::{disasm_iter, Ins};
|
|
|
|
pub mod flow;
|
|
pub mod slices;
|
|
|
|
use crate::flow::FlowGraph;
|
|
use crate::slices::BasicSlices;
|
|
use dol::Dol;
|
|
|
|
fn main() {
|
|
let matches = clap::Command::new("ppc750cl-flow-graph")
|
|
.version("0.2.0")
|
|
.about("Control flow graph analysis for PowerPC 750CL")
|
|
.arg(
|
|
clap::Arg::new("START")
|
|
.long("--start")
|
|
.required(true)
|
|
.takes_value(true)
|
|
.help("Start address"),
|
|
)
|
|
.arg(
|
|
clap::Arg::new("STOP")
|
|
.long("--stop")
|
|
.required(true)
|
|
.takes_value(true)
|
|
.help("Stop address"),
|
|
)
|
|
.arg(
|
|
clap::Arg::new("INPUT")
|
|
.required(true)
|
|
.help("Binary input file"),
|
|
)
|
|
.get_matches();
|
|
|
|
let start_addr = matches.value_of("START").unwrap();
|
|
let start_addr: u32 = ::parse_int::parse(start_addr).expect("Invalid address flag");
|
|
let stop_addr = matches.value_of("STOP").unwrap();
|
|
let stop_addr: u32 = ::parse_int::parse(stop_addr).expect("Invalid address flag");
|
|
|
|
let file_path = matches.value_of("INPUT").unwrap();
|
|
let dol_file = std::fs::File::open(file_path).expect("Failed to read file");
|
|
let dol = Dol::read_from(&dol_file).expect("Invalid DOL file");
|
|
drop(dol_file);
|
|
let mut bytes = vec![0u8; (stop_addr - start_addr) as usize];
|
|
dol.virtual_read(&mut bytes, start_addr)
|
|
.expect("Invalid address range");
|
|
|
|
// Create control flow graph.
|
|
let ins_list: Vec<Ins> = disasm_iter(&bytes, start_addr).collect();
|
|
let basic_slices = BasicSlices::from_code(&ins_list);
|
|
let graph = FlowGraph::from_basic_slices(&basic_slices, &ins_list);
|
|
|
|
// Output graphviz.
|
|
let graphviz = Dot::with_config(
|
|
&graph.graph,
|
|
&[DotConfig::EdgeNoLabel, DotConfig::GraphContentOnly],
|
|
);
|
|
println!(
|
|
concat!(
|
|
"digraph func {{\n",
|
|
"node [shape=record fontname=Arial];\n",
|
|
"{:?}\n",
|
|
"}}"
|
|
),
|
|
graphviz
|
|
);
|
|
}
|