summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorRubens Brandao <git@rubens.io>2023-11-18 15:58:33 -0300
committerKyle Martin <krm504@nyu.edu>2023-11-21 15:18:50 -0500
commit8c9cdd38c3302280087c9e6d94f7f57083885edd (patch)
tree8bccf380b4470e0de8ac11c23b164e0acf6ffbb0 /rust/src
parentb040fcfce48db861600eeb122cd0e2ff802fac96 (diff)
add mlil to rust
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/function.rs23
-rw-r--r--rust/src/interaction.rs2
-rw-r--r--rust/src/lib.rs1
-rw-r--r--rust/src/mlil/block.rs63
-rw-r--r--rust/src/mlil/function.rs116
-rw-r--r--rust/src/mlil/instruction.rs812
-rw-r--r--rust/src/mlil/lift.rs139
-rw-r--r--rust/src/mlil/mod.rs10
-rw-r--r--rust/src/mlil/operation.rs2170
-rw-r--r--rust/src/types.rs16
10 files changed, 3349 insertions, 3 deletions
diff --git a/rust/src/function.rs b/rust/src/function.rs
index ab504bb7..0a01f337 100644
--- a/rust/src/function.rs
+++ b/rust/src/function.rs
@@ -16,11 +16,12 @@ use binaryninjacore_sys::*;
use crate::rc::*;
use crate::string::*;
+use crate::types::Variable;
use crate::{
architecture::CoreArchitecture,
basicblock::{BasicBlock, BlockContext},
binaryview::{BinaryView, BinaryViewExt},
- llil,
+ llil, mlil,
platform::Platform,
symbol::Symbol,
types::{Conf, NamedTypedVariable, Type},
@@ -216,6 +217,26 @@ impl Function {
}
}
+ pub fn get_variable_name(&self, var: &Variable) -> BnString {
+ unsafe {
+ let raw_var = var.raw();
+ let raw_name = BNGetVariableName(self.handle, &raw_var);
+ BnString::from_raw(raw_name)
+ }
+ }
+
+ pub fn medium_level_il(&self) -> Result<Ref<mlil::MediumLevelILFunction>, ()> {
+ unsafe {
+ let mlil = BNGetFunctionMediumLevelIL(self.handle);
+
+ if mlil.is_null() {
+ return Err(());
+ }
+
+ Ok(Ref::new(mlil::MediumLevelILFunction::from_raw(mlil)))
+ }
+ }
+
pub fn low_level_il(&self) -> Result<Ref<llil::RegularFunction<CoreArchitecture>>, ()> {
unsafe {
let llil = BNGetFunctionLowLevelIL(self.handle);
diff --git a/rust/src/interaction.rs b/rust/src/interaction.rs
index f558a9ea..13785369 100644
--- a/rust/src/interaction.rs
+++ b/rust/src/interaction.rs
@@ -16,7 +16,7 @@
use binaryninjacore_sys::*;
-use std::os::raw::{c_void, c_char};
+use std::os::raw::{c_char, c_void};
use std::path::PathBuf;
use crate::binaryview::BinaryView;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 352ecef9..3eff5ea1 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -153,6 +153,7 @@ pub mod linearview;
pub mod llil;
pub mod logger;
pub mod metadata;
+pub mod mlil;
pub mod platform;
pub mod rc;
pub mod references;
diff --git a/rust/src/mlil/block.rs b/rust/src/mlil/block.rs
new file mode 100644
index 00000000..734d6512
--- /dev/null
+++ b/rust/src/mlil/block.rs
@@ -0,0 +1,63 @@
+use std::ops::Range;
+
+use binaryninjacore_sys::BNGetMediumLevelILIndexForInstruction;
+
+use crate::basicblock::{BasicBlock, BlockContext};
+use crate::rc::Ref;
+
+use super::{MediumLevelILFunction, MediumLevelILInstruction};
+
+pub struct MediumLevelILBlockIter {
+ function: Ref<MediumLevelILFunction>,
+ range: Range<u64>,
+}
+
+impl Iterator for MediumLevelILBlockIter {
+ type Item = MediumLevelILInstruction;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.range
+ .next()
+ .map(|i| unsafe {
+ BNGetMediumLevelILIndexForInstruction(self.function.handle, i as usize)
+ })
+ .map(|i| MediumLevelILInstruction::new(&self.function, i))
+ }
+}
+
+pub struct MediumLevelILBlock {
+ pub(crate) function: Ref<MediumLevelILFunction>,
+}
+
+impl core::fmt::Debug for MediumLevelILBlock {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "mlil_bb {:?}", self.function)
+ }
+}
+
+impl BlockContext for MediumLevelILBlock {
+ type Iter = MediumLevelILBlockIter;
+ type Instruction = MediumLevelILInstruction;
+
+ fn start(&self, block: &BasicBlock<Self>) -> MediumLevelILInstruction {
+ let expr_idx = unsafe {
+ BNGetMediumLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize)
+ };
+ MediumLevelILInstruction::new(&self.function, expr_idx)
+ }
+
+ fn iter(&self, block: &BasicBlock<Self>) -> MediumLevelILBlockIter {
+ MediumLevelILBlockIter {
+ function: self.function.to_owned(),
+ range: block.raw_start()..block.raw_end(),
+ }
+ }
+}
+
+impl Clone for MediumLevelILBlock {
+ fn clone(&self) -> Self {
+ MediumLevelILBlock {
+ function: self.function.to_owned(),
+ }
+ }
+}
diff --git a/rust/src/mlil/function.rs b/rust/src/mlil/function.rs
new file mode 100644
index 00000000..63c63a34
--- /dev/null
+++ b/rust/src/mlil/function.rs
@@ -0,0 +1,116 @@
+use core::hash::{Hash, Hasher};
+
+use binaryninjacore_sys::BNFreeMediumLevelILFunction;
+use binaryninjacore_sys::BNGetMediumLevelILBasicBlockList;
+use binaryninjacore_sys::BNGetMediumLevelILInstructionCount;
+use binaryninjacore_sys::BNGetMediumLevelILOwnerFunction;
+use binaryninjacore_sys::BNGetMediumLevelILSSAForm;
+use binaryninjacore_sys::BNMediumLevelILFunction;
+use binaryninjacore_sys::BNMediumLevelILGetInstructionStart;
+use binaryninjacore_sys::BNNewMediumLevelILFunctionReference;
+
+use crate::basicblock::BasicBlock;
+use crate::function::Function;
+use crate::function::Location;
+use crate::rc::{Array, Ref, RefCountable};
+
+use super::{MediumLevelILBlock, MediumLevelILInstruction};
+
+pub struct MediumLevelILFunction {
+ pub(crate) handle: *mut BNMediumLevelILFunction,
+}
+
+unsafe impl Send for MediumLevelILFunction {}
+unsafe impl Sync for MediumLevelILFunction {}
+
+impl Eq for MediumLevelILFunction {}
+impl PartialEq for MediumLevelILFunction {
+ fn eq(&self, rhs: &Self) -> bool {
+ self.handle == rhs.handle
+ }
+}
+
+impl Hash for MediumLevelILFunction {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.handle.hash(state);
+ }
+}
+
+impl MediumLevelILFunction {
+ pub(crate) unsafe fn from_raw(handle: *mut BNMediumLevelILFunction) -> Self {
+ debug_assert!(!handle.is_null());
+
+ Self { handle }
+ }
+
+ pub fn instruction_at<L: Into<Location>>(&self, loc: L) -> Option<MediumLevelILInstruction> {
+ let loc: Location = loc.into();
+ let arch_handle = loc.arch.unwrap();
+
+ let expr_idx =
+ unsafe { BNMediumLevelILGetInstructionStart(self.handle, arch_handle.0, loc.addr) };
+
+ if expr_idx >= self.instruction_count() {
+ None
+ } else {
+ Some(MediumLevelILInstruction::new(self, expr_idx))
+ }
+ }
+
+ pub fn instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILInstruction {
+ MediumLevelILInstruction::new(self, expr_idx)
+ }
+
+ pub fn instruction_count(&self) -> usize {
+ unsafe { BNGetMediumLevelILInstructionCount(self.handle) }
+ }
+
+ pub fn ssa_form(&self) -> MediumLevelILFunction {
+ let ssa = unsafe { BNGetMediumLevelILSSAForm(self.handle) };
+ assert!(!ssa.is_null());
+ MediumLevelILFunction { handle: ssa }
+ }
+
+ pub fn get_function(&self) -> Ref<Function> {
+ unsafe {
+ let func = BNGetMediumLevelILOwnerFunction(self.handle);
+ Function::from_raw(func)
+ }
+ }
+
+ pub fn basic_blocks(&self) -> Array<BasicBlock<MediumLevelILBlock>> {
+ let mut count = 0;
+ let blocks = unsafe { BNGetMediumLevelILBasicBlockList(self.handle, &mut count) };
+ let context = MediumLevelILBlock {
+ function: self.to_owned(),
+ };
+
+ unsafe { Array::new(blocks, count, context) }
+ }
+}
+
+impl ToOwned for MediumLevelILFunction {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+unsafe impl RefCountable for MediumLevelILFunction {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: BNNewMediumLevelILFunctionReference(handle.handle),
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeMediumLevelILFunction(handle.handle);
+ }
+}
+
+impl core::fmt::Debug for MediumLevelILFunction {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "<mlil func handle {:p}>", self.handle)
+ }
+}
diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs
new file mode 100644
index 00000000..5e237128
--- /dev/null
+++ b/rust/src/mlil/instruction.rs
@@ -0,0 +1,812 @@
+use binaryninjacore_sys::BNGetMediumLevelILByIndex;
+use binaryninjacore_sys::BNMediumLevelILOperation;
+
+use crate::mlil::MediumLevelILLiftedOperation;
+use crate::rc::Ref;
+
+use super::operation::*;
+use super::{MediumLevelILFunction, MediumLevelILLiftedInstruction};
+
+#[derive(Clone)]
+pub struct MediumLevelILInstruction {
+ pub(crate) function: Ref<MediumLevelILFunction>,
+ pub(crate) address: u64,
+ pub(crate) operation: MediumLevelILOperation,
+}
+
+#[derive(Copy, Clone)]
+pub enum MediumLevelILOperation {
+ Nop(NoArgs),
+ Noret(NoArgs),
+ Bp(NoArgs),
+ Undef(NoArgs),
+ Unimpl(NoArgs),
+ If(MediumLevelILOperationIf),
+ FloatConst(FloatConst),
+ Const(Constant),
+ ConstPtr(Constant),
+ Import(Constant),
+ ExternPtr(ExternPtr),
+ ConstData(ConstData),
+ Jump(Jump),
+ RetHint(Jump),
+ StoreSsa(StoreSsa),
+ StoreStructSsa(StoreStructSsa),
+ StoreStruct(StoreStruct),
+ Store(Store),
+ JumpTo(JumpTo),
+ Goto(Goto),
+ FreeVarSlot(FreeVarSlot),
+ SetVarField(SetVarField),
+ SetVar(SetVar),
+ FreeVarSlotSsa(FreeVarSlotSsa),
+ SetVarSsaField(SetVarSsaField),
+ SetVarAliasedField(SetVarSsaField),
+ SetVarAliased(SetVarAliased),
+ SetVarSsa(SetVarSsa),
+ VarPhi(VarPhi),
+ MemPhi(MemPhi),
+ VarSplit(VarSplit),
+ SetVarSplit(SetVarSplit),
+ VarSplitSsa(VarSplitSsa),
+ SetVarSplitSsa(SetVarSplitSsa),
+ Add(BinaryOp),
+ Sub(BinaryOp),
+ And(BinaryOp),
+ Or(BinaryOp),
+ Xor(BinaryOp),
+ Lsl(BinaryOp),
+ Lsr(BinaryOp),
+ Asr(BinaryOp),
+ Rol(BinaryOp),
+ Ror(BinaryOp),
+ Mul(BinaryOp),
+ MuluDp(BinaryOp),
+ MulsDp(BinaryOp),
+ Divu(BinaryOp),
+ DivuDp(BinaryOp),
+ Divs(BinaryOp),
+ DivsDp(BinaryOp),
+ Modu(BinaryOp),
+ ModuDp(BinaryOp),
+ Mods(BinaryOp),
+ ModsDp(BinaryOp),
+ CmpE(BinaryOp),
+ CmpNe(BinaryOp),
+ CmpSlt(BinaryOp),
+ CmpUlt(BinaryOp),
+ CmpSle(BinaryOp),
+ CmpUle(BinaryOp),
+ CmpSge(BinaryOp),
+ CmpUge(BinaryOp),
+ CmpSgt(BinaryOp),
+ CmpUgt(BinaryOp),
+ TestBit(BinaryOp),
+ AddOverflow(BinaryOp),
+ FcmpE(BinaryOp),
+ FcmpNe(BinaryOp),
+ FcmpLt(BinaryOp),
+ FcmpLe(BinaryOp),
+ FcmpGe(BinaryOp),
+ FcmpGt(BinaryOp),
+ FcmpO(BinaryOp),
+ FcmpUo(BinaryOp),
+ Fadd(BinaryOp),
+ Fsub(BinaryOp),
+ Fmul(BinaryOp),
+ Fdiv(BinaryOp),
+ Adc(BinaryOpCarry),
+ Sbb(BinaryOpCarry),
+ Rlc(BinaryOpCarry),
+ Rrc(BinaryOpCarry),
+ Call(Call),
+ Tailcall(Call),
+ Syscall(Syscall),
+ Intrinsic(Intrinsic),
+ IntrinsicSsa(IntrinsicSsa),
+ CallSsa(CallSsa),
+ TailcallSsa(CallSsa),
+ CallUntypedSsa(CallUntypedSsa),
+ TailcallUntypedSsa(CallUntypedSsa),
+ SyscallSsa(SyscallSsa),
+ SyscallUntypedSsa(SyscallUntypedSsa),
+ CallUntyped(CallUntyped),
+ TailcallUntyped(CallUntyped),
+ SyscallUntyped(SyscallUntyped),
+ Neg(UnaryOp),
+ Not(UnaryOp),
+ Sx(UnaryOp),
+ Zx(UnaryOp),
+ LowPart(UnaryOp),
+ BoolToInt(UnaryOp),
+ UnimplMem(UnaryOp),
+ Fsqrt(UnaryOp),
+ Fneg(UnaryOp),
+ Fabs(UnaryOp),
+ FloatToInt(UnaryOp),
+ IntToFloat(UnaryOp),
+ FloatConv(UnaryOp),
+ RoundToInt(UnaryOp),
+ Floor(UnaryOp),
+ Ceil(UnaryOp),
+ Ftrunc(UnaryOp),
+ Load(UnaryOp),
+ LoadStruct(LoadStruct),
+ LoadStructSsa(LoadStructSsa),
+ LoadSsa(LoadSsa),
+ Ret(Ret),
+ Var(Var),
+ AddressOf(Var),
+ VarField(Field),
+ AddressOfField(Field),
+ VarSsa(VarSsa),
+ VarAliased(VarSsa),
+ VarSsaField(VarSsaField),
+ VarAliasedField(VarSsaField),
+ Trap(Trap),
+}
+
+impl core::fmt::Debug for MediumLevelILInstruction {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(
+ f,
+ "<{} at 0x{:08}>",
+ core::any::type_name::<Self>(),
+ self.address,
+ )
+ }
+}
+
+impl MediumLevelILInstruction {
+ pub(crate) fn new(function: &MediumLevelILFunction, idx: usize) -> Self {
+ let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) };
+ use BNMediumLevelILOperation::*;
+ use MediumLevelILOperation as Op;
+ let info = match op.operation {
+ MLIL_NOP => Op::Nop(NoArgs::default()),
+ MLIL_NORET => Op::Noret(NoArgs::default()),
+ MLIL_BP => Op::Bp(NoArgs::default()),
+ MLIL_UNDEF => Op::Undef(NoArgs::default()),
+ MLIL_UNIMPL => Op::Unimpl(NoArgs::default()),
+ MLIL_IF => Op::If(MediumLevelILOperationIf::new(
+ op.operands[0] as usize,
+ op.operands[1],
+ op.operands[2],
+ )),
+ 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(ConstData::new((op.operands[0], op.operands[1]))),
+ 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(
+ op.operands[0] as usize,
+ op.operands[1],
+ op.operands[2],
+ op.operands[3] as usize,
+ )),
+ MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa::new(
+ op.operands[0] as usize,
+ op.operands[1],
+ op.operands[2],
+ op.operands[3],
+ op.operands[4] as usize,
+ )),
+ MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct::new(
+ op.operands[0] as usize,
+ op.operands[1],
+ op.operands[2] 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(
+ op.operands[0] as usize,
+ (op.operands[1] as usize, op.operands[2] as usize),
+ )),
+ 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(
+ op.operands[0],
+ op.operands[1],
+ op.operands[2] 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(
+ (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(
+ (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(
+ (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(
+ (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(
+ (op.operands[0], op.operands[1] as usize),
+ op.operands[2] as usize,
+ )),
+ MLIL_VAR_PHI => Op::VarPhi(VarPhi::new(
+ (op.operands[0], op.operands[1] as usize),
+ (op.operands[2] as usize, op.operands[3] as usize),
+ )),
+ MLIL_MEM_PHI => Op::MemPhi(MemPhi::new(
+ op.operands[0],
+ (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(
+ op.operands[0],
+ op.operands[1],
+ op.operands[2] as usize,
+ )),
+ MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa::new(
+ (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(
+ (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(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_SUB => Op::Sub(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_AND => Op::And(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_OR => Op::Or(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_XOR => Op::Xor(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_LSL => Op::Lsl(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_LSR => Op::Lsr(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_ASR => Op::Asr(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_ROL => Op::Rol(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_ROR => Op::Ror(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MUL => Op::Mul(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MULU_DP => Op::MuluDp(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MULS_DP => Op::MulsDp(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_DIVU => Op::Divu(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_DIVU_DP => Op::DivuDp(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_DIVS => Op::Divs(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_DIVS_DP => Op::DivsDp(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MODU => Op::Modu(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MODU_DP => Op::ModuDp(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MODS => Op::Mods(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_MODS_DP => Op::ModsDp(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_E => Op::CmpE(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_NE => Op::CmpNe(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_SLE => Op::CmpSle(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_ULE => Op::CmpUle(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_SGE => Op::CmpSge(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_UGE => Op::CmpUge(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_TEST_BIT => Op::TestBit(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_E => Op::FcmpE(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_O => Op::FcmpO(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FADD => Op::Fadd(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FSUB => Op::Fsub(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FMUL => Op::Fmul(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_FDIV => Op::Fdiv(BinaryOp::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
+ MLIL_ADC => Op::Adc(BinaryOpCarry::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] as usize,
+ )),
+ MLIL_SBB => Op::Sbb(BinaryOpCarry::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] as usize,
+ )),
+ MLIL_RLC => Op::Rlc(BinaryOpCarry::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] as usize,
+ )),
+ MLIL_RRC => Op::Rrc(BinaryOpCarry::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] as usize,
+ )),
+ MLIL_CALL => Op::Call(Call::new(
+ (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),
+ )),
+ MLIL_TAILCALL => Op::Tailcall(Call::new(
+ (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),
+ )),
+ MLIL_SYSCALL => Op::Syscall(Syscall::new(
+ (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(
+ (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),
+ )),
+ MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new(
+ (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),
+ )),
+ MLIL_CALL_SSA => Op::CallSsa(CallSsa::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ (op.operands[2] as usize, op.operands[3] as usize),
+ op.operands[4],
+ )),
+ MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ (op.operands[2] as usize, op.operands[3] as usize),
+ op.operands[4],
+ )),
+ MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa::new(
+ 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(
+ 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(
+ op.operands[0] as usize,
+ (op.operands[1] as usize, op.operands[2] as usize),
+ op.operands[3],
+ )),
+ MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] as usize,
+ )),
+ MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped::new(
+ 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(
+ 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(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] 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_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa::new(
+ op.operands[0] as usize,
+ op.operands[1],
+ op.operands[2],
+ )),
+ 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_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(
+ (op.operands[0], op.operands[1] as usize),
+ op.operands[2],
+ )),
+ MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField::new(
+ (op.operands[0], op.operands[1] as usize),
+ op.operands[2],
+ )),
+ MLIL_TRAP => Op::Trap(Trap::new(op.operands[0])),
+ // translated directly into a list for Expression or Variables
+ MLIL_CALL_OUTPUT | MLIL_CALL_PARAM | MLIL_CALL_PARAM_SSA | MLIL_CALL_OUTPUT_SSA => {
+ unreachable!()
+ }
+ };
+ Self {
+ function: function.to_owned(),
+ address: op.address,
+ operation: info,
+ }
+ }
+
+ pub fn function(&self) -> &MediumLevelILFunction {
+ &self.function
+ }
+
+ pub fn address(&self) -> u64 {
+ self.address
+ }
+
+ pub fn operation(&self) -> &MediumLevelILOperation {
+ &self.operation
+ }
+
+ pub fn lift(&self) -> MediumLevelILLiftedInstruction {
+ use MediumLevelILLiftedOperation as Lifted;
+ use MediumLevelILOperation::*;
+
+ let operation = match self.operation {
+ Nop(op) => Lifted::Nop(op),
+ Noret(op) => Lifted::Noret(op),
+ Bp(op) => Lifted::Bp(op),
+ Undef(op) => Lifted::Undef(op),
+ Unimpl(op) => Lifted::Unimpl(op),
+ If(op) => Lifted::If(op.lift(&self.function)),
+ 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(op.lift(&self.function)),
+ Jump(op) => Lifted::Jump(op.lift(&self.function)),
+ RetHint(op) => Lifted::RetHint(op.lift(&self.function)),
+ StoreSsa(op) => Lifted::StoreSsa(op.lift(&self.function)),
+ StoreStructSsa(op) => Lifted::StoreStructSsa(op.lift(&self.function)),
+ StoreStruct(op) => Lifted::StoreStruct(op.lift(&self.function)),
+ Store(op) => Lifted::Store(op.lift(&self.function)),
+ JumpTo(op) => Lifted::JumpTo(op.lift(&self.function)),
+ Goto(op) => Lifted::Goto(op),
+ FreeVarSlot(op) => Lifted::FreeVarSlot(op),
+ SetVarField(op) => Lifted::SetVarField(op.lift(&self.function)),
+ SetVar(op) => Lifted::SetVar(op.lift(&self.function)),
+ FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op.lift()),
+ SetVarSsaField(op) => Lifted::SetVarSsaField(op.lift(&self.function)),
+ SetVarAliasedField(op) => Lifted::SetVarAliasedField(op.lift(&self.function)),
+ SetVarAliased(op) => Lifted::SetVarAliased(op.lift(&self.function)),
+ SetVarSsa(op) => Lifted::SetVarSsa(op.lift(&self.function)),
+ VarPhi(op) => Lifted::VarPhi(op.lift(&self.function)),
+ MemPhi(op) => Lifted::MemPhi(op.lift(&self.function)),
+ VarSplit(op) => Lifted::VarSplit(op.lift()),
+ SetVarSplit(op) => Lifted::SetVarSplit(op.lift(&self.function)),
+ VarSplitSsa(op) => Lifted::VarSplitSsa(op.lift()),
+ SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(op.lift(&self.function)),
+ Add(op) => Lifted::Add(op.lift(&self.function)),
+ Sub(op) => Lifted::Sub(op.lift(&self.function)),
+ And(op) => Lifted::And(op.lift(&self.function)),
+ Or(op) => Lifted::Or(op.lift(&self.function)),
+ Xor(op) => Lifted::Xor(op.lift(&self.function)),
+ Lsl(op) => Lifted::Lsl(op.lift(&self.function)),
+ Lsr(op) => Lifted::Lsr(op.lift(&self.function)),
+ Asr(op) => Lifted::Asr(op.lift(&self.function)),
+ Rol(op) => Lifted::Rol(op.lift(&self.function)),
+ Ror(op) => Lifted::Ror(op.lift(&self.function)),
+ Mul(op) => Lifted::Mul(op.lift(&self.function)),
+ MuluDp(op) => Lifted::MuluDp(op.lift(&self.function)),
+ MulsDp(op) => Lifted::MulsDp(op.lift(&self.function)),
+ Divu(op) => Lifted::Divu(op.lift(&self.function)),
+ DivuDp(op) => Lifted::DivuDp(op.lift(&self.function)),
+ Divs(op) => Lifted::Divs(op.lift(&self.function)),
+ DivsDp(op) => Lifted::DivsDp(op.lift(&self.function)),
+ Modu(op) => Lifted::Modu(op.lift(&self.function)),
+ ModuDp(op) => Lifted::ModuDp(op.lift(&self.function)),
+ Mods(op) => Lifted::Mods(op.lift(&self.function)),
+ ModsDp(op) => Lifted::ModsDp(op.lift(&self.function)),
+ CmpE(op) => Lifted::CmpE(op.lift(&self.function)),
+ CmpNe(op) => Lifted::CmpNe(op.lift(&self.function)),
+ CmpSlt(op) => Lifted::CmpSlt(op.lift(&self.function)),
+ CmpUlt(op) => Lifted::CmpUlt(op.lift(&self.function)),
+ CmpSle(op) => Lifted::CmpSle(op.lift(&self.function)),
+ CmpUle(op) => Lifted::CmpUle(op.lift(&self.function)),
+ CmpSge(op) => Lifted::CmpSge(op.lift(&self.function)),
+ CmpUge(op) => Lifted::CmpUge(op.lift(&self.function)),
+ CmpSgt(op) => Lifted::CmpSgt(op.lift(&self.function)),
+ CmpUgt(op) => Lifted::CmpUgt(op.lift(&self.function)),
+ TestBit(op) => Lifted::TestBit(op.lift(&self.function)),
+ AddOverflow(op) => Lifted::AddOverflow(op.lift(&self.function)),
+ FcmpE(op) => Lifted::FcmpE(op.lift(&self.function)),
+ FcmpNe(op) => Lifted::FcmpNe(op.lift(&self.function)),
+ FcmpLt(op) => Lifted::FcmpLt(op.lift(&self.function)),
+ FcmpLe(op) => Lifted::FcmpLe(op.lift(&self.function)),
+ FcmpGe(op) => Lifted::FcmpGe(op.lift(&self.function)),
+ FcmpGt(op) => Lifted::FcmpGt(op.lift(&self.function)),
+ FcmpO(op) => Lifted::FcmpO(op.lift(&self.function)),
+ FcmpUo(op) => Lifted::FcmpUo(op.lift(&self.function)),
+ Fadd(op) => Lifted::Fadd(op.lift(&self.function)),
+ Fsub(op) => Lifted::Fsub(op.lift(&self.function)),
+ Fmul(op) => Lifted::Fmul(op.lift(&self.function)),
+ Fdiv(op) => Lifted::Fdiv(op.lift(&self.function)),
+ Adc(op) => Lifted::Adc(op.lift(&self.function)),
+ Sbb(op) => Lifted::Sbb(op.lift(&self.function)),
+ Rlc(op) => Lifted::Rlc(op.lift(&self.function)),
+ Rrc(op) => Lifted::Rrc(op.lift(&self.function)),
+ Call(op) => Lifted::Call(op.lift(&self.function)),
+ Tailcall(op) => Lifted::Tailcall(op.lift(&self.function)),
+ Intrinsic(op) => Lifted::Intrinsic(op.lift(&self.function)),
+ Syscall(op) => Lifted::Syscall(op.lift(&self.function)),
+ IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift(&self.function)),
+ CallSsa(op) => Lifted::CallSsa(op.lift(&self.function)),
+ TailcallSsa(op) => Lifted::TailcallSsa(op.lift(&self.function)),
+ CallUntypedSsa(op) => Lifted::CallUntypedSsa(op.lift(&self.function)),
+ TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(op.lift(&self.function)),
+ SyscallSsa(op) => Lifted::SyscallSsa(op.lift(&self.function)),
+ SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(op.lift(&self.function)),
+ CallUntyped(op) => Lifted::CallUntyped(op.lift(&self.function)),
+ TailcallUntyped(op) => Lifted::TailcallUntyped(op.lift(&self.function)),
+ SyscallUntyped(op) => Lifted::SyscallUntyped(op.lift(&self.function)),
+ Neg(op) => Lifted::Neg(op.lift(&self.function)),
+ Not(op) => Lifted::Not(op.lift(&self.function)),
+ Sx(op) => Lifted::Sx(op.lift(&self.function)),
+ Zx(op) => Lifted::Zx(op.lift(&self.function)),
+ LowPart(op) => Lifted::LowPart(op.lift(&self.function)),
+ BoolToInt(op) => Lifted::BoolToInt(op.lift(&self.function)),
+ UnimplMem(op) => Lifted::UnimplMem(op.lift(&self.function)),
+ Fsqrt(op) => Lifted::Fsqrt(op.lift(&self.function)),
+ Fneg(op) => Lifted::Fneg(op.lift(&self.function)),
+ Fabs(op) => Lifted::Fabs(op.lift(&self.function)),
+ FloatToInt(op) => Lifted::FloatToInt(op.lift(&self.function)),
+ IntToFloat(op) => Lifted::IntToFloat(op.lift(&self.function)),
+ FloatConv(op) => Lifted::FloatConv(op.lift(&self.function)),
+ RoundToInt(op) => Lifted::RoundToInt(op.lift(&self.function)),
+ Floor(op) => Lifted::Floor(op.lift(&self.function)),
+ Ceil(op) => Lifted::Ceil(op.lift(&self.function)),
+ Ftrunc(op) => Lifted::Ftrunc(op.lift(&self.function)),
+ Load(op) => Lifted::Load(op.lift(&self.function)),
+ LoadStruct(op) => Lifted::LoadStruct(op.lift(&self.function)),
+ LoadStructSsa(op) => Lifted::LoadStructSsa(op.lift(&self.function)),
+ LoadSsa(op) => Lifted::LoadSsa(op.lift(&self.function)),
+ Ret(op) => Lifted::Ret(op.lift(&self.function)),
+ 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 {
+ address: self.address,
+ operation,
+ }
+ }
+
+ pub fn operands(&self) -> Box<dyn Iterator<Item = (&'static str, MediumLevelILOperand)>> {
+ use MediumLevelILOperation::*;
+ match &self.operation {
+ Nop(_op) | Noret(_op) | Bp(_op) | Undef(_op) | Unimpl(_op) => Box::new([].into_iter()),
+ If(op) => Box::new(op.operands(&self.function)),
+ FloatConst(op) => Box::new(op.operands()),
+ Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()),
+ ExternPtr(op) => Box::new(op.operands(&self.function)),
+ ConstData(op) => Box::new(op.operands(&self.function)),
+ Jump(op) | RetHint(op) => Box::new(op.operands(&self.function)),
+ StoreSsa(op) => Box::new(op.operands(&self.function)),
+ StoreStructSsa(op) => Box::new(op.operands(&self.function)),
+ StoreStruct(op) => Box::new(op.operands(&self.function)),
+ Store(op) => Box::new(op.operands(&self.function)),
+ JumpTo(op) => Box::new(op.operands(&self.function)),
+ Goto(op) => Box::new(op.operands()),
+ FreeVarSlot(op) => Box::new(op.operands()),
+ SetVarField(op) => Box::new(op.operands(&self.function)),
+ SetVar(op) => Box::new(op.operands(&self.function)),
+ FreeVarSlotSsa(op) => Box::new(op.operands()),
+ SetVarSsaField(op) | SetVarAliasedField(op) => Box::new(op.operands(&self.function)),
+ SetVarAliased(op) => Box::new(op.operands(&self.function)),
+ SetVarSsa(op) => Box::new(op.operands(&self.function)),
+ VarPhi(op) => Box::new(op.operands(&self.function)),
+ MemPhi(op) => Box::new(op.operands(&self.function)),
+ VarSplit(op) => Box::new(op.operands()),
+ SetVarSplit(op) => Box::new(op.operands(&self.function)),
+ VarSplitSsa(op) => Box::new(op.operands()),
+ SetVarSplitSsa(op) => Box::new(op.operands(&self.function)),
+ 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(&self.function))
+ }
+ Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands(&self.function)),
+ Call(op) | Tailcall(op) => Box::new(op.operands(&self.function)),
+ Syscall(op) => Box::new(op.operands(&self.function)),
+ Intrinsic(op) => Box::new(op.operands(&self.function)),
+ IntrinsicSsa(op) => Box::new(op.operands(&self.function)),
+ CallSsa(op) | TailcallSsa(op) => Box::new(op.operands(&self.function)),
+ CallUntypedSsa(op) | TailcallUntypedSsa(op) => Box::new(op.operands(&self.function)),
+ SyscallSsa(op) => Box::new(op.operands(&self.function)),
+ SyscallUntypedSsa(op) => Box::new(op.operands(&self.function)),
+ CallUntyped(op) | TailcallUntyped(op) => Box::new(op.operands(&self.function)),
+ SyscallUntyped(op) => Box::new(op.operands(&self.function)),
+ 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(&self.function))
+ }
+ LoadStruct(op) => Box::new(op.operands(&self.function)),
+ LoadStructSsa(op) => Box::new(op.operands(&self.function)),
+ LoadSsa(op) => Box::new(op.operands(&self.function)),
+ Ret(op) => Box::new(op.operands(&self.function)),
+ 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()),
+ }
+ }
+}
diff --git a/rust/src/mlil/lift.rs b/rust/src/mlil/lift.rs
new file mode 100644
index 00000000..68a7884e
--- /dev/null
+++ b/rust/src/mlil/lift.rs
@@ -0,0 +1,139 @@
+use super::operation::*;
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct MediumLevelILLiftedInstruction {
+ pub address: u64,
+ pub operation: MediumLevelILLiftedOperation,
+}
+
+#[derive(Clone, Debug, PartialEq)]
+pub enum MediumLevelILLiftedOperation {
+ Nop(NoArgs),
+ Noret(NoArgs),
+ Bp(NoArgs),
+ Undef(NoArgs),
+ Unimpl(NoArgs),
+ If(LiftedIf),
+ FloatConst(FloatConst),
+ Const(Constant),
+ ConstPtr(Constant),
+ Import(Constant),
+ ExternPtr(ExternPtr),
+ ConstData(ConstantData),
+ Jump(LiftedJump),
+ RetHint(LiftedJump),
+ StoreSsa(LiftedStoreSsa),
+ StoreStructSsa(LiftedStoreStructSsa),
+ StoreStruct(LiftedStoreStruct),
+ Store(LiftedStore),
+ JumpTo(LiftedJumpTo),
+ Goto(Goto),
+ FreeVarSlot(FreeVarSlot),
+ SetVarField(LiftedSetVarField),
+ SetVar(LiftedSetVar),
+ FreeVarSlotSsa(FreeVarSlotSsa),
+ SetVarSsaField(LiftedSetVarSsaField),
+ SetVarAliasedField(LiftedSetVarSsaField),
+ SetVarAliased(LiftedSetVarAliased),
+ SetVarSsa(LiftedSetVarSsa),
+ VarPhi(LiftedVarPhi),
+ MemPhi(LiftedMemPhi),
+ VarSplit(VarSplit),
+ SetVarSplit(LiftedSetVarSplit),
+ VarSplitSsa(VarSplitSsa),
+ SetVarSplitSsa(LiftedSetVarSplitSsa),
+ Add(LiftedBinaryOp),
+ Sub(LiftedBinaryOp),
+ And(LiftedBinaryOp),
+ Or(LiftedBinaryOp),
+ Xor(LiftedBinaryOp),
+ Lsl(LiftedBinaryOp),
+ Lsr(LiftedBinaryOp),
+ Asr(LiftedBinaryOp),
+ Rol(LiftedBinaryOp),
+ Ror(LiftedBinaryOp),
+ Mul(LiftedBinaryOp),
+ MuluDp(LiftedBinaryOp),
+ MulsDp(LiftedBinaryOp),
+ Divu(LiftedBinaryOp),
+ DivuDp(LiftedBinaryOp),
+ Divs(LiftedBinaryOp),
+ DivsDp(LiftedBinaryOp),
+ Modu(LiftedBinaryOp),
+ ModuDp(LiftedBinaryOp),
+ Mods(LiftedBinaryOp),
+ ModsDp(LiftedBinaryOp),
+ CmpE(LiftedBinaryOp),
+ CmpNe(LiftedBinaryOp),
+ CmpSlt(LiftedBinaryOp),
+ CmpUlt(LiftedBinaryOp),
+ CmpSle(LiftedBinaryOp),
+ CmpUle(LiftedBinaryOp),
+ CmpSge(LiftedBinaryOp),
+ CmpUge(LiftedBinaryOp),
+ CmpSgt(LiftedBinaryOp),
+ CmpUgt(LiftedBinaryOp),
+ TestBit(LiftedBinaryOp),
+ AddOverflow(LiftedBinaryOp),
+ FcmpE(LiftedBinaryOp),
+ FcmpNe(LiftedBinaryOp),
+ FcmpLt(LiftedBinaryOp),
+ FcmpLe(LiftedBinaryOp),
+ FcmpGe(LiftedBinaryOp),
+ FcmpGt(LiftedBinaryOp),
+ FcmpO(LiftedBinaryOp),
+ FcmpUo(LiftedBinaryOp),
+ Fadd(LiftedBinaryOp),
+ Fsub(LiftedBinaryOp),
+ Fmul(LiftedBinaryOp),
+ Fdiv(LiftedBinaryOp),
+ Adc(LiftedBinaryOpCarry),
+ Sbb(LiftedBinaryOpCarry),
+ Rlc(LiftedBinaryOpCarry),
+ Rrc(LiftedBinaryOpCarry),
+ Call(LiftedCall),
+ Tailcall(LiftedCall),
+ Intrinsic(LiftedInnerCall),
+ Syscall(LiftedInnerCall),
+ IntrinsicSsa(LiftedIntrinsicSsa),
+ CallSsa(LiftedCallSsa),
+ TailcallSsa(LiftedCallSsa),
+ CallUntypedSsa(LiftedCallUntypedSsa),
+ TailcallUntypedSsa(LiftedCallUntypedSsa),
+ SyscallSsa(LiftedSyscallSsa),
+ SyscallUntypedSsa(LiftedSyscallUntypedSsa),
+ CallUntyped(LiftedCallUntyped),
+ TailcallUntyped(LiftedCallUntyped),
+ SyscallUntyped(LiftedSyscallUntyped),
+ Neg(LiftedUnaryOp),
+ Not(LiftedUnaryOp),
+ Sx(LiftedUnaryOp),
+ Zx(LiftedUnaryOp),
+ LowPart(LiftedUnaryOp),
+ BoolToInt(LiftedUnaryOp),
+ UnimplMem(LiftedUnaryOp),
+ Fsqrt(LiftedUnaryOp),
+ Fneg(LiftedUnaryOp),
+ Fabs(LiftedUnaryOp),
+ FloatToInt(LiftedUnaryOp),
+ IntToFloat(LiftedUnaryOp),
+ FloatConv(LiftedUnaryOp),
+ RoundToInt(LiftedUnaryOp),
+ Floor(LiftedUnaryOp),
+ Ceil(LiftedUnaryOp),
+ Ftrunc(LiftedUnaryOp),
+ Load(LiftedUnaryOp),
+ LoadStruct(LiftedLoadStruct),
+ LoadStructSsa(LiftedLoadStructSsa),
+ LoadSsa(LiftedLoadSsa),
+ Ret(LiftedRet),
+ Var(Var),
+ AddressOf(Var),
+ VarField(Field),
+ AddressOfField(Field),
+ VarSsa(VarSsa),
+ VarAliased(VarSsa),
+ VarSsaField(VarSsaField),
+ VarAliasedField(VarSsaField),
+ Trap(Trap),
+}
diff --git a/rust/src/mlil/mod.rs b/rust/src/mlil/mod.rs
new file mode 100644
index 00000000..8a9103ac
--- /dev/null
+++ b/rust/src/mlil/mod.rs
@@ -0,0 +1,10 @@
+mod block;
+mod function;
+mod instruction;
+mod lift;
+pub mod operation;
+
+pub use self::block::*;
+pub use self::function::*;
+pub use self::instruction::*;
+pub use self::lift::*;
diff --git a/rust/src/mlil/operation.rs b/rust/src/mlil/operation.rs
new file mode 100644
index 00000000..4b234bf1
--- /dev/null
+++ b/rust/src/mlil/operation.rs
@@ -0,0 +1,2170 @@
+use std::collections::HashMap;
+
+use binaryninjacore_sys::BNFromVariableIdentifier;
+use binaryninjacore_sys::BNGetMediumLevelILByIndex;
+use binaryninjacore_sys::BNMediumLevelILInstruction;
+use binaryninjacore_sys::BNMediumLevelILOperation;
+
+use crate::rc::Ref;
+use crate::types::{SSAVariable, Variable};
+
+use super::{MediumLevelILFunction, MediumLevelILInstruction, MediumLevelILLiftedInstruction};
+
+pub enum MediumLevelILOperand {
+ //TODO
+ //ConstantData(!),
+ //TODO
+ //Intrinsic(!),
+ 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 {
+ function: Ref<MediumLevelILFunction>,
+ remaining: usize,
+ next_node_idx: Option<usize>,
+
+ current_node: core::array::IntoIter<u64, 4>,
+}
+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();
+ }
+ Self {
+ function: function.to_owned(),
+ remaining: number,
+ next_node_idx: Some(idx),
+ current_node: iter,
+ }
+ }
+ fn duble(self) -> OperandDubleList {
+ assert_eq!(self.len() % 2, 0);
+ OperandDubleList(self)
+ }
+ fn map_expr(self) -> OperandExprList {
+ OperandExprList(self)
+ }
+ fn map_var(self) -> OperandVariableList {
+ OperandVariableList(self)
+ }
+ fn map_ssa_var(self) -> OperandSSAVariableList {
+ OperandSSAVariableList(self.duble())
+ }
+}
+impl Iterator for OperandList {
+ type Item = u64;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // if there is an item in this node, return it
+ if let Some(current_node) = self.current_node.next() {
+ return Some(current_node);
+ }
+
+ // no more items to fetch
+ if self.remaining == 0 {
+ return None;
+ }
+
+ // otherwise get the next node
+ let next_idx = self.next_node_idx?;
+ let node = unsafe { BNGetMediumLevelILByIndex(self.function.handle, next_idx) };
+ assert_eq!(node.operation, BNMediumLevelILOperation::MLIL_UNDEF);
+
+ // each node contains at most 4, the last is reserved to next node idx
+ let consume = if self.remaining > 4 {
+ // there are more nodes after this one
+ self.next_node_idx = Some(node.operands[4] as usize);
+ self.remaining -= 4;
+ &node.operands[0..4]
+ } else {
+ // last part of the list, there is no next node
+ self.next_node_idx = None;
+ let nodes = &node.operands[0..self.remaining];
+ self.remaining = 0;
+ nodes
+ };
+ // the iter need to have a space of 4, but we may have less then that,
+ // solution is create a dummy elements at the start and discard it
+ let mut nodes = [0; 4];
+ let dummy_values = 4 - consume.len();
+ nodes[dummy_values..4].copy_from_slice(consume);
+ self.current_node = nodes.into_iter();
+ for _ in 0..dummy_values {
+ let _ = self.current_node.next();
+ }
+
+ self.current_node.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+impl ExactSizeIterator for OperandList {
+ fn len(&self) -> usize {
+ self.remaining + self.current_node.len()
+ }
+}
+
+// Iterator similar to OperationList, but returns two elements
+pub struct OperandDubleList(OperandList);
+impl Iterator for OperandDubleList {
+ type Item = (u64, u64);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let first = self.0.next()?;
+ let second = self.0.next().unwrap();
+ Some((first, second))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+impl ExactSizeIterator for OperandDubleList {
+ fn len(&self) -> usize {
+ self.0.len() / 2
+ }
+}
+
+pub struct OperandExprList(OperandList);
+impl Iterator for OperandExprList {
+ type Item = 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()))
+ }
+}
+impl ExactSizeIterator for OperandExprList {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+pub struct OperandVariableList(OperandList);
+impl Iterator for OperandVariableList {
+ type Item = Variable;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next().map(get_var)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.0.len(), Some(self.0.len()))
+ }
+}
+impl ExactSizeIterator for OperandVariableList {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+pub struct OperandSSAVariableList(OperandDubleList);
+impl Iterator for OperandSSAVariableList {
+ type Item = SSAVariable;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next().map(|(id, version)| {
+ let raw = unsafe { BNFromVariableIdentifier(id) };
+ let var = unsafe { Variable::from_raw(raw) };
+ SSAVariable::new(var, version as usize)
+ })
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+impl ExactSizeIterator for OperandSSAVariableList {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+fn get_float(value: u64, size: usize) -> f64 {
+ match size {
+ 4 => f32::from_bits(value as u32) as f64,
+ 8 => f64::from_bits(value),
+ // TODO how to handle this value?
+ size => todo!("float size {}", size),
+ }
+}
+
+// TODO implement ConstantData
+fn get_constant_data(
+ _function: &MediumLevelILFunction,
+ _value: u64,
+ _state: u64,
+ _size: usize,
+) -> ! {
+ todo!()
+}
+
+// TODO implement Intrinsic
+fn get_intrinsic(_function: &MediumLevelILFunction, _idx: usize) -> ! {
+ todo!()
+}
+
+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) }
+}
+
+fn get_var(id: u64) -> Variable {
+ unsafe { Variable::from_raw(BNFromVariableIdentifier(id)) }
+}
+
+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 as usize)
+}
+
+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()
+}
+
+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) -> OperandVariableList {
+ get_call_list(function, BNMediumLevelILOperation::MLIL_CALL_PARAM, idx)
+}
+
+fn get_call_list_ssa(
+ function: &MediumLevelILFunction,
+ op_type: BNMediumLevelILOperation,
+ idx: usize,
+) -> OperandSSAVariableList {
+ 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()
+}
+
+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) -> OperandSSAVariableList {
+ get_call_list_ssa(function, BNMediumLevelILOperation::MLIL_CALL_PARAM_SSA, idx)
+}
+
+// NOP, NORET, BP, UNDEF, UNIMPL
+#[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct NoArgs {}
+
+// IF
+#[derive(Copy, Clone)]
+pub struct MediumLevelILOperationIf {
+ condition: usize,
+ dest_true: u64,
+ dest_false: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedIf {
+ pub condition: Box<MediumLevelILLiftedInstruction>,
+ pub dest_true: u64,
+ pub dest_false: u64,
+}
+impl MediumLevelILOperationIf {
+ pub fn new(condition: usize, dest_true: u64, dest_false: u64) -> Self {
+ Self {
+ condition,
+ dest_true,
+ dest_false,
+ }
+ }
+ pub fn condition(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(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, function: &MediumLevelILFunction) -> LiftedIf {
+ LiftedIf {
+ condition: Box::new(self.condition(function).lift()),
+ dest_true: self.dest_true(),
+ dest_false: self.dest_false(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("condition", Expr(self.condition(function))),
+ ("dest_true", Int(self.dest_true())),
+ ("dest_false", Int(self.dest_false())),
+ ]
+ .into_iter()
+ }
+}
+
+// FLOAT_CONST
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub struct FloatConst {
+ pub constant: f64,
+}
+impl FloatConst {
+ pub fn new(constant: u64, size: usize) -> Self {
+ Self {
+ 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(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Constant {
+ pub constant: u64,
+}
+impl Constant {
+ pub fn new(constant: u64) -> Self {
+ Self { 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()
+ }
+}
+
+// EXTERN_PTR
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct ExternPtr {
+ pub constant: u64,
+ pub offset: u64,
+}
+impl ExternPtr {
+ pub fn new(constant: u64, offset: u64) -> Self {
+ Self { constant, offset }
+ }
+ pub fn constant(&self) -> u64 {
+ self.constant
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn operands(
+ &self,
+ _function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("constant", MediumLevelILOperand::Int(self.constant())),
+ ("offset", MediumLevelILOperand::Int(self.offset())),
+ ]
+ .into_iter()
+ }
+}
+
+// CONST_DATA
+#[derive(Copy, Clone)]
+pub struct ConstData {
+ constant_data: (u64, u64),
+}
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct ConstantData {
+ //pub constant_data: !,
+}
+impl ConstData {
+ pub fn new(constant_data: (u64, u64)) -> Self {
+ Self { constant_data }
+ }
+ pub fn constant_data(&self, function: &MediumLevelILFunction, size: usize) -> ! {
+ get_constant_data(function, self.constant_data.0, self.constant_data.1, size)
+ }
+ pub fn lift(&self, _function: &MediumLevelILFunction) -> ConstantData {
+ ConstantData {
+ // TODO
+ }
+ }
+ pub fn operands(
+ &self,
+ _function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ // TODO
+ [
+ //("contant_data", MediumLevelILOperand::ConstData(_self.constant_data(function, self.size)))
+ ]
+ .into_iter()
+ }
+}
+
+// JUMP, RET_HINT
+#[derive(Copy, Clone)]
+pub struct Jump {
+ dest: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedJump {
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+}
+impl Jump {
+ pub fn new(dest: usize) -> Self {
+ Self { dest }
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedJump {
+ LiftedJump {
+ dest: Box::new(self.dest(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [("dest", MediumLevelILOperand::Expr(self.dest(&function)))].into_iter()
+ }
+}
+
+// STORE_SSA
+#[derive(Copy, Clone)]
+pub struct StoreSsa {
+ dest: usize,
+ dest_memory: u64,
+ src_memory: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedStoreSsa {
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub dest_memory: u64,
+ pub src_memory: u64,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl StoreSsa {
+ pub fn new(dest: usize, dest_memory: u64, src_memory: u64, src: usize) -> Self {
+ Self {
+ dest,
+ dest_memory,
+ src_memory,
+ src,
+ }
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(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, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreSsa {
+ LiftedStoreSsa {
+ dest: Box::new(self.dest(function).lift()),
+ dest_memory: self.dest_memory(),
+ src_memory: self.src_memory(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::Expr(self.dest(&function))),
+ ("dest_memory", MediumLevelILOperand::Int(self.dest_memory())),
+ ("src_memory", MediumLevelILOperand::Int(self.src_memory())),
+ ("src", MediumLevelILOperand::Expr(self.src(&function))),
+ ]
+ .into_iter()
+ }
+}
+
+// STORE_STRUCT_SSA
+#[derive(Copy, Clone)]
+pub struct StoreStructSsa {
+ dest: usize,
+ offset: u64,
+ dest_memory: u64,
+ src_memory: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedStoreStructSsa {
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub offset: u64,
+ pub dest_memory: u64,
+ pub src_memory: u64,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl StoreStructSsa {
+ pub fn new(dest: usize, offset: u64, dest_memory: u64, src_memory: u64, src: usize) -> Self {
+ Self {
+ dest,
+ offset,
+ dest_memory,
+ src_memory,
+ src,
+ }
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(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, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreStructSsa {
+ LiftedStoreStructSsa {
+ dest: Box::new(self.dest(function).lift()),
+ offset: self.offset(),
+ dest_memory: self.dest_memory(),
+ src_memory: self.src_memory(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ ("offset", MediumLevelILOperand::Int(self.offset())),
+ ("dest_memory", MediumLevelILOperand::Int(self.dest_memory())),
+ ("src_memory", MediumLevelILOperand::Int(self.src_memory())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// STORE_STRUCT
+#[derive(Copy, Clone)]
+pub struct StoreStruct {
+ dest: usize,
+ offset: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedStoreStruct {
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub offset: u64,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl StoreStruct {
+ pub fn new(dest: usize, offset: u64, src: usize) -> Self {
+ Self { dest, offset, src }
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreStruct {
+ LiftedStoreStruct {
+ dest: Box::new(self.dest(function).lift()),
+ offset: self.offset(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ ("offset", MediumLevelILOperand::Int(self.offset())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// STORE
+#[derive(Copy, Clone)]
+pub struct Store {
+ dest: usize,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedStore {
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl Store {
+ pub fn new(dest: usize, src: usize) -> Self {
+ Self { dest, src }
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStore {
+ LiftedStore {
+ dest: Box::new(self.dest(function).lift()),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// JUMP_TO
+#[derive(Copy, Clone)]
+pub struct JumpTo {
+ dest: usize,
+ targets: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedJumpTo {
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub targets: HashMap<u64, u64>,
+}
+impl JumpTo {
+ pub fn new(dest: usize, targets: (usize, usize)) -> Self {
+ Self { dest, targets }
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn targets(&self, function: &MediumLevelILFunction) -> OperandDubleList {
+ OperandList::new(function, self.targets.1, self.targets.0).duble()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedJumpTo {
+ LiftedJumpTo {
+ dest: Box::new(self.dest(function).lift()),
+ targets: self.targets(function).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("dest", Expr(self.dest(function))),
+ ("targets", TargetMap(self.targets(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// GOTO
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
+pub struct Goto {
+ pub dest: u64,
+}
+impl Goto {
+ pub fn new(dest: u64) -> Self {
+ Self { 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()
+ }
+}
+
+// FREE_VAR_SLOT
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct FreeVarSlot {
+ pub dest: Variable,
+}
+impl FreeVarSlot {
+ pub fn new(dest: u64) -> Self {
+ Self {
+ 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(Copy, Clone)]
+pub struct SetVarField {
+ dest: u64,
+ offset: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVarField {
+ pub dest: Variable,
+ pub offset: u64,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVarField {
+ pub fn new(dest: u64, offset: u64, src: usize) -> Self {
+ Self { dest, offset, src }
+ }
+ pub fn dest(&self) -> Variable {
+ get_var(self.dest)
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarField {
+ LiftedSetVarField {
+ dest: self.dest(),
+ offset: self.offset(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::Var(self.dest())),
+ ("offset", MediumLevelILOperand::Int(self.offset())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// SET_VAR
+#[derive(Copy, Clone)]
+pub struct SetVar {
+ dest: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVar {
+ pub dest: Variable,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVar {
+ pub fn new(dest: u64, src: usize) -> Self {
+ Self { dest, src }
+ }
+ pub fn dest(&self) -> Variable {
+ get_var(self.dest)
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVar {
+ LiftedSetVar {
+ dest: self.dest(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::Var(self.dest())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// FREE_VAR_SLOT_SSA
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct FreeVarSlotSsa {
+ pub dest: SSAVariable,
+ pub prev: SSAVariable,
+}
+impl FreeVarSlotSsa {
+ pub fn new(dest: (u64, usize), prev: (u64, usize)) -> Self {
+ Self {
+ 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 {
+ 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(Copy, Clone)]
+pub struct SetVarSsaField {
+ dest: (u64, usize),
+ prev: (u64, usize),
+ offset: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVarSsaField {
+ pub dest: SSAVariable,
+ pub prev: SSAVariable,
+ pub offset: u64,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVarSsaField {
+ pub fn new(dest: (u64, usize), prev: (u64, usize), offset: u64, src: usize) -> Self {
+ Self {
+ dest,
+ prev,
+ 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, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSsaField {
+ LiftedSetVarSsaField {
+ dest: self.dest(),
+ prev: self.prev(),
+ offset: self.offset(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> 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(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// SET_VAR_ALIASED
+#[derive(Copy, Clone)]
+pub struct SetVarAliased {
+ dest: (u64, usize),
+ prev: (u64, usize),
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVarAliased {
+ pub dest: SSAVariable,
+ pub prev: SSAVariable,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVarAliased {
+ pub fn new(dest: (u64, usize), prev: (u64, usize), src: usize) -> Self {
+ Self { dest, prev, 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, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarAliased {
+ LiftedSetVarAliased {
+ dest: self.dest(),
+ prev: self.prev(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::VarSsa(self.dest())),
+ ("prev", MediumLevelILOperand::VarSsa(self.prev())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// SET_VAR_SSA
+#[derive(Copy, Clone)]
+pub struct SetVarSsa {
+ dest: (u64, usize),
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVarSsa {
+ pub dest: SSAVariable,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVarSsa {
+ pub fn new(dest: (u64, usize), src: usize) -> Self {
+ Self { dest, src }
+ }
+ pub fn dest(&self) -> SSAVariable {
+ get_var_ssa(self.dest.0, self.dest.1)
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSsa {
+ LiftedSetVarSsa {
+ dest: self.dest(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::VarSsa(self.dest())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// VAR_PHI
+#[derive(Copy, Clone)]
+pub struct VarPhi {
+ dest: (u64, usize),
+ src: (usize, usize),
+}
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct LiftedVarPhi {
+ pub dest: SSAVariable,
+ pub src: Vec<SSAVariable>,
+}
+impl VarPhi {
+ pub fn new(dest: (u64, usize), src: (usize, usize)) -> Self {
+ Self { dest, src }
+ }
+ pub fn dest(&self) -> SSAVariable {
+ get_var_ssa(self.dest.0, self.dest.1)
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ OperandList::new(function, self.src.1, self.src.0).map_ssa_var()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedVarPhi {
+ LiftedVarPhi {
+ dest: self.dest(),
+ src: self.src(function).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("dest", MediumLevelILOperand::VarSsa(self.dest())),
+ ("src", MediumLevelILOperand::VarSsaList(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// MEM_PHI
+#[derive(Copy, Clone)]
+pub struct MemPhi {
+ dest_memory: u64,
+ src_memory: (usize, usize),
+}
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct LiftedMemPhi {
+ pub dest_memory: u64,
+ pub src_memory: Vec<u64>,
+}
+impl MemPhi {
+ pub fn new(dest_memory: u64, src_memory: (usize, usize)) -> Self {
+ Self {
+ dest_memory,
+ src_memory,
+ }
+ }
+ pub fn dest_memory(&self) -> u64 {
+ self.dest_memory
+ }
+ pub fn src_memory(&self, function: &MediumLevelILFunction) -> OperandList {
+ OperandList::new(function, self.src_memory.1, self.src_memory.0)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedMemPhi {
+ LiftedMemPhi {
+ dest_memory: self.dest_memory(),
+ src_memory: self.src_memory(function).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("dest_memory", Int(self.dest_memory())),
+ ("src_memory", IntList(self.src_memory(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// VAR_SPLIT
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct VarSplit {
+ pub high: Variable,
+ pub low: Variable,
+}
+impl VarSplit {
+ pub fn new(high: u64, low: u64) -> Self {
+ Self {
+ 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 {
+ 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(Copy, Clone)]
+pub struct SetVarSplit {
+ high: u64,
+ low: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVarSplit {
+ pub high: Variable,
+ pub low: Variable,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVarSplit {
+ pub fn new(high: u64, low: u64, src: usize) -> Self {
+ Self { high, low, src }
+ }
+ pub fn high(&self) -> Variable {
+ get_var(self.high)
+ }
+ pub fn low(&self) -> Variable {
+ get_var(self.low)
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSplit {
+ LiftedSetVarSplit {
+ high: self.high(),
+ low: self.low(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("high", MediumLevelILOperand::Var(self.high())),
+ ("low", MediumLevelILOperand::Var(self.low())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// VAR_SPLIT_SSA
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct VarSplitSsa {
+ pub high: SSAVariable,
+ pub low: SSAVariable,
+}
+impl VarSplitSsa {
+ pub fn new(high: (u64, usize), low: (u64, usize)) -> Self {
+ Self {
+ 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 {
+ 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(Copy, Clone)]
+pub struct SetVarSplitSsa {
+ high: (u64, usize),
+ low: (u64, usize),
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSetVarSplitSsa {
+ pub high: SSAVariable,
+ pub low: SSAVariable,
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl SetVarSplitSsa {
+ pub fn new(high: (u64, usize), low: (u64, usize), src: usize) -> Self {
+ Self { high, low, 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, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSplitSsa {
+ LiftedSetVarSplitSsa {
+ high: self.high(),
+ low: self.low(),
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("high", MediumLevelILOperand::VarSsa(self.high())),
+ ("low", MediumLevelILOperand::VarSsa(self.low())),
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ]
+ .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(Copy, Clone)]
+pub struct BinaryOp {
+ left: usize,
+ right: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedBinaryOp {
+ pub left: Box<MediumLevelILLiftedInstruction>,
+ pub right: Box<MediumLevelILLiftedInstruction>,
+}
+impl BinaryOp {
+ pub fn new(left: usize, right: usize) -> Self {
+ Self { left, right }
+ }
+ pub fn left(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.left)
+ }
+ pub fn right(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.right)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedBinaryOp {
+ LiftedBinaryOp {
+ left: Box::new(self.left(function).lift()),
+ right: Box::new(self.right(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("left", MediumLevelILOperand::Expr(self.left(function))),
+ ("right", MediumLevelILOperand::Expr(self.right(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// ADC, SBB, RLC, RRC
+#[derive(Copy, Clone)]
+pub struct BinaryOpCarry {
+ left: usize,
+ right: usize,
+ carry: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedBinaryOpCarry {
+ pub left: Box<MediumLevelILLiftedInstruction>,
+ pub right: Box<MediumLevelILLiftedInstruction>,
+ pub carry: Box<MediumLevelILLiftedInstruction>,
+}
+impl BinaryOpCarry {
+ pub fn new(left: usize, right: usize, carry: usize) -> Self {
+ Self { left, right, carry }
+ }
+ pub fn left(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.left)
+ }
+ pub fn right(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.right)
+ }
+ pub fn carry(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.carry)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedBinaryOpCarry {
+ LiftedBinaryOpCarry {
+ left: Box::new(self.left(function).lift()),
+ right: Box::new(self.right(function).lift()),
+ carry: Box::new(self.carry(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("left", MediumLevelILOperand::Expr(self.left(function))),
+ ("right", MediumLevelILOperand::Expr(self.right(function))),
+ ("carry", MediumLevelILOperand::Expr(self.carry(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// CALL, TAILCALL
+#[derive(Copy, Clone)]
+pub struct Call {
+ output: (usize, usize),
+ dest: usize,
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCall {
+ pub output: Vec<Variable>,
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub params: Vec<MediumLevelILLiftedInstruction>,
+}
+impl Call {
+ pub fn new(output: (usize, usize), dest: usize, params: (usize, usize)) -> Self {
+ Self {
+ output,
+ dest,
+ params,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ OperandList::new(function, self.output.1, self.output.0).map_var()
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.params.1, self.params.0).map_expr()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCall {
+ LiftedCall {
+ output: self.output(function).collect(),
+ dest: Box::new(self.dest(function).lift()),
+ params: self.params(function).map(|instr| instr.lift()).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ (
+ "output",
+ MediumLevelILOperand::VarList(self.output(function)),
+ ),
+ ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ (
+ "params",
+ MediumLevelILOperand::ExprList(self.params(function)),
+ ),
+ ]
+ .into_iter()
+ }
+}
+
+// SYSCALL
+#[derive(Copy, Clone)]
+pub struct Syscall {
+ output: (usize, usize),
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedInnerCall {
+ pub output: Vec<Variable>,
+ pub params: Vec<MediumLevelILLiftedInstruction>,
+}
+impl Syscall {
+ pub fn new(output: (usize, usize), params: (usize, usize)) -> Self {
+ Self { output, params }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ OperandList::new(function, self.output.1, self.output.0).map_var()
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.params.1, self.params.0).map_expr()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedInnerCall {
+ LiftedInnerCall {
+ output: self.output(function).collect(),
+ params: self.params(function).map(|instr| instr.lift()).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarList(self.output(function))),
+ ("params", ExprList(self.params(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// INTRINSIC
+#[derive(Copy, Clone)]
+pub struct Intrinsic {
+ output: (usize, usize),
+ intrinsic: usize,
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct MediumLevelILLiftedIntrinsic {
+ pub output: Vec<Variable>,
+ //pub intrinsic: !,
+ pub params: Vec<MediumLevelILLiftedInstruction>,
+}
+impl Intrinsic {
+ pub fn new(output: (usize, usize), intrinsic: usize, params: (usize, usize)) -> Self {
+ Self {
+ output,
+ intrinsic,
+ params,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ OperandList::new(function, self.output.1, self.output.0).map_var()
+ }
+ pub fn intrinsic(&self, function: &MediumLevelILFunction) -> ! {
+ get_intrinsic(function, self.intrinsic)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.params.1, self.params.0).map_expr()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedInnerCall {
+ LiftedInnerCall {
+ output: self.output(function).collect(),
+ //intrinsic: get_intrinsic(function, self.intrinsic),
+ params: self.params(function).map(|instr| instr.lift()).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarList(self.output(function))),
+ //("intrinsic", VarList(self.output(function))),
+ ("params", ExprList(self.params(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// INTRINSIC_SSA
+#[derive(Copy, Clone)]
+pub struct IntrinsicSsa {
+ output: (usize, usize),
+ intrinsic: usize,
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedIntrinsicSsa {
+ pub output: Vec<SSAVariable>,
+ //pub intrinsic: !,
+ pub params: Vec<MediumLevelILLiftedInstruction>,
+}
+impl IntrinsicSsa {
+ pub fn new(output: (usize, usize), intrinsic: usize, params: (usize, usize)) -> Self {
+ Self {
+ output,
+ intrinsic,
+ params,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ OperandList::new(function, self.output.1, self.output.0).map_ssa_var()
+ }
+ pub fn intrinsic(&self, function: &MediumLevelILFunction) -> ! {
+ get_intrinsic(function, self.intrinsic)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.params.1, self.params.0).map_expr()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedIntrinsicSsa {
+ LiftedIntrinsicSsa {
+ output: self.output(function).collect(),
+ //intrinsic: get_intrinsic(function, self.intrinsic),
+ params: self.params(function).map(|instr| instr.lift()).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarSsaList(self.output(function))),
+ ("params", ExprList(self.params(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// CALL_SSA, TAILCALL_SSA
+#[derive(Copy, Clone)]
+pub struct CallSsa {
+ output: usize,
+ dest: usize,
+ params: (usize, usize),
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCallSsa {
+ pub output: Vec<SSAVariable>,
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub params: Vec<MediumLevelILLiftedInstruction>,
+ pub src_memory: u64,
+}
+impl CallSsa {
+ pub fn new(output: usize, dest: usize, params: (usize, usize), src_memory: u64) -> Self {
+ Self {
+ output,
+ dest,
+ params,
+ src_memory,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ get_call_output_ssa(function, self.output)
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.params.1, self.params.0).map_expr()
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallSsa {
+ LiftedCallSsa {
+ output: self.output(function).collect(),
+ dest: Box::new(self.dest(function).lift()),
+ params: self.params(function).map(|instr| instr.lift()).collect(),
+ src_memory: self.src_memory(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarSsaList(self.output(function))),
+ ("dest", Expr(self.dest(function))),
+ ("params", ExprList(self.params(function))),
+ ("src_memory", Int(self.src_memory())),
+ ]
+ .into_iter()
+ }
+}
+
+// CALL_UNTYPED_SSA, TAILCALL_UNTYPED_SSA
+#[derive(Copy, Clone)]
+pub struct CallUntypedSsa {
+ output: usize,
+ dest: usize,
+ params: usize,
+ stack: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCallUntypedSsa {
+ pub output: Vec<SSAVariable>,
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub params: Vec<SSAVariable>,
+ pub stack: Box<MediumLevelILLiftedInstruction>,
+}
+impl CallUntypedSsa {
+ pub fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self {
+ Self {
+ output,
+ dest,
+ params,
+ stack,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ get_call_output_ssa(function, self.output)
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ get_call_params_ssa(function, self.params)
+ }
+ pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.stack)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallUntypedSsa {
+ LiftedCallUntypedSsa {
+ output: self.output(function).collect(),
+ dest: Box::new(self.dest(function).lift()),
+ params: self.params(function).collect(),
+ stack: Box::new(self.stack(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarSsaList(self.output(function))),
+ ("dest", Expr(self.dest(function))),
+ ("params", VarSsaList(self.params(function))),
+ ("stack", Expr(self.stack(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// SYSCALL_SSA
+#[derive(Copy, Clone)]
+pub struct SyscallSsa {
+ output: usize,
+ params: (usize, usize),
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSyscallSsa {
+ pub output: Vec<SSAVariable>,
+ pub params: Vec<MediumLevelILLiftedInstruction>,
+ pub src_memory: u64,
+}
+impl SyscallSsa {
+ pub fn new(output: usize, params: (usize, usize), src_memory: u64) -> Self {
+ Self {
+ output,
+ params,
+ src_memory,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ get_call_output_ssa(function, self.output)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.params.1, self.params.0).map_expr()
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallSsa {
+ LiftedSyscallSsa {
+ output: self.output(function).collect(),
+ params: self.params(function).map(|instr| instr.lift()).collect(),
+ src_memory: self.src_memory(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarSsaList(self.output(function))),
+ ("params", ExprList(self.params(function))),
+ ("src_memory", MediumLevelILOperand::Int(self.src_memory())),
+ ]
+ .into_iter()
+ }
+}
+
+// SYSCALL_UNTYPED_SSA
+#[derive(Copy, Clone)]
+pub struct SyscallUntypedSsa {
+ output: usize,
+ params: usize,
+ stack: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSyscallUntypedSsa {
+ pub output: Vec<SSAVariable>,
+ pub params: Vec<SSAVariable>,
+ pub stack: Box<MediumLevelILLiftedInstruction>,
+}
+impl SyscallUntypedSsa {
+ pub fn new(output: usize, params: usize, stack: usize) -> Self {
+ Self {
+ output,
+ params,
+ stack,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ get_call_output_ssa(function, self.output)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
+ get_call_params_ssa(function, self.params)
+ }
+ pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.stack)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallUntypedSsa {
+ LiftedSyscallUntypedSsa {
+ output: self.output(function).collect(),
+ params: self.params(function).collect(),
+ stack: Box::new(self.stack(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarSsaList(self.output(function))),
+ ("params", VarSsaList(self.params(function))),
+ ("stack", Expr(self.stack(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// CALL_UNTYPED, TAILCALL_UNTYPED
+#[derive(Copy, Clone)]
+pub struct CallUntyped {
+ output: usize,
+ dest: usize,
+ params: usize,
+ stack: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCallUntyped {
+ pub output: Vec<Variable>,
+ pub dest: Box<MediumLevelILLiftedInstruction>,
+ pub params: Vec<Variable>,
+ pub stack: Box<MediumLevelILLiftedInstruction>,
+}
+impl CallUntyped {
+ pub fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self {
+ Self {
+ output,
+ dest,
+ params,
+ stack,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ get_call_output(function, self.output)
+ }
+ pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.dest)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ get_call_params(function, self.params)
+ }
+ pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.stack)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallUntyped {
+ LiftedCallUntyped {
+ output: self.output(function).collect(),
+ dest: Box::new(self.dest(function).lift()),
+ params: self.params(function).collect(),
+ stack: Box::new(self.stack(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarList(self.output(function))),
+ ("dest", Expr(self.dest(function))),
+ ("params", VarList(self.params(function))),
+ ("stack", Expr(self.stack(function))),
+ ]
+ .into_iter()
+ }
+}
+
+// SYSCALL_UNTYPED
+#[derive(Copy, Clone)]
+pub struct SyscallUntyped {
+ output: usize,
+ params: usize,
+ stack: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSyscallUntyped {
+ pub output: Vec<Variable>,
+ pub params: Vec<Variable>,
+ pub stack: Box<MediumLevelILLiftedInstruction>,
+}
+impl SyscallUntyped {
+ pub fn new(output: usize, params: usize, stack: usize) -> Self {
+ Self {
+ output,
+ params,
+ stack,
+ }
+ }
+ pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ get_call_output(function, self.output)
+ }
+ pub fn params(&self, function: &MediumLevelILFunction) -> OperandVariableList {
+ get_call_params(function, self.params)
+ }
+ pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.stack)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallUntyped {
+ LiftedSyscallUntyped {
+ output: self.output(function).collect(),
+ params: self.params(function).collect(),
+ stack: Box::new(self.stack(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ use MediumLevelILOperand::*;
+ [
+ ("output", VarList(self.output(function))),
+ ("params", VarList(self.params(function))),
+ ("stack", Expr(self.stack(function))),
+ ]
+ .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(Copy, Clone)]
+pub struct UnaryOp {
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedUnaryOp {
+ pub src: Box<MediumLevelILLiftedInstruction>,
+}
+impl UnaryOp {
+ pub fn new(src: usize) -> Self {
+ Self { src }
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedUnaryOp {
+ LiftedUnaryOp {
+ src: Box::new(self.src(function).lift()),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [("src", MediumLevelILOperand::Expr(self.src(function)))].into_iter()
+ }
+}
+
+// LOAD_STRUCT
+#[derive(Copy, Clone)]
+pub struct LoadStruct {
+ src: usize,
+ offset: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedLoadStruct {
+ pub src: Box<MediumLevelILLiftedInstruction>,
+ pub offset: u64,
+}
+impl LoadStruct {
+ pub fn new(src: usize, offset: u64) -> Self {
+ Self { src, offset }
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadStruct {
+ LiftedLoadStruct {
+ src: Box::new(self.src(function).lift()),
+ offset: self.offset(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("offset", MediumLevelILOperand::Int(self.offset())),
+ ]
+ .into_iter()
+ }
+}
+
+// LOAD_STRUCT_SSA
+#[derive(Copy, Clone)]
+pub struct LoadStructSsa {
+ src: usize,
+ offset: u64,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedLoadStructSsa {
+ pub src: Box<MediumLevelILLiftedInstruction>,
+ pub offset: u64,
+ pub src_memory: u64,
+}
+impl LoadStructSsa {
+ pub fn new(src: usize, offset: u64, src_memory: u64) -> Self {
+ Self {
+ src,
+ offset,
+ src_memory,
+ }
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadStructSsa {
+ LiftedLoadStructSsa {
+ src: Box::new(self.src(function).lift()),
+ offset: self.offset(),
+ src_memory: self.src_memory(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("offset", MediumLevelILOperand::Int(self.offset())),
+ ("src_memory", MediumLevelILOperand::Int(self.src_memory())),
+ ]
+ .into_iter()
+ }
+}
+
+// LOAD_SSA
+#[derive(Copy, Clone)]
+pub struct LoadSsa {
+ src: usize,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedLoadSsa {
+ pub src: Box<MediumLevelILLiftedInstruction>,
+ pub src_memory: u64,
+}
+impl LoadSsa {
+ pub fn new(src: usize, src_memory: u64) -> Self {
+ Self { src, src_memory }
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
+ get_operation(function, self.src)
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadSsa {
+ LiftedLoadSsa {
+ src: Box::new(self.src(function).lift()),
+ src_memory: self.src_memory(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [
+ ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src_memory", MediumLevelILOperand::Int(self.src_memory())),
+ ]
+ .into_iter()
+ }
+}
+
+// RET
+#[derive(Copy, Clone)]
+pub struct Ret {
+ src: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedRet {
+ pub src: Vec<MediumLevelILLiftedInstruction>,
+}
+impl Ret {
+ pub fn new(src: (usize, usize)) -> Self {
+ Self { src }
+ }
+ pub fn src(&self, function: &MediumLevelILFunction) -> OperandExprList {
+ OperandList::new(function, self.src.1, self.src.0).map_expr()
+ }
+ pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedRet {
+ LiftedRet {
+ src: self.src(function).map(|instr| instr.lift()).collect(),
+ }
+ }
+ pub fn operands(
+ &self,
+ function: &MediumLevelILFunction,
+ ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [("src", MediumLevelILOperand::ExprList(self.src(function)))].into_iter()
+ }
+}
+
+// VAR, ADDRESS_OF
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Var {
+ pub src: Variable,
+}
+impl Var {
+ pub fn new(src: u64) -> Self {
+ Self { 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()
+ }
+}
+
+// VAR_FIELD, ADDRESS_OF_FIELD
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Field {
+ pub src: Variable,
+ pub offset: u64,
+}
+impl Field {
+ pub fn new(src: u64, offset: u64) -> Self {
+ Self {
+ 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(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct VarSsa {
+ pub src: SSAVariable,
+}
+impl VarSsa {
+ pub fn new(src: (u64, usize)) -> Self {
+ Self {
+ 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(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct VarSsaField {
+ pub src: SSAVariable,
+ pub offset: u64,
+}
+impl VarSsaField {
+ pub fn new(src: (u64, usize), offset: u64) -> Self {
+ Self {
+ 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(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Trap {
+ pub vector: u64,
+}
+impl Trap {
+ pub fn new(vector: u64) -> Self {
+ Self { 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()
+ }
+}
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 5c568142..d86ffc82 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -29,7 +29,6 @@ use crate::{
};
use lazy_static::lazy_static;
-use std::ptr::null_mut;
use std::{
borrow::Cow,
collections::HashSet,
@@ -1392,6 +1391,21 @@ impl Variable {
}
}
+//////////////
+// SSAVariable
+
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
+pub struct SSAVariable {
+ pub variable: Variable,
+ pub version: usize,
+}
+
+impl SSAVariable {
+ pub fn new(variable: Variable, version: usize) -> Self {
+ Self { variable, version }
+ }
+}
+
///////////////
// NamedVariable