use crate::{DisassemblyResult, Result};
#[derive(Debug, Clone)]
pub struct DisassemblyStatistics {
num_functions: usize,
num_recursive_functions: usize,
num_leaf_functions: usize,
num_basic_blocks: usize,
num_instructions: usize,
num_api_calls: usize,
num_function_calls: usize,
num_failed_functions: usize,
}
impl DisassemblyStatistics {
pub fn new(disassembly_result: &mut DisassemblyResult) -> Result<DisassemblyStatistics> {
Ok(DisassemblyStatistics {
num_functions: disassembly_result.functions.len(),
num_recursive_functions: disassembly_result.recursive_functions.len(),
num_leaf_functions: disassembly_result.leaf_functions.len(),
num_basic_blocks: DisassemblyStatistics::count_blocks(disassembly_result)?,
num_instructions: DisassemblyStatistics::count_instructions(disassembly_result)?,
num_api_calls: DisassemblyStatistics::count_api_calls(disassembly_result)?,
num_function_calls: DisassemblyStatistics::count_function_calls(disassembly_result)?,
num_failed_functions: disassembly_result.failed_analysis_addr.len(),
})
}
fn count_blocks(disassembly_result: &DisassemblyResult) -> Result<usize> {
let mut num_blocks = 0;
for blocks in disassembly_result.functions.values() {
num_blocks += blocks.len();
}
Ok(num_blocks)
}
fn count_api_calls(disassembly_result: &mut DisassemblyResult) -> Result<usize> {
Ok(disassembly_result.get_all_api_refs()?.len())
}
fn count_instructions(disassembly_result: &DisassemblyResult) -> Result<usize> {
let mut num_ins = 0;
for function_offset in disassembly_result.functions.keys() {
for block in &disassembly_result.functions[function_offset] {
num_ins += block.len();
}
}
Ok(num_ins)
}
fn count_function_calls(disassembly_result: &DisassemblyResult) -> Result<usize> {
let mut num_calls = 0;
for function_start in disassembly_result.functions.keys() {
if disassembly_result.code_refs_to.contains_key(function_start) {
num_calls += disassembly_result.code_refs_to[function_start].len();
}
}
Ok(num_calls)
}
}