nabla-decompiler 0.1.2

Binary decompilation engine with CFG analysis and pseudocode generation
Documentation
//! Nabla Binary Decompiler Engine
//! 
//! Provides binary analysis, control flow graph generation, and pseudocode lifting
//! for reverse engineering and security analysis of embedded systems firmware.

pub mod analysis;
pub mod cfg;
pub mod cfg_analyzer;
pub mod disasm;
pub mod lifting;
pub mod patcher;
pub mod types;

pub use types::*;

use anyhow::Result;
use nabla_scanner::binary::analysis::BinaryAnalysis;
use serde::{Deserialize, Serialize};

/// Main decompiler interface
pub struct Decompiler {
    binary_analysis: BinaryAnalysis,
}

impl Decompiler {
    /// Create a new decompiler instance from binary analysis
    pub fn new(binary_analysis: BinaryAnalysis) -> Self {
        Self { binary_analysis }
    }

    /// Perform full decompilation analysis
    pub fn analyze(&self) -> Result<DecompilerAnalysis> {
        let disasm = disasm::disassemble_binary(&self.binary_analysis)?;
        
        // Extract architecture and format from binary analysis
        let arch = self.binary_analysis.architecture.as_str();
        let format = self.binary_analysis.format.as_str();
        
        let functions = analysis::identify_functions_with_yara(&disasm, arch, format)?;
        let call_graph = cfg::build_call_graph(&functions)?;
        let function_cfgs = cfg::build_function_cfgs(&functions, &disasm, arch, format)?;
        let pseudocode = lifting::generate_pseudocode(&functions, &disasm)?;

        Ok(DecompilerAnalysis {
            binary: self.binary_analysis.clone(),
            disassembly: disasm,
            functions,
            call_graph,
            function_cfgs,
            pseudocode,
            analysis_timestamp: chrono::Utc::now(),
        })
    }

    /// Analyze a specific function by address
    pub fn analyze_function(&self, address: u64) -> Result<FunctionAnalysis> {
        let disasm = disasm::disassemble_from_address(&self.binary_analysis, address)?;
        
        // Extract architecture and format from binary analysis
        let arch = self.binary_analysis.architecture.as_str();
        let format = self.binary_analysis.format.as_str();
        
        let function = analysis::analyze_single_function_with_arch(&disasm, address, arch, format)?;
        let cfg = cfg::build_function_cfg_with_arch(&function, &disasm, arch, format)?;
        let pseudocode = lifting::lift_function_to_pseudocode(&function, &disasm)?;

        Ok(FunctionAnalysis {
            function,
            cfg,
            pseudocode,
            disassembly: disasm,
        })
    }
}

/// Request structure for decompilation operations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DecompileRequest {
    pub binary_path: String,
    pub function_address: Option<u64>,
    pub output_format: String,
}

/// Engine for handling decompilation operations
pub struct DecompilerEngine {
    // Future: could cache decompilers or configurations here
}

impl DecompilerEngine {
    /// Create a new decompiler engine
    pub async fn new() -> Result<Self> {
        Ok(Self {})
    }

    /// Perform decompilation based on request
    pub async fn decompile(&mut self, request: DecompileRequest, binary_analysis: &BinaryAnalysis) -> Result<DecompilerResult> {
        let decompiler = Decompiler::new(binary_analysis.clone());
        
        match request.function_address {
            Some(address) => {
                let func_analysis = decompiler.analyze_function(address)?;
                Ok(DecompilerResult::FunctionAnalysis(func_analysis))
            }
            None => {
                let full_analysis = decompiler.analyze()?;
                Ok(DecompilerResult::FullAnalysis(full_analysis))
            }
        }
    }
}

/// Result type for decompilation operations
#[derive(Debug, Clone)]
pub enum DecompilerResult {
    FullAnalysis(DecompilerAnalysis),
    FunctionAnalysis(FunctionAnalysis),
}

#[cfg(test)]
mod tests {
    include!("lifting_tests.rs");
}