diff options
| author | Michael Krasnitski <michael.krasnitski@gmail.com> | 2024-02-07 11:44:06 -0500 |
|---|---|---|
| committer | Kyle Martin <krm504@nyu.edu> | 2024-03-18 17:46:37 -0400 |
| commit | 5fcf6bc59ebc2110d053360d223e6570cdd2272c (patch) | |
| tree | ed6eafd132cf53fd9e7105f541967324b4165db0 /rust/src | |
| parent | bdd012af7941c7d17b97b3e69628a7bc7cc2411e (diff) | |
Refactor MLIL instructions
* Turn `MediumLevelILInstruction` into a struct with a `kind` field to
indicate the instruction variant, and pull out the `function` and
`address` fields from each variant to live in the top-level struct.
* Make variant fields public, remove field getter methods and centralize
lifting logic to happen all at once. Split tuple fields into
individual named fields.
* Move the `operands` method to `MediumLevelILLiftedInstruction`, and
make it return an owned `Vec` of operands rather than a borrowed
iterator.
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/mlil/function.rs | 6 | ||||
| -rw-r--r-- | rust/src/mlil/instruction.rs | 1255 | ||||
| -rw-r--r-- | rust/src/mlil/lift.rs | 250 | ||||
| -rw-r--r-- | rust/src/mlil/operation.rs | 2337 |
4 files changed, 1121 insertions, 2727 deletions
diff --git a/rust/src/mlil/function.rs b/rust/src/mlil/function.rs index 8f5ed73d..16cc5102 100644 --- a/rust/src/mlil/function.rs +++ b/rust/src/mlil/function.rs @@ -14,7 +14,7 @@ use crate::function::Function; use crate::function::Location; use crate::rc::{Array, Ref, RefCountable}; -use super::{MediumLevelILBlock, MediumLevelILInstruction}; +use super::{MediumLevelILBlock, MediumLevelILInstruction, MediumLevelILLiftedInstruction}; pub struct MediumLevelILFunction { pub(crate) handle: *mut BNMediumLevelILFunction, @@ -61,6 +61,10 @@ impl MediumLevelILFunction { MediumLevelILInstruction::new(self.to_owned(), expr_idx) } + pub fn lifted_instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILLiftedInstruction { + self.instruction_from_idx(expr_idx).lift() + } + pub fn instruction_count(&self) -> usize { unsafe { BNGetMediumLevelILInstructionCount(self.handle) } } diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs index 306a1352..50154f34 100644 --- a/rust/src/mlil/instruction.rs +++ b/rust/src/mlil/instruction.rs @@ -1,19 +1,27 @@ use binaryninjacore_sys::BNGetMediumLevelILByIndex; use binaryninjacore_sys::BNMediumLevelILOperation; -use crate::mlil::MediumLevelILLiftedInstruction; use crate::rc::Ref; +use crate::types::ILIntrinsic; +use super::lift::*; use super::operation::*; use super::MediumLevelILFunction; #[derive(Clone)] -pub enum MediumLevelILInstruction { - Nop(NoArgs), - Noret(NoArgs), - Bp(NoArgs), - Undef(NoArgs), - Unimpl(NoArgs), +pub struct MediumLevelILInstruction { + pub function: Ref<MediumLevelILFunction>, + pub address: u64, + pub kind: MediumLevelILInstructionKind, +} + +#[derive(Copy, Clone)] +pub enum MediumLevelILInstructionKind { + Nop, + Noret, + Bp, + Undef, + Unimpl, If(MediumLevelILOperationIf), FloatConst(FloatConst), Const(Constant), @@ -147,7 +155,7 @@ impl core::fmt::Debug for MediumLevelILInstruction { f, "<{} at 0x{:08}>", core::any::type_name::<Self>(), - self.address(), + self.address, ) } } @@ -156,54 +164,37 @@ impl MediumLevelILInstruction { pub(crate) fn new(function: Ref<MediumLevelILFunction>, idx: usize) -> Self { let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) }; use BNMediumLevelILOperation::*; - use MediumLevelILInstruction as Op; - match op.operation { - MLIL_NOP => Op::Nop(NoArgs::new(function, op.address)), - MLIL_NORET => Op::Noret(NoArgs::new(function, op.address)), - MLIL_BP => Op::Bp(NoArgs::new(function, op.address)), - MLIL_UNDEF => Op::Undef(NoArgs::new(function, op.address)), - MLIL_UNIMPL => Op::Unimpl(NoArgs::new(function, op.address)), + use MediumLevelILInstructionKind as Op; + let kind = match op.operation { + MLIL_NOP => Op::Nop, + MLIL_NORET => Op::Noret, + MLIL_BP => Op::Bp, + MLIL_UNDEF => Op::Undef, + MLIL_UNIMPL => Op::Unimpl, MLIL_IF => Op::If(MediumLevelILOperationIf::new( - function, - op.address, op.operands[0] as usize, op.operands[1], op.operands[2], )), - MLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new( - function, - op.address, - op.operands[0], - op.size, - )), - MLIL_CONST => Op::Const(Constant::new(function, op.address, op.operands[0])), - MLIL_CONST_PTR => Op::ConstPtr(Constant::new(function, op.address, op.operands[0])), - MLIL_IMPORT => Op::Import(Constant::new(function, op.address, op.operands[0])), - MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new( - function, - op.address, - op.operands[0], - op.operands[1], - )), + MLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(op.operands[0], op.size)), + MLIL_CONST => Op::Const(Constant::new(op.operands[0])), + MLIL_CONST_PTR => Op::ConstPtr(Constant::new(op.operands[0])), + MLIL_IMPORT => Op::Import(Constant::new(op.operands[0])), + MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(op.operands[0], op.operands[1])), MLIL_CONST_DATA => Op::ConstData(ConstantData::new( - function, - op.address, - (op.operands[0], op.operands[1]), + op.operands[0] as u32, + op.operands[1] as i64, op.size, )), - MLIL_JUMP => Op::Jump(Jump::new(function, op.address, op.operands[0] as usize)), - MLIL_RET_HINT => Op::RetHint(Jump::new(function, op.address, op.operands[0] as usize)), + MLIL_JUMP => Op::Jump(Jump::new(op.operands[0] as usize)), + MLIL_RET_HINT => Op::RetHint(Jump::new(op.operands[0] as usize)), MLIL_STORE_SSA => Op::StoreSsa(StoreSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1], op.operands[2], op.operands[3] as usize, )), MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1], op.operands[2], @@ -211,1099 +202,803 @@ impl MediumLevelILInstruction { op.operands[4] as usize, )), MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct::new( - function, - op.address, op.operands[0] as usize, op.operands[1], op.operands[2] as usize, )), - MLIL_STORE => Op::Store(Store::new( - function, - op.address, - op.operands[0] as usize, - op.operands[1] as usize, - )), + MLIL_STORE => Op::Store(Store::new(op.operands[0] as usize, op.operands[1] as usize)), MLIL_JUMP_TO => Op::JumpTo(JumpTo::new( - function, - op.address, op.operands[0] as usize, - (op.operands[1] as usize, op.operands[2] as usize), + op.operands[1] as usize, + op.operands[2] as usize, )), - MLIL_GOTO => Op::Goto(Goto::new(function, op.address, op.operands[0])), - MLIL_FREE_VAR_SLOT => { - Op::FreeVarSlot(FreeVarSlot::new(function, op.address, op.operands[0])) - } + MLIL_GOTO => Op::Goto(Goto::new(op.operands[0])), + MLIL_FREE_VAR_SLOT => Op::FreeVarSlot(FreeVarSlot::new(op.operands[0])), MLIL_SET_VAR_FIELD => Op::SetVarField(SetVarField::new( - function, - op.address, op.operands[0], op.operands[1], op.operands[2] as usize, )), - MLIL_SET_VAR => Op::SetVar(SetVar::new( - function, - op.address, - op.operands[0], - op.operands[1] as usize, - )), + MLIL_SET_VAR => Op::SetVar(SetVar::new(op.operands[0], op.operands[1] as usize)), MLIL_FREE_VAR_SLOT_SSA => Op::FreeVarSlotSsa(FreeVarSlotSsa::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), (op.operands[0], op.operands[2] as usize), )), MLIL_SET_VAR_SSA_FIELD => Op::SetVarSsaField(SetVarSsaField::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), (op.operands[0], op.operands[2] as usize), op.operands[3], op.operands[4] as usize, )), MLIL_SET_VAR_ALIASED_FIELD => Op::SetVarAliasedField(SetVarSsaField::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), (op.operands[0], op.operands[2] as usize), op.operands[3], op.operands[4] as usize, )), MLIL_SET_VAR_ALIASED => Op::SetVarAliased(SetVarAliased::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), (op.operands[0], op.operands[2] as usize), op.operands[3] as usize, )), MLIL_SET_VAR_SSA => Op::SetVarSsa(SetVarSsa::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), op.operands[2] as usize, )), MLIL_VAR_PHI => Op::VarPhi(VarPhi::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), - (op.operands[2] as usize, op.operands[3] as usize), + op.operands[2] as usize, + op.operands[3] as usize, )), MLIL_MEM_PHI => Op::MemPhi(MemPhi::new( - function, - op.address, - op.operands[0], - (op.operands[1] as usize, op.operands[2] as usize), - )), - MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new( - function, - op.address, op.operands[0], - op.operands[1], + op.operands[1] as usize, + op.operands[2] as usize, )), + MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new(op.operands[0], op.operands[1])), MLIL_SET_VAR_SPLIT => Op::SetVarSplit(SetVarSplit::new( - function, - op.address, op.operands[0], op.operands[1], op.operands[2] as usize, )), MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), (op.operands[2], op.operands[3] as usize), )), MLIL_SET_VAR_SPLIT_SSA => Op::SetVarSplitSsa(SetVarSplitSsa::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), (op.operands[2], op.operands[3] as usize), op.operands[4] as usize, )), MLIL_ADD => Op::Add(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_SUB => Op::Sub(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_AND => Op::And(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_OR => Op::Or(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_XOR => Op::Xor(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_LSL => Op::Lsl(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_LSR => Op::Lsr(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_ASR => Op::Asr(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_ROL => Op::Rol(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_ROR => Op::Ror(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MUL => Op::Mul(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MULU_DP => Op::MuluDp(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MULS_DP => Op::MulsDp(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_DIVU => Op::Divu(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_DIVU_DP => Op::DivuDp(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_DIVS => Op::Divs(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_DIVS_DP => Op::DivsDp(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MODU => Op::Modu(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MODU_DP => Op::ModuDp(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MODS => Op::Mods(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_MODS_DP => Op::ModsDp(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_E => Op::CmpE(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_NE => Op::CmpNe(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_SLE => Op::CmpSle(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_ULE => Op::CmpUle(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_SGE => Op::CmpSge(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_UGE => Op::CmpUge(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_TEST_BIT => Op::TestBit(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_E => Op::FcmpE(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_O => Op::FcmpO(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FADD => Op::Fadd(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FSUB => Op::Fsub(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FMUL => Op::Fmul(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_FDIV => Op::Fdiv(BinaryOp::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, )), MLIL_ADC => Op::Adc(BinaryOpCarry::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, )), MLIL_SBB => Op::Sbb(BinaryOpCarry::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, )), MLIL_RLC => Op::Rlc(BinaryOpCarry::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, )), MLIL_RRC => Op::Rrc(BinaryOpCarry::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, )), MLIL_CALL => Op::Call(Call::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), + 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), + op.operands[3] as usize, + op.operands[4] as usize, )), MLIL_TAILCALL => Op::Tailcall(Call::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), + 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), + op.operands[3] as usize, + op.operands[4] as usize, )), MLIL_SYSCALL => Op::Syscall(Syscall::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), - (op.operands[2] as usize, op.operands[3] as usize), + op.operands[0] as usize, + op.operands[1] as usize, + op.operands[2] as usize, + op.operands[3] as usize, )), MLIL_INTRINSIC => Op::Intrinsic(Intrinsic::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), + op.operands[0] as usize, + op.operands[1] as usize, op.operands[2] as u32, - (op.operands[3] as usize, op.operands[4] as usize), + op.operands[3] as usize, + op.operands[4] as usize, )), MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), + op.operands[0] as usize, + op.operands[1] as usize, op.operands[2] as u32, - (op.operands[3] as usize, op.operands[4] as usize), + op.operands[3] as usize, + op.operands[4] as usize, )), MLIL_CALL_SSA => Op::CallSsa(CallSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, - (op.operands[2] as usize, op.operands[3] as usize), + op.operands[2] as usize, + op.operands[3] as usize, op.operands[4], )), MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, - (op.operands[2] as usize, op.operands[3] as usize), + op.operands[2] as usize, + op.operands[3] as usize, op.operands[4], )), MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, op.operands[3] as usize, )), MLIL_TAILCALL_UNTYPED_SSA => Op::TailcallUntypedSsa(CallUntypedSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, op.operands[3] as usize, )), MLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa::new( - function, - op.address, op.operands[0] as usize, - (op.operands[1] as usize, op.operands[2] as usize), + op.operands[1] as usize, + op.operands[2] as usize, op.operands[3], )), MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, )), MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, op.operands[3] as usize, )), MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, op.operands[3] as usize, )), MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped::new( - function, - op.address, op.operands[0] as usize, op.operands[1] as usize, op.operands[2] as usize, )), - MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), - )), - MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), - )), - MLIL_NEG => Op::Neg(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_NOT => Op::Not(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_SX => Op::Sx(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_ZX => Op::Zx(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_LOW_PART => { - Op::LowPart(UnaryOp::new(function, op.address, op.operands[0] as usize)) - } - MLIL_BOOL_TO_INT => { - Op::BoolToInt(UnaryOp::new(function, op.address, op.operands[0] as usize)) - } - MLIL_UNIMPL_MEM => { - Op::UnimplMem(UnaryOp::new(function, op.address, op.operands[0] as usize)) + MLIL_NEG => Op::Neg(UnaryOp::new(op.operands[0] as usize)), + MLIL_NOT => Op::Not(UnaryOp::new(op.operands[0] as usize)), + MLIL_SX => Op::Sx(UnaryOp::new(op.operands[0] as usize)), + MLIL_ZX => Op::Zx(UnaryOp::new(op.operands[0] as usize)), + MLIL_LOW_PART => Op::LowPart(UnaryOp::new(op.operands[0] as usize)), + MLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp::new(op.operands[0] as usize)), + MLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp::new(op.operands[0] as usize)), + MLIL_FSQRT => Op::Fsqrt(UnaryOp::new(op.operands[0] as usize)), + MLIL_FNEG => Op::Fneg(UnaryOp::new(op.operands[0] as usize)), + MLIL_FABS => Op::Fabs(UnaryOp::new(op.operands[0] as usize)), + MLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp::new(op.operands[0] as usize)), + MLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp::new(op.operands[0] as usize)), + MLIL_FLOAT_CONV => Op::FloatConv(UnaryOp::new(op.operands[0] as usize)), + MLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp::new(op.operands[0] as usize)), + MLIL_FLOOR => Op::Floor(UnaryOp::new(op.operands[0] as usize)), + MLIL_CEIL => Op::Ceil(UnaryOp::new(op.operands[0] as usize)), + MLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(op.operands[0] as usize)), + MLIL_LOAD => Op::Load(UnaryOp::new(op.operands[0] as usize)), + MLIL_LOAD_STRUCT => { + Op::LoadStruct(LoadStruct::new(op.operands[0] as usize, op.operands[1])) } - MLIL_FSQRT => Op::Fsqrt(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_FNEG => Op::Fneg(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_FABS => Op::Fabs(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_FLOAT_TO_INT => { - Op::FloatToInt(UnaryOp::new(function, op.address, op.operands[0] as usize)) - } - MLIL_INT_TO_FLOAT => { - Op::IntToFloat(UnaryOp::new(function, op.address, op.operands[0] as usize)) - } - MLIL_FLOAT_CONV => { - Op::FloatConv(UnaryOp::new(function, op.address, op.operands[0] as usize)) - } - MLIL_ROUND_TO_INT => { - Op::RoundToInt(UnaryOp::new(function, op.address, op.operands[0] as usize)) - } - MLIL_FLOOR => Op::Floor(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_CEIL => Op::Ceil(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_LOAD => Op::Load(UnaryOp::new(function, op.address, op.operands[0] as usize)), - MLIL_LOAD_STRUCT => Op::LoadStruct(LoadStruct::new( - function, - op.address, - op.operands[0] as usize, - op.operands[1], - )), MLIL_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa::new( - function, - op.address, op.operands[0] as usize, op.operands[1], op.operands[2], )), - MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa::new( - function, - op.address, + MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa::new(op.operands[0] as usize, op.operands[1])), + MLIL_RET => Op::Ret(Ret::new(op.operands[0] as usize, op.operands[1] as usize)), + MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList::new( op.operands[0] as usize, - op.operands[1], - )), - MLIL_RET => Op::Ret(Ret::new( - function, - op.address, - (op.operands[0] as usize, op.operands[1] as usize), - )), - MLIL_VAR => Op::Var(Var::new(function, op.address, op.operands[0])), - MLIL_ADDRESS_OF => Op::AddressOf(Var::new(function, op.address, op.operands[0])), - MLIL_VAR_FIELD => Op::VarField(Field::new( - function, - op.address, - op.operands[0], - op.operands[1], - )), - MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field::new( - function, - op.address, - op.operands[0], - op.operands[1], - )), - MLIL_VAR_SSA => Op::VarSsa(VarSsa::new( - function, - op.address, - (op.operands[0], op.operands[1] as usize), + op.operands[1] as usize, )), - MLIL_VAR_ALIASED => Op::VarAliased(VarSsa::new( - function, - op.address, - (op.operands[0], op.operands[1] as usize), + MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot::new( + op.operands[0] as usize, + op.operands[1] as usize, )), + MLIL_VAR => Op::Var(Var::new(op.operands[0])), + MLIL_ADDRESS_OF => Op::AddressOf(Var::new(op.operands[0])), + MLIL_VAR_FIELD => Op::VarField(Field::new(op.operands[0], op.operands[1])), + MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field::new(op.operands[0], op.operands[1])), + MLIL_VAR_SSA => Op::VarSsa(VarSsa::new((op.operands[0], op.operands[1] as usize))), + MLIL_VAR_ALIASED => { + Op::VarAliased(VarSsa::new((op.operands[0], op.operands[1] as usize))) + } MLIL_VAR_SSA_FIELD => Op::VarSsaField(VarSsaField::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), op.operands[2], )), MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField::new( - function, - op.address, (op.operands[0], op.operands[1] as usize), op.operands[2], )), - MLIL_TRAP => Op::Trap(Trap::new(function, op.address, op.operands[0])), + MLIL_TRAP => Op::Trap(Trap::new(op.operands[0])), // translated directly into a list for Expression or Variables // TODO MLIL_MEMORY_INTRINSIC_SSA needs to be handled properly MLIL_CALL_OUTPUT | MLIL_CALL_PARAM | MLIL_CALL_PARAM_SSA | MLIL_CALL_OUTPUT_SSA | MLIL_MEMORY_INTRINSIC_OUTPUT_SSA | MLIL_MEMORY_INTRINSIC_SSA => { unreachable!() } + }; + + Self { + function, + address: op.address, + kind, } } - pub fn function(&self) -> &MediumLevelILFunction { - use MediumLevelILInstruction::*; - match self { - Nop(op) => &op.function, - Noret(op) => &op.function, - Bp(op) => &op.function, - Undef(op) => &op.function, - Unimpl(op) => &op.function, - If(op) => &op.function, - FloatConst(op) => &op.function, - Const(op) => &op.function, - ConstPtr(op) => &op.function, - Import(op) => &op.function, - ExternPtr(op) => &op.function, - ConstData(op) => &op.function, - Jump(op) => &op.function, - RetHint(op) => &op.function, - StoreSsa(op) => &op.function, - StoreStructSsa(op) => &op.function, - StoreStruct(op) => &op.function, - Store(op) => &op.function, - JumpTo(op) => &op.function, - Goto(op) => &op.function, - FreeVarSlot(op) => &op.function, - SetVarField(op) => &op.function, - SetVar(op) => &op.function, - FreeVarSlotSsa(op) => &op.function, - SetVarSsaField(op) => &op.function, - SetVarAliasedField(op) => &op.function, - SetVarAliased(op) => &op.function, - SetVarSsa(op) => &op.function, - VarPhi(op) => &op.function, - MemPhi(op) => &op.function, - VarSplit(op) => &op.function, - SetVarSplit(op) => &op.function, - VarSplitSsa(op) => &op.function, - SetVarSplitSsa(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, - 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, - Fadd(op) => &op.function, - Fsub(op) => &op.function, - Fmul(op) => &op.function, - Fdiv(op) => &op.function, - Adc(op) => &op.function, - Sbb(op) => &op.function, - Rlc(op) => &op.function, - Rrc(op) => &op.function, - Call(op) => &op.function, - Tailcall(op) => &op.function, - Syscall(op) => &op.function, - Intrinsic(op) => &op.function, - IntrinsicSsa(op) => &op.function, - CallSsa(op) => &op.function, - TailcallSsa(op) => &op.function, - CallUntypedSsa(op) => &op.function, - TailcallUntypedSsa(op) => &op.function, - SyscallSsa(op) => &op.function, - SyscallUntypedSsa(op) => &op.function, - CallUntyped(op) => &op.function, - TailcallUntyped(op) => &op.function, - SyscallUntyped(op) => &op.function, - SeparateParamList(op) => &op.function, - SharedParamSlot(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, - Load(op) => &op.function, - LoadStruct(op) => &op.function, - LoadStructSsa(op) => &op.function, - LoadSsa(op) => &op.function, - Ret(op) => &op.function, - Var(op) => &op.function, - AddressOf(op) => &op.function, - VarField(op) => &op.function, - AddressOfField(op) => &op.function, - VarSsa(op) => &op.function, - VarAliased(op) => &op.function, - VarSsaField(op) => &op.function, - VarAliasedField(op) => &op.function, - Trap(op) => &op.function, + pub fn lift(&self) -> MediumLevelILLiftedInstruction { + use MediumLevelILInstructionKind::*; + use MediumLevelILLiftedInstructionKind as Lifted; + + let kind = match self.kind { + Nop => Lifted::Nop, + Noret => Lifted::Noret, + Bp => Lifted::Bp, + Undef => Lifted::Undef, + Unimpl => Lifted::Unimpl, + If(op) => Lifted::If(LiftedIf { + condition: self.lift_operand(op.condition), + dest_true: op.dest_true, + dest_false: op.dest_false, + }), + + FloatConst(op) => Lifted::FloatConst(op), + Const(op) => Lifted::Const(op), + ConstPtr(op) => Lifted::ConstPtr(op), + Import(op) => Lifted::Import(op), + ExternPtr(op) => Lifted::ExternPtr(op), + + ConstData(op) => Lifted::ConstData(LiftedConstantData { + constant_data: get_constant_data( + &self.function, + op.constant_data_kind, + op.constant_data_value, + op.size, + ), + }), + Jump(op) => Lifted::Jump(LiftedJump { + dest: self.lift_operand(op.dest), + }), + RetHint(op) => Lifted::RetHint(LiftedJump { + dest: self.lift_operand(op.dest), + }), + StoreSsa(op) => Lifted::StoreSsa(LiftedStoreSsa { + dest: self.lift_operand(op.dest), + dest_memory: op.dest_memory, + src_memory: op.src_memory, + src: self.lift_operand(op.src), + }), + StoreStructSsa(op) => Lifted::StoreStructSsa(LiftedStoreStructSsa { + dest: self.lift_operand(op.dest), + offset: op.offset, + dest_memory: op.dest_memory, + src_memory: op.src_memory, + src: self.lift_operand(op.src), + }), + StoreStruct(op) => Lifted::StoreStruct(LiftedStoreStruct { + dest: self.lift_operand(op.dest), + offset: op.offset, + src: self.lift_operand(op.src), + }), + Store(op) => Lifted::Store(LiftedStore { + dest: self.lift_operand(op.dest), + src: self.lift_operand(op.src), + }), + JumpTo(op) => Lifted::JumpTo(LiftedJumpTo { + dest: self.lift_operand(op.dest), + targets: OperandIter::new(&self.function, op.first_operand, op.num_operands) + .as_pairs() + .collect(), + }), + Goto(op) => Lifted::Goto(op), + FreeVarSlot(op) => Lifted::FreeVarSlot(op), + SetVarField(op) => Lifted::SetVarField(LiftedSetVarField { + dest: op.dest, + offset: op.offset, + src: self.lift_operand(op.src), + }), + SetVar(op) => Lifted::SetVar(LiftedSetVar { + dest: op.dest, + src: self.lift_operand(op.src), + }), + FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op), + SetVarSsaField(op) => Lifted::SetVarSsaField(LiftedSetVarSsaField { + dest: op.dest, + prev: op.prev, + offset: op.offset, + src: self.lift_operand(op.src), + }), + SetVarAliasedField(op) => Lifted::SetVarAliasedField(LiftedSetVarSsaField { + dest: op.dest, + prev: op.prev, + offset: op.offset, + src: self.lift_operand(op.src), + }), + SetVarAliased(op) => Lifted::SetVarAliased(LiftedSetVarAliased { + dest: op.dest, + prev: op.prev, + src: self.lift_operand(op.src), + }), + SetVarSsa(op) => Lifted::SetVarSsa(LiftedSetVarSsa { + dest: op.dest, + src: self.lift_operand(op.src), + }), + VarPhi(op) => Lifted::VarPhi(LiftedVarPhi { + dest: op.dest, + src: OperandIter::new(&self.function, op.first_operand, op.num_operands) + .as_ssa_vars() + .collect(), + }), + MemPhi(op) => Lifted::MemPhi(LiftedMemPhi { + dest_memory: op.dest_memory, + src_memory: OperandIter::new(&self.function, op.first_operand, op.num_operands) + .collect(), + }), + VarSplit(op) => Lifted::VarSplit(op), + SetVarSplit(op) => Lifted::SetVarSplit(LiftedSetVarSplit { + high: op.high, + low: op.low, + src: self.lift_operand(op.src), + }), + VarSplitSsa(op) => Lifted::VarSplitSsa(op), + SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(LiftedSetVarSplitSsa { + high: op.high, + low: op.low, + src: self.lift_operand(op.src), + }), + + Add(op) => Lifted::Add(self.lift_binary_op(op)), + Sub(op) => Lifted::Sub(self.lift_binary_op(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)), + Ror(op) => Lifted::Ror(self.lift_binary_op(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)), + 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)), + AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_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)), + 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)), + + Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)), + Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)), + Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)), + Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)), + + Call(op) => Lifted::Call(self.lift_call(op)), + Tailcall(op) => Lifted::Tailcall(self.lift_call(op)), + + Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic { + output: OperandIter::new(&self.function, op.first_output, op.num_outputs) + .as_vars() + .collect(), + intrinsic: ILIntrinsic::new(self.function.get_function().arch(), op.intrinsic), + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + }), + Syscall(op) => Lifted::Syscall(LiftedSyscallCall { + output: OperandIter::new(&self.function, op.first_output, op.num_outputs) + .as_vars() + .collect(), + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + }), + IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa { + output: OperandIter::new(&self.function, op.first_output, op.num_outputs) + .as_ssa_vars() + .collect(), + intrinsic: ILIntrinsic::new(self.function.get_function().arch(), op.intrinsic), + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + }), + + CallSsa(op) => Lifted::CallSsa(self.lift_call_ssa(op)), + TailcallSsa(op) => Lifted::TailcallSsa(self.lift_call_ssa(op)), + + CallUntypedSsa(op) => Lifted::CallUntypedSsa(self.lift_call_untyped_ssa(op)), + TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(self.lift_call_untyped_ssa(op)), + + SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa { + output: get_call_output_ssa(&self.function, op.output).collect(), + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + src_memory: op.src_memory, + }), + SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(LiftedSyscallUntypedSsa { + output: get_call_output_ssa(&self.function, op.output).collect(), + params: get_call_params_ssa(&self.function, op.params) + .map(|param| param.lift()) + .collect(), + stack: self.lift_operand(op.stack), + }), + + CallUntyped(op) => Lifted::CallUntyped(self.lift_call_untyped(op)), + TailcallUntyped(op) => Lifted::TailcallUntyped(self.lift_call_untyped(op)), + SyscallUntyped(op) => Lifted::SyscallUntyped(LiftedSyscallUntyped { + output: get_call_output(&self.function, op.output).collect(), + params: get_call_params(&self.function, op.params) + .map(|param| param.lift()) + .collect(), + stack: self.lift_operand(op.stack), + }), + + 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)), + BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)), + UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_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)), + Load(op) => Lifted::Load(self.lift_unary_op(op)), + + LoadStruct(op) => Lifted::LoadStruct(LiftedLoadStruct { + src: self.lift_operand(op.src), + offset: op.offset, + }), + LoadStructSsa(op) => Lifted::LoadStructSsa(LiftedLoadStructSsa { + src: self.lift_operand(op.src), + offset: op.offset, + src_memory: op.src_memory, + }), + LoadSsa(op) => Lifted::LoadSsa(LiftedLoadSsa { + src: self.lift_operand(op.src), + src_memory: op.src_memory, + }), + Ret(op) => Lifted::Ret(LiftedRet { + src: OperandIter::new(&self.function, op.first_operand, op.num_operands) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + }), + SeparateParamList(op) => Lifted::SeparateParamList(LiftedSeparateParamList { + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + }), + SharedParamSlot(op) => Lifted::SharedParamSlot(LiftedSharedParamSlot { + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + }), + Var(op) => Lifted::Var(op), + AddressOf(op) => Lifted::AddressOf(op), + VarField(op) => Lifted::VarField(op), + AddressOfField(op) => Lifted::AddressOfField(op), + VarSsa(op) => Lifted::VarSsa(op), + VarAliased(op) => Lifted::VarAliased(op), + VarSsaField(op) => Lifted::VarSsaField(op), + VarAliasedField(op) => Lifted::VarAliasedField(op), + Trap(op) => Lifted::Trap(op), + }; + + MediumLevelILLiftedInstruction { + function: self.function.clone(), + address: self.address, + kind, } } - pub fn address(&self) -> u64 { - use MediumLevelILInstruction::*; - match self { - Nop(op) => op.address, - Noret(op) => op.address, - Bp(op) => op.address, - Undef(op) => op.address, - Unimpl(op) => op.address, - If(op) => op.address, - FloatConst(op) => op.address, - Const(op) => op.address, - ConstPtr(op) => op.address, - Import(op) => op.address, - ExternPtr(op) => op.address, - ConstData(op) => op.address, - Jump(op) => op.address, - RetHint(op) => op.address, - StoreSsa(op) => op.address, - StoreStructSsa(op) => op.address, - StoreStruct(op) => op.address, - Store(op) => op.address, - JumpTo(op) => op.address, - Goto(op) => op.address, - FreeVarSlot(op) => op.address, - SetVarField(op) => op.address, - SetVar(op) => op.address, - FreeVarSlotSsa(op) => op.address, - SetVarSsaField(op) => op.address, - SetVarAliasedField(op) => op.address, - SetVarAliased(op) => op.address, - SetVarSsa(op) => op.address, - VarPhi(op) => op.address, - MemPhi(op) => op.address, - VarSplit(op) => op.address, - SetVarSplit(op) => op.address, - VarSplitSsa(op) => op.address, - SetVarSplitSsa(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, - 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, - Fadd(op) => op.address, - Fsub(op) => op.address, - Fmul(op) => op.address, - Fdiv(op) => op.address, - Adc(op) => op.address, - Sbb(op) => op.address, - Rlc(op) => op.address, - Rrc(op) => op.address, - Call(op) => op.address, - Tailcall(op) => op.address, - Syscall(op) => op.address, - Intrinsic(op) => op.address, - IntrinsicSsa(op) => op.address, - CallSsa(op) => op.address, - TailcallSsa(op) => op.address, - CallUntypedSsa(op) => op.address, - TailcallUntypedSsa(op) => op.address, - SyscallSsa(op) => op.address, - SyscallUntypedSsa(op) => op.address, - CallUntyped(op) => op.address, - TailcallUntyped(op) => op.address, - SyscallUntyped(op) => op.address, - SeparateParamList(op) => op.address, - SharedParamSlot(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, - Load(op) => op.address, - LoadStruct(op) => op.address, - LoadStructSsa(op) => op.address, - LoadSsa(op) => op.address, - Ret(op) => op.address, - Var(op) => op.address, - AddressOf(op) => op.address, - VarField(op) => op.address, - AddressOfField(op) => op.address, - VarSsa(op) => op.address, - VarAliased(op) => op.address, - VarSsaField(op) => op.address, - VarAliasedField(op) => op.address, - Trap(op) => op.address, + fn lift_operand(&self, expr_idx: usize) -> Box<MediumLevelILLiftedInstruction> { + 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) -> MediumLevelILLiftedInstruction { - use MediumLevelILInstruction::*; - use MediumLevelILLiftedInstruction as Lifted; + 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), + } + } - match self { - Nop(op) => Lifted::Nop(op.clone()), - Noret(op) => Lifted::Noret(op.clone()), - Bp(op) => Lifted::Bp(op.clone()), - Undef(op) => Lifted::Undef(op.clone()), - Unimpl(op) => Lifted::Unimpl(op.clone()), - If(op) => Lifted::If(op.lift()), - FloatConst(op) => Lifted::FloatConst(op.clone()), - Const(op) => Lifted::Const(op.clone()), - ConstPtr(op) => Lifted::ConstPtr(op.clone()), - Import(op) => Lifted::Import(op.clone()), - ExternPtr(op) => Lifted::ExternPtr(op.clone()), - ConstData(op) => Lifted::ConstData(op.lift()), - Jump(op) => Lifted::Jump(op.lift()), - RetHint(op) => Lifted::RetHint(op.lift()), - StoreSsa(op) => Lifted::StoreSsa(op.lift()), - StoreStructSsa(op) => Lifted::StoreStructSsa(op.lift()), - StoreStruct(op) => Lifted::StoreStruct(op.lift()), - Store(op) => Lifted::Store(op.lift()), - JumpTo(op) => Lifted::JumpTo(op.lift()), - Goto(op) => Lifted::Goto(op.clone()), - FreeVarSlot(op) => Lifted::FreeVarSlot(op.clone()), - SetVarField(op) => Lifted::SetVarField(op.lift()), - SetVar(op) => Lifted::SetVar(op.lift()), - FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op.lift()), - SetVarSsaField(op) => Lifted::SetVarSsaField(op.lift()), - SetVarAliasedField(op) => Lifted::SetVarAliasedField(op.lift()), - SetVarAliased(op) => Lifted::SetVarAliased(op.lift()), - SetVarSsa(op) => Lifted::SetVarSsa(op.lift()), - VarPhi(op) => Lifted::VarPhi(op.lift()), - MemPhi(op) => Lifted::MemPhi(op.lift()), - VarSplit(op) => Lifted::VarSplit(op.lift()), - SetVarSplit(op) => Lifted::SetVarSplit(op.lift()), - VarSplitSsa(op) => Lifted::VarSplitSsa(op.lift()), - SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(op.lift()), - Add(op) => Lifted::Add(op.lift()), - Sub(op) => Lifted::Sub(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()), - Ror(op) => Lifted::Ror(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()), - 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()), - AddOverflow(op) => Lifted::AddOverflow(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()), - Fadd(op) => Lifted::Fadd(op.lift()), - Fsub(op) => Lifted::Fsub(op.lift()), - Fmul(op) => Lifted::Fmul(op.lift()), - Fdiv(op) => Lifted::Fdiv(op.lift()), - Adc(op) => Lifted::Adc(op.lift()), - Sbb(op) => Lifted::Sbb(op.lift()), - Rlc(op) => Lifted::Rlc(op.lift()), - Rrc(op) => Lifted::Rrc(op.lift()), - Call(op) => Lifted::Call(op.lift()), - Tailcall(op) => Lifted::Tailcall(op.lift()), - Intrinsic(op) => Lifted::Intrinsic(op.lift()), - Syscall(op) => Lifted::Syscall(op.lift()), - IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift()), - CallSsa(op) => Lifted::CallSsa(op.lift()), - TailcallSsa(op) => Lifted::TailcallSsa(op.lift()), - CallUntypedSsa(op) => Lifted::CallUntypedSsa(op.lift()), - TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(op.lift()), - SyscallSsa(op) => Lifted::SyscallSsa(op.lift()), - SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(op.lift()), - CallUntyped(op) => Lifted::CallUntyped(op.lift()), - TailcallUntyped(op) => Lifted::TailcallUntyped(op.lift()), - SyscallUntyped(op) => Lifted::SyscallUntyped(op.lift()), - SeparateParamList(op) => Lifted::SeparateParamList(op.lift()), - SharedParamSlot(op) => Lifted::SharedParamSlot(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()), - BoolToInt(op) => Lifted::BoolToInt(op.lift()), - UnimplMem(op) => Lifted::UnimplMem(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()), - Load(op) => Lifted::Load(op.lift()), - LoadStruct(op) => Lifted::LoadStruct(op.lift()), - LoadStructSsa(op) => Lifted::LoadStructSsa(op.lift()), - LoadSsa(op) => Lifted::LoadSsa(op.lift()), - Ret(op) => Lifted::Ret(op.lift()), - Var(op) => Lifted::Var(op.clone()), - AddressOf(op) => Lifted::AddressOf(op.clone()), - VarField(op) => Lifted::VarField(op.clone()), - AddressOfField(op) => Lifted::AddressOfField(op.clone()), - VarSsa(op) => Lifted::VarSsa(op.clone()), - VarAliased(op) => Lifted::VarAliased(op.clone()), - VarSsaField(op) => Lifted::VarSsaField(op.clone()), - VarAliasedField(op) => Lifted::VarAliasedField(op.clone()), - Trap(op) => Lifted::Trap(op.clone()), + fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp { + LiftedUnaryOp { + src: self.lift_operand(op.src), } } - pub fn operands(&self) -> Box<dyn Iterator<Item = (&'static str, MediumLevelILOperand)> + '_> { - use MediumLevelILInstruction::*; - match self { - Nop(_op) | Noret(_op) | Bp(_op) | Undef(_op) | Unimpl(_op) => Box::new([].into_iter()), - If(op) => Box::new(op.operands()), - FloatConst(op) => Box::new(op.operands()), - Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()), - ExternPtr(op) => Box::new(op.operands()), - ConstData(op) => Box::new(op.operands()), - Jump(op) | RetHint(op) => Box::new(op.operands()), - StoreSsa(op) => Box::new(op.operands()), - StoreStructSsa(op) => Box::new(op.operands()), - StoreStruct(op) => Box::new(op.operands()), - Store(op) => Box::new(op.operands()), - JumpTo(op) => Box::new(op.operands()), - Goto(op) => Box::new(op.operands()), - FreeVarSlot(op) => Box::new(op.operands()), - SetVarField(op) => Box::new(op.operands()), - SetVar(op) => Box::new(op.operands()), - FreeVarSlotSsa(op) => Box::new(op.operands()), - SetVarSsaField(op) | SetVarAliasedField(op) => Box::new(op.operands()), - SetVarAliased(op) => Box::new(op.operands()), - SetVarSsa(op) => Box::new(op.operands()), - VarPhi(op) => Box::new(op.operands()), - MemPhi(op) => Box::new(op.operands()), - VarSplit(op) => Box::new(op.operands()), - SetVarSplit(op) => Box::new(op.operands()), - VarSplitSsa(op) => Box::new(op.operands()), - SetVarSplitSsa(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) | FcmpE(op) - | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op) - | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => Box::new(op.operands()), - Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands()), - Call(op) | Tailcall(op) => Box::new(op.operands()), - Syscall(op) => Box::new(op.operands()), - Intrinsic(op) => Box::new(op.operands()), - IntrinsicSsa(op) => Box::new(op.operands()), - CallSsa(op) | TailcallSsa(op) => Box::new(op.operands()), - CallUntypedSsa(op) | TailcallUntypedSsa(op) => Box::new(op.operands()), - SyscallSsa(op) => Box::new(op.operands()), - SyscallUntypedSsa(op) => Box::new(op.operands()), - CallUntyped(op) | TailcallUntyped(op) => Box::new(op.operands()), - SyscallUntyped(op) => Box::new(op.operands()), - SeparateParamList(op) => Box::new(op.operands()), - SharedParamSlot(op) => Box::new(op.operands()), - 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) | Load(op) => { - Box::new(op.operands()) - } - LoadStruct(op) => Box::new(op.operands()), - LoadStructSsa(op) => Box::new(op.operands()), - LoadSsa(op) => Box::new(op.operands()), - Ret(op) => Box::new(op.operands()), - Var(op) | AddressOf(op) => Box::new(op.operands()), - VarField(op) | AddressOfField(op) => Box::new(op.operands()), - VarSsa(op) | VarAliased(op) => Box::new(op.operands()), - VarSsaField(op) | VarAliasedField(op) => Box::new(op.operands()), - Trap(op) => Box::new(op.operands()), + fn lift_call(&self, op: Call) -> LiftedCall { + LiftedCall { + output: OperandIter::new(&self.function, op.first_output, op.num_outputs) + .as_vars() + .collect(), + dest: self.lift_operand(op.dest), + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + } + } + + fn lift_call_untyped(&self, op: CallUntyped) -> LiftedCallUntyped { + LiftedCallUntyped { + output: get_call_output(&self.function, op.output).collect(), + dest: self.lift_operand(op.dest), + params: get_call_params(&self.function, op.params) + .map(|expr| expr.lift()) + .collect(), + stack: self.lift_operand(op.stack), + } + } + + fn lift_call_ssa(&self, op: CallSsa) -> LiftedCallSsa { + LiftedCallSsa { + output: get_call_output_ssa(&self.function, op.output).collect(), + dest: self.lift_operand(op.dest), + params: OperandIter::new(&self.function, op.first_param, op.num_params) + .as_exprs() + .map(|expr| expr.lift()) + .collect(), + src_memory: op.src_memory, + } + } + + fn lift_call_untyped_ssa(&self, op: CallUntypedSsa) -> LiftedCallUntypedSsa { + LiftedCallUntypedSsa { + output: get_call_output_ssa(&self.function, op.output).collect(), + dest: self.lift_operand(op.dest), + params: get_call_params_ssa(&self.function, op.params) + .map(|param| param.lift()) + .collect(), + stack: self.lift_operand(op.stack), } } } diff --git a/rust/src/mlil/lift.rs b/rust/src/mlil/lift.rs index bf7f16db..0cf669bf 100644 --- a/rust/src/mlil/lift.rs +++ b/rust/src/mlil/lift.rs @@ -1,12 +1,43 @@ +use std::collections::HashMap; + +use crate::rc::Ref; +use crate::types; +use crate::types::ILIntrinsic; +use crate::types::{SSAVariable, Variable}; + use super::operation::*; +use super::MediumLevelILFunction; + +#[derive(Clone)] +pub enum MediumLevelILLiftedOperand { + ConstantData(types::ConstantData), + Intrinsic(ILIntrinsic), + Expr(MediumLevelILLiftedInstruction), + ExprList(Vec<MediumLevelILLiftedInstruction>), + Float(f64), + Int(u64), + IntList(Vec<u64>), + TargetMap(HashMap<u64, u64>), + Var(Variable), + VarList(Vec<Variable>), + VarSsa(SSAVariable), + VarSsaList(Vec<SSAVariable>), +} #[derive(Clone, Debug, PartialEq)] -pub enum MediumLevelILLiftedInstruction { - Nop(NoArgs), - Noret(NoArgs), - Bp(NoArgs), - Undef(NoArgs), - Unimpl(NoArgs), +pub struct MediumLevelILLiftedInstruction { + pub function: Ref<MediumLevelILFunction>, + pub address: u64, + pub kind: MediumLevelILLiftedInstructionKind, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum MediumLevelILLiftedInstructionKind { + Nop, + Noret, + Bp, + Undef, + Unimpl, If(LiftedIf), FloatConst(FloatConst), Const(Constant), @@ -133,3 +164,210 @@ pub enum MediumLevelILLiftedInstruction { VarAliasedField(VarSsaField), Trap(Trap), } + +impl MediumLevelILLiftedInstruction { + pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> { + use MediumLevelILLiftedInstructionKind::*; + use MediumLevelILLiftedOperand as Operand; + match &self.kind { + Nop | Noret | Bp | Undef | Unimpl => vec![], + If(op) => vec![ + ("condition", Operand::Expr(*op.condition.clone())), + ("dest_true", Operand::Int(op.dest_true)), + ("dest_false", Operand::Int(op.dest_false)), + ], + FloatConst(op) => vec![("constant", Operand::Float(op.constant))], + Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))], + ExternPtr(op) => vec![ + ("constant", Operand::Int(op.constant)), + ("offset", Operand::Int(op.offset)), + ], + ConstData(op) => vec![( + "constant_data", + Operand::ConstantData(op.constant_data.clone()), + )], + Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))], + StoreSsa(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ("src", Operand::Expr(*op.src.clone())), + ], + StoreStructSsa(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("offset", Operand::Int(op.offset)), + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::Int(op.src_memory)), + ("src", Operand::Expr(*op.src.clone())), + ], + StoreStruct(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("offset", Operand::Int(op.offset)), + ("src", Operand::Expr(*op.src.clone())), + ], + Store(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("src", Operand::Expr(*op.src.clone())), + ], + JumpTo(op) => vec![ + ("dest", Operand::Expr(*op.dest.clone())), + ("targets", Operand::TargetMap(op.targets.clone())), + ], + Goto(op) => vec![("dest", Operand::Int(op.dest))], + FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))], + SetVarField(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("offset", Operand::Int(op.offset)), + ("src", Operand::Expr(*op.src.clone())), + ], + SetVar(op) => vec![ + ("dest", Operand::Var(op.dest)), + ("src", Operand::Expr(*op.src.clone())), + ], + FreeVarSlotSsa(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("prev", Operand::VarSsa(op.prev)), + ], + SetVarSsaField(op) | SetVarAliasedField(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("prev", Operand::VarSsa(op.prev)), + ("offset", Operand::Int(op.offset)), + ("src", Operand::Expr(*op.src.clone())), + ], + SetVarAliased(op) => vec![ + ("dest", Operand::VarSsa(op.dest)), + ("prev", Operand::VarSsa(op.prev)), + ("src", Operand::Expr(*op.src.clone())), + ], + SetVarSsa(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())), + ], + MemPhi(op) => vec![ + ("dest_memory", Operand::Int(op.dest_memory)), + ("src_memory", Operand::IntList(op.src_memory.clone())), + ], + VarSplit(op) => vec![ + ("high", Operand::Var(op.high)), + ("low", Operand::Var(op.low)), + ], + SetVarSplit(op) => vec![ + ("high", Operand::Var(op.high)), + ("low", Operand::Var(op.low)), + ("src", Operand::Expr(*op.src.clone())), + ], + VarSplitSsa(op) => vec![ + ("high", Operand::VarSsa(op.high)), + ("low", Operand::VarSsa(op.low)), + ], + SetVarSplitSsa(op) => vec![ + ("high", Operand::VarSsa(op.high)), + ("low", Operand::VarSsa(op.low)), + ("src", Operand::Expr(*op.src.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) | FcmpE(op) + | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op) + | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![ + ("left", Operand::Expr(*op.left.clone())), + ("right", Operand::Expr(*op.right.clone())), + ], + 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())), + ], + Call(op) | Tailcall(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ], + Syscall(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ], + Intrinsic(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("intrinsic", Operand::Intrinsic(op.intrinsic)), + ("params", Operand::ExprList(op.params.clone())), + ], + IntrinsicSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("intrinsic", Operand::Intrinsic(op.intrinsic)), + ("params", Operand::ExprList(op.params.clone())), + ], + CallSsa(op) | TailcallSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + SyscallSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + SyscallUntypedSsa(op) => vec![ + ("output", Operand::VarSsaList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + CallUntyped(op) | TailcallUntyped(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("dest", Operand::Expr(*op.dest.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + SyscallUntyped(op) => vec![ + ("output", Operand::VarList(op.output.clone())), + ("params", Operand::ExprList(op.params.clone())), + ("stack", Operand::Expr(*op.stack.clone())), + ], + 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) | Load(op) => { + vec![("src", Operand::Expr(*op.src.clone()))] + } + LoadStruct(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("offset", Operand::Int(op.offset)), + ], + LoadStructSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("offset", Operand::Int(op.offset)), + ("src_memory", Operand::Int(op.src_memory)), + ], + LoadSsa(op) => vec![ + ("src", Operand::Expr(*op.src.clone())), + ("src_memory", Operand::Int(op.src_memory)), + ], + Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))], + SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))], + SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))], + Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))], + VarField(op) | AddressOfField(op) => vec![ + ("src", Operand::Var(op.src)), + ("offset", Operand::Int(op.offset)), + ], + VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))], + VarSsaField(op) | VarAliasedField(op) => vec![ + ("src", Operand::VarSsa(op.src)), + ("offset", Operand::Int(op.offset)), + ], + Trap(op) => vec![("vector", Operand::Int(op.vector))], + } + } +} diff --git a/rust/src/mlil/operation.rs b/rust/src/mlil/operation.rs index 876337dd..544fe275 100644 --- a/rust/src/mlil/operation.rs +++ b/rust/src/mlil/operation.rs @@ -14,189 +14,170 @@ use crate::types::{SSAVariable, Variable}; use super::{MediumLevelILFunction, MediumLevelILInstruction, MediumLevelILLiftedInstruction}; -pub enum MediumLevelILOperand { - ConstantData(types::ConstantData), - Intrinsic(ILIntrinsic), - Expr(MediumLevelILInstruction), - ExprList(OperandExprList), - Float(f64), - Int(u64), - IntList(OperandList), - TargetMap(OperandDubleList), - Var(Variable), - VarList(OperandVariableList), - 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 { +pub struct OperandIter { function: Ref<MediumLevelILFunction>, remaining: usize, - next_node_idx: Option<usize>, - - current_node: core::array::IntoIter<u64, 4>, + next_iter_idx: Option<usize>, + current_iter: OperandIterInner, } -impl OperandList { - fn new(function: &MediumLevelILFunction, 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(); - } + +impl OperandIter { + pub(crate) fn new(function: &MediumLevelILFunction, idx: usize, number: usize) -> Self { Self { function: function.to_owned(), remaining: number, - next_node_idx: Some(idx), - current_node: iter, + next_iter_idx: Some(idx), + current_iter: OperandIterInner::empty(), } } - fn duble(self) -> OperandDubleList { + + pub fn as_pairs(self) -> OperandPairIter { assert_eq!(self.len() % 2, 0); - OperandDubleList(self) + OperandPairIter(self) } - fn map_expr(self) -> OperandExprList { - OperandExprList(self) + + pub fn as_exprs(self) -> OperandExprIter { + OperandExprIter(self) } - fn map_var(self) -> OperandVariableList { - OperandVariableList(self) + + pub fn as_vars(self) -> OperandVarIter { + OperandVarIter(self) } - fn map_ssa_var(self) -> OperandSSAVariableList { - OperandSSAVariableList(self.duble()) + + pub fn as_ssa_vars(self) -> OperandSSAVarIter { + OperandSSAVarIter(self.as_pairs()) } } -impl Iterator for OperandList { - type Item = u64; +impl Iterator for OperandIter { + 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); - } + if let Some(item) = self.current_iter.next() { + self.remaining -= 1; + Some(item) + } else { + // Will short-circuit and return `None` once iter is exhausted + let iter_idx = self.next_iter_idx?; + let node = unsafe { BNGetMediumLevelILByIndex(self.function.handle, iter_idx) }; + assert_eq!(node.operation, BNMediumLevelILOperation::MLIL_UNDEF); - // no more items to fetch - if self.remaining == 0 { - return None; + let next = if self.remaining > 4 { + self.next_iter_idx = Some(node.operands[4] as usize); + &node.operands[..4] + } else { + self.next_iter_idx = None; + &node.operands[..self.remaining] + }; + + self.current_iter = OperandIterInner::from_slice(next); + self.next() } + } +} +impl ExactSizeIterator for OperandIter { + fn len(&self) -> usize { + self.remaining + self.current_iter.len() + } +} - // otherwise get the next node - let next_idx = self.next_node_idx?; - let node = unsafe { BNGetMediumLevelILByIndex(self.function.handle, next_idx) }; - assert_eq!(node.operation, BNMediumLevelILOperation::MLIL_UNDEF); +struct OperandIterInner { + arr: [u64; 4], + idx: usize, +} - // 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(); - } +impl OperandIterInner { + fn from_slice(slice: &[u64]) -> Self { + assert!(slice.len() <= 4); + let idx = 4 - slice.len(); + let mut arr = [0; 4]; + arr[idx..].copy_from_slice(slice); + Self { arr, idx } + } - self.current_node.next() + fn empty() -> Self { + Self { + arr: [0; 4], + idx: 4, + } } +} + +impl Iterator for OperandIterInner { + type Item = u64; - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) + fn next(&mut self) -> Option<Self::Item> { + if self.idx < 4 { + let val = self.arr[self.idx]; + self.idx += 1; + Some(val) + } else { + None + } } } -impl ExactSizeIterator for OperandList { +impl ExactSizeIterator for OperandIterInner { fn len(&self) -> usize { - self.remaining + self.current_node.len() + 4 - self.idx } } -// Iterator similar to OperationList, but returns two elements -pub struct OperandDubleList(OperandList); -impl Iterator for OperandDubleList { +pub struct OperandPairIter(OperandIter); +impl Iterator for OperandPairIter { type Item = (u64, u64); fn next(&mut self) -> Option<Self::Item> { let first = self.0.next()?; - let second = self.0.next().unwrap(); + let second = self.0.next()?; Some((first, second)) } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.len(), Some(self.len())) - } } -impl ExactSizeIterator for OperandDubleList { +impl ExactSizeIterator for OperandPairIter { fn len(&self) -> usize { self.0.len() / 2 } } -pub struct OperandExprList(OperandList); -impl Iterator for OperandExprList { +pub struct OperandExprIter(OperandIter); +impl Iterator for OperandExprIter { type Item = MediumLevelILInstruction; fn next(&mut self) -> Option<Self::Item> { self.0 .next() - .map(|idx| get_operation(&self.0.function, idx as usize)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.0.len(), Some(self.0.len())) + .map(|idx| self.0.function.instruction_from_idx(idx as usize)) } } -impl ExactSizeIterator for OperandExprList { +impl ExactSizeIterator for OperandExprIter { fn len(&self) -> usize { self.0.len() } } -pub struct OperandVariableList(OperandList); -impl Iterator for OperandVariableList { +pub struct OperandVarIter(OperandIter); +impl Iterator for OperandVarIter { 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 { +impl ExactSizeIterator for OperandVarIter { fn len(&self) -> usize { self.0.len() } } -pub struct OperandSSAVariableList(OperandDubleList); -impl Iterator for OperandSSAVariableList { +pub struct OperandSSAVarIter(OperandPairIter); +impl Iterator for OperandSSAVarIter { 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())) + self.0 + .next() + .map(|(id, version)| get_var_ssa(id, version as usize)) } } -impl ExactSizeIterator for OperandSSAVariableList { +impl ExactSizeIterator for OperandSSAVarIter { fn len(&self) -> usize { self.0.len() } @@ -211,31 +192,23 @@ fn get_float(value: u64, size: usize) -> f64 { } } -fn get_constant_data( +pub(super) fn get_constant_data( function: &MediumLevelILFunction, - state: u64, - value: u64, + state: u32, + value: i64, size: usize, ) -> types::ConstantData { types::ConstantData::new( function.get_function(), RegisterValue::new( - RegisterValueType::from_raw_value(state as u32).unwrap(), - value as i64, + RegisterValueType::from_raw_value(state).unwrap(), + value, 0, size, ), ) } -fn get_intrinsic(function: &MediumLevelILFunction, idx: u32) -> ILIntrinsic { - ILIntrinsic::new(function.get_function().arch(), idx) -} - -fn get_operation(function: &MediumLevelILFunction, idx: usize) -> MediumLevelILInstruction { - function.instruction_from_idx(idx) -} - fn get_raw_operation(function: &MediumLevelILFunction, idx: usize) -> BNMediumLevelILInstruction { unsafe { BNGetMediumLevelILByIndex(function.handle, idx) } } @@ -245,413 +218,168 @@ fn get_var(id: u64) -> Variable { } fn get_var_ssa(id: u64, version: usize) -> SSAVariable { - let raw = unsafe { BNFromVariableIdentifier(id) }; - let var = unsafe { Variable::from_raw(raw) }; - SSAVariable::new(var, version) -} - -fn get_call_list( - function: &MediumLevelILFunction, - op_type: BNMediumLevelILOperation, - idx: usize, -) -> OperandVariableList { - let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) }; - assert_eq!(op.operation, op_type); - OperandList::new(function, op.operands[1] as usize, op.operands[0] as usize).map_var() + SSAVariable::new(get_var(id), version) } -fn get_call_exprs( - function: &MediumLevelILFunction, - op_type: BNMediumLevelILOperation, - idx: usize, -) -> OperandExprList { - let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) }; - assert_eq!(op.operation, op_type); - OperandList::new(function, op.operands[1] as usize, op.operands[0] as usize).map_expr() -} - -fn get_call_output(function: &MediumLevelILFunction, idx: usize) -> OperandVariableList { - get_call_list(function, BNMediumLevelILOperation::MLIL_CALL_OUTPUT, idx) -} - -fn get_call_params(function: &MediumLevelILFunction, idx: usize) -> OperandExprList { - get_call_exprs(function, BNMediumLevelILOperation::MLIL_CALL_PARAM, idx) +pub(super) fn get_call_output(function: &MediumLevelILFunction, idx: usize) -> OperandVarIter { + let op = get_raw_operation(function, idx); + assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_OUTPUT); + OperandIter::new(function, op.operands[1] as usize, op.operands[0] as usize).as_vars() } -fn get_call_list_ssa( - function: &MediumLevelILFunction, - op_type: BNMediumLevelILOperation, - idx: usize, -) -> OperandSSAVariableList { +pub(super) fn get_call_params(function: &MediumLevelILFunction, idx: usize) -> OperandExprIter { let op = get_raw_operation(function, idx); - assert_eq!(op.operation, op_type); - OperandList::new(function, op.operands[2] as usize, op.operands[1] as usize).map_ssa_var() + assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_PARAM); + OperandIter::new(function, op.operands[1] as usize, op.operands[0] as usize).as_exprs() } -fn get_call_exprs_ssa( +pub(super) fn get_call_output_ssa( function: &MediumLevelILFunction, - op_type: BNMediumLevelILOperation, idx: usize, -) -> OperandExprList { +) -> OperandSSAVarIter { let op = get_raw_operation(function, idx); - assert_eq!(op.operation, op_type); - OperandList::new(function, op.operands[2] as usize, op.operands[1] as usize).map_expr() -} - -fn get_call_output_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandSSAVariableList { - get_call_list_ssa( - function, - BNMediumLevelILOperation::MLIL_CALL_OUTPUT_SSA, - idx, - ) -} - -fn get_call_params_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandExprList { - get_call_exprs_ssa(function, BNMediumLevelILOperation::MLIL_CALL_PARAM_SSA, idx) -} - -// NOP, NORET, BP, UNDEF, UNIMPL -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct NoArgs { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, + assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_OUTPUT_SSA); + OperandIter::new(function, op.operands[2] as usize, op.operands[1] as usize).as_ssa_vars() } -impl NoArgs { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, 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, MediumLevelILOperand)> + '_ { - [].into_iter() - } +pub(super) fn get_call_params_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandExprIter { + let op = get_raw_operation(function, idx); + assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_PARAM_SSA); + OperandIter::new(function, op.operands[2] as usize, op.operands[1] as usize).as_exprs() } // IF -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct MediumLevelILOperationIf { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - condition: usize, - dest_true: u64, - dest_false: u64, + pub condition: usize, + pub dest_true: u64, + pub dest_false: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIf { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub condition: Box<MediumLevelILLiftedInstruction>, pub dest_true: u64, pub dest_false: u64, } impl MediumLevelILOperationIf { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - condition: usize, - dest_true: u64, - dest_false: u64, - ) -> Self { + pub(crate) fn new(condition: usize, dest_true: u64, dest_false: u64) -> Self { Self { - function, - address, condition, dest_true, dest_false, } } - pub fn condition(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.condition) - } - pub fn dest_true(&self) -> u64 { - self.dest_true - } - pub fn dest_false(&self) -> u64 { - self.dest_false - } - pub fn lift(&self) -> LiftedIf { - LiftedIf { - function: self.function.clone(), - address: self.address, - condition: Box::new(self.condition().lift()), - dest_true: self.dest_true(), - dest_false: self.dest_false(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("condition", Expr(self.condition())), - ("dest_true", Int(self.dest_true())), - ("dest_false", Int(self.dest_false())), - ] - .into_iter() - } } // FLOAT_CONST -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct FloatConst { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub constant: f64, } impl FloatConst { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - 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, MediumLevelILOperand)> + '_ { - [("constant", MediumLevelILOperand::Float(self.constant()))].into_iter() - } } // CONST, CONST_PTR, IMPORT -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Constant { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub constant: u64, } impl Constant { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, 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, MediumLevelILOperand)> + '_ { - [("constant", MediumLevelILOperand::Int(self.constant()))].into_iter() + pub(crate) fn new(constant: u64) -> Self { + Self { constant } } } // EXTERN_PTR -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ExternPtr { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub constant: u64, pub offset: u64, } impl ExternPtr { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - 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, MediumLevelILOperand)> + '_ { - [ - ("constant", MediumLevelILOperand::Int(self.constant())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ] - .into_iter() + pub(crate) fn new(constant: u64, offset: u64) -> Self { + Self { constant, offset } } } // CONST_DATA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct ConstantData { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - constant_data: (u64, u64), - size: usize, + pub constant_data_kind: u32, + pub constant_data_value: i64, + pub size: usize, } #[derive(Clone, Debug, Hash, PartialEq)] pub struct LiftedConstantData { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub constant_data: types::ConstantData, } impl ConstantData { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - constant_data: (u64, u64), - size: 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) -> types::ConstantData { - get_constant_data( - &self.function, - self.constant_data.0, - self.constant_data.1, - self.size, - ) - } - - pub fn lift(&self) -> LiftedConstantData { - LiftedConstantData { - function: self.function.clone(), - address: self.address, - constant_data: self.constant_data(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [( - "contant_data", - MediumLevelILOperand::ConstantData(self.constant_data()), - )] - .into_iter() - } } // JUMP, RET_HINT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Jump { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: usize, + pub dest: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedJump { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Box<MediumLevelILLiftedInstruction>, } impl Jump { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, dest: usize) -> Self { - Self { - function, - address, - dest, - } - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn lift(&self) -> LiftedJump { - LiftedJump { - function: self.function.clone(), - address: self.address, - dest: Box::new(self.dest().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("dest", MediumLevelILOperand::Expr(self.dest()))].into_iter() + pub(crate) fn new(dest: usize) -> Self { + Self { dest } } } // STORE_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct StoreSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: usize, - dest_memory: u64, - src_memory: u64, - src: usize, + pub dest: usize, + pub dest_memory: u64, + pub src_memory: u64, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedStoreSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Box<MediumLevelILLiftedInstruction>, pub dest_memory: u64, pub src_memory: u64, pub src: Box<MediumLevelILLiftedInstruction>, } impl StoreSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: usize, - dest_memory: u64, - src_memory: u64, - src: usize, - ) -> Self { + pub(crate) fn new(dest: usize, dest_memory: u64, src_memory: u64, src: usize) -> Self { Self { - function, - address, dest, dest_memory, src_memory, src, } } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedStoreSsa { - LiftedStoreSsa { - function: self.function.clone(), - address: self.address, - dest: Box::new(self.dest().lift()), - dest_memory: self.dest_memory(), - src_memory: self.src_memory(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::Expr(self.dest())), - ("dest_memory", MediumLevelILOperand::Int(self.dest_memory())), - ("src_memory", MediumLevelILOperand::Int(self.src_memory())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // STORE_STRUCT_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct StoreStructSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: usize, - offset: u64, - dest_memory: u64, - src_memory: u64, - src: usize, + pub dest: usize, + pub offset: u64, + pub dest_memory: u64, + pub src_memory: u64, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedStoreStructSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Box<MediumLevelILLiftedInstruction>, pub offset: u64, pub dest_memory: u64, @@ -660,8 +388,6 @@ pub struct LiftedStoreStructSsa { } impl StoreStructSsa { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, dest: usize, offset: u64, dest_memory: u64, @@ -669,8 +395,6 @@ impl StoreStructSsa { src: usize, ) -> Self { Self { - function, - address, dest, offset, dest_memory, @@ -678,1279 +402,512 @@ impl StoreStructSsa { src, } } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedStoreStructSsa { - LiftedStoreStructSsa { - function: self.function.clone(), - address: self.address, - dest: Box::new(self.dest().lift()), - offset: self.offset(), - dest_memory: self.dest_memory(), - src_memory: self.src_memory(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::Expr(self.dest())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ("dest_memory", MediumLevelILOperand::Int(self.dest_memory())), - ("src_memory", MediumLevelILOperand::Int(self.src_memory())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // STORE_STRUCT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct StoreStruct { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: usize, - offset: u64, - src: usize, + pub dest: usize, + pub offset: u64, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedStoreStruct { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Box<MediumLevelILLiftedInstruction>, pub offset: u64, pub src: Box<MediumLevelILLiftedInstruction>, } impl StoreStruct { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: usize, - offset: u64, - src: usize, - ) -> Self { - Self { - function, - address, - dest, - offset, - src, - } - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedStoreStruct { - LiftedStoreStruct { - function: self.function.clone(), - address: self.address, - dest: Box::new(self.dest().lift()), - offset: self.offset(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::Expr(self.dest())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() + pub(crate) fn new(dest: usize, offset: u64, src: usize) -> Self { + Self { dest, offset, src } } } // STORE -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Store { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: usize, - src: usize, + pub dest: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedStore { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Box<MediumLevelILLiftedInstruction>, pub src: Box<MediumLevelILLiftedInstruction>, } impl Store { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: usize, - src: usize, - ) -> Self { - Self { - function, - address, - dest, - src, - } - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedStore { - LiftedStore { - function: self.function.clone(), - address: self.address, - dest: Box::new(self.dest().lift()), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::Expr(self.dest())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() + pub(crate) fn new(dest: usize, src: usize) -> Self { + Self { dest, src } } } // JUMP_TO -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct JumpTo { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: usize, - targets: (usize, usize), + pub dest: usize, + pub first_operand: usize, + pub num_operands: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedJumpTo { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Box<MediumLevelILLiftedInstruction>, pub targets: HashMap<u64, u64>, } impl JumpTo { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: usize, - targets: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: usize, num_operands: usize, first_operand: usize) -> Self { Self { - function, - address, dest, - targets, + first_operand, + num_operands, } } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn targets(&self) -> OperandDubleList { - OperandList::new(&self.function, self.targets.1, self.targets.0).duble() - } - pub fn lift(&self) -> LiftedJumpTo { - LiftedJumpTo { - function: self.function.clone(), - address: self.address, - dest: Box::new(self.dest().lift()), - targets: self.targets().collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("dest", Expr(self.dest())), - ("targets", TargetMap(self.targets())), - ] - .into_iter() - } } // GOTO -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Goto { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: u64, } impl Goto { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, dest: u64) -> Self { - Self { - function, - address, - dest, - } - } - pub fn dest(&self) -> u64 { - self.dest - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("dest", MediumLevelILOperand::Int(self.dest()))].into_iter() + pub(crate) fn new(dest: u64) -> Self { + Self { dest } } } // FREE_VAR_SLOT -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct FreeVarSlot { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Variable, } impl FreeVarSlot { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, dest: u64) -> Self { + pub(crate) fn new(dest: u64) -> Self { Self { - function, - address, dest: get_var(dest), } } - pub fn dest(&self) -> Variable { - self.dest - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("dest", MediumLevelILOperand::Var(self.dest()))].into_iter() - } } // SET_VAR_FIELD -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVarField { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: u64, - offset: u64, - src: usize, + pub dest: Variable, + pub offset: u64, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVarField { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Variable, pub offset: u64, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVarField { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: u64, - offset: u64, - src: usize, - ) -> Self { + pub(crate) fn new(dest: u64, offset: u64, src: usize) -> Self { Self { - function, - address, - dest, + dest: get_var(dest), offset, src, } } - pub fn dest(&self) -> Variable { - get_var(self.dest) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVarField { - LiftedSetVarField { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - offset: self.offset(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::Var(self.dest())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // SET_VAR -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVar { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: u64, - src: usize, + pub dest: Variable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVar { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: Variable, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVar { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: u64, - src: usize, - ) -> Self { + pub(crate) fn new(dest: u64, src: usize) -> Self { Self { - function, - address, - dest, + dest: get_var(dest), src, } } - pub fn dest(&self) -> Variable { - get_var(self.dest) - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVar { - LiftedSetVar { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::Var(self.dest())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // FREE_VAR_SLOT_SSA -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct FreeVarSlotSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub prev: SSAVariable, } impl FreeVarSlotSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: (u64, usize), - prev: (u64, usize), - ) -> Self { + pub(crate) fn new(dest: (u64, usize), prev: (u64, usize)) -> Self { Self { - function, - address, dest: get_var_ssa(dest.0, dest.1), prev: get_var_ssa(prev.0, prev.1), } } - pub fn dest(&self) -> SSAVariable { - self.dest - } - pub fn prev(&self) -> SSAVariable { - self.prev - } - pub fn lift(&self) -> FreeVarSlotSsa { - FreeVarSlotSsa { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - prev: self.prev(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::VarSsa(self.dest())), - ("prev", MediumLevelILOperand::VarSsa(self.prev())), - ] - .into_iter() - } } // SET_VAR_SSA_FIELD, SET_VAR_ALIASED_FIELD -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVarSsaField { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: (u64, usize), - prev: (u64, usize), - offset: u64, - src: usize, + pub dest: SSAVariable, + pub prev: SSAVariable, + pub offset: u64, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVarSsaField { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub prev: SSAVariable, pub offset: u64, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVarSsaField { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: (u64, usize), - prev: (u64, usize), - offset: u64, - src: usize, - ) -> Self { + pub(crate) fn new(dest: (u64, usize), prev: (u64, usize), offset: u64, src: usize) -> Self { Self { - function, - address, - dest, - prev, + dest: get_var_ssa(dest.0, dest.1), + prev: get_var_ssa(prev.0, prev.1), offset, src, } } - pub fn dest(&self) -> SSAVariable { - get_var_ssa(self.dest.0, self.dest.1) - } - pub fn prev(&self) -> SSAVariable { - get_var_ssa(self.prev.0, self.prev.1) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVarSsaField { - LiftedSetVarSsaField { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - prev: self.prev(), - offset: self.offset(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::VarSsa(self.dest())), - ("prev", MediumLevelILOperand::VarSsa(self.prev())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // SET_VAR_ALIASED -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVarAliased { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: (u64, usize), - prev: (u64, usize), - src: usize, + pub dest: SSAVariable, + pub prev: SSAVariable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVarAliased { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub prev: SSAVariable, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVarAliased { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: (u64, usize), - prev: (u64, usize), - src: usize, - ) -> Self { + pub(crate) fn new(dest: (u64, usize), prev: (u64, usize), src: usize) -> Self { Self { - function, - address, - dest, - prev, + dest: get_var_ssa(dest.0, dest.1), + prev: get_var_ssa(prev.0, prev.1), src, } } - pub fn dest(&self) -> SSAVariable { - get_var_ssa(self.dest.0, self.dest.1) - } - pub fn prev(&self) -> SSAVariable { - get_var_ssa(self.prev.0, self.prev.1) - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVarAliased { - LiftedSetVarAliased { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - prev: self.prev(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::VarSsa(self.dest())), - ("prev", MediumLevelILOperand::VarSsa(self.prev())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // SET_VAR_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVarSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: (u64, usize), - src: usize, + pub dest: SSAVariable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVarSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVarSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: (u64, usize), - src: usize, - ) -> Self { + pub(crate) fn new(dest: (u64, usize), src: usize) -> Self { Self { - function, - address, - dest, + dest: get_var_ssa(dest.0, dest.1), src, } } - pub fn dest(&self) -> SSAVariable { - get_var_ssa(self.dest.0, self.dest.1) - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVarSsa { - LiftedSetVarSsa { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::VarSsa(self.dest())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // VAR_PHI -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct VarPhi { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest: (u64, usize), - src: (usize, usize), + pub dest: SSAVariable, + pub first_operand: usize, + pub num_operands: usize, } #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct LiftedVarPhi { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest: SSAVariable, pub src: Vec<SSAVariable>, } impl VarPhi { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest: (u64, usize), - src: (usize, usize), - ) -> Self { + pub(crate) fn new(dest: (u64, usize), num_operands: usize, first_operand: usize) -> Self { Self { - function, - address, - dest, - src, - } - } - pub fn dest(&self) -> SSAVariable { - get_var_ssa(self.dest.0, self.dest.1) - } - pub fn src(&self) -> OperandSSAVariableList { - OperandList::new(&self.function, self.src.1, self.src.0).map_ssa_var() - } - pub fn lift(&self) -> LiftedVarPhi { - LiftedVarPhi { - function: self.function.clone(), - address: self.address, - dest: self.dest(), - src: self.src().collect(), + dest: get_var_ssa(dest.0, dest.1), + first_operand, + num_operands, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("dest", MediumLevelILOperand::VarSsa(self.dest())), - ("src", MediumLevelILOperand::VarSsaList(self.src())), - ] - .into_iter() - } } // MEM_PHI -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct MemPhi { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - dest_memory: u64, - src_memory: (usize, usize), + pub dest_memory: u64, + pub first_operand: usize, + pub num_operands: usize, } #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct LiftedMemPhi { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub dest_memory: u64, pub src_memory: Vec<u64>, } impl MemPhi { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - dest_memory: u64, - src_memory: (usize, usize), - ) -> Self { + pub(crate) fn new(dest_memory: u64, num_operands: usize, first_operand: usize) -> Self { Self { - function, - address, dest_memory, - src_memory, + first_operand, + num_operands, } } - pub fn dest_memory(&self) -> u64 { - self.dest_memory - } - pub fn src_memory(&self) -> OperandList { - OperandList::new(&self.function, self.src_memory.1, self.src_memory.0) - } - pub fn lift(&self) -> LiftedMemPhi { - LiftedMemPhi { - function: self.function.clone(), - address: self.address, - dest_memory: self.dest_memory(), - src_memory: self.src_memory().collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("dest_memory", Int(self.dest_memory())), - ("src_memory", IntList(self.src_memory())), - ] - .into_iter() - } } // VAR_SPLIT -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSplit { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub high: Variable, pub low: Variable, } impl VarSplit { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - high: u64, - low: u64, - ) -> Self { + pub(crate) fn new(high: u64, low: u64) -> Self { Self { - function, - address, high: get_var(high), low: get_var(low), } } - pub fn high(&self) -> Variable { - self.high - } - pub fn low(&self) -> Variable { - self.low - } - pub fn lift(&self) -> VarSplit { - VarSplit { - function: self.function.clone(), - address: self.address, - high: self.high(), - low: self.low(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("high", MediumLevelILOperand::Var(self.high())), - ("low", MediumLevelILOperand::Var(self.low())), - ] - .into_iter() - } } // SET_VAR_SPLIT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVarSplit { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - high: u64, - low: u64, - src: usize, + pub high: Variable, + pub low: Variable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVarSplit { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub high: Variable, pub low: Variable, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVarSplit { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - high: u64, - low: u64, - src: usize, - ) -> Self { + pub(crate) fn new(high: u64, low: u64, src: usize) -> Self { Self { - function, - address, - high, - low, + high: get_var(high), + low: get_var(low), src, } } - pub fn high(&self) -> Variable { - get_var(self.high) - } - pub fn low(&self) -> Variable { - get_var(self.low) - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVarSplit { - LiftedSetVarSplit { - function: self.function.clone(), - address: self.address, - high: self.high(), - low: self.low(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("high", MediumLevelILOperand::Var(self.high())), - ("low", MediumLevelILOperand::Var(self.low())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // VAR_SPLIT_SSA -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSplitSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub high: SSAVariable, pub low: SSAVariable, } impl VarSplitSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - high: (u64, usize), - low: (u64, usize), - ) -> Self { + pub(crate) fn new(high: (u64, usize), low: (u64, usize)) -> Self { Self { - function, - address, high: get_var_ssa(high.0, high.1), low: get_var_ssa(low.0, low.1), } } - pub fn high(&self) -> SSAVariable { - self.high - } - pub fn low(&self) -> SSAVariable { - self.low - } - pub fn lift(&self) -> VarSplitSsa { - VarSplitSsa { - function: self.function.clone(), - address: self.address, - high: self.high(), - low: self.low(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("high", MediumLevelILOperand::VarSsa(self.high())), - ("low", MediumLevelILOperand::VarSsa(self.low())), - ] - .into_iter() - } } // SET_VAR_SPLIT_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SetVarSplitSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - high: (u64, usize), - low: (u64, usize), - src: usize, + pub high: SSAVariable, + pub low: SSAVariable, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSetVarSplitSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub high: SSAVariable, pub low: SSAVariable, pub src: Box<MediumLevelILLiftedInstruction>, } impl SetVarSplitSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - high: (u64, usize), - low: (u64, usize), - src: usize, - ) -> Self { + pub(crate) fn new(high: (u64, usize), low: (u64, usize), src: usize) -> Self { Self { - function, - address, - high, - low, + high: get_var_ssa(high.0, high.1), + low: get_var_ssa(low.0, low.1), src, } } - pub fn high(&self) -> SSAVariable { - get_var_ssa(self.high.0, self.high.1) - } - pub fn low(&self) -> SSAVariable { - get_var_ssa(self.low.0, self.low.1) - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedSetVarSplitSsa { - LiftedSetVarSplitSsa { - function: self.function.clone(), - address: self.address, - high: self.high(), - low: self.low(), - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("high", MediumLevelILOperand::VarSsa(self.high())), - ("low", MediumLevelILOperand::VarSsa(self.low())), - ("src", MediumLevelILOperand::Expr(self.src())), - ] - .into_iter() - } } // 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, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO, FADD, FSUB, FMUL, FDIV -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct BinaryOp { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - left: usize, - right: usize, + pub left: usize, + pub right: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedBinaryOp { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub left: Box<MediumLevelILLiftedInstruction>, pub right: Box<MediumLevelILLiftedInstruction>, } impl BinaryOp { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - left: usize, - right: usize, - ) -> Self { - Self { - function, - address, - left, - right, - } - } - pub fn left(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.left) - } - pub fn right(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.right) - } - pub fn lift(&self) -> LiftedBinaryOp { - LiftedBinaryOp { - function: self.function.clone(), - address: self.address, - left: Box::new(self.left().lift()), - right: Box::new(self.right().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("left", MediumLevelILOperand::Expr(self.left())), - ("right", MediumLevelILOperand::Expr(self.right())), - ] - .into_iter() + pub(crate) fn new(left: usize, right: usize) -> Self { + Self { left, right } } } // ADC, SBB, RLC, RRC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct BinaryOpCarry { - pub function: Ref<MediumLevelILFunction>, - 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<MediumLevelILFunction>, - pub address: u64, pub left: Box<MediumLevelILLiftedInstruction>, pub right: Box<MediumLevelILLiftedInstruction>, pub carry: Box<MediumLevelILLiftedInstruction>, } impl BinaryOpCarry { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - left: usize, - right: usize, - carry: usize, - ) -> Self { - Self { - function, - address, - left, - right, - carry, - } - } - pub fn left(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.left) - } - pub fn right(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.right) - } - pub fn carry(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.carry) - } - pub fn lift(&self) -> LiftedBinaryOpCarry { - LiftedBinaryOpCarry { - function: self.function.clone(), - 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, MediumLevelILOperand)> + '_ { - [ - ("left", MediumLevelILOperand::Expr(self.left())), - ("right", MediumLevelILOperand::Expr(self.right())), - ("carry", MediumLevelILOperand::Expr(self.carry())), - ] - .into_iter() + pub(crate) fn new(left: usize, right: usize, carry: usize) -> Self { + Self { left, right, carry } } } // CALL, TAILCALL -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Call { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: (usize, usize), - dest: usize, - params: (usize, usize), + pub first_output: usize, + pub num_outputs: usize, + pub dest: usize, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCall { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<Variable>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, } impl Call { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: (usize, usize), + num_outputs: usize, + first_output: usize, dest: usize, - params: (usize, usize), + num_params: usize, + first_param: usize, ) -> Self { Self { - function, - address, - output, + num_outputs, + first_output, dest, - params, + num_params, + first_param, } } - pub fn output(&self) -> OperandVariableList { - OperandList::new(&self.function, self.output.1, self.output.0).map_var() - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn lift(&self) -> LiftedCall { - LiftedCall { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - dest: Box::new(self.dest().lift()), - params: self.params().map(|instr| instr.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("output", MediumLevelILOperand::VarList(self.output())), - ("dest", MediumLevelILOperand::Expr(self.dest())), - ("params", MediumLevelILOperand::ExprList(self.params())), - ] - .into_iter() - } } // SYSCALL -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Syscall { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: (usize, usize), - params: (usize, usize), + pub first_output: usize, + pub num_outputs: usize, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallCall { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<Variable>, pub params: Vec<MediumLevelILLiftedInstruction>, } impl Syscall { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: (usize, usize), - params: (usize, usize), + num_outputs: usize, + first_output: usize, + num_params: usize, + first_param: usize, ) -> Self { Self { - function, - address, - output, - params, + num_outputs, + first_output, + num_params, + first_param, } } - pub fn output(&self) -> OperandVariableList { - OperandList::new(&self.function, self.output.1, self.output.0).map_var() - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn lift(&self) -> LiftedSyscallCall { - LiftedSyscallCall { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - params: self.params().map(|instr| instr.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarList(self.output())), - ("params", ExprList(self.params())), - ] - .into_iter() - } } // INTRINSIC -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Intrinsic { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: (usize, usize), - intrinsic: u32, - params: (usize, usize), + pub first_output: usize, + pub num_outputs: usize, + pub intrinsic: u32, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIntrinsic { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<Variable>, pub intrinsic: ILIntrinsic, pub params: Vec<MediumLevelILLiftedInstruction>, } impl Intrinsic { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: (usize, usize), + num_outputs: usize, + first_output: usize, intrinsic: u32, - params: (usize, usize), + num_params: usize, + first_param: usize, ) -> Self { Self { - function, - address, - output, + num_outputs, + first_output, intrinsic, - params, - } - } - pub fn output(&self) -> OperandVariableList { - OperandList::new(&self.function, self.output.1, self.output.0).map_var() - } - pub fn intrinsic(&self) -> ILIntrinsic { - get_intrinsic(&self.function, self.intrinsic) - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn lift(&self) -> LiftedIntrinsic { - LiftedIntrinsic { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - intrinsic: self.intrinsic(), - params: self.params().map(|instr| instr.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarList(self.output())), - ("intrinsic", Intrinsic(self.intrinsic())), - ("params", ExprList(self.params())), - ] - .into_iter() - } } // INTRINSIC_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct IntrinsicSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: (usize, usize), - intrinsic: u32, - params: (usize, usize), + pub first_output: usize, + pub num_outputs: usize, + pub intrinsic: u32, + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedIntrinsicSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<SSAVariable>, pub intrinsic: ILIntrinsic, pub params: Vec<MediumLevelILLiftedInstruction>, } impl IntrinsicSsa { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: (usize, usize), + num_outputs: usize, + first_output: usize, intrinsic: u32, - params: (usize, usize), + num_params: usize, + first_param: usize, ) -> Self { Self { - function, - address, - output, + num_outputs, + first_output, intrinsic, - params, + num_params, + first_param, } } - pub fn output(&self) -> OperandSSAVariableList { - OperandList::new(&self.function, self.output.1, self.output.0).map_ssa_var() - } - pub fn intrinsic(&self) -> ILIntrinsic { - get_intrinsic(&self.function, self.intrinsic) - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn lift(&self) -> LiftedIntrinsicSsa { - LiftedIntrinsicSsa { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - intrinsic: get_intrinsic(&self.function, self.intrinsic), - params: self.params().map(|instr| instr.lift()).collect(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarSsaList(self.output())), - ("intrinsic", Intrinsic(self.intrinsic())), - ("params", ExprList(self.params())), - ] - .into_iter() - } } // CALL_SSA, TAILCALL_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct CallSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: usize, - dest: usize, - params: (usize, usize), - src_memory: u64, + pub output: usize, + pub dest: usize, + pub first_param: usize, + pub num_params: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<SSAVariable>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, @@ -1958,840 +915,340 @@ pub struct LiftedCallSsa { } impl CallSsa { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, output: usize, dest: usize, - params: (usize, usize), + num_params: usize, + first_param: usize, src_memory: u64, ) -> Self { Self { - function, - address, output, dest, - params, + first_param, + num_params, src_memory, } } - pub fn output(&self) -> OperandSSAVariableList { - get_call_output_ssa(&self.function, self.output) - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedCallSsa { - LiftedCallSsa { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - dest: Box::new(self.dest().lift()), - params: self.params().map(|instr| instr.lift()).collect(), - src_memory: self.src_memory(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarSsaList(self.output())), - ("dest", Expr(self.dest())), - ("params", ExprList(self.params())), - ("src_memory", Int(self.src_memory())), - ] - .into_iter() - } } // CALL_UNTYPED_SSA, TAILCALL_UNTYPED_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct CallUntypedSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: usize, - dest: usize, - params: usize, - stack: usize, + pub output: usize, + pub dest: usize, + pub params: usize, + pub stack: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallUntypedSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<SSAVariable>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, } impl CallUntypedSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: usize, - dest: usize, - params: usize, - stack: usize, - ) -> Self { + pub(crate) fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self { Self { - function, - address, output, dest, params, stack, } } - pub fn output(&self) -> OperandSSAVariableList { - get_call_output_ssa(&self.function, self.output) - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - get_call_params_ssa(&self.function, self.params) - } - pub fn stack(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.stack) - } - pub fn lift(&self) -> LiftedCallUntypedSsa { - LiftedCallUntypedSsa { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - dest: Box::new(self.dest().lift()), - params: self.params().map(|instr| instr.lift()).collect(), - stack: Box::new(self.stack().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarSsaList(self.output())), - ("dest", Expr(self.dest())), - ("params", ExprList(self.params())), - ("stack", Expr(self.stack())), - ] - .into_iter() - } } // SYSCALL_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SyscallSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: usize, - params: (usize, usize), - src_memory: u64, + pub output: usize, + pub first_param: usize, + pub num_params: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<SSAVariable>, pub params: Vec<MediumLevelILLiftedInstruction>, pub src_memory: u64, } impl SyscallSsa { pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, output: usize, - params: (usize, usize), + num_params: usize, + first_param: usize, src_memory: u64, ) -> Self { Self { - function, - address, output, - params, + first_param, + num_params, src_memory, } } - pub fn output(&self) -> OperandSSAVariableList { - get_call_output_ssa(&self.function, self.output) - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedSyscallSsa { - LiftedSyscallSsa { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - params: self.params().map(|instr| instr.lift()).collect(), - src_memory: self.src_memory(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarSsaList(self.output())), - ("params", ExprList(self.params())), - ("src_memory", MediumLevelILOperand::Int(self.src_memory())), - ] - .into_iter() - } } // SYSCALL_UNTYPED_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SyscallUntypedSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: usize, - params: usize, - stack: usize, + pub output: usize, + pub params: usize, + pub stack: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallUntypedSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<SSAVariable>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, } impl SyscallUntypedSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: usize, - params: usize, - stack: usize, - ) -> Self { + pub(crate) fn new(output: usize, params: usize, stack: usize) -> Self { Self { - function, - address, output, params, stack, } } - pub fn output(&self) -> OperandSSAVariableList { - get_call_output_ssa(&self.function, self.output) - } - pub fn params(&self) -> OperandExprList { - get_call_params_ssa(&self.function, self.params) - } - pub fn stack(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.stack) - } - pub fn lift(&self) -> LiftedSyscallUntypedSsa { - LiftedSyscallUntypedSsa { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - params: self.params().map(|instr| instr.lift()).collect(), - stack: Box::new(self.stack().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarSsaList(self.output())), - ("params", ExprList(self.params())), - ("stack", Expr(self.stack())), - ] - .into_iter() - } } // CALL_UNTYPED, TAILCALL_UNTYPED -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct CallUntyped { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: usize, - dest: usize, - params: usize, - stack: usize, + pub output: usize, + pub dest: usize, + pub params: usize, + pub stack: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedCallUntyped { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<Variable>, pub dest: Box<MediumLevelILLiftedInstruction>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, } impl CallUntyped { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: usize, - dest: usize, - params: usize, - stack: usize, - ) -> Self { + pub(crate) fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self { Self { - function, - address, output, dest, params, stack, } } - pub fn output(&self) -> OperandVariableList { - get_call_output(&self.function, self.output) - } - pub fn dest(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.dest) - } - pub fn params(&self) -> OperandExprList { - get_call_params(&self.function, self.params) - } - pub fn stack(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.stack) - } - pub fn lift(&self) -> LiftedCallUntyped { - LiftedCallUntyped { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - dest: Box::new(self.dest().lift()), - params: self.params().map(|instr| instr.lift()).collect(), - stack: Box::new(self.stack().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarList(self.output())), - ("dest", Expr(self.dest())), - ("params", ExprList(self.params())), - ("stack", Expr(self.stack())), - ] - .into_iter() - } } // SYSCALL_UNTYPED -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SyscallUntyped { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - output: usize, - params: usize, - stack: usize, + pub output: usize, + pub params: usize, + pub stack: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSyscallUntyped { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub output: Vec<Variable>, pub params: Vec<MediumLevelILLiftedInstruction>, pub stack: Box<MediumLevelILLiftedInstruction>, } impl SyscallUntyped { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - output: usize, - params: usize, - stack: usize, - ) -> Self { + pub(crate) fn new(output: usize, params: usize, stack: usize) -> Self { Self { - function, - address, output, params, stack, } } - pub fn output(&self) -> OperandVariableList { - get_call_output(&self.function, self.output) - } - pub fn params(&self) -> OperandExprList { - get_call_params(&self.function, self.params) - } - pub fn stack(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.stack) - } - pub fn lift(&self) -> LiftedSyscallUntyped { - LiftedSyscallUntyped { - function: self.function.clone(), - address: self.address, - output: self.output().collect(), - params: self.params().map(|instr| instr.lift()).collect(), - stack: Box::new(self.stack().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - use MediumLevelILOperand::*; - [ - ("output", VarList(self.output())), - ("params", ExprList(self.params())), - ("stack", Expr(self.stack())), - ] - .into_iter() - } } // 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, LOAD -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct UnaryOp { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - src: usize, + pub src: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedUnaryOp { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Box<MediumLevelILLiftedInstruction>, } impl UnaryOp { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, src: usize) -> Self { - Self { - function, - address, - src, - } - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn lift(&self) -> LiftedUnaryOp { - LiftedUnaryOp { - function: self.function.clone(), - address: self.address, - src: Box::new(self.src().lift()), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("src", MediumLevelILOperand::Expr(self.src()))].into_iter() + pub(crate) fn new(src: usize) -> Self { + Self { src } } } // LOAD_STRUCT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct LoadStruct { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - src: usize, - offset: u64, + pub src: usize, + pub offset: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedLoadStruct { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Box<MediumLevelILLiftedInstruction>, pub offset: u64, } impl LoadStruct { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: usize, - offset: u64, - ) -> Self { - Self { - function, - address, - src, - offset, - } - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn lift(&self) -> LiftedLoadStruct { - LiftedLoadStruct { - function: self.function.clone(), - address: self.address, - src: Box::new(self.src().lift()), - offset: self.offset(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("src", MediumLevelILOperand::Expr(self.src())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ] - .into_iter() + pub(crate) fn new(src: usize, offset: u64) -> Self { + Self { src, offset } } } // LOAD_STRUCT_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct LoadStructSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - src: usize, - offset: u64, - src_memory: u64, + pub src: usize, + pub offset: u64, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedLoadStructSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Box<MediumLevelILLiftedInstruction>, pub offset: u64, pub src_memory: u64, } impl LoadStructSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: usize, - offset: u64, - src_memory: u64, - ) -> Self { + pub(crate) fn new(src: usize, offset: u64, src_memory: u64) -> Self { Self { - function, - address, src, offset, src_memory, } } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedLoadStructSsa { - LiftedLoadStructSsa { - function: self.function.clone(), - address: self.address, - src: Box::new(self.src().lift()), - offset: self.offset(), - src_memory: self.src_memory(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("src", MediumLevelILOperand::Expr(self.src())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ("src_memory", MediumLevelILOperand::Int(self.src_memory())), - ] - .into_iter() - } } // LOAD_SSA -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct LoadSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - src: usize, - src_memory: u64, + pub src: usize, + pub src_memory: u64, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedLoadSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Box<MediumLevelILLiftedInstruction>, pub src_memory: u64, } impl LoadSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: usize, - src_memory: u64, - ) -> Self { - Self { - function, - address, - src, - src_memory, - } - } - pub fn src(&self) -> MediumLevelILInstruction { - get_operation(&self.function, self.src) - } - pub fn src_memory(&self) -> u64 { - self.src_memory - } - pub fn lift(&self) -> LiftedLoadSsa { - LiftedLoadSsa { - function: self.function.clone(), - address: self.address, - src: Box::new(self.src().lift()), - src_memory: self.src_memory(), - } - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("src", MediumLevelILOperand::Expr(self.src())), - ("src_memory", MediumLevelILOperand::Int(self.src_memory())), - ] - .into_iter() + pub(crate) fn new(src: usize, src_memory: u64) -> Self { + Self { src, src_memory } } } // RET -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Ret { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - src: (usize, usize), + pub first_operand: usize, + pub num_operands: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedRet { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Vec<MediumLevelILLiftedInstruction>, } impl Ret { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: (usize, usize), - ) -> Self { + pub(crate) fn new(num_operands: usize, first_operand: usize) -> Self { Self { - function, - address, - src, - } - } - pub fn src(&self) -> OperandExprList { - OperandList::new(&self.function, self.src.1, self.src.0).map_expr() - } - pub fn lift(&self) -> LiftedRet { - LiftedRet { - function: self.function.clone(), - address: self.address, - src: self.src().map(|instr| instr.lift()).collect(), + first_operand, + num_operands, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("src", MediumLevelILOperand::ExprList(self.src()))].into_iter() - } } // SEPARATE_PARAM_LIST -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SeparateParamList { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - params: (usize, usize), + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSeparateParamList { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub params: Vec<MediumLevelILLiftedInstruction>, } impl SeparateParamList { - pub fn new(function: Ref<MediumLevelILFunction>, address: u64, params: (usize, usize)) -> Self { + pub fn new(num_params: usize, first_param: usize) -> Self { Self { - function, - address, - params, - } - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn lift(&self) -> LiftedSeparateParamList { - LiftedSeparateParamList { - function: self.function.clone(), - address: self.address, - params: self.params().map(|instr| instr.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { - [("params", MediumLevelILOperand::ExprList(self.params()))].into_iter() - } } // SHARED_PARAM_SLOT -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct SharedParamSlot { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, - params: (usize, usize), + pub first_param: usize, + pub num_params: usize, } #[derive(Clone, Debug, PartialEq)] pub struct LiftedSharedParamSlot { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub params: Vec<MediumLevelILLiftedInstruction>, } impl SharedParamSlot { - pub fn new(function: Ref<MediumLevelILFunction>, address: u64, params: (usize, usize)) -> Self { + pub fn new(num_params: usize, first_param: usize) -> Self { Self { - function, - address, - params, - } - } - pub fn params(&self) -> OperandExprList { - OperandList::new(&self.function, self.params.1, self.params.0).map_expr() - } - pub fn lift(&self) -> LiftedSharedParamSlot { - LiftedSharedParamSlot { - function: self.function.clone(), - address: self.address, - params: self.params().map(|instr| instr.lift()).collect(), + num_params, + first_param, } } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> { - [("params", MediumLevelILOperand::ExprList(self.params()))].into_iter() - } } // VAR, ADDRESS_OF -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Var { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Variable, } impl Var { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, src: u64) -> Self { - Self { - function, - address, - src: get_var(src), - } - } - pub fn src(&self) -> Variable { - self.src - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("src", MediumLevelILOperand::Var(self.src()))].into_iter() + pub(crate) fn new(src: u64) -> Self { + Self { src: get_var(src) } } } // VAR_FIELD, ADDRESS_OF_FIELD -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Field { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: Variable, pub offset: u64, } impl Field { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: u64, - offset: u64, - ) -> Self { + pub(crate) fn new(src: u64, offset: u64) -> Self { Self { - function, - address, src: get_var(src), offset, } } - pub fn src(&self) -> Variable { - self.src - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("src", MediumLevelILOperand::Var(self.src())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ] - .into_iter() - } } // VAR_SSA, VAR_ALIASED -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSsa { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: SSAVariable, } impl VarSsa { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: (u64, usize), - ) -> Self { + pub(crate) fn new(src: (u64, usize)) -> Self { Self { - function, - address, src: get_var_ssa(src.0, src.1), } } - pub fn src(&self) -> SSAVariable { - self.src - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [("src", MediumLevelILOperand::VarSsa(self.src()))].into_iter() - } } // VAR_SSA_FIELD, VAR_ALIASED_FIELD -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct VarSsaField { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub src: SSAVariable, pub offset: u64, } impl VarSsaField { - pub(crate) fn new( - function: Ref<MediumLevelILFunction>, - address: u64, - src: (u64, usize), - offset: u64, - ) -> Self { + pub(crate) fn new(src: (u64, usize), offset: u64) -> Self { Self { - function, - address, src: get_var_ssa(src.0, src.1), offset, } } - pub fn src(&self) -> SSAVariable { - self.src - } - pub fn offset(&self) -> u64 { - self.offset - } - pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ { - [ - ("src", MediumLevelILOperand::VarSsa(self.src())), - ("offset", MediumLevelILOperand::Int(self.offset())), - ] - .into_iter() - } } // TRAP -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Trap { - pub function: Ref<MediumLevelILFunction>, - pub address: u64, pub vector: u64, } impl Trap { - pub(crate) fn new(function: Ref<MediumLevelILFunction>, 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, MediumLevelILOperand)> + '_ { - [("vector", MediumLevelILOperand::Int(self.vector()))].into_iter() + pub(crate) fn new(vector: u64) -> Self { + Self { vector } } } |
