diff options
| author | Michael Krasnitski <michael.krasnitski@gmail.com> | 2024-02-11 15:27:22 -0500 |
|---|---|---|
| committer | Kyle Martin <krm504@nyu.edu> | 2024-03-18 17:46:37 -0400 |
| commit | 9939d850f0b8ccaf1ae048bcb5f788a6c3e606bf (patch) | |
| tree | 91b582cd51820d826efcd5312e234e56617ca7f9 /rust/src | |
| parent | 970fe84875e2d6eed918f5bdc9ff689ef37b05ce (diff) | |
Refactor HLIL instructions
Similar to MLIL. Also, reintroduce `LiftedJump` and `LiftedLabel` types.
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/hlil/block.rs | 4 | ||||
| -rw-r--r-- | rust/src/hlil/function.rs | 28 | ||||
| -rw-r--r-- | rust/src/hlil/instruction.rs | 1564 | ||||
| -rw-r--r-- | rust/src/hlil/lift.rs | 470 | ||||
| -rw-r--r-- | rust/src/hlil/operation.rs | 2037 |
5 files changed, 1092 insertions, 3011 deletions
diff --git a/rust/src/hlil/block.rs b/rust/src/hlil/block.rs index a90429a4..0bbedd18 100644 --- a/rust/src/hlil/block.rs +++ b/rust/src/hlil/block.rs @@ -21,7 +21,7 @@ impl Iterator for HighLevelILBlockIter { .map(|i| unsafe { BNGetHighLevelILIndexForInstruction(self.function.handle, i as usize) }) - .map(|i| HighLevelILInstruction::new(&self.function, i)) + .map(|i| HighLevelILInstruction::new(self.function.to_owned(), i)) } } @@ -43,7 +43,7 @@ impl BlockContext for HighLevelILBlock { let expr_idx = unsafe { BNGetHighLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize) }; - HighLevelILInstruction::new(&self.function, expr_idx) + HighLevelILInstruction::new(self.function.to_owned(), expr_idx) } fn iter(&self, block: &BasicBlock<Self>) -> HighLevelILBlockIter { diff --git a/rust/src/hlil/function.rs b/rust/src/hlil/function.rs index 40d01dfe..cef23784 100644 --- a/rust/src/hlil/function.rs +++ b/rust/src/hlil/function.rs @@ -2,17 +2,20 @@ use std::hash::{Hash, Hasher}; use binaryninjacore_sys::BNFreeHighLevelILFunction; use binaryninjacore_sys::BNGetHighLevelILBasicBlockList; +use binaryninjacore_sys::BNGetHighLevelILByIndex; use binaryninjacore_sys::BNGetHighLevelILInstructionCount; use binaryninjacore_sys::BNGetHighLevelILOwnerFunction; use binaryninjacore_sys::BNGetHighLevelILSSAForm; use binaryninjacore_sys::BNHighLevelILFunction; +use binaryninjacore_sys::BNHighLevelILInstruction; +use binaryninjacore_sys::BNHighLevelILOperation; use binaryninjacore_sys::BNNewHighLevelILFunctionReference; use crate::basicblock::BasicBlock; -use crate::function::Function; +use crate::function::{Function, ILFunction}; use crate::rc::{Array, Ref, RefCountable}; -use super::{HighLevelILBlock, HighLevelILInstruction}; +use super::{HighLevelILBlock, HighLevelILInstruction, HighLevelILLiftedInstruction}; pub struct HighLevelILFunction { pub(crate) full_ast: bool, @@ -45,7 +48,11 @@ impl HighLevelILFunction { } pub fn instruction_from_idx(&self, expr_idx: usize) -> HighLevelILInstruction { - HighLevelILInstruction::new(self, expr_idx) + HighLevelILInstruction::new(self.to_owned(), expr_idx) + } + + pub fn lifted_instruction_from_idx(&self, expr_idx: usize) -> HighLevelILLiftedInstruction { + self.instruction_from_idx(expr_idx).lift() } pub fn instruction_count(&self) -> usize { @@ -79,6 +86,21 @@ impl HighLevelILFunction { } } +impl ILFunction for HighLevelILFunction { + type BNInstruction = BNHighLevelILInstruction; + type Instruction = HighLevelILInstruction; + + fn il_instruction_from_idx(&self, expr_idx: usize) -> Self::Instruction { + self.instruction_from_idx(expr_idx) + } + + fn operands_from_idx(&self, expr_idx: usize) -> [u64; 5] { + let node = unsafe { BNGetHighLevelILByIndex(self.handle, expr_idx, self.full_ast) }; + assert_eq!(node.operation, BNHighLevelILOperation::HLIL_UNDEF); + node.operands + } +} + impl ToOwned for HighLevelILFunction { type Owned = Ref<Self>; diff --git a/rust/src/hlil/instruction.rs b/rust/src/hlil/instruction.rs index acdc5cf7..882bc60b 100644 --- a/rust/src/hlil/instruction.rs +++ b/rust/src/hlil/instruction.rs @@ -1,11 +1,22 @@ use binaryninjacore_sys::BNGetHighLevelILByIndex; use binaryninjacore_sys::BNHighLevelILOperation; +use crate::operand_iter::OperandIter; +use crate::rc::Ref; +use crate::types::{ConstantData, ILIntrinsic, RegisterValue, RegisterValueType}; + use super::operation::*; -use super::{HighLevelILFunction, HighLevelILLiftedInstruction}; +use super::{HighLevelILFunction, HighLevelILLiftedInstruction, HighLevelILLiftedInstructionKind}; #[derive(Clone)] -pub enum HighLevelILInstruction { +pub struct HighLevelILInstruction { + pub function: Ref<HighLevelILFunction>, + pub address: u64, + pub kind: HighLevelILInstructionKind, +} + +#[derive(Copy, Clone)] +pub enum HighLevelILInstructionKind { Adc(BinaryOpCarry), Sbb(BinaryOpCarry), Rlc(BinaryOpCarry), @@ -102,14 +113,14 @@ pub enum HighLevelILInstruction { IntrinsicSsa(IntrinsicSsa), Jump(Jump), MemPhi(MemPhi), - Nop(NoArgs), - Break(NoArgs), - Continue(NoArgs), - Noret(NoArgs), - Unreachable(NoArgs), - Bp(NoArgs), - Undef(NoArgs), - Unimpl(NoArgs), + Nop, + Break, + Continue, + Noret, + Unreachable, + Bp, + Undef, + Unimpl, Ret(Ret), Split(Split), StructField(StructField), @@ -130,1144 +141,727 @@ pub enum HighLevelILInstruction { DoWhileSsa(WhileSsa), } impl HighLevelILInstruction { - pub(crate) fn new(function: &HighLevelILFunction, idx: usize) -> Self { + pub(crate) fn new(function: Ref<HighLevelILFunction>, idx: usize) -> Self { let op = unsafe { BNGetHighLevelILByIndex(function.handle, idx, function.full_ast) }; use BNHighLevelILOperation::*; - use HighLevelILInstruction as Op; - match op.operation { + use HighLevelILInstructionKind as Op; + let kind = match op.operation { HLIL_ADC => Op::Adc(BinaryOpCarry::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_SBB => Op::Sbb(BinaryOpCarry::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_RLC => Op::Rlc(BinaryOpCarry::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_RRC => Op::Rrc(BinaryOpCarry::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_ADD => Op::Add(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_SUB => Op::Sub(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_AND => Op::And(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_OR => Op::Or(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_XOR => Op::Xor(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_LSL => Op::Lsl(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_LSR => Op::Lsr(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ASR => Op::Asr(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ROL => Op::Rol(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ROR => Op::Ror(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MUL => Op::Mul(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MULU_DP => Op::MuluDp(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MULS_DP => Op::MulsDp(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_DIVU => Op::Divu(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_DIVU_DP => Op::DivuDp(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_DIVS => Op::Divs(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_DIVS_DP => Op::DivsDp(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MODU => Op::Modu(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MODU_DP => Op::ModuDp(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MODS => Op::Mods(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_MODS_DP => Op::ModsDp(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_E => Op::CmpE(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_NE => Op::CmpNe(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_SLE => Op::CmpSle(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_ULE => Op::CmpUle(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_SGE => Op::CmpSge(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_UGE => Op::CmpUge(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_TEST_BIT => Op::TestBit(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FADD => Op::Fadd(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FSUB => Op::Fsub(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FMUL => Op::Fmul(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FDIV => Op::Fdiv(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_E => Op::FcmpE(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_O => Op::FcmpO(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ARRAY_INDEX => Op::ArrayIndex(ArrayIndex::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ARRAY_INDEX_SSA => Op::ArrayIndexSsa(ArrayIndexSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize], - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1], + op.operands[2] as usize, )), HLIL_ASSIGN => Op::Assign(Assign::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_ASSIGN_MEM_SSA => Op::AssignMemSsa(AssignMemSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize], - op.operands[2usize] as usize, - op.operands[3usize], + op.operands[0] as usize, + op.operands[1], + op.operands[2] as usize, + op.operands[3], )), HLIL_ASSIGN_UNPACK => Op::AssignUnpack(AssignUnpack::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_ASSIGN_UNPACK_MEM_SSA => Op::AssignUnpackMemSsa(AssignUnpackMemSsa::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), - op.operands[2usize], - op.operands[3usize] as usize, - op.operands[4usize], - )), - HLIL_BLOCK => Op::Block(Block::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2], + op.operands[3] as usize, + op.operands[4], )), + HLIL_BLOCK => Op::Block(Block::new(op.operands[0] as usize, op.operands[1] as usize)), HLIL_CALL => Op::Call(Call::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - (op.operands[1usize] as usize, op.operands[2usize] as usize), + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_TAILCALL => Op::Tailcall(Call::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - (op.operands[1usize] as usize, op.operands[2usize] as usize), + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_CALL_SSA => Op::CallSsa(CallSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - (op.operands[1usize] as usize, op.operands[2usize] as usize), - op.operands[3usize], - op.operands[4usize], + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, + op.operands[3], + op.operands[4], )), HLIL_CASE => Op::Case(Case::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), - op.operands[2usize] as usize, - )), - HLIL_CONST => Op::Const(Const::new( - function.to_owned(), - op.address, - op.operands[0usize], - )), - HLIL_CONST_PTR => Op::ConstPtr(Const::new( - function.to_owned(), - op.address, - op.operands[0usize], - )), - HLIL_IMPORT => Op::Import(Const::new( - function.to_owned(), - op.address, - op.operands[0usize], + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), + HLIL_CONST => Op::Const(Const::new(op.operands[0])), + HLIL_CONST_PTR => Op::ConstPtr(Const::new(op.operands[0])), + HLIL_IMPORT => Op::Import(Const::new(op.operands[0])), HLIL_CONST_DATA => Op::ConstData(ConstData::new( - function.to_owned(), - op.address, - ( - op.operands[0usize].try_into().unwrap(), - op.operands[1usize], - op.size, - ), - )), - HLIL_DEREF => Op::Deref(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_ADDRESS_OF => Op::AddressOf(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_NEG => Op::Neg(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_NOT => Op::Not(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_SX => Op::Sx(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_ZX => Op::Zx(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_LOW_PART => Op::LowPart(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FSQRT => Op::Fsqrt(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FNEG => Op::Fneg(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FABS => Op::Fabs(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FLOAT_CONV => Op::FloatConv(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FLOOR => Op::Floor(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_CEIL => Op::Ceil(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - )), - HLIL_FTRUNC => Op::Ftrunc(UnaryOp::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, + op.operands[0] as u32, + op.operands[1] as i64, + op.size, )), + HLIL_DEREF => Op::Deref(UnaryOp::new(op.operands[0] as usize)), + HLIL_ADDRESS_OF => Op::AddressOf(UnaryOp::new(op.operands[0] as usize)), + HLIL_NEG => Op::Neg(UnaryOp::new(op.operands[0] as usize)), + HLIL_NOT => Op::Not(UnaryOp::new(op.operands[0] as usize)), + HLIL_SX => Op::Sx(UnaryOp::new(op.operands[0] as usize)), + HLIL_ZX => Op::Zx(UnaryOp::new(op.operands[0] as usize)), + HLIL_LOW_PART => Op::LowPart(UnaryOp::new(op.operands[0] as usize)), + HLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp::new(op.operands[0] as usize)), + HLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp::new(op.operands[0] as usize)), + HLIL_FSQRT => Op::Fsqrt(UnaryOp::new(op.operands[0] as usize)), + HLIL_FNEG => Op::Fneg(UnaryOp::new(op.operands[0] as usize)), + HLIL_FABS => Op::Fabs(UnaryOp::new(op.operands[0] as usize)), + HLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp::new(op.operands[0] as usize)), + HLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp::new(op.operands[0] as usize)), + HLIL_FLOAT_CONV => Op::FloatConv(UnaryOp::new(op.operands[0] as usize)), + HLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp::new(op.operands[0] as usize)), + HLIL_FLOOR => Op::Floor(UnaryOp::new(op.operands[0] as usize)), + HLIL_CEIL => Op::Ceil(UnaryOp::new(op.operands[0] as usize)), + HLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(op.operands[0] as usize)), HLIL_DEREF_FIELD_SSA => Op::DerefFieldSsa(DerefFieldSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize], - op.operands[2usize], - op.operands[3usize], - )), - HLIL_DEREF_SSA => Op::DerefSsa(DerefSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize], - )), - HLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new( - function.to_owned(), - op.address, - op.operands[0usize], - op.operands[1usize], - )), - HLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new( - function.to_owned(), - op.address, - op.operands[0usize], - op.size, + op.operands[0] as usize, + op.operands[1], + op.operands[2], + op.operands[3], )), + HLIL_DEREF_SSA => Op::DerefSsa(DerefSsa::new(op.operands[0] as usize, op.operands[1])), + HLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(op.operands[0], op.operands[1])), + HLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(op.operands[0], op.size)), HLIL_FOR => Op::For(ForLoop::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, - op.operands[3usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, + op.operands[3] as usize, )), HLIL_FOR_SSA => Op::ForSsa(ForLoopSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, - op.operands[3usize] as usize, - op.operands[4usize] as usize, - )), - HLIL_GOTO => Op::Goto(Label::new( - function.to_owned(), - op.address, - op.operands[0usize], - )), - HLIL_LABEL => Op::Label(Label::new( - function.to_owned(), - op.address, - op.operands[0usize], + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, + op.operands[3] as usize, + op.operands[4] as usize, )), + HLIL_GOTO => Op::Goto(Label::new(op.operands[0])), + HLIL_LABEL => Op::Label(Label::new(op.operands[0])), HLIL_IF => Op::If(If::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_INTRINSIC => Op::Intrinsic(Intrinsic::new( - function.to_owned(), - op.address, - op.operands[0usize] as u32, - (op.operands[1usize] as usize, op.operands[2usize] as usize), + op.operands[0] as u32, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as u32, - (op.operands[1usize] as usize, op.operands[2usize] as usize), - op.operands[3usize], - op.operands[4usize], - )), - HLIL_JUMP => Op::Jump(Jump::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, + op.operands[0] as u32, + op.operands[1] as usize, + op.operands[2] as usize, + op.operands[3], + op.operands[4], )), + HLIL_JUMP => Op::Jump(Jump::new(op.operands[0] as usize)), HLIL_MEM_PHI => Op::MemPhi(MemPhi::new( - function.to_owned(), - op.address, - op.operands[0usize], - (op.operands[1usize] as usize, op.operands[2usize] as usize), - )), - HLIL_NOP => Op::Nop(NoArgs::new(function.to_owned(), op.address)), - HLIL_BREAK => Op::Break(NoArgs::new(function.to_owned(), op.address)), - HLIL_CONTINUE => Op::Continue(NoArgs::new(function.to_owned(), op.address)), - HLIL_NORET => Op::Noret(NoArgs::new(function.to_owned(), op.address)), - HLIL_UNREACHABLE => Op::Unreachable(NoArgs::new(function.to_owned(), op.address)), - HLIL_BP => Op::Bp(NoArgs::new(function.to_owned(), op.address)), - HLIL_UNDEF => Op::Undef(NoArgs::new(function.to_owned(), op.address)), - HLIL_UNIMPL => Op::Unimpl(NoArgs::new(function.to_owned(), op.address)), - HLIL_RET => Op::Ret(Ret::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), - )), - HLIL_SPLIT => Op::Split(Split::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + op.operands[0], + op.operands[1] as usize, + op.operands[2] as usize, )), + HLIL_NOP => Op::Nop, + HLIL_BREAK => Op::Break, + HLIL_CONTINUE => Op::Continue, + HLIL_NORET => Op::Noret, + HLIL_UNREACHABLE => Op::Unreachable, + HLIL_BP => Op::Bp, + HLIL_UNDEF => Op::Undef, + HLIL_UNIMPL => Op::Unimpl, + HLIL_RET => Op::Ret(Ret::new(op.operands[0] as usize, op.operands[1] as usize)), + HLIL_SPLIT => Op::Split(Split::new(op.operands[0] as usize, op.operands[1] as usize)), HLIL_STRUCT_FIELD => Op::StructField(StructField::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize], - op.operands[2usize], + op.operands[0] as usize, + op.operands[1], + op.operands[2], )), HLIL_DEREF_FIELD => Op::DerefField(StructField::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize], - op.operands[2usize], + op.operands[0] as usize, + op.operands[1], + op.operands[2], )), HLIL_SWITCH => Op::Switch(Switch::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - (op.operands[2usize] as usize, op.operands[3usize] as usize), + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, + op.operands[3] as usize, )), HLIL_SYSCALL => Op::Syscall(Syscall::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), + op.operands[0] as usize, + op.operands[1] as usize, )), HLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa::new( - function.to_owned(), - op.address, - (op.operands[0usize] as usize, op.operands[1usize] as usize), - op.operands[2usize], - op.operands[3usize], - )), - HLIL_TRAP => Op::Trap(Trap::new( - function.to_owned(), - op.address, - op.operands[0usize], - )), - HLIL_VAR_DECLARE => Op::VarDeclare(Var::new( - function.to_owned(), - op.address, - op.operands[0usize], - )), - HLIL_VAR => Op::Var(Var::new( - function.to_owned(), - op.address, - op.operands[0usize], - )), - HLIL_VAR_INIT => Op::VarInit(VarInit::new( - function.to_owned(), - op.address, - op.operands[0usize], - op.operands[1usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2], + op.operands[3], )), + HLIL_TRAP => Op::Trap(Trap::new(op.operands[0])), + HLIL_VAR_DECLARE => Op::VarDeclare(Var::new(op.operands[0])), + HLIL_VAR => Op::Var(Var::new(op.operands[0])), + HLIL_VAR_INIT => Op::VarInit(VarInit::new(op.operands[0], op.operands[1] as usize)), HLIL_VAR_INIT_SSA => Op::VarInitSsa(VarInitSsa::new( - function.to_owned(), - op.address, - (op.operands[0usize], op.operands[1usize] as usize), - op.operands[2usize] as usize, + (op.operands[0], op.operands[1] as usize), + op.operands[2] as usize, )), HLIL_VAR_PHI => Op::VarPhi(VarPhi::new( - function.to_owned(), - op.address, - (op.operands[0usize], op.operands[1usize] as usize), - (op.operands[2usize] as usize, op.operands[3usize] as usize), - )), - HLIL_VAR_SSA => Op::VarSsa(VarSsa::new( - function.to_owned(), - op.address, - (op.operands[0usize], op.operands[1usize] as usize), - )), - HLIL_WHILE => Op::While(While::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - )), - HLIL_DO_WHILE => Op::DoWhile(While::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, + (op.operands[0], op.operands[1] as usize), + op.operands[2] as usize, + op.operands[3] as usize, )), + HLIL_VAR_SSA => Op::VarSsa(VarSsa::new((op.operands[0], op.operands[1] as usize))), + HLIL_WHILE => Op::While(While::new(op.operands[0] as usize, op.operands[1] as usize)), + HLIL_DO_WHILE => { + Op::DoWhile(While::new(op.operands[0] as usize, op.operands[1] as usize)) + } HLIL_WHILE_SSA => Op::WhileSsa(WhileSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), HLIL_DO_WHILE_SSA => Op::DoWhileSsa(WhileSsa::new( - function.to_owned(), - op.address, - op.operands[0usize] as usize, - op.operands[1usize] as usize, - op.operands[2usize] as usize, + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, )), + }; + Self { + function, + address: op.address, + kind, } } - pub fn function(&self) -> &HighLevelILFunction { - use HighLevelILInstruction::*; - match self { - Adc(op) => &op.function, - Sbb(op) => &op.function, - Rlc(op) => &op.function, - Rrc(op) => &op.function, - Add(op) => &op.function, - Sub(op) => &op.function, - And(op) => &op.function, - Or(op) => &op.function, - Xor(op) => &op.function, - Lsl(op) => &op.function, - Lsr(op) => &op.function, - Asr(op) => &op.function, - Rol(op) => &op.function, - Ror(op) => &op.function, - Mul(op) => &op.function, - MuluDp(op) => &op.function, - MulsDp(op) => &op.function, - Divu(op) => &op.function, - DivuDp(op) => &op.function, - Divs(op) => &op.function, - DivsDp(op) => &op.function, - Modu(op) => &op.function, - ModuDp(op) => &op.function, - Mods(op) => &op.function, - ModsDp(op) => &op.function, - CmpE(op) => &op.function, - CmpNe(op) => &op.function, - CmpSlt(op) => &op.function, - CmpUlt(op) => &op.function, - CmpSle(op) => &op.function, - CmpUle(op) => &op.function, - CmpSge(op) => &op.function, - CmpUge(op) => &op.function, - CmpSgt(op) => &op.function, - CmpUgt(op) => &op.function, - TestBit(op) => &op.function, - AddOverflow(op) => &op.function, - Fadd(op) => &op.function, - Fsub(op) => &op.function, - Fmul(op) => &op.function, - Fdiv(op) => &op.function, - FcmpE(op) => &op.function, - FcmpNe(op) => &op.function, - FcmpLt(op) => &op.function, - FcmpLe(op) => &op.function, - FcmpGe(op) => &op.function, - FcmpGt(op) => &op.function, - FcmpO(op) => &op.function, - FcmpUo(op) => &op.function, - ArrayIndex(op) => &op.function, - ArrayIndexSsa(op) => &op.function, - Assign(op) => &op.function, - AssignMemSsa(op) => &op.function, - AssignUnpack(op) => &op.function, - AssignUnpackMemSsa(op) => &op.function, - Block(op) => &op.function, - Call(op) => &op.function, - Tailcall(op) => &op.function, - CallSsa(op) => &op.function, - Case(op) => &op.function, - Const(op) => &op.function, - ConstPtr(op) => &op.function, - Import(op) => &op.function, - ConstData(op) => &op.function, - Deref(op) => &op.function, - AddressOf(op) => &op.function, - Neg(op) => &op.function, - Not(op) => &op.function, - Sx(op) => &op.function, - Zx(op) => &op.function, - LowPart(op) => &op.function, - BoolToInt(op) => &op.function, - UnimplMem(op) => &op.function, - Fsqrt(op) => &op.function, - Fneg(op) => &op.function, - Fabs(op) => &op.function, - FloatToInt(op) => &op.function, - IntToFloat(op) => &op.function, - FloatConv(op) => &op.function, - RoundToInt(op) => &op.function, - Floor(op) => &op.function, - Ceil(op) => &op.function, - Ftrunc(op) => &op.function, - DerefFieldSsa(op) => &op.function, - DerefSsa(op) => &op.function, - ExternPtr(op) => &op.function, - FloatConst(op) => &op.function, - For(op) => &op.function, - ForSsa(op) => &op.function, - Goto(op) => &op.function, - Label(op) => &op.function, - If(op) => &op.function, - Intrinsic(op) => &op.function, - IntrinsicSsa(op) => &op.function, - Jump(op) => &op.function, - MemPhi(op) => &op.function, - Nop(op) => &op.function, - Break(op) => &op.function, - Continue(op) => &op.function, - Noret(op) => &op.function, - Unreachable(op) => &op.function, - Bp(op) => &op.function, - Undef(op) => &op.function, - Unimpl(op) => &op.function, - Ret(op) => &op.function, - Split(op) => &op.function, - StructField(op) => &op.function, - DerefField(op) => &op.function, - Switch(op) => &op.function, - Syscall(op) => &op.function, - SyscallSsa(op) => &op.function, - Trap(op) => &op.function, - VarDeclare(op) => &op.function, - Var(op) => &op.function, - VarInit(op) => &op.function, - VarInitSsa(op) => &op.function, - VarPhi(op) => &op.function, - VarSsa(op) => &op.function, - While(op) => &op.function, - DoWhile(op) => &op.function, - WhileSsa(op) => &op.function, - DoWhileSsa(op) => &op.function, + + pub fn lift(&self) -> HighLevelILLiftedInstruction { + use HighLevelILInstructionKind::*; + use HighLevelILLiftedInstructionKind as Lifted; + let kind = match self.kind { + Nop => Lifted::Nop, + Block(op) => Lifted::Block(LiftedBlock { + body: self.lift_instruction_list(op.first_param, op.num_params), + }), + If(op) => Lifted::If(LiftedIf { + condition: self.lift_operand(op.condition), + cond_true: self.lift_operand(op.cond_true), + cond_false: self.lift_operand(op.cond_false), + }), + While(op) => Lifted::While(self.lift_while(op)), + WhileSsa(op) => Lifted::WhileSsa(self.lift_while_ssa(op)), + DoWhile(op) => Lifted::DoWhile(self.lift_while(op)), + DoWhileSsa(op) => Lifted::DoWhileSsa(self.lift_while_ssa(op)), + For(op) => Lifted::For(LiftedForLoop { + init: self.lift_operand(op.init), + condition: self.lift_operand(op.condition), + update: self.lift_operand(op.update), + body: self.lift_operand(op.body), + }), + ForSsa(op) => Lifted::ForSsa(LiftedForLoopSsa { + init: self.lift_operand(op.init), + condition_phi: self.lift_operand(op.condition_phi), + condition: self.lift_operand(op.condition), + update: self.lift_operand(op.update), + body: self.lift_operand(op.body), + }), + Switch(op) => Lifted::Switch(LiftedSwitch { + condition: self.lift_operand(op.condition), + default: self.lift_operand(op.default), + cases: self.lift_instruction_list(op.first_case, op.num_cases), + }), + Case(op) => Lifted::Case(LiftedCase { + values: self.lift_instruction_list(op.first_value, op.num_values), + body: self.lift_operand(op.body), + }), + Break => Lifted::Break, + Continue => Lifted::Continue, + Jump(op) => Lifted::Jump(LiftedJump { + dest: self.lift_operand(op.dest), + }), + Ret(op) => Lifted::Ret(LiftedRet { + src: self.lift_instruction_list(op.first_src, op.num_srcs), + }), + Noret => Lifted::Noret, + Unreachable => Lifted::Unreachable, + Goto(op) => Lifted::Goto(self.lift_label(op)), + Label(op) => Lifted::Label(self.lift_label(op)), + VarDeclare(op) => Lifted::VarDeclare(op), + VarInit(op) => Lifted::VarInit(LiftedVarInit { + dest: op.dest, + src: self.lift_operand(op.src), + }), + VarInitSsa(op) => Lifted::VarInitSsa(LiftedVarInitSsa { + dest: op.dest, + src: self.lift_operand(op.src), + }), + Assign(op) => Lifted::Assign(LiftedAssign { + dest: self.lift_operand(op.dest), + src: self.lift_operand(op.src), + }), + AssignUnpack(op) => Lifted::AssignUnpack(LiftedAssignUnpack { + dest: self.lift_instruction_list(op.first_dest, op.num_dests), + src: self.lift_operand(op.src), + }), + AssignMemSsa(op) => Lifted::AssignMemSsa(LiftedAssignMemSsa { + dest: self.lift_operand(op.dest), + dest_memory: op.dest_memory, + src: self.lift_operand(op.src), + src_memory: op.src_memory, + }), + AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(LiftedAssignUnpackMemSsa { + dest: self.lift_instruction_list(op.first_dest, op.num_dests), + dest_memory: op.dest_memory, + src: self.lift_operand(op.src), + src_memory: op.src_memory, + }), + Var(op) => Lifted::Var(op), + VarSsa(op) => Lifted::VarSsa(op), + VarPhi(op) => Lifted::VarPhi(LiftedVarPhi { + dest: op.dest, + src: OperandIter::new(&*self.function, op.first_src, op.num_srcs) + .ssa_vars() + .collect(), + }), + MemPhi(op) => Lifted::MemPhi(LiftedMemPhi { + dest: op.dest, + src: OperandIter::new(&*self.function, op.first_src, op.num_srcs).collect(), + }), + ArrayIndex(op) => Lifted::ArrayIndex(LiftedArrayIndex { + src: self.lift_operand(op.src), + index: self.lift_operand(op.index), + }), + ArrayIndexSsa(op) => Lifted::ArrayIndexSsa(LiftedArrayIndexSsa { + src: self.lift_operand(op.src), + src_memory: op.src_memory, + index: self.lift_operand(op.index), + }), + Split(op) => Lifted::Split(LiftedSplit { + high: self.lift_operand(op.high), + low: self.lift_operand(op.low), + }), + Deref(op) => Lifted::Deref(self.lift_unary_op(op)), + StructField(op) => Lifted::StructField(self.lift_struct_field(op)), + DerefField(op) => Lifted::DerefField(self.lift_struct_field(op)), + DerefSsa(op) => Lifted::DerefSsa(LiftedDerefSsa { + src: self.lift_operand(op.src), + src_memory: op.src_memory, + }), + DerefFieldSsa(op) => Lifted::DerefFieldSsa(LiftedDerefFieldSsa { + src: self.lift_operand(op.src), + src_memory: op.src_memory, + offset: op.offset, + member_index: op.member_index, + }), + AddressOf(op) => Lifted::AddressOf(self.lift_unary_op(op)), + Const(op) => Lifted::Const(op), + ConstPtr(op) => Lifted::ConstPtr(op), + ExternPtr(op) => Lifted::ExternPtr(op), + FloatConst(op) => Lifted::FloatConst(op), + Import(op) => Lifted::Import(op), + ConstData(op) => Lifted::ConstData(LiftedConstantData { + constant_data: ConstantData::new( + self.function.get_function(), + RegisterValue { + state: RegisterValueType::from_raw_value(op.constant_data_kind).unwrap(), + value: op.constant_data_value, + offset: 0, + size: op.size, + }, + ), + }), + Add(op) => Lifted::Add(self.lift_binary_op(op)), + Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)), + Sub(op) => Lifted::Sub(self.lift_binary_op(op)), + Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)), + And(op) => Lifted::And(self.lift_binary_op(op)), + Or(op) => Lifted::Or(self.lift_binary_op(op)), + Xor(op) => Lifted::Xor(self.lift_binary_op(op)), + Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)), + Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)), + Asr(op) => Lifted::Asr(self.lift_binary_op(op)), + Rol(op) => Lifted::Rol(self.lift_binary_op(op)), + Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)), + Ror(op) => Lifted::Ror(self.lift_binary_op(op)), + Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)), + Mul(op) => Lifted::Mul(self.lift_binary_op(op)), + MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)), + MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)), + Divu(op) => Lifted::Divu(self.lift_binary_op(op)), + DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)), + Divs(op) => Lifted::Divs(self.lift_binary_op(op)), + DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)), + Modu(op) => Lifted::Modu(self.lift_binary_op(op)), + ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)), + Mods(op) => Lifted::Mods(self.lift_binary_op(op)), + ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)), + Neg(op) => Lifted::Neg(self.lift_unary_op(op)), + Not(op) => Lifted::Not(self.lift_unary_op(op)), + Sx(op) => Lifted::Sx(self.lift_unary_op(op)), + Zx(op) => Lifted::Zx(self.lift_unary_op(op)), + LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)), + Call(op) => Lifted::Call(self.lift_call(op)), + CallSsa(op) => Lifted::CallSsa(LiftedCallSsa { + dest: self.lift_operand(op.dest), + params: self.lift_instruction_list(op.first_param, op.num_params), + dest_memory: op.dest_memory, + src_memory: op.src_memory, + }), + CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)), + CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)), + CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)), + CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)), + CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)), + CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)), + CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)), + CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)), + CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)), + CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)), + TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)), + BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)), + AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)), + Syscall(op) => Lifted::Syscall(LiftedSyscall { + params: self.lift_instruction_list(op.first_param, op.num_params), + }), + SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa { + params: self.lift_instruction_list(op.first_param, op.num_params), + dest_memory: op.dest_memory, + src_memory: op.src_memory, + }), + Tailcall(op) => Lifted::Tailcall(self.lift_call(op)), + Bp => Lifted::Bp, + Trap(op) => Lifted::Trap(op), + Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic { + intrinsic: ILIntrinsic::new(self.function.get_function().arch(), op.intrinsic), + params: self.lift_instruction_list(op.first_param, op.num_params), + }), + IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa { + intrinsic: ILIntrinsic::new(self.function.get_function().arch(), op.intrinsic), + params: self.lift_instruction_list(op.first_param, op.num_params), + dest_memory: op.dest_memory, + src_memory: op.src_memory, + }), + Undef => Lifted::Undef, + Unimpl => Lifted::Unimpl, + UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)), + Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)), + Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)), + Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)), + Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)), + Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)), + Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)), + Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)), + FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)), + IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)), + FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)), + RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)), + Floor(op) => Lifted::Floor(self.lift_unary_op(op)), + Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)), + Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)), + FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)), + FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)), + FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)), + FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)), + FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)), + FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)), + FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)), + FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)), + }; + HighLevelILLiftedInstruction { + function: self.function.clone(), + address: self.address, + kind, } } - pub fn address(&self) -> u64 { - use HighLevelILInstruction::*; - match self { - Adc(op) => op.address, - Sbb(op) => op.address, - Rlc(op) => op.address, - Rrc(op) => op.address, - Add(op) => op.address, - Sub(op) => op.address, - And(op) => op.address, - Or(op) => op.address, - Xor(op) => op.address, - Lsl(op) => op.address, - Lsr(op) => op.address, - Asr(op) => op.address, - Rol(op) => op.address, - Ror(op) => op.address, - Mul(op) => op.address, - MuluDp(op) => op.address, - MulsDp(op) => op.address, - Divu(op) => op.address, - DivuDp(op) => op.address, - Divs(op) => op.address, - DivsDp(op) => op.address, - Modu(op) => op.address, - ModuDp(op) => op.address, - Mods(op) => op.address, - ModsDp(op) => op.address, - CmpE(op) => op.address, - CmpNe(op) => op.address, - CmpSlt(op) => op.address, - CmpUlt(op) => op.address, - CmpSle(op) => op.address, - CmpUle(op) => op.address, - CmpSge(op) => op.address, - CmpUge(op) => op.address, - CmpSgt(op) => op.address, - CmpUgt(op) => op.address, - TestBit(op) => op.address, - AddOverflow(op) => op.address, - Fadd(op) => op.address, - Fsub(op) => op.address, - Fmul(op) => op.address, - Fdiv(op) => op.address, - FcmpE(op) => op.address, - FcmpNe(op) => op.address, - FcmpLt(op) => op.address, - FcmpLe(op) => op.address, - FcmpGe(op) => op.address, - FcmpGt(op) => op.address, - FcmpO(op) => op.address, - FcmpUo(op) => op.address, - ArrayIndex(op) => op.address, - ArrayIndexSsa(op) => op.address, - Assign(op) => op.address, - AssignMemSsa(op) => op.address, - AssignUnpack(op) => op.address, - AssignUnpackMemSsa(op) => op.address, - Block(op) => op.address, - Call(op) => op.address, - Tailcall(op) => op.address, - CallSsa(op) => op.address, - Case(op) => op.address, - Const(op) => op.address, - ConstPtr(op) => op.address, - Import(op) => op.address, - ConstData(op) => op.address, - Deref(op) => op.address, - AddressOf(op) => op.address, - Neg(op) => op.address, - Not(op) => op.address, - Sx(op) => op.address, - Zx(op) => op.address, - LowPart(op) => op.address, - BoolToInt(op) => op.address, - UnimplMem(op) => op.address, - Fsqrt(op) => op.address, - Fneg(op) => op.address, - Fabs(op) => op.address, - FloatToInt(op) => op.address, - IntToFloat(op) => op.address, - FloatConv(op) => op.address, - RoundToInt(op) => op.address, - Floor(op) => op.address, - Ceil(op) => op.address, - Ftrunc(op) => op.address, - DerefFieldSsa(op) => op.address, - DerefSsa(op) => op.address, - ExternPtr(op) => op.address, - FloatConst(op) => op.address, - For(op) => op.address, - ForSsa(op) => op.address, - Goto(op) => op.address, - Label(op) => op.address, - If(op) => op.address, - Intrinsic(op) => op.address, - IntrinsicSsa(op) => op.address, - Jump(op) => op.address, - MemPhi(op) => op.address, - Nop(op) => op.address, - Break(op) => op.address, - Continue(op) => op.address, - Noret(op) => op.address, - Unreachable(op) => op.address, - Bp(op) => op.address, - Undef(op) => op.address, - Unimpl(op) => op.address, - Ret(op) => op.address, - Split(op) => op.address, - StructField(op) => op.address, - DerefField(op) => op.address, - Switch(op) => op.address, - Syscall(op) => op.address, - SyscallSsa(op) => op.address, - Trap(op) => op.address, - VarDeclare(op) => op.address, - Var(op) => op.address, - VarInit(op) => op.address, - VarInitSsa(op) => op.address, - VarPhi(op) => op.address, - VarSsa(op) => op.address, - While(op) => op.address, - DoWhile(op) => op.address, - WhileSsa(op) => op.address, - DoWhileSsa(op) => op.address, + + fn lift_operand(&self, expr_idx: usize) -> Box<HighLevelILLiftedInstruction> { + Box::new(self.function.lifted_instruction_from_idx(expr_idx)) + } + + fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp { + LiftedBinaryOp { + left: self.lift_operand(op.left), + right: self.lift_operand(op.right), } } - pub fn lift(&self) -> HighLevelILLiftedInstruction { - use HighLevelILInstruction::*; - use HighLevelILLiftedInstruction as Lifted; - match self { - Nop(op) => Lifted::Nop(op.clone()), - Block(op) => Lifted::Block(op.lift()), - If(op) => Lifted::If(op.lift()), - While(op) => Lifted::While(op.lift()), - WhileSsa(op) => Lifted::WhileSsa(op.lift()), - DoWhile(op) => Lifted::DoWhile(op.lift()), - DoWhileSsa(op) => Lifted::DoWhileSsa(op.lift()), - For(op) => Lifted::For(op.lift()), - ForSsa(op) => Lifted::ForSsa(op.lift()), - Switch(op) => Lifted::Switch(op.lift()), - Case(op) => Lifted::Case(op.lift()), - Break(op) => Lifted::Break(op.clone()), - Continue(op) => Lifted::Continue(op.clone()), - Jump(op) => Lifted::Jump(op.clone()), - Ret(op) => Lifted::Ret(op.lift()), - Noret(op) => Lifted::Noret(op.clone()), - Unreachable(op) => Lifted::Unreachable(op.clone()), - Goto(op) => Lifted::Goto(op.clone()), - Label(op) => Lifted::Label(op.clone()), - VarDeclare(op) => Lifted::VarDeclare(op.clone()), - VarInit(op) => Lifted::VarInit(op.lift()), - VarInitSsa(op) => Lifted::VarInitSsa(op.lift()), - Assign(op) => Lifted::Assign(op.lift()), - AssignUnpack(op) => Lifted::AssignUnpack(op.lift()), - AssignMemSsa(op) => Lifted::AssignMemSsa(op.lift()), - AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(op.lift()), - Var(op) => Lifted::Var(op.clone()), - VarSsa(op) => Lifted::VarSsa(op.clone()), - VarPhi(op) => Lifted::VarPhi(op.lift()), - MemPhi(op) => Lifted::MemPhi(op.lift()), - ArrayIndex(op) => Lifted::ArrayIndex(op.lift()), - ArrayIndexSsa(op) => Lifted::ArrayIndexSsa(op.lift()), - Split(op) => Lifted::Split(op.lift()), - Deref(op) => Lifted::Deref(op.lift()), - StructField(op) => Lifted::StructField(op.lift()), - DerefField(op) => Lifted::DerefField(op.lift()), - DerefSsa(op) => Lifted::DerefSsa(op.lift()), - DerefFieldSsa(op) => Lifted::DerefFieldSsa(op.lift()), - AddressOf(op) => Lifted::AddressOf(op.lift()), - Const(op) => Lifted::Const(op.clone()), - ConstPtr(op) => Lifted::ConstPtr(op.clone()), - ExternPtr(op) => Lifted::ExternPtr(op.clone()), - FloatConst(op) => Lifted::FloatConst(op.clone()), - Import(op) => Lifted::Import(op.clone()), - ConstData(op) => Lifted::ConstData(op.lift()), - Add(op) => Lifted::Add(op.lift()), - Adc(op) => Lifted::Adc(op.lift()), - Sub(op) => Lifted::Sub(op.lift()), - Sbb(op) => Lifted::Sbb(op.lift()), - And(op) => Lifted::And(op.lift()), - Or(op) => Lifted::Or(op.lift()), - Xor(op) => Lifted::Xor(op.lift()), - Lsl(op) => Lifted::Lsl(op.lift()), - Lsr(op) => Lifted::Lsr(op.lift()), - Asr(op) => Lifted::Asr(op.lift()), - Rol(op) => Lifted::Rol(op.lift()), - Rlc(op) => Lifted::Rlc(op.lift()), - Ror(op) => Lifted::Ror(op.lift()), - Rrc(op) => Lifted::Rrc(op.lift()), - Mul(op) => Lifted::Mul(op.lift()), - MuluDp(op) => Lifted::MuluDp(op.lift()), - MulsDp(op) => Lifted::MulsDp(op.lift()), - Divu(op) => Lifted::Divu(op.lift()), - DivuDp(op) => Lifted::DivuDp(op.lift()), - Divs(op) => Lifted::Divs(op.lift()), - DivsDp(op) => Lifted::DivsDp(op.lift()), - Modu(op) => Lifted::Modu(op.lift()), - ModuDp(op) => Lifted::ModuDp(op.lift()), - Mods(op) => Lifted::Mods(op.lift()), - ModsDp(op) => Lifted::ModsDp(op.lift()), - Neg(op) => Lifted::Neg(op.lift()), - Not(op) => Lifted::Not(op.lift()), - Sx(op) => Lifted::Sx(op.lift()), - Zx(op) => Lifted::Zx(op.lift()), - LowPart(op) => Lifted::LowPart(op.lift()), - Call(op) => Lifted::Call(op.lift()), - CallSsa(op) => Lifted::CallSsa(op.lift()), - CmpE(op) => Lifted::CmpE(op.lift()), - CmpNe(op) => Lifted::CmpNe(op.lift()), - CmpSlt(op) => Lifted::CmpSlt(op.lift()), - CmpUlt(op) => Lifted::CmpUlt(op.lift()), - CmpSle(op) => Lifted::CmpSle(op.lift()), - CmpUle(op) => Lifted::CmpUle(op.lift()), - CmpSge(op) => Lifted::CmpSge(op.lift()), - CmpUge(op) => Lifted::CmpUge(op.lift()), - CmpSgt(op) => Lifted::CmpSgt(op.lift()), - CmpUgt(op) => Lifted::CmpUgt(op.lift()), - TestBit(op) => Lifted::TestBit(op.lift()), - BoolToInt(op) => Lifted::BoolToInt(op.lift()), - AddOverflow(op) => Lifted::AddOverflow(op.lift()), - Syscall(op) => Lifted::Syscall(op.lift()), - SyscallSsa(op) => Lifted::SyscallSsa(op.lift()), - Tailcall(op) => Lifted::Tailcall(op.lift()), - Bp(op) => Lifted::Bp(op.clone()), - Trap(op) => Lifted::Trap(op.clone()), - Intrinsic(op) => Lifted::Intrinsic(op.lift()), - IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift()), - Undef(op) => Lifted::Undef(op.clone()), - Unimpl(op) => Lifted::Unimpl(op.clone()), - UnimplMem(op) => Lifted::UnimplMem(op.lift()), - Fadd(op) => Lifted::Fadd(op.lift()), - Fsub(op) => Lifted::Fsub(op.lift()), - Fmul(op) => Lifted::Fmul(op.lift()), - Fdiv(op) => Lifted::Fdiv(op.lift()), - Fsqrt(op) => Lifted::Fsqrt(op.lift()), - Fneg(op) => Lifted::Fneg(op.lift()), - Fabs(op) => Lifted::Fabs(op.lift()), - FloatToInt(op) => Lifted::FloatToInt(op.lift()), - IntToFloat(op) => Lifted::IntToFloat(op.lift()), - FloatConv(op) => Lifted::FloatConv(op.lift()), - RoundToInt(op) => Lifted::RoundToInt(op.lift()), - Floor(op) => Lifted::Floor(op.lift()), - Ceil(op) => Lifted::Ceil(op.lift()), - Ftrunc(op) => Lifted::Ftrunc(op.lift()), - FcmpE(op) => Lifted::FcmpE(op.lift()), - FcmpNe(op) => Lifted::FcmpNe(op.lift()), - FcmpLt(op) => Lifted::FcmpLt(op.lift()), - FcmpLe(op) => Lifted::FcmpLe(op.lift()), - FcmpGe(op) => Lifted::FcmpGe(op.lift()), - FcmpGt(op) => Lifted::FcmpGt(op.lift()), - FcmpO(op) => Lifted::FcmpO(op.lift()), - FcmpUo(op) => Lifted::FcmpUo(op.lift()), + + fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry { + LiftedBinaryOpCarry { + left: self.lift_operand(op.left), + right: self.lift_operand(op.right), + carry: self.lift_operand(op.carry), } } - pub fn operands<'a>( - &'a self, - ) -> Box<dyn Iterator<Item = (&'static str, HighLevelILOperand)> + 'a> { - use HighLevelILInstruction::*; - match self { - Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands()), - Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op) - | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op) - | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op) - | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op) - | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | Fadd(op) - | Fsub(op) | Fmul(op) | Fdiv(op) | FcmpE(op) | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) - | FcmpGe(op) | FcmpGt(op) | FcmpO(op) | FcmpUo(op) => Box::new(op.operands()), - ArrayIndex(op) => Box::new(op.operands()), - ArrayIndexSsa(op) => Box::new(op.operands()), - Assign(op) => Box::new(op.operands()), - AssignMemSsa(op) => Box::new(op.operands()), - AssignUnpack(op) => Box::new(op.operands()), - AssignUnpackMemSsa(op) => Box::new(op.operands()), - Block(op) => Box::new(op.operands()), - Call(op) | Tailcall(op) => Box::new(op.operands()), - CallSsa(op) => Box::new(op.operands()), - Case(op) => Box::new(op.operands()), - Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()), - ConstData(op) => Box::new(op.operands()), - Deref(op) | AddressOf(op) | Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) - | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) - | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op) - | Ftrunc(op) => Box::new(op.operands()), - DerefFieldSsa(op) => Box::new(op.operands()), - DerefSsa(op) => Box::new(op.operands()), - ExternPtr(op) => Box::new(op.operands()), - FloatConst(op) => Box::new(op.operands()), - For(op) => Box::new(op.operands()), - ForSsa(op) => Box::new(op.operands()), - Goto(op) | Label(op) => Box::new(op.operands()), - If(op) => Box::new(op.operands()), - Intrinsic(op) => Box::new(op.operands()), - IntrinsicSsa(op) => Box::new(op.operands()), - Jump(op) => Box::new(op.operands()), - MemPhi(op) => Box::new(op.operands()), - Nop(op) | Break(op) | Continue(op) | Noret(op) | Unreachable(op) | Bp(op) - | Undef(op) | Unimpl(op) => Box::new(op.operands()), - Ret(op) => Box::new(op.operands()), - Split(op) => Box::new(op.operands()), - StructField(op) | DerefField(op) => Box::new(op.operands()), - Switch(op) => Box::new(op.operands()), - Syscall(op) => Box::new(op.operands()), - SyscallSsa(op) => Box::new(op.operands()), - Trap(op) => Box::new(op.operands()), - VarDeclare(op) | Var(op) => Box::new(op.operands()), - VarInit(op) => Box::new(op.operands()), - VarInitSsa(op) => Box::new(op.operands()), - VarPhi(op) => Box::new(op.operands()), - VarSsa(op) => Box::new(op.operands()), - While(op) | DoWhile(op) => Box::new(op.operands()), - WhileSsa(op) | DoWhileSsa(op) => Box::new(op.operands()), + + fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp { + LiftedUnaryOp { + src: self.lift_operand(op.src), } } + + fn lift_label(&self, op: Label) -> LiftedLabel { + LiftedLabel { + target: GotoLabel { + function: self.function.get_function(), + target: op.target, + }, + } + } + + fn lift_call(&self, op: Call) -> LiftedCall { + LiftedCall { + dest: self.lift_operand(op.dest), + params: OperandIter::new(&*self.function, op.first_param, op.num_params) + .exprs() + .map(|expr| expr.lift()) + .collect(), + } + } + + fn lift_while(&self, op: While) -> LiftedWhile { + LiftedWhile { + condition: self.lift_operand(op.condition), + body: self.lift_operand(op.body), + } + } + + fn lift_while_ssa(&self, op: WhileSsa) -> LiftedWhileSsa { + LiftedWhileSsa { + condition_phi: self.lift_operand(op.condition_phi), + condition: self.lift_operand(op.condition), + body: self.lift_operand(op.body), + } + } + + fn lift_struct_field(&self, op: StructField) -> LiftedStructField { + LiftedStructField { + src: self.lift_operand(op.src), + offset: op.offset, + member_index: op.member_index, + } + } + + fn lift_instruction_list( + &self, + first_instruction: usize, + num_instructions: usize, + ) -> Vec<HighLevelILLiftedInstruction> { + OperandIter::new(&*self.function, first_instruction, num_instructions) + .exprs() + .map(|expr| expr.lift()) + .collect() + } } impl core::fmt::Debug for HighLevelILInstruction { @@ -1276,7 +870,7 @@ impl core::fmt::Debug for HighLevelILInstruction { f, "<{} at 0x{:08}>", core::any::type_name::<Self>(), - self.address(), + self.address, ) } } diff --git a/rust/src/hlil/lift.rs b/rust/src/hlil/lift.rs index 5ed7a33c..06338dea 100644 --- a/rust/src/hlil/lift.rs +++ b/rust/src/hlil/lift.rs @@ -1,7 +1,33 @@ use super::{operation::*, HighLevelILFunction}; +use crate::rc::Ref; +use crate::types::{ConstantData, ILIntrinsic, SSAVariable, Variable}; + +#[derive(Clone)] +pub enum HighLevelILLiftedOperand { + ConstantData(ConstantData), + Expr(HighLevelILLiftedInstruction), + ExprList(Vec<HighLevelILLiftedInstruction>), + Float(f64), + Int(u64), + IntList(Vec<u64>), + Intrinsic(ILIntrinsic), + Label(GotoLabel), + MemberIndex(Option<usize>), + Var(Variable), + VarSsa(SSAVariable), + VarSsaList(Vec<SSAVariable>), +} + #[derive(Clone, Debug, PartialEq)] -pub enum HighLevelILLiftedInstruction { +pub struct HighLevelILLiftedInstruction { + pub function: Ref<HighLevelILFunction>, + pub address: u64, + pub kind: HighLevelILLiftedInstructionKind, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum HighLevelILLiftedInstructionKind { Adc(LiftedBinaryOpCarry), Sbb(LiftedBinaryOpCarry), Rlc(LiftedBinaryOpCarry), @@ -91,21 +117,21 @@ pub enum HighLevelILLiftedInstruction { FloatConst(FloatConst), For(LiftedForLoop), ForSsa(LiftedForLoopSsa), - Goto(Label), - Label(Label), + Goto(LiftedLabel), + Label(LiftedLabel), If(LiftedIf), Intrinsic(LiftedIntrinsic), IntrinsicSsa(LiftedIntrinsicSsa), - Jump(Jump), + Jump(LiftedJump), MemPhi(LiftedMemPhi), - Nop(NoArgs), - Break(NoArgs), - Continue(NoArgs), - Noret(NoArgs), - Unreachable(NoArgs), - Bp(NoArgs), - Undef(NoArgs), - Unimpl(NoArgs), + Nop, + Break, + Continue, + Noret, + Unreachable, + Bp, + Undef, + Unimpl, Ret(LiftedRet), Split(LiftedSplit), StructField(LiftedStructField), @@ -127,259 +153,173 @@ pub enum HighLevelILLiftedInstruction { } impl HighLevelILLiftedInstruction { - pub fn address(&self) -> u64 { - use HighLevelILLiftedInstruction::*; - match self { - Adc(op) => op.address, - Sbb(op) => op.address, - Rlc(op) => op.address, - Rrc(op) => op.address, - Add(op) => op.address, - Sub(op) => op.address, - And(op) => op.address, - Or(op) => op.address, - Xor(op) => op.address, - Lsl(op) => op.address, - Lsr(op) => op.address, - Asr(op) => op.address, - Rol(op) => op.address, - Ror(op) => op.address, - Mul(op) => op.address, - MuluDp(op) => op.address, - MulsDp(op) => op.address, - Divu(op) => op.address, - DivuDp(op) => op.address, - Divs(op) => op.address, - DivsDp(op) => op.address, - Modu(op) => op.address, - ModuDp(op) => op.address, - Mods(op) => op.address, - ModsDp(op) => op.address, - CmpE(op) => op.address, - CmpNe(op) => op.address, - CmpSlt(op) => op.address, - CmpUlt(op) => op.address, - CmpSle(op) => op.address, - CmpUle(op) => op.address, - CmpSge(op) => op.address, - CmpUge(op) => op.address, - CmpSgt(op) => op.address, - CmpUgt(op) => op.address, - TestBit(op) => op.address, - AddOverflow(op) => op.address, - Fadd(op) => op.address, - Fsub(op) => op.address, - Fmul(op) => op.address, - Fdiv(op) => op.address, - FcmpE(op) => op.address, - FcmpNe(op) => op.address, - FcmpLt(op) => op.address, - FcmpLe(op) => op.address, - FcmpGe(op) => op.address, - FcmpGt(op) => op.address, - FcmpO(op) => op.address, - FcmpUo(op) => op.address, - ArrayIndex(op) => op.address, - ArrayIndexSsa(op) => op.address, - Assign(op) => op.address, - AssignMemSsa(op) => op.address, - AssignUnpack(op) => op.address, - AssignUnpackMemSsa(op) => op.address, - Block(op) => op.address, - Call(op) => op.address, - Tailcall(op) => op.address, - CallSsa(op) => op.address, - Case(op) => op.address, - Const(op) => op.address, - ConstPtr(op) => op.address, - Import(op) => op.address, - ConstData(op) => op.address, - Deref(op) => op.address, - AddressOf(op) => op.address, - Neg(op) => op.address, - Not(op) => op.address, - Sx(op) => op.address, - Zx(op) => op.address, - LowPart(op) => op.address, - BoolToInt(op) => op.address, - UnimplMem(op) => op.address, - Fsqrt(op) => op.address, - Fneg(op) => op.address, - Fabs(op) => op.address, - FloatToInt(op) => op.address, - IntToFloat(op) => op.address, - FloatConv(op) => op.address, - RoundToInt(op) => op.address, - Floor(op) => op.address, - Ceil(op) => op.address, - Ftrunc(op) => op.address, - DerefFieldSsa(op) => op.address, - DerefSsa(op) => op.address, - ExternPtr(op) => op.address, - FloatConst(op) => op.address, - For(op) => op.address, - ForSsa(op) => op.address, - Goto(op) => op.address, - Label(op) => op.address, - If(op) => op.address, - Intrinsic(op) => op.address, - IntrinsicSsa(op) => op.address, - Jump(op) => op.address, - MemPhi(op) => op.address, - Nop(op) => op.address, - Break(op) => op.address, - Continue(op) => op.address, - Noret(op) => op.address, - Unreachable(op) => op.address, - Bp(op) => op.address, - Undef(op) => op.address, - Unimpl(op) => op.address, - Ret(op) => op.address, - Split(op) => op.address, - StructField(op) => op.address, - DerefField(op) => op.address, - Switch(op) => op.address, - Syscall(op) => op.address, - SyscallSsa(op) => op.address, - Trap(op) => op.address, - VarDeclare(op) => op.address, - Var(op) => op.address, - VarInit(op) => op.address, - VarInitSsa(op) => op.address, - VarPhi(op) => op.address, - VarSsa(op) => op.address, - While(op) => op.address, - DoWhile(op) => op.address, - WhileSsa(op) => op.address, - DoWhileSsa(op) => op.address, - } - } - - pub fn function(&self) -> &HighLevelILFunction { - use HighLevelILLiftedInstruction::*; - match self { - Adc(op) => &op.function, - Sbb(op) => &op.function, - Rlc(op) => &op.function, - Rrc(op) => &op.function, - Add(op) => &op.function, - Sub(op) => &op.function, - And(op) => &op.function, - Or(op) => &op.function, - Xor(op) => &op.function, - Lsl(op) => &op.function, - Lsr(op) => &op.function, - Asr(op) => &op.function, - Rol(op) => &op.function, - Ror(op) => &op.function, - Mul(op) => &op.function, - MuluDp(op) => &op.function, - MulsDp(op) => &op.function, - Divu(op) => &op.function, - DivuDp(op) => &op.function, - Divs(op) => &op.function, - DivsDp(op) => &op.function, - Modu(op) => &op.function, - ModuDp(op) => &op.function, - Mods(op) => &op.function, - ModsDp(op) => &op.function, - CmpE(op) => &op.function, - CmpNe(op) => &op.function, - CmpSlt(op) => &op.function, - CmpUlt(op) => &op.function, - CmpSle(op) => &op.function, - CmpUle(op) => &op.function, - CmpSge(op) => &op.function, - CmpUge(op) => &op.function, - CmpSgt(op) => &op.function, - CmpUgt(op) => &op.function, - TestBit(op) => &op.function, - AddOverflow(op) => &op.function, - Fadd(op) => &op.function, - Fsub(op) => &op.function, - Fmul(op) => &op.function, - Fdiv(op) => &op.function, - FcmpE(op) => &op.function, - FcmpNe(op) => &op.function, - FcmpLt(op) => &op.function, - FcmpLe(op) => &op.function, - FcmpGe(op) => &op.function, - FcmpGt(op) => &op.function, - FcmpO(op) => &op.function, - FcmpUo(op) => &op.function, - ArrayIndex(op) => &op.function, - ArrayIndexSsa(op) => &op.function, - Assign(op) => &op.function, - AssignMemSsa(op) => &op.function, - AssignUnpack(op) => &op.function, - AssignUnpackMemSsa(op) => &op.function, - Block(op) => &op.function, - Call(op) => &op.function, - Tailcall(op) => &op.function, - CallSsa(op) => &op.function, - Case(op) => &op.function, - Const(op) => &op.function, - ConstPtr(op) => &op.function, - Import(op) => &op.function, - ConstData(op) => &op.function, - Deref(op) => &op.function, - AddressOf(op) => &op.function, - Neg(op) => &op.function, - Not(op) => &op.function, - Sx(op) => &op.function, - Zx(op) => &op.function, - LowPart(op) => &op.function, - BoolToInt(op) => &op.function, - UnimplMem(op) => &op.function, - Fsqrt(op) => &op.function, - Fneg(op) => &op.function, - Fabs(op) => &op.function, - FloatToInt(op) => &op.function, - IntToFloat(op) => &op.function, - FloatConv(op) => &op.function, - RoundToInt(op) => &op.function, - Floor(op) => &op.function, - Ceil(op) => &op.function, - Ftrunc(op) => &op.function, - DerefFieldSsa(op) => &op.function, - DerefSsa(op) => &op.function, - ExternPtr(op) => &op.function, - FloatConst(op) => &op.function, - For(op) => &op.function, - ForSsa(op) => &op.function, - Goto(op) => &op.function, - Label(op) => &op.function, - If(op) => &op.function, - Intrinsic(op) => &op.function, - IntrinsicSsa(op) => &op.function, - Jump(op) => &op.function, - MemPhi(op) => &op.function, - Nop(op) => &op.function, - Break(op) => &op.function, - Continue(op) => &op.function, - Noret(op) => &op.function, - Unreachable(op) => &op.function, - Bp(op) => &op.function, - Undef(op) => &op.function, - Unimpl(op) => &op.function, - Ret(op) => &op.function, - Split(op) => &op.function, - StructField(op) => &op.function, - DerefField(op) => &op.function, - Switch(op) => &op.function, - Syscall(op) => &op.function, - SyscallSsa(op) => &op.function, - Trap(op) => &op.function, - VarDeclare(op) => &op.function, - Var(op) => &op.function, - VarInit(op) => &op.function, - VarInitSsa(op) => &op.function, - VarPhi(op) => &op.function, - VarSsa(op) => &op.function, - While(op) => &op.function, - DoWhile(op) => &op.function, - WhileSsa(op) => &op.function, - DoWhileSsa(op) => &op.function, + pub fn operands(&self) -> Vec<(&'static str, HighLevelILLiftedOperand)> { + use HighLevelILLiftedInstructionKind::*; + use HighLevelILLiftedOperand as Operand; + match &self.kind { + Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![ + ("left", Operand::Expr(*op.left.clone())), + ("right", Operand::Expr(*op.right.clone())), + ("carry", Operand::Expr(*op.carry.clone())), + ], + Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op) + | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op) + | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op) + | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op) + | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | Fadd(op) + | Fsub(op) | Fmul(op) | Fdiv(op) | FcmpE(op) | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) + | FcmpGe(op) | FcmpGt(op) | FcmpO(op) | FcmpUo(op) => vec![ + ("left", Operand::Expr(*op.left.clone())), + ("right", Operand::Expr(*op.right.clone())), + ], + ArrayIndex(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("index", Operand::Expr(*op.index.clone())), + ], + ArrayIndexSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ("index", Operand::Expr(*op.index.clone())), + ], + Assign(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("src", Operand::Expr(*op.src.clone())), + ], + AssignMemSsa(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + AssignUnpack(op) => vec![ + ("dest", Operand::ExprList(op.dest.clone())), + ("src", Operand::Expr(*op.src.clone())), + ], + AssignUnpackMemSsa(op) => vec![ + ("dest", Operand::ExprList(op.dest.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + Block(op) => vec![("body", Operand::ExprList(op.body.clone()))], + Call(op) | Tailcall(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ], + CallSsa(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ], + Case(op) => vec![ + ("values", Operand::ExprList(op.values.clone())), + ("body", Operand::Expr(*op.body.clone())), + ], + Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))], + ConstData(op) => vec![( + "constant_data", + Operand::ConstantData(op.constant_data.clone()), + )], + Deref(op) | AddressOf(op) | Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) + | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) + | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op) + | Ftrunc(op) => vec![("src", Operand::Expr(*op.src.clone()))], + DerefFieldSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ("offset", Operand::Int(op.offset)), + ("member_index", Operand::MemberIndex(op.member_index)), + ], + DerefSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + ExternPtr(op) => vec![ + ("constant", Operand::Int(op.constant)), + ("offset", Operand::Int(op.offset)), + ], + FloatConst(op) => vec![("constant", Operand::Float(op.constant))], + For(op) => vec![ + ("init", Operand::Expr(*op.init.clone())), + ("condition", Operand::Expr(*op.condition.clone())), + ("update", Operand::Expr(*op.update.clone())), + ("body", Operand::Expr(*op.body.clone())), + ], + ForSsa(op) => vec![ + ("init", Operand::Expr(*op.init.clone())), + ("condition_phi", Operand::Expr(*op.condition_phi.clone())), + ("condition", Operand::Expr(*op.condition.clone())), + ("update", Operand::Expr(*op.update.clone())), + ("body", Operand::Expr(*op.body.clone())), + ], + Goto(op) | Label(op) => vec![("target", Operand::Label(op.target.clone()))], + If(op) => vec![ + ("condition", Operand::Expr(*op.condition.clone())), + ("cond_true", Operand::Expr(*op.cond_true.clone())), + ("cond_false", Operand::Expr(*op.cond_false.clone())), + ], + Intrinsic(op) => vec![ + ("intrinsic", Operand::Intrinsic(op.intrinsic)), + ("params", Operand::ExprList(op.params.clone())), + ], + IntrinsicSsa(op) => vec![ + ("intrinsic", Operand::Intrinsic(op.intrinsic)), + ("params", Operand::ExprList(op.params.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ], + Jump(op) => vec![("dest", Operand::Expr(*op.dest.clone()))], + MemPhi(op) => vec![ + ("dest", Operand::Int(op.dest)), + ("src", Operand::IntList(op.src.clone())), + ], + Nop | Break | Continue | Noret | Unreachable | Bp | Undef | Unimpl => vec![], + Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))], + Split(op) => vec![ + ("high", Operand::Expr(*op.high.clone())), + ("low", Operand::Expr(*op.low.clone())), + ], + StructField(op) | DerefField(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("offset", Operand::Int(op.offset)), + ("member_index", Operand::MemberIndex(op.member_index)), + ], + Switch(op) => vec![ + ("condition", Operand::Expr(*op.condition.clone())), + ("default", Operand::Expr(*op.default.clone())), + ("cases", Operand::ExprList(op.cases.clone())), + ], + Syscall(op) => vec![("params", Operand::ExprList(op.params.clone()))], + SyscallSsa(op) => vec![ + ("params", Operand::ExprList(op.params.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ], + Trap(op) => vec![("vector", Operand::Int(op.vector))], + VarDeclare(op) | Var(op) => vec![("var", Operand::Var(op.var))], + VarInit(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("src", Operand::Expr(*op.src.clone())), + ], + VarInitSsa(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("src", Operand::Expr(*op.src.clone())), + ], + VarPhi(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("src", Operand::VarSsaList(op.src.clone())), + ], + VarSsa(op) => vec![("var", Operand::VarSsa(op.var))], + While(op) | DoWhile(op) => vec![ + ("condition", Operand::Expr(*op.condition.clone())), + ("body", Operand::Expr(*op.body.clone())), + ], + WhileSsa(op) | DoWhileSsa(op) => vec![ + ("condition_phi", Operand::Expr(*op.condition_phi.clone())), + ("condition", Operand::Expr(*op.condition.clone())), + ("body", Operand::Expr(*op.body.clone())), + ], } } } diff --git a/rust/src/hlil/operation.rs b/rust/src/hlil/operation.rs index 769861e0..eeb322e3 100644 --- a/rust/src/hlil/operation.rs +++ b/rust/src/hlil/operation.rs @@ -1,201 +1,11 @@ use binaryninjacore_sys::BNFromVariableIdentifier; use binaryninjacore_sys::BNGetGotoLabelName; -use binaryninjacore_sys::BNGetHighLevelILByIndex; -use binaryninjacore_sys::BNHighLevelILInstruction; -use binaryninjacore_sys::BNHighLevelILOperation; use crate::function::Function; use crate::rc::Ref; -use crate::types::{ - ConstantData, ILIntrinsic, RegisterValue, RegisterValueType, SSAVariable, Variable, -}; +use crate::types::{ConstantData, ILIntrinsic, SSAVariable, Variable}; -use super::{HighLevelILFunction, HighLevelILInstruction, HighLevelILLiftedInstruction}; - -pub enum HighLevelILOperand { - ConstantData(ConstantData), - Expr(HighLevelILInstruction), - ExprList(OperandExprList), - Float(f64), - Int(u64), - IntList(OperandList), - Intrinsic(ILIntrinsic), - Label(GotoLabel), - MemberIndex(Option<usize>), - Var(Variable), - VarSsa(SSAVariable), - VarSsaList(OperandSSAVariableList), -} - -// Iterator for the get_list, this is better then a inline iterator because -// this also implement ExactSizeIterator, what a inline iterator does not. -pub struct OperandList { - function: Ref<HighLevelILFunction>, - remaining: usize, - next_node_idx: Option<usize>, - - current_node: core::array::IntoIter<u64, 4>, -} -impl OperandList { - fn new(function: &HighLevelILFunction, idx: usize, number: usize) -> Self { - // alternative to core::array::IntoIter::empty(); - let mut iter = [0; 4].into_iter(); - for _ in 0..4 { - let _ = iter.next(); - } - Self { - function: function.to_owned(), - remaining: number, - next_node_idx: Some(idx), - current_node: iter, - } - } - fn double(self) -> OperandDubleList { - assert_eq!(self.len() % 2, 0); - OperandDubleList(self) - } - fn map_expr(self) -> OperandExprList { - OperandExprList(self) - } - fn map_ssa_var(self) -> OperandSSAVariableList { - OperandSSAVariableList(self.double()) - } -} -impl Iterator for OperandList { - type Item = u64; - - fn next(&mut self) -> Option<Self::Item> { - // if there is an item in this node, return it - if let Some(current_node) = self.current_node.next() { - return Some(current_node); - } - - // no more items to fetch - if self.remaining == 0 { - return None; - } - - // otherwise get the next node - let next_idx = self.next_node_idx?; - let node = get_raw_operation(&self.function, next_idx); - assert_eq!(node.operation, BNHighLevelILOperation::HLIL_UNDEF); - - // each node contains at most 4, the last is reserved to next node idx - let consume = if self.remaining > 4 { - // there are more nodes after this one - self.next_node_idx = Some(node.operands[4] as usize); - self.remaining -= 4; - &node.operands[0..4] - } else { - // last part of the list, there is no next node - self.next_node_idx = None; - let nodes = &node.operands[0..self.remaining]; - self.remaining = 0; - nodes - }; - // the iter need to have a space of 4, but we may have less then that, - // solution is create a dummy elements at the start and discard it - let mut nodes = [0; 4]; - let dummy_values = 4 - consume.len(); - nodes[dummy_values..4].copy_from_slice(consume); - self.current_node = nodes.into_iter(); - for _ in 0..dummy_values { - let _ = self.current_node.next(); - } - - self.current_node.next() - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } -} -impl ExactSizeIterator for OperandList { - fn len(&self) -> usize { - self.remaining + self.current_node.len() - } -} - -// Iterator similar to OperationList, but returns two elements -pub struct OperandDubleList(OperandList); -impl Iterator for OperandDubleList { - type Item = (u64, u64); - - fn next(&mut self) -> Option<Self::Item> { - let first = self.0.next()?; - let second = self.0.next().unwrap(); - Some((first, second)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } -} -impl ExactSizeIterator for OperandDubleList { - fn len(&self) -> usize { - self.0.len() / 2 - } -} - -pub struct OperandExprList(OperandList); -impl Iterator for OperandExprList { - type Item = HighLevelILInstruction; - - fn next(&mut self) -> Option<Self::Item> { - self.0 - .next() - .map(|idx| get_instruction(&self.0.function, idx as usize)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.0.len(), Some(self.0.len())) - } -} -impl ExactSizeIterator for OperandExprList { - fn len(&self) -> usize { - self.0.len() - } -} - -pub struct OperandVariableList(OperandList); -impl Iterator for OperandVariableList { - type Item = Variable; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().map(get_var) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.0.len(), Some(self.0.len())) - } -} -impl ExactSizeIterator for OperandVariableList { - fn len(&self) -> usize { - self.0.len() - } -} - -pub struct OperandSSAVariableList(OperandDubleList); -impl Iterator for OperandSSAVariableList { - type Item = SSAVariable; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().map(|(id, version)| { - let raw = unsafe { BNFromVariableIdentifier(id) }; - let var = unsafe { Variable::from_raw(raw) }; - SSAVariable::new(var, version as usize) - }) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } -} -impl ExactSizeIterator for OperandSSAVariableList { - fn len(&self) -> usize { - self.0.len() - } -} +use super::HighLevelILLiftedInstruction; fn get_float(value: u64, size: usize) -> f64 { match size { @@ -206,22 +16,6 @@ fn get_float(value: u64, size: usize) -> f64 { } } -fn get_instruction(function: &HighLevelILFunction, idx: usize) -> HighLevelILInstruction { - function.instruction_from_idx(idx) -} - -fn get_instruction_list(function: &HighLevelILFunction, list: (usize, usize)) -> OperandExprList { - OperandList::new(function, list.1, list.0).map_expr() -} - -fn get_int_list(function: &HighLevelILFunction, list: (usize, usize)) -> OperandList { - OperandList::new(function, list.1, list.0) -} - -fn get_raw_operation(function: &HighLevelILFunction, idx: usize) -> BNHighLevelILInstruction { - unsafe { BNGetHighLevelILByIndex(function.handle, idx, function.full_ast) } -} - fn get_var(id: u64) -> Variable { unsafe { Variable::from_raw(BNFromVariableIdentifier(id)) } } @@ -236,17 +30,10 @@ fn get_var_ssa(input: (u64, usize)) -> SSAVariable { SSAVariable::new(var, input.1) } -fn get_var_ssa_list( - function: &HighLevelILFunction, - list: (usize, usize), -) -> OperandSSAVariableList { - OperandList::new(function, list.1, list.0).map_ssa_var() -} - #[derive(Clone, Debug, PartialEq, Eq)] pub struct GotoLabel { - function: Ref<Function>, - target: u64, + pub(crate) function: Ref<Function>, + pub(crate) target: u64, } impl GotoLabel { @@ -258,419 +45,157 @@ impl GotoLabel { } // ADC, SBB, RLC, RRC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct BinaryOpCarry { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - left: usize, - right: usize, - carry: usize, + pub left: usize, + pub right: usize, + pub carry: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBinaryOpCarry { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub left: Box<HighLevelILLiftedInstruction>, pub right: Box<HighLevelILLiftedInstruction>, pub carry: Box<HighLevelILLiftedInstruction>, } impl BinaryOpCarry { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - left: usize, - right: usize, - carry: usize, - ) -> Self { - Self { - function, - address, - left, - right, - carry, - } - } - pub fn left(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.left) - } - pub fn right(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.right) - } - pub fn carry(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.carry) - } - pub fn lift(&self) -> LiftedBinaryOpCarry { - LiftedBinaryOpCarry { - function: self.function.to_owned(), - address: self.address, - left: Box::new(self.left().lift()), - right: Box::new(self.right().lift()), - carry: Box::new(self.carry().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("left", Expr(self.left())), - 1usize => ("right", Expr(self.right())), - 2usize => ("carry", Expr(self.carry())), - _ => unreachable!(), - }) + pub(crate) fn new(left: usize, right: usize, carry: usize) -> Self { + Self { left, right, carry } } } + // ADD, SUB, AND, OR, XOR, LSL, LSR, ASR, ROL, ROR, MUL, MULU_DP, MULS_DP, DIVU, DIVU_DP, DIVS, DIVS_DP, MODU, MODU_DP, MODS, MODS_DP, CMP_E, CMP_NE, CMP_SLT, CMP_ULT, CMP_SLE, CMP_ULE, CMP_SGE, CMP_UGE, CMP_SGT, CMP_UGT, TEST_BIT, ADD_OVERFLOW, FADD, FSUB, FMUL, FDIV, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct BinaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - left: usize, - right: usize, + pub left: usize, + pub right: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBinaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub left: Box<HighLevelILLiftedInstruction>, pub right: Box<HighLevelILLiftedInstruction>, } impl BinaryOp { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - left: usize, - right: usize, - ) -> Self { - Self { - function, - address, - left, - right, - } - } - pub fn left(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.left) - } - pub fn right(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.right) - } - pub fn lift(&self) -> LiftedBinaryOp { - LiftedBinaryOp { - function: self.function.to_owned(), - address: self.address, - left: Box::new(self.left().lift()), - right: Box::new(self.right().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("left", Expr(self.left())), - 1usize => ("right", Expr(self.right())), - _ => unreachable!(), - }) + pub(crate) fn new(left: usize, right: usize) -> Self { + Self { left, right } } } + // ARRAY_INDEX -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ArrayIndex { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - index: usize, + pub src: usize, + pub index: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedArrayIndex { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub index: Box<HighLevelILLiftedInstruction>, } impl ArrayIndex { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - index: usize, - ) -> Self { - Self { - function, - address, - src, - index, - } - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn index(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.index) - } - pub fn lift(&self) -> LiftedArrayIndex { - LiftedArrayIndex { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - index: Box::new(self.index().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("index", Expr(self.index())), - _ => unreachable!(), - }) + pub(crate) fn new(src: usize, index: usize) -> Self { + Self { src, index } } } + // ARRAY_INDEX_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ArrayIndexSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, - index: usize, + pub src: usize, + pub src_memory: u64, + pub index: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedArrayIndexSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, pub index: Box<HighLevelILLiftedInstruction>, } impl ArrayIndexSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - index: usize, - ) -> Self { + pub(crate) fn new(src: usize, src_memory: u64, index: usize) -> Self { Self { - function, - address, src, src_memory, index, } } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn index(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.index) - } - pub fn lift(&self) -> LiftedArrayIndexSsa { - LiftedArrayIndexSsa { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - index: Box::new(self.index().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("src_memory", Int(self.src_memory())), - 2usize => ("index", Expr(self.index())), - _ => unreachable!(), - }) - } } + // ASSIGN -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Assign { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - src: usize, + pub dest: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssign { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub src: Box<HighLevelILLiftedInstruction>, } impl Assign { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: usize, - src: usize, - ) -> Self { - Self { - function, - address, - dest, - src, - } - } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedAssign { - LiftedAssign { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) + pub(crate) fn new(dest: usize, src: usize) -> Self { + Self { dest, src } } } + // ASSIGN_MEM_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct AssignMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - dest_memory: u64, - src: usize, - src_memory: u64, + pub dest: usize, + pub dest_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssignMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub dest_memory: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, } impl AssignMemSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: usize, - dest_memory: u64, - src: usize, - src_memory: u64, - ) -> Self { + pub(crate) fn new(dest: usize, dest_memory: u64, src: usize, src_memory: u64) -> Self { Self { - function, - address, dest, dest_memory, src, src_memory, } } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedAssignMemSsa { - LiftedAssignMemSsa { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - dest_memory: self.dest_memory, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("dest_memory", Int(self.dest_memory())), - 2usize => ("src", Expr(self.src())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // ASSIGN_UNPACK -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct AssignUnpack { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: (usize, usize), - src: usize, + pub first_dest: usize, + pub num_dests: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssignUnpack { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Vec<HighLevelILLiftedInstruction>, pub src: Box<HighLevelILLiftedInstruction>, } impl AssignUnpack { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (usize, usize), - src: usize, - ) -> Self { + pub(crate) fn new(num_dests: usize, first_dest: usize, src: usize) -> Self { Self { - function, - address, - dest, + num_dests, + first_dest, src, } } - pub fn dest(&self) -> OperandExprList { - get_instruction_list(&self.function, self.dest) - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedAssignUnpack { - LiftedAssignUnpack { - function: self.function.to_owned(), - address: self.address, - dest: self.dest().map(|x| x.lift()).collect(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", ExprList(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) - } } + // ASSIGN_UNPACK_MEM_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct AssignUnpackMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: (usize, usize), - dest_memory: u64, - src: usize, - src_memory: u64, + pub first_dest: usize, + pub num_dests: usize, + pub dest_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedAssignUnpackMemSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, pub src: Box<HighLevelILLiftedInstruction>, @@ -678,164 +203,74 @@ pub struct LiftedAssignUnpackMemSsa { } impl AssignUnpackMemSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (usize, usize), + num_dests: usize, + first_dest: usize, dest_memory: u64, src: usize, src_memory: u64, ) -> Self { Self { - function, - address, - dest, + num_dests, + first_dest, dest_memory, src, src_memory, } } - pub fn dest(&self) -> OperandExprList { - get_instruction_list(&self.function, self.dest) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedAssignUnpackMemSsa { - LiftedAssignUnpackMemSsa { - function: self.function.to_owned(), - address: self.address, - dest: self.dest().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("dest", ExprList(self.dest())), - 1usize => ("dest_memory", Int(self.dest_memory())), - 2usize => ("src", Expr(self.src())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // BLOCK -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Block { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - body: (usize, usize), + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBlock { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub body: Vec<HighLevelILLiftedInstruction>, } impl Block { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - body: (usize, usize), - ) -> Self { + pub(crate) fn new(num_params: usize, first_param: usize) -> Self { Self { - function, - address, - body, + num_params, + first_param, } } - pub fn body(&self) -> OperandExprList { - get_instruction_list(&self.function, self.body) - } - pub fn lift(&self) -> LiftedBlock { - LiftedBlock { - function: self.function.to_owned(), - address: self.address, - body: self.body().map(|x| x.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("body", ExprList(self.body())), - _ => unreachable!(), - }) - } } + // CALL, TAILCALL -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Call { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - params: (usize, usize), + pub dest: usize, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCall { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub params: Vec<HighLevelILLiftedInstruction>, } impl Call { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: usize, - params: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: usize, num_params: usize, first_param: usize) -> Self { Self { - function, - address, dest, - params, - } - } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn lift(&self) -> LiftedCall { - LiftedCall { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - params: self.params().map(|x| x.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("params", ExprList(self.params())), - _ => unreachable!(), - }) - } } + // CALL_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct CallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: usize, - params: (usize, usize), - dest_memory: u64, - src_memory: u64, + pub dest: usize, + pub first_param: usize, + pub num_params: usize, + pub dest_memory: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Box<HighLevelILLiftedInstruction>, pub params: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, @@ -843,496 +278,196 @@ pub struct LiftedCallSsa { } impl CallSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, dest: usize, - params: (usize, usize), + num_params: usize, + first_param: usize, dest_memory: u64, src_memory: u64, ) -> Self { Self { - function, - address, dest, - params, + num_params, + first_param, dest_memory, src_memory, } } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedCallSsa { - LiftedCallSsa { - function: self.function.to_owned(), - address: self.address, - dest: Box::new(self.dest().lift()), - params: self.params().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - 1usize => ("params", ExprList(self.params())), - 2usize => ("dest_memory", Int(self.dest_memory())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // CASE -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Case { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - values: (usize, usize), - body: usize, + pub first_value: usize, + pub num_values: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCase { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub values: Vec<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl Case { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - values: (usize, usize), - body: usize, - ) -> Self { + pub(crate) fn new(num_values: usize, first_value: usize, body: usize) -> Self { Self { - function, - address, - values, + num_values, + first_value, body, } } - pub fn values(&self) -> OperandExprList { - get_instruction_list(&self.function, self.values) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedCase { - LiftedCase { - function: self.function.to_owned(), - address: self.address, - values: self.values().map(|x| x.lift()).collect(), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("values", ExprList(self.values())), - 1usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } + // CONST, CONST_PTR, IMPORT -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Const { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant: u64, } impl Const { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, constant: u64) -> Self { - Self { - function, - address, - constant, - } - } - pub fn constant(&self) -> u64 { - self.constant - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("constant", Int(self.constant())), - _ => unreachable!(), - }) + pub(crate) fn new(constant: u64) -> Self { + Self { constant } } } + // CONST_DATA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ConstData { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - constant_data: (u32, u64, usize), + pub constant_data_kind: u32, + pub constant_data_value: i64, + pub size: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedConstantData { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant_data: ConstantData, } impl ConstData { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - constant_data: (u32, u64, usize), - ) -> Self { + pub(crate) fn new(constant_data_kind: u32, constant_data_value: i64, size: usize) -> Self { Self { - function, - address, - constant_data, + constant_data_kind, + constant_data_value, + size, } } - pub fn constant_data(&self) -> ConstantData { - let register_value = RegisterValue { - state: RegisterValueType::from_raw_value(self.constant_data.0).unwrap(), - value: self.constant_data.1 as i64, - offset: 0, - size: self.constant_data.2, - }; - ConstantData::new(self.function.get_function(), register_value) - } - pub fn lift(&self) -> LiftedConstantData { - LiftedConstantData { - function: self.function.to_owned(), - address: self.address, - constant_data: self.constant_data(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("constant_data", ConstantData(self.constant_data())), - _ => unreachable!(), - }) - } } + // DEREF, ADDRESS_OF, NEG, NOT, SX, ZX, LOW_PART, BOOL_TO_INT, UNIMPL_MEM, FSQRT, FNEG, FABS, FLOAT_TO_INT, INT_TO_FLOAT, FLOAT_CONV, ROUND_TO_INT, FLOOR, CEIL, FTRUNC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct UnaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedUnaryOp { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, } impl UnaryOp { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, src: usize) -> Self { - Self { - function, - address, - src, - } - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedUnaryOp { - LiftedUnaryOp { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) + pub(crate) fn new(src: usize) -> Self { + Self { src } } } + // DEREF_FIELD_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct DerefFieldSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, - offset: u64, - member_index: Option<usize>, + pub src: usize, + pub src_memory: u64, + pub offset: u64, + pub member_index: Option<usize>, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedDerefFieldSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, pub offset: u64, pub member_index: Option<usize>, } impl DerefFieldSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - offset: u64, - member_index: u64, - ) -> Self { + pub(crate) fn new(src: usize, src_memory: u64, offset: u64, member_index: u64) -> Self { Self { - function, - address, src, src_memory, offset, member_index: get_member_index(member_index), } } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn member_index(&self) -> Option<usize> { - self.member_index - } - pub fn lift(&self) -> LiftedDerefFieldSsa { - LiftedDerefFieldSsa { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - offset: self.offset, - member_index: self.member_index, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("src_memory", Int(self.src_memory())), - 2usize => ("offset", Int(self.offset())), - 3usize => ("member_index", MemberIndex(self.member_index())), - _ => unreachable!(), - }) - } } + // DEREF_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct DerefSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedDerefSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub src_memory: u64, } impl DerefSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - ) -> Self { - Self { - function, - address, - src, - src_memory, - } - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedDerefSsa { - LiftedDerefSsa { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) + pub(crate) fn new(src: usize, src_memory: u64) -> Self { + Self { src, src_memory } } } + // EXTERN_PTR -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ExternPtr { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant: u64, pub offset: u64, } impl ExternPtr { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - constant: u64, - offset: u64, - ) -> Self { - Self { - function, - address, - constant, - offset, - } - } - pub fn constant(&self) -> u64 { - self.constant - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("constant", Int(self.constant())), - 1usize => ("offset", Int(self.offset())), - _ => unreachable!(), - }) + pub(crate) fn new(constant: u64, offset: u64) -> Self { + Self { constant, offset } } } + // FLOAT_CONST -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct FloatConst { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub constant: f64, } impl FloatConst { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - constant: u64, - size: usize, - ) -> Self { + pub(crate) fn new(constant: u64, size: usize) -> Self { Self { - function, - address, constant: get_float(constant, size), } } - pub fn constant(&self) -> f64 { - self.constant - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("constant", Float(self.constant())), - _ => unreachable!(), - }) - } } + // FOR -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ForLoop { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - init: usize, - condition: usize, - update: usize, - body: usize, + pub init: usize, + pub condition: usize, + pub update: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedForLoop { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub init: Box<HighLevelILLiftedInstruction>, pub condition: Box<HighLevelILLiftedInstruction>, pub update: Box<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl ForLoop { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - init: usize, - condition: usize, - update: usize, - body: usize, - ) -> Self { + pub(crate) fn new(init: usize, condition: usize, update: usize, body: usize) -> Self { Self { - function, - address, init, condition, update, body, } } - pub fn init(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.init) - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn update(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.update) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedForLoop { - LiftedForLoop { - function: self.function.to_owned(), - address: self.address, - init: Box::new(self.init().lift()), - condition: Box::new(self.condition().lift()), - update: Box::new(self.update().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("init", Expr(self.init())), - 1usize => ("condition", Expr(self.condition())), - 2usize => ("update", Expr(self.update())), - 3usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } + // FOR_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ForLoopSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - init: usize, - condition_phi: usize, - condition: usize, - update: usize, - body: usize, + pub init: usize, + pub condition_phi: usize, + pub condition: usize, + pub update: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedForLoopSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub init: Box<HighLevelILLiftedInstruction>, pub condition_phi: Box<HighLevelILLiftedInstruction>, pub condition: Box<HighLevelILLiftedInstruction>, @@ -1341,8 +476,6 @@ pub struct LiftedForLoopSsa { } impl ForLoopSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, init: usize, condition_phi: usize, condition: usize, @@ -1350,8 +483,6 @@ impl ForLoopSsa { body: usize, ) -> Self { Self { - function, - address, init, condition_phi, condition, @@ -1359,200 +490,78 @@ impl ForLoopSsa { body, } } - pub fn init(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.init) - } - pub fn condition_phi(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition_phi) - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn update(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.update) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedForLoopSsa { - LiftedForLoopSsa { - function: self.function.to_owned(), - address: self.address, - init: Box::new(self.init().lift()), - condition_phi: Box::new(self.condition_phi().lift()), - condition: Box::new(self.condition().lift()), - update: Box::new(self.update().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..5usize).map(move |i| match i { - 0usize => ("init", Expr(self.init())), - 1usize => ("condition_phi", Expr(self.condition_phi())), - 2usize => ("condition", Expr(self.condition())), - 3usize => ("update", Expr(self.update())), - 4usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } + // GOTO, LABEL -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone)] pub struct Label { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub target: u64, } +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedLabel { + pub target: GotoLabel, +} impl Label { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, target: u64) -> Self { - Self { - function, - address, - target, - } - } - pub fn target(&self) -> GotoLabel { - GotoLabel { - function: self.function.get_function(), - target: self.target, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("target", Label(self.target())), - _ => unreachable!(), - }) + pub(crate) fn new(target: u64) -> Self { + Self { target } } } // IF -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct If { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition: usize, - cond_true: usize, - cond_false: usize, + pub condition: usize, + pub cond_true: usize, + pub cond_false: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIf { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition: Box<HighLevelILLiftedInstruction>, pub cond_true: Box<HighLevelILLiftedInstruction>, pub cond_false: Box<HighLevelILLiftedInstruction>, } impl If { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - condition: usize, - cond_true: usize, - cond_false: usize, - ) -> Self { + pub(crate) fn new(condition: usize, cond_true: usize, cond_false: usize) -> Self { Self { - function, - address, condition, cond_true, cond_false, } } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn cond_true(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.cond_true) - } - pub fn cond_false(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.cond_false) - } - pub fn lift(&self) -> LiftedIf { - LiftedIf { - function: self.function.to_owned(), - address: self.address, - condition: Box::new(self.condition().lift()), - cond_true: Box::new(self.cond_true().lift()), - cond_false: Box::new(self.cond_false().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("condition", Expr(self.condition())), - 1usize => ("cond_true", Expr(self.cond_true())), - 2usize => ("cond_false", Expr(self.cond_false())), - _ => unreachable!(), - }) - } } + // INTRINSIC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Intrinsic { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - intrinsic: u32, - params: (usize, usize), + pub intrinsic: u32, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIntrinsic { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub intrinsic: ILIntrinsic, pub params: Vec<HighLevelILLiftedInstruction>, } impl Intrinsic { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - intrinsic: u32, - params: (usize, usize), - ) -> Self { + pub(crate) fn new(intrinsic: u32, num_params: usize, first_param: usize) -> Self { Self { - function, - address, intrinsic, - params, - } - } - pub fn intrinsic(&self) -> ILIntrinsic { - ILIntrinsic::new(self.function.get_function().arch(), self.intrinsic) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn lift(&self) -> LiftedIntrinsic { - LiftedIntrinsic { - function: self.function.to_owned(), - address: self.address, - intrinsic: self.intrinsic(), - params: self.params().map(|x| x.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("intrinsic", Intrinsic(self.intrinsic())), - 1usize => ("params", ExprList(self.params())), - _ => unreachable!(), - }) - } } + // INTRINSIC_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct IntrinsicSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - intrinsic: u32, - params: (usize, usize), - dest_memory: u64, - src_memory: u64, + pub intrinsic: u32, + pub first_param: usize, + pub num_params: usize, + pub dest_memory: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIntrinsicSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub intrinsic: ILIntrinsic, pub params: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, @@ -1560,814 +569,330 @@ pub struct LiftedIntrinsicSsa { } impl IntrinsicSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, intrinsic: u32, - params: (usize, usize), + num_params: usize, + first_param: usize, dest_memory: u64, src_memory: u64, ) -> Self { Self { - function, - address, intrinsic, - params, + num_params, + first_param, dest_memory, src_memory, } } - pub fn intrinsic(&self) -> ILIntrinsic { - ILIntrinsic::new(self.function.get_function().arch(), self.intrinsic) - } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedIntrinsicSsa { - LiftedIntrinsicSsa { - function: self.function.to_owned(), - address: self.address, - intrinsic: self.intrinsic(), - params: self.params().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..4usize).map(move |i| match i { - 0usize => ("intrinsic", Intrinsic(self.intrinsic())), - 1usize => ("params", ExprList(self.params())), - 2usize => ("dest_memory", Int(self.dest_memory())), - 3usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // JUMP -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone)] pub struct Jump { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: usize, } +#[derive(Clone, Debug, PartialEq)] +pub struct LiftedJump { + pub dest: Box<HighLevelILLiftedInstruction>, +} impl Jump { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, dest: usize) -> Self { - Self { - function, - address, - dest, - } - } - pub fn dest(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.dest) - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("dest", Expr(self.dest())), - _ => unreachable!(), - }) + pub(crate) fn new(dest: usize) -> Self { + Self { dest } } } + // MEM_PHI -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct MemPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: u64, - src: (usize, usize), + pub dest: u64, + pub first_src: usize, + pub num_srcs: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedMemPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: u64, pub src: Vec<u64>, } impl MemPhi { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: u64, - src: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: u64, num_srcs: usize, first_src: usize) -> Self { Self { - function, - address, dest, - src, + num_srcs, + first_src, } } - pub fn dest(&self) -> u64 { - self.dest - } - pub fn src(&self) -> OperandList { - get_int_list(&self.function, self.src) - } - pub fn lift(&self) -> LiftedMemPhi { - LiftedMemPhi { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: self.src().collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Int(self.dest())), - 1usize => ("src", IntList(self.src())), - _ => unreachable!(), - }) - } -} -// NOP, BREAK, CONTINUE, NORET, UNREACHABLE, BP, UNDEF, UNIMPL -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct NoArgs { - pub function: Ref<HighLevelILFunction>, - pub address: u64, -} -impl NoArgs { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64) -> Self { - Self { function, address } - } - // NOTE self is not required, it's present just in case data is added to - // the struct in the future - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - [].into_iter() - } } + // RET -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Ret { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: (usize, usize), + pub first_src: usize, + pub num_srcs: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedRet { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Vec<HighLevelILLiftedInstruction>, } impl Ret { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: (usize, usize), - ) -> Self { + pub(crate) fn new(num_srcs: usize, first_src: usize) -> Self { Self { - function, - address, - src, - } - } - pub fn src(&self) -> OperandExprList { - get_instruction_list(&self.function, self.src) - } - pub fn lift(&self) -> LiftedRet { - LiftedRet { - function: self.function.to_owned(), - address: self.address, - src: self.src().map(|x| x.lift()).collect(), + first_src, + num_srcs, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("src", ExprList(self.src())), - _ => unreachable!(), - }) - } } + // SPLIT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Split { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - high: usize, - low: usize, + pub high: usize, + pub low: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSplit { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub high: Box<HighLevelILLiftedInstruction>, pub low: Box<HighLevelILLiftedInstruction>, } impl Split { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - high: usize, - low: usize, - ) -> Self { - Self { - function, - address, - high, - low, - } - } - pub fn high(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.high) - } - pub fn low(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.low) - } - pub fn lift(&self) -> LiftedSplit { - LiftedSplit { - function: self.function.to_owned(), - address: self.address, - high: Box::new(self.high().lift()), - low: Box::new(self.low().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("high", Expr(self.high())), - 1usize => ("low", Expr(self.low())), - _ => unreachable!(), - }) + pub(crate) fn new(high: usize, low: usize) -> Self { + Self { high, low } } } + // STRUCT_FIELD, DEREF_FIELD -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct StructField { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - src: usize, - offset: u64, - member_index: Option<usize>, + pub src: usize, + pub offset: u64, + pub member_index: Option<usize>, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedStructField { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub src: Box<HighLevelILLiftedInstruction>, pub offset: u64, pub member_index: Option<usize>, } impl StructField { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - src: usize, - offset: u64, - member_index: u64, - ) -> Self { + pub(crate) fn new(src: usize, offset: u64, member_index: u64) -> Self { Self { - function, - address, src, offset, member_index: get_member_index(member_index), } } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn member_index(&self) -> Option<usize> { - self.member_index - } - pub fn lift(&self) -> LiftedStructField { - LiftedStructField { - function: self.function.to_owned(), - address: self.address, - src: Box::new(self.src().lift()), - offset: self.offset, - member_index: self.member_index, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("src", Expr(self.src())), - 1usize => ("offset", Int(self.offset())), - 2usize => ("member_index", MemberIndex(self.member_index())), - _ => unreachable!(), - }) - } } + // SWITCH -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Switch { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition: usize, - default: usize, - cases: (usize, usize), + pub condition: usize, + pub default: usize, + pub first_case: usize, + pub num_cases: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSwitch { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition: Box<HighLevelILLiftedInstruction>, pub default: Box<HighLevelILLiftedInstruction>, pub cases: Vec<HighLevelILLiftedInstruction>, } impl Switch { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, condition: usize, default: usize, - cases: (usize, usize), + num_cases: usize, + first_case: usize, ) -> Self { Self { - function, - address, condition, default, - cases, - } - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn default(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.default) - } - pub fn cases(&self) -> OperandExprList { - get_instruction_list(&self.function, self.cases) - } - pub fn lift(&self) -> LiftedSwitch { - LiftedSwitch { - function: self.function.to_owned(), - address: self.address, - condition: Box::new(self.condition().lift()), - default: Box::new(self.default().lift()), - cases: self.cases().map(|x| x.lift()).collect(), + num_cases, + first_case, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("condition", Expr(self.condition())), - 1usize => ("default", Expr(self.default())), - 2usize => ("cases", ExprList(self.cases())), - _ => unreachable!(), - }) - } } + // SYSCALL -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Syscall { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - params: (usize, usize), + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscall { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub params: Vec<HighLevelILLiftedInstruction>, } impl Syscall { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - params: (usize, usize), - ) -> Self { + pub(crate) fn new(num_params: usize, first_param: usize) -> Self { Self { - function, - address, - params, + num_params, + first_param, } } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn lift(&self) -> LiftedSyscall { - LiftedSyscall { - function: self.function.to_owned(), - address: self.address, - params: self.params().map(|x| x.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("params", ExprList(self.params())), - _ => unreachable!(), - }) - } } + // SYSCALL_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SyscallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - params: (usize, usize), - dest_memory: u64, - src_memory: u64, + pub first_param: usize, + pub num_params: usize, + pub dest_memory: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub params: Vec<HighLevelILLiftedInstruction>, pub dest_memory: u64, pub src_memory: u64, } impl SyscallSsa { pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - params: (usize, usize), + num_params: usize, + first_param: usize, dest_memory: u64, src_memory: u64, ) -> Self { Self { - function, - address, - params, + num_params, + first_param, dest_memory, src_memory, } } - pub fn params(&self) -> OperandExprList { - get_instruction_list(&self.function, self.params) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedSyscallSsa { - LiftedSyscallSsa { - function: self.function.to_owned(), - address: self.address, - params: self.params().map(|x| x.lift()).collect(), - dest_memory: self.dest_memory, - src_memory: self.src_memory, - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("params", ExprList(self.params())), - 1usize => ("dest_memory", Int(self.dest_memory())), - 2usize => ("src_memory", Int(self.src_memory())), - _ => unreachable!(), - }) - } } + // TRAP -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Trap { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub vector: u64, } impl Trap { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, vector: u64) -> Self { - Self { - function, - address, - vector, - } - } - pub fn vector(&self) -> u64 { - self.vector - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("vector", Int(self.vector())), - _ => unreachable!(), - }) + pub(crate) fn new(vector: u64) -> Self { + Self { vector } } } + // VAR_DECLARE, VAR -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Var { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub var: Variable, } impl Var { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, var: u64) -> Self { - Self { - function, - address, - var: get_var(var), - } - } - pub fn var(&self) -> Variable { - self.var - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("var", Var(self.var())), - _ => unreachable!(), - }) + pub(crate) fn new(var: u64) -> Self { + Self { var: get_var(var) } } } + // VAR_INIT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarInit { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: Variable, - src: usize, + pub dest: Variable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedVarInit { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: Variable, pub src: Box<HighLevelILLiftedInstruction>, } impl VarInit { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: u64, - src: usize, - ) -> Self { + pub(crate) fn new(dest: u64, src: usize) -> Self { Self { - function, - address, dest: get_var(dest), src, } } - pub fn dest(&self) -> Variable { - self.dest - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedVarInit { - LiftedVarInit { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", Var(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) - } } + // VAR_INIT_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarInitSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: SSAVariable, - src: usize, + pub dest: SSAVariable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedVarInitSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub src: Box<HighLevelILLiftedInstruction>, } impl VarInitSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (u64, usize), - src: usize, - ) -> Self { + pub(crate) fn new(dest: (u64, usize), src: usize) -> Self { Self { - function, - address, dest: get_var_ssa(dest), src, } } - pub fn dest(&self) -> SSAVariable { - self.dest - } - pub fn src(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.src) - } - pub fn lift(&self) -> LiftedVarInitSsa { - LiftedVarInitSsa { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", VarSsa(self.dest())), - 1usize => ("src", Expr(self.src())), - _ => unreachable!(), - }) - } } + // VAR_PHI -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - dest: SSAVariable, - src: (usize, usize), + pub dest: SSAVariable, + pub first_src: usize, + pub num_srcs: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedVarPhi { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub src: Vec<SSAVariable>, } impl VarPhi { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - dest: (u64, usize), - src: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: (u64, usize), num_srcs: usize, first_src: usize) -> Self { Self { - function, - address, dest: get_var_ssa(dest), - src, + num_srcs, + first_src, } } - pub fn dest(&self) -> SSAVariable { - self.dest - } - pub fn src(&self) -> OperandSSAVariableList { - get_var_ssa_list(&self.function, self.src) - } - pub fn lift(&self) -> LiftedVarPhi { - LiftedVarPhi { - function: self.function.to_owned(), - address: self.address, - dest: self.dest, - src: self.src().collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("dest", VarSsa(self.dest())), - 1usize => ("src", VarSsaList(self.src())), - _ => unreachable!(), - }) - } } + // VAR_SSA -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub var: SSAVariable, } impl VarSsa { - pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, var: (u64, usize)) -> Self { + pub(crate) fn new(var: (u64, usize)) -> Self { Self { - function, - address, var: get_var_ssa(var), } } - pub fn var(&self) -> SSAVariable { - self.var - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..1usize).map(move |i| match i { - 0usize => ("var", VarSsa(self.var())), - _ => unreachable!(), - }) - } } + // WHILE, DO_WHILE -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct While { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition: usize, - body: usize, + pub condition: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedWhile { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition: Box<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl While { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - condition: usize, - body: usize, - ) -> Self { - Self { - function, - address, - condition, - body, - } - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedWhile { - LiftedWhile { - function: self.function.to_owned(), - address: self.address, - condition: Box::new(self.condition().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..2usize).map(move |i| match i { - 0usize => ("condition", Expr(self.condition())), - 1usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) + pub(crate) fn new(condition: usize, body: usize) -> Self { + Self { condition, body } } } + // WHILE_SSA, DO_WHILE_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct WhileSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, - condition_phi: usize, - condition: usize, - body: usize, + pub condition_phi: usize, + pub condition: usize, + pub body: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedWhileSsa { - pub function: Ref<HighLevelILFunction>, - pub address: u64, pub condition_phi: Box<HighLevelILLiftedInstruction>, pub condition: Box<HighLevelILLiftedInstruction>, pub body: Box<HighLevelILLiftedInstruction>, } impl WhileSsa { - pub(crate) fn new( - function: Ref<HighLevelILFunction>, - address: u64, - condition_phi: usize, - condition: usize, - body: usize, - ) -> Self { + pub(crate) fn new(condition_phi: usize, condition: usize, body: usize) -> Self { Self { - function, - address, condition_phi, condition, body, } } - pub fn condition_phi(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition_phi) - } - pub fn condition(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.condition) - } - pub fn body(&self) -> HighLevelILInstruction { - get_instruction(&self.function, self.body) - } - pub fn lift(&self) -> LiftedWhileSsa { - LiftedWhileSsa { - function: self.function.to_owned(), - address: self.address, - condition_phi: Box::new(self.condition_phi().lift()), - condition: Box::new(self.condition().lift()), - body: Box::new(self.body().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ { - use HighLevelILOperand::*; - (0..3usize).map(move |i| match i { - 0usize => ("condition_phi", Expr(self.condition_phi())), - 1usize => ("condition", Expr(self.condition())), - 2usize => ("body", Expr(self.body())), - _ => unreachable!(), - }) - } } |
