nabla-decompiler 0.1.2

Binary decompilation engine with CFG analysis and pseudocode generation
Documentation
//! Core data types for the decompiler

use chrono::{DateTime, Utc};
use nabla_scanner::binary::analysis::BinaryAnalysis;
use petgraph::Graph;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;

/// Memory address type
pub type Address = u64;

/// Complete decompilation analysis of a binary
#[derive(Debug, Clone, serde::Serialize)]
pub struct DecompilerAnalysis {
    pub binary: BinaryAnalysis,
    pub disassembly: Disassembly,
    pub functions: Vec<Function>,
    #[serde(skip)] // Skip graphs for JSON serialization
    pub call_graph: CallGraph,
    #[serde(skip)] // Skip graphs for JSON serialization
    pub function_cfgs: HashMap<Address, ControlFlowGraph>,
    pub pseudocode: HashMap<Address, PseudoCode>,
    pub analysis_timestamp: DateTime<Utc>,
}

/// Analysis of a single function
#[derive(Debug, Clone, serde::Serialize)]
pub struct FunctionAnalysis {
    pub function: Function,
    #[serde(skip)] // Skip CFG for JSON serialization
    pub cfg: ControlFlowGraph,
    pub pseudocode: PseudoCode,
    pub disassembly: Disassembly,
}

/// Disassembled binary representation
#[derive(Debug, Clone, serde::Serialize)]
pub struct Disassembly {
    pub instructions: Vec<Instruction>,
    pub sections: Vec<Section>,
    pub symbols: HashMap<Address, String>,
}

/// Single assembly instruction
#[derive(Debug, Clone, serde::Serialize)]
pub struct Instruction {
    pub address: Address,
    pub bytes: Vec<u8>,
    pub mnemonic: String,
    pub operands: String,
    pub size: usize,
    pub group: InstructionGroup,
}

/// Instruction classification
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum InstructionGroup {
    Jump,
    Call,
    Return,
    Move,
    Arithmetic,
    Logical,
    Compare,
    Load,
    Store,
    Nop,
    Other,
}

/// Binary section information
#[derive(Debug, Clone, serde::Serialize)]
pub struct Section {
    pub name: String,
    pub address: Address,
    pub size: u64,
    pub permissions: String,
}

/// Function representation
#[derive(Debug, Clone, serde::Serialize)]
pub struct Function {
    pub address: Address,
    pub name: Option<String>,
    pub size: u64,
    pub instructions: Vec<Address>,
    pub basic_blocks: Vec<BasicBlock>,
    pub entry_point: Address,
    pub exit_points: Vec<Address>,
    pub calls: Vec<Address>, // Functions this calls
    pub called_by: Vec<Address>, // Functions that call this
}

/// Basic block in a function
#[derive(Debug, Clone, serde::Serialize)]
pub struct BasicBlock {
    pub id: Uuid,
    pub start_address: Address,
    pub end_address: Address,
    pub instructions: Vec<Address>,
    pub predecessors: Vec<Uuid>,
    pub successors: Vec<Uuid>,
    pub block_type: BlockType,
}

/// Basic block classification
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum BlockType {
    Entry,
    Normal,
    Conditional,
    Loop,
    Exit,
}

/// Function call graph
pub type CallGraph = Graph<FunctionNode, CallEdge>;

#[derive(Debug, Clone, serde::Serialize)]
pub struct FunctionNode {
    pub address: Address,
    pub name: Option<String>,
    pub size: u64,
}

#[derive(Debug, Clone, serde::Serialize)]
pub struct CallEdge {
    pub call_type: CallType,
    pub call_site: Address,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CallType {
    Direct,
    Indirect,
    Tail,
}

/// Control flow graph for a single function
pub type ControlFlowGraph = Graph<BasicBlockNode, ControlFlowEdge>;

#[derive(Debug, Clone, serde::Serialize)]
pub struct BasicBlockNode {
    pub id: Uuid,
    pub start_address: Address,
    pub end_address: Address,
    pub instruction_count: usize,
    pub block_type: BlockType,
}

#[derive(Debug, Clone, serde::Serialize)]
pub struct ControlFlowEdge {
    pub edge_type: ControlFlowType,
    pub condition: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ControlFlowType {
    Unconditional,
    ConditionalTrue,
    ConditionalFalse,
    FallThrough,
}

/// Generated pseudocode
#[derive(Debug, Clone, serde::Serialize)]
pub struct PseudoCode {
    pub function_address: Address,
    pub function_name: Option<String>,
    pub code: String,
    pub variables: Vec<Variable>,
    pub comments: HashMap<Address, String>,
    pub confidence: f32, // 0.0 - 1.0 confidence in pseudocode accuracy
}

/// Variable in pseudocode
#[derive(Debug, Clone, serde::Serialize)]
pub struct Variable {
    pub name: String,
    pub var_type: VariableType,
    pub first_use: Address,
    pub scope: VariableScope,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum VariableType {
    Integer(u8), // bit width
    Float(u8),   // bit width
    Pointer,
    Array(Box<VariableType>, usize),
    Struct(String),
    Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum VariableScope {
    Local,
    Parameter,
    Global,
    Register,
}

/// Error types for decompiler
#[derive(thiserror::Error, Debug)]
pub enum DecompilerError {
    #[error("Disassembly failed: {0}")]
    DisassemblyError(String),
    
    #[error("Function analysis failed: {0}")]
    FunctionAnalysisError(String),
    
    #[error("CFG generation failed: {0}")]
    CfgError(String),
    
    #[error("Pseudocode generation failed: {0}")]
    LiftingError(String),
    
    #[error("Binary format not supported: {0}")]
    UnsupportedFormat(String),
    
    #[error("Invalid address: 0x{0:x}")]
    InvalidAddress(u64),
}