use chrono::{DateTime, Utc};
use nabla_scanner::binary::analysis::BinaryAnalysis;
use petgraph::Graph;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
pub type Address = u64;
#[derive(Debug, Clone, serde::Serialize)]
pub struct DecompilerAnalysis {
pub binary: BinaryAnalysis,
pub disassembly: Disassembly,
pub functions: Vec<Function>,
#[serde(skip)] pub call_graph: CallGraph,
#[serde(skip)] pub function_cfgs: HashMap<Address, ControlFlowGraph>,
pub pseudocode: HashMap<Address, PseudoCode>,
pub analysis_timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct FunctionAnalysis {
pub function: Function,
#[serde(skip)] pub cfg: ControlFlowGraph,
pub pseudocode: PseudoCode,
pub disassembly: Disassembly,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct Disassembly {
pub instructions: Vec<Instruction>,
pub sections: Vec<Section>,
pub symbols: HashMap<Address, String>,
}
#[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,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum InstructionGroup {
Jump,
Call,
Return,
Move,
Arithmetic,
Logical,
Compare,
Load,
Store,
Nop,
Other,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct Section {
pub name: String,
pub address: Address,
pub size: u64,
pub permissions: String,
}
#[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>, pub called_by: Vec<Address>, }
#[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,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum BlockType {
Entry,
Normal,
Conditional,
Loop,
Exit,
}
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,
}
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,
}
#[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, }
#[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), Float(u8), Pointer,
Array(Box<VariableType>, usize),
Struct(String),
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum VariableScope {
Local,
Parameter,
Global,
Register,
}
#[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),
}