summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorRubens Brandao <git@rubens.io>2023-11-22 18:57:28 -0300
committerKyleMiles <krm504@nyu.edu>2024-02-02 13:32:45 -0500
commitf682ca69b356755fe6c06bcdd8f4fab73f7d2c78 (patch)
tree3cfc324cfe8043ccc8db1161f1f90c448d097c8a /rust/src
parente1a6bdcd576f7caeaa6f97ff1e337a259057b333 (diff)
Rust API : Add HLIL Bindings
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/function.rs43
-rw-r--r--rust/src/functionrecognizer.rs2
-rw-r--r--rust/src/hlil/block.rs63
-rw-r--r--rust/src/hlil/function.rs107
-rw-r--r--rust/src/hlil/instruction.rs1282
-rw-r--r--rust/src/hlil/lift.rs385
-rw-r--r--rust/src/hlil/mod.rs10
-rw-r--r--rust/src/hlil/operation.rs2373
-rw-r--r--rust/src/lib.rs1
-rw-r--r--rust/src/llil/function.rs18
-rw-r--r--rust/src/mlil/block.rs4
-rw-r--r--rust/src/mlil/function.rs12
-rw-r--r--rust/src/mlil/instruction.rs994
-rw-r--r--rust/src/mlil/lift.rs14
-rw-r--r--rust/src/mlil/operation.rs1793
-rw-r--r--rust/src/types.rs156
16 files changed, 6358 insertions, 899 deletions
diff --git a/rust/src/function.rs b/rust/src/function.rs
index 93af0dd9..7f9ad862 100644
--- a/rust/src/function.rs
+++ b/rust/src/function.rs
@@ -21,12 +21,13 @@ use crate::{
architecture::CoreArchitecture,
basicblock::{BasicBlock, BlockContext},
binaryview::{BinaryView, BinaryViewExt},
- llil, mlil,
+ hlil, llil, mlil,
platform::Platform,
symbol::Symbol,
types::{Conf, NamedTypedVariable, Type},
};
+use std::hash::Hash;
use std::{fmt, mem};
pub struct Location {
@@ -108,7 +109,7 @@ impl BlockContext for NativeBlock {
}
}
-#[derive(PartialEq, Eq, Hash)]
+#[derive(Eq)]
pub struct Function {
pub(crate) handle: *mut BNFunction,
}
@@ -225,6 +226,18 @@ impl Function {
}
}
+ pub fn high_level_il(&self, full_ast: bool) -> Result<Ref<hlil::HighLevelILFunction>, ()> {
+ unsafe {
+ let hlil = BNGetFunctionHighLevelIL(self.handle);
+
+ if hlil.is_null() {
+ return Err(());
+ }
+
+ Ok(hlil::HighLevelILFunction::ref_from_raw(hlil, full_ast))
+ }
+ }
+
pub fn medium_level_il(&self) -> Result<Ref<mlil::MediumLevelILFunction>, ()> {
unsafe {
let mlil = BNGetFunctionMediumLevelIL(self.handle);
@@ -233,7 +246,7 @@ impl Function {
return Err(());
}
- Ok(Ref::new(mlil::MediumLevelILFunction::from_raw(mlil)))
+ Ok(mlil::MediumLevelILFunction::ref_from_raw(mlil))
}
}
@@ -245,7 +258,7 @@ impl Function {
return Err(());
}
- Ok(Ref::new(llil::RegularFunction::from_raw(self.arch(), llil)))
+ Ok(llil::RegularFunction::from_raw(self.arch(), llil))
}
}
@@ -257,7 +270,7 @@ impl Function {
return Err(());
}
- Ok(Ref::new(llil::LiftedFunction::from_raw(self.arch(), llil)))
+ Ok(llil::LiftedFunction::from_raw(self.arch(), llil))
}
}
@@ -354,6 +367,26 @@ unsafe impl<'a> CoreArrayWrapper<'a> for Function {
}
}
+impl Hash for Function {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ let start_address = self.start();
+ let architecture = self.arch();
+ let platform = self.platform();
+ (start_address, architecture, platform).hash(state)
+ }
+}
+
+impl PartialEq for Function {
+ fn eq(&self, other: &Self) -> bool {
+ if self.handle == other.handle {
+ return true;
+ }
+ self.start() == other.start()
+ && self.arch() == other.arch()
+ && self.platform() == other.platform()
+ }
+}
+
/////////////////
// AddressRange
diff --git a/rust/src/functionrecognizer.rs b/rust/src/functionrecognizer.rs
index ec567308..c63edcab 100644
--- a/rust/src/functionrecognizer.rs
+++ b/rust/src/functionrecognizer.rs
@@ -70,7 +70,7 @@ where
let custom_handler = unsafe { &*(ctxt as *mut R) };
let bv = unsafe { BinaryView::from_raw(BNNewViewReference(bv)) };
let func = unsafe { Function::from_raw(BNNewFunctionReference(func)) };
- let mlil = unsafe { mlil::MediumLevelILFunction::from_raw(mlil) };
+ let mlil = unsafe { mlil::MediumLevelILFunction::ref_from_raw(mlil) };
custom_handler.recognize_medium_level_il(bv.as_ref(), func.as_ref(), &mlil)
}
diff --git a/rust/src/hlil/block.rs b/rust/src/hlil/block.rs
new file mode 100644
index 00000000..a90429a4
--- /dev/null
+++ b/rust/src/hlil/block.rs
@@ -0,0 +1,63 @@
+use std::ops::Range;
+
+use binaryninjacore_sys::BNGetHighLevelILIndexForInstruction;
+
+use crate::basicblock::{BasicBlock, BlockContext};
+use crate::rc::Ref;
+
+use super::{HighLevelILFunction, HighLevelILInstruction};
+
+pub struct HighLevelILBlockIter {
+ function: Ref<HighLevelILFunction>,
+ range: Range<u64>,
+}
+
+impl Iterator for HighLevelILBlockIter {
+ type Item = HighLevelILInstruction;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.range
+ .next()
+ .map(|i| unsafe {
+ BNGetHighLevelILIndexForInstruction(self.function.handle, i as usize)
+ })
+ .map(|i| HighLevelILInstruction::new(&self.function, i))
+ }
+}
+
+pub struct HighLevelILBlock {
+ pub(crate) function: Ref<HighLevelILFunction>,
+}
+
+impl core::fmt::Debug for HighLevelILBlock {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "mlil_bb {:?}", self.function)
+ }
+}
+
+impl BlockContext for HighLevelILBlock {
+ type Iter = HighLevelILBlockIter;
+ type Instruction = HighLevelILInstruction;
+
+ fn start(&self, block: &BasicBlock<Self>) -> HighLevelILInstruction {
+ let expr_idx = unsafe {
+ BNGetHighLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize)
+ };
+ HighLevelILInstruction::new(&self.function, expr_idx)
+ }
+
+ fn iter(&self, block: &BasicBlock<Self>) -> HighLevelILBlockIter {
+ HighLevelILBlockIter {
+ function: self.function.to_owned(),
+ range: block.raw_start()..block.raw_end(),
+ }
+ }
+}
+
+impl Clone for HighLevelILBlock {
+ fn clone(&self) -> Self {
+ HighLevelILBlock {
+ function: self.function.to_owned(),
+ }
+ }
+}
diff --git a/rust/src/hlil/function.rs b/rust/src/hlil/function.rs
new file mode 100644
index 00000000..40d01dfe
--- /dev/null
+++ b/rust/src/hlil/function.rs
@@ -0,0 +1,107 @@
+use std::hash::{Hash, Hasher};
+
+use binaryninjacore_sys::BNFreeHighLevelILFunction;
+use binaryninjacore_sys::BNGetHighLevelILBasicBlockList;
+use binaryninjacore_sys::BNGetHighLevelILInstructionCount;
+use binaryninjacore_sys::BNGetHighLevelILOwnerFunction;
+use binaryninjacore_sys::BNGetHighLevelILSSAForm;
+use binaryninjacore_sys::BNHighLevelILFunction;
+use binaryninjacore_sys::BNNewHighLevelILFunctionReference;
+
+use crate::basicblock::BasicBlock;
+use crate::function::Function;
+use crate::rc::{Array, Ref, RefCountable};
+
+use super::{HighLevelILBlock, HighLevelILInstruction};
+
+pub struct HighLevelILFunction {
+ pub(crate) full_ast: bool,
+ pub(crate) handle: *mut BNHighLevelILFunction,
+}
+
+unsafe impl Send for HighLevelILFunction {}
+unsafe impl Sync for HighLevelILFunction {}
+
+impl Eq for HighLevelILFunction {}
+impl PartialEq for HighLevelILFunction {
+ fn eq(&self, rhs: &Self) -> bool {
+ self.get_function().eq(&rhs.get_function())
+ }
+}
+
+impl Hash for HighLevelILFunction {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.get_function().hash(state)
+ }
+}
+
+impl HighLevelILFunction {
+ pub(crate) unsafe fn ref_from_raw(
+ handle: *mut BNHighLevelILFunction,
+ full_ast: bool,
+ ) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+ Self { handle, full_ast }.to_owned()
+ }
+
+ pub fn instruction_from_idx(&self, expr_idx: usize) -> HighLevelILInstruction {
+ HighLevelILInstruction::new(self, expr_idx)
+ }
+
+ pub fn instruction_count(&self) -> usize {
+ unsafe { BNGetHighLevelILInstructionCount(self.handle) }
+ }
+
+ pub fn ssa_form(&self) -> HighLevelILFunction {
+ let ssa = unsafe { BNGetHighLevelILSSAForm(self.handle) };
+ assert!(!ssa.is_null());
+ HighLevelILFunction {
+ handle: ssa,
+ full_ast: self.full_ast,
+ }
+ }
+
+ pub fn get_function(&self) -> Ref<Function> {
+ unsafe {
+ let func = BNGetHighLevelILOwnerFunction(self.handle);
+ Function::from_raw(func)
+ }
+ }
+
+ pub fn basic_blocks(&self) -> Array<BasicBlock<HighLevelILBlock>> {
+ let mut count = 0;
+ let blocks = unsafe { BNGetHighLevelILBasicBlockList(self.handle, &mut count) };
+ let context = HighLevelILBlock {
+ function: self.to_owned(),
+ };
+
+ unsafe { Array::new(blocks, count, context) }
+ }
+}
+
+impl ToOwned for HighLevelILFunction {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+unsafe impl RefCountable for HighLevelILFunction {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: BNNewHighLevelILFunctionReference(handle.handle),
+ full_ast: handle.full_ast,
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeHighLevelILFunction(handle.handle);
+ }
+}
+
+impl core::fmt::Debug for HighLevelILFunction {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "<hlil func handle {:p}>", self.handle)
+ }
+}
diff --git a/rust/src/hlil/instruction.rs b/rust/src/hlil/instruction.rs
new file mode 100644
index 00000000..acdc5cf7
--- /dev/null
+++ b/rust/src/hlil/instruction.rs
@@ -0,0 +1,1282 @@
+use binaryninjacore_sys::BNGetHighLevelILByIndex;
+use binaryninjacore_sys::BNHighLevelILOperation;
+
+use super::operation::*;
+use super::{HighLevelILFunction, HighLevelILLiftedInstruction};
+
+#[derive(Clone)]
+pub enum HighLevelILInstruction {
+ Adc(BinaryOpCarry),
+ Sbb(BinaryOpCarry),
+ Rlc(BinaryOpCarry),
+ Rrc(BinaryOpCarry),
+ 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),
+ Fadd(BinaryOp),
+ Fsub(BinaryOp),
+ Fmul(BinaryOp),
+ Fdiv(BinaryOp),
+ FcmpE(BinaryOp),
+ FcmpNe(BinaryOp),
+ FcmpLt(BinaryOp),
+ FcmpLe(BinaryOp),
+ FcmpGe(BinaryOp),
+ FcmpGt(BinaryOp),
+ FcmpO(BinaryOp),
+ FcmpUo(BinaryOp),
+ ArrayIndex(ArrayIndex),
+ ArrayIndexSsa(ArrayIndexSsa),
+ Assign(Assign),
+ AssignMemSsa(AssignMemSsa),
+ AssignUnpack(AssignUnpack),
+ AssignUnpackMemSsa(AssignUnpackMemSsa),
+ Block(Block),
+ Call(Call),
+ Tailcall(Call),
+ CallSsa(CallSsa),
+ Case(Case),
+ Const(Const),
+ ConstPtr(Const),
+ Import(Const),
+ ConstData(ConstData),
+ Deref(UnaryOp),
+ AddressOf(UnaryOp),
+ 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),
+ DerefFieldSsa(DerefFieldSsa),
+ DerefSsa(DerefSsa),
+ ExternPtr(ExternPtr),
+ FloatConst(FloatConst),
+ For(ForLoop),
+ ForSsa(ForLoopSsa),
+ Goto(Label),
+ Label(Label),
+ If(If),
+ Intrinsic(Intrinsic),
+ IntrinsicSsa(IntrinsicSsa),
+ Jump(Jump),
+ MemPhi(MemPhi),
+ Nop(NoArgs),
+ Break(NoArgs),
+ Continue(NoArgs),
+ Noret(NoArgs),
+ Unreachable(NoArgs),
+ Bp(NoArgs),
+ Undef(NoArgs),
+ Unimpl(NoArgs),
+ Ret(Ret),
+ Split(Split),
+ StructField(StructField),
+ DerefField(StructField),
+ Switch(Switch),
+ Syscall(Syscall),
+ SyscallSsa(SyscallSsa),
+ Trap(Trap),
+ VarDeclare(Var),
+ Var(Var),
+ VarInit(VarInit),
+ VarInitSsa(VarInitSsa),
+ VarPhi(VarPhi),
+ VarSsa(VarSsa),
+ While(While),
+ DoWhile(While),
+ WhileSsa(WhileSsa),
+ DoWhileSsa(WhileSsa),
+}
+impl HighLevelILInstruction {
+ pub(crate) fn new(function: &HighLevelILFunction, idx: usize) -> Self {
+ let op = unsafe { BNGetHighLevelILByIndex(function.handle, idx, function.full_ast) };
+ use BNHighLevelILOperation::*;
+ use HighLevelILInstruction as Op;
+ match op.operation {
+ HLIL_ADC => Op::Adc(BinaryOpCarry::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ HLIL_SBB => Op::Sbb(BinaryOpCarry::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ HLIL_RLC => Op::Rlc(BinaryOpCarry::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ HLIL_RRC => Op::Rrc(BinaryOpCarry::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ HLIL_ADD => Op::Add(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_SUB => Op::Sub(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_AND => Op::And(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_OR => Op::Or(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_XOR => Op::Xor(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_LSL => Op::Lsl(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_LSR => Op::Lsr(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ASR => Op::Asr(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ROL => Op::Rol(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ROR => Op::Ror(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MUL => Op::Mul(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MULU_DP => Op::MuluDp(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MULS_DP => Op::MulsDp(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_DIVU => Op::Divu(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_DIVU_DP => Op::DivuDp(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_DIVS => Op::Divs(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_DIVS_DP => Op::DivsDp(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MODU => Op::Modu(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MODU_DP => Op::ModuDp(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MODS => Op::Mods(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_MODS_DP => Op::ModsDp(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_E => Op::CmpE(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_NE => Op::CmpNe(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_SLE => Op::CmpSle(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_ULE => Op::CmpUle(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_SGE => Op::CmpSge(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_UGE => Op::CmpUge(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_TEST_BIT => Op::TestBit(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FADD => Op::Fadd(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FSUB => Op::Fsub(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FMUL => Op::Fmul(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FDIV => Op::Fdiv(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_E => Op::FcmpE(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_O => Op::FcmpO(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ARRAY_INDEX => Op::ArrayIndex(ArrayIndex::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ARRAY_INDEX_SSA => Op::ArrayIndexSsa(ArrayIndexSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize],
+ op.operands[2usize] as usize,
+ )),
+ HLIL_ASSIGN => Op::Assign(Assign::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_ASSIGN_MEM_SSA => Op::AssignMemSsa(AssignMemSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize],
+ op.operands[2usize] as usize,
+ op.operands[3usize],
+ )),
+ HLIL_ASSIGN_UNPACK => Op::AssignUnpack(AssignUnpack::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ op.operands[2usize] as usize,
+ )),
+ HLIL_ASSIGN_UNPACK_MEM_SSA => Op::AssignUnpackMemSsa(AssignUnpackMemSsa::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ op.operands[2usize],
+ op.operands[3usize] as usize,
+ op.operands[4usize],
+ )),
+ HLIL_BLOCK => Op::Block(Block::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ )),
+ HLIL_CALL => Op::Call(Call::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ (op.operands[1usize] as usize, op.operands[2usize] as usize),
+ )),
+ HLIL_TAILCALL => Op::Tailcall(Call::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ (op.operands[1usize] as usize, op.operands[2usize] as usize),
+ )),
+ HLIL_CALL_SSA => Op::CallSsa(CallSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ (op.operands[1usize] as usize, op.operands[2usize] as usize),
+ op.operands[3usize],
+ op.operands[4usize],
+ )),
+ HLIL_CASE => Op::Case(Case::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ op.operands[2usize] as usize,
+ )),
+ HLIL_CONST => Op::Const(Const::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_CONST_PTR => Op::ConstPtr(Const::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_IMPORT => Op::Import(Const::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_CONST_DATA => Op::ConstData(ConstData::new(
+ function.to_owned(),
+ op.address,
+ (
+ op.operands[0usize].try_into().unwrap(),
+ op.operands[1usize],
+ op.size,
+ ),
+ )),
+ HLIL_DEREF => Op::Deref(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_ADDRESS_OF => Op::AddressOf(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_NEG => Op::Neg(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_NOT => Op::Not(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_SX => Op::Sx(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_ZX => Op::Zx(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_LOW_PART => Op::LowPart(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FSQRT => Op::Fsqrt(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FNEG => Op::Fneg(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FABS => Op::Fabs(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FLOAT_CONV => Op::FloatConv(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FLOOR => Op::Floor(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_CEIL => Op::Ceil(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_DEREF_FIELD_SSA => Op::DerefFieldSsa(DerefFieldSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize],
+ op.operands[2usize],
+ op.operands[3usize],
+ )),
+ HLIL_DEREF_SSA => Op::DerefSsa(DerefSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize],
+ )),
+ HLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ op.operands[1usize],
+ )),
+ HLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ op.size,
+ )),
+ HLIL_FOR => Op::For(ForLoop::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ op.operands[3usize] as usize,
+ )),
+ HLIL_FOR_SSA => Op::ForSsa(ForLoopSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ op.operands[3usize] as usize,
+ op.operands[4usize] as usize,
+ )),
+ HLIL_GOTO => Op::Goto(Label::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_LABEL => Op::Label(Label::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_IF => Op::If(If::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ HLIL_INTRINSIC => Op::Intrinsic(Intrinsic::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as u32,
+ (op.operands[1usize] as usize, op.operands[2usize] as usize),
+ )),
+ HLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as u32,
+ (op.operands[1usize] as usize, op.operands[2usize] as usize),
+ op.operands[3usize],
+ op.operands[4usize],
+ )),
+ HLIL_JUMP => Op::Jump(Jump::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ )),
+ HLIL_MEM_PHI => Op::MemPhi(MemPhi::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ (op.operands[1usize] as usize, op.operands[2usize] as usize),
+ )),
+ HLIL_NOP => Op::Nop(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_BREAK => Op::Break(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_CONTINUE => Op::Continue(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_NORET => Op::Noret(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_UNREACHABLE => Op::Unreachable(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_BP => Op::Bp(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_UNDEF => Op::Undef(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_UNIMPL => Op::Unimpl(NoArgs::new(function.to_owned(), op.address)),
+ HLIL_RET => Op::Ret(Ret::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ )),
+ HLIL_SPLIT => Op::Split(Split::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_STRUCT_FIELD => Op::StructField(StructField::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize],
+ op.operands[2usize],
+ )),
+ HLIL_DEREF_FIELD => Op::DerefField(StructField::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize],
+ op.operands[2usize],
+ )),
+ HLIL_SWITCH => Op::Switch(Switch::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ (op.operands[2usize] as usize, op.operands[3usize] as usize),
+ )),
+ HLIL_SYSCALL => Op::Syscall(Syscall::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ )),
+ HLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize] as usize, op.operands[1usize] as usize),
+ op.operands[2usize],
+ op.operands[3usize],
+ )),
+ HLIL_TRAP => Op::Trap(Trap::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_VAR_DECLARE => Op::VarDeclare(Var::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_VAR => Op::Var(Var::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ )),
+ HLIL_VAR_INIT => Op::VarInit(VarInit::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize],
+ op.operands[1usize] as usize,
+ )),
+ HLIL_VAR_INIT_SSA => Op::VarInitSsa(VarInitSsa::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize], op.operands[1usize] as usize),
+ op.operands[2usize] as usize,
+ )),
+ HLIL_VAR_PHI => Op::VarPhi(VarPhi::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize], op.operands[1usize] as usize),
+ (op.operands[2usize] as usize, op.operands[3usize] as usize),
+ )),
+ HLIL_VAR_SSA => Op::VarSsa(VarSsa::new(
+ function.to_owned(),
+ op.address,
+ (op.operands[0usize], op.operands[1usize] as usize),
+ )),
+ HLIL_WHILE => Op::While(While::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_DO_WHILE => Op::DoWhile(While::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ )),
+ HLIL_WHILE_SSA => Op::WhileSsa(WhileSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ HLIL_DO_WHILE_SSA => Op::DoWhileSsa(WhileSsa::new(
+ function.to_owned(),
+ op.address,
+ op.operands[0usize] as usize,
+ op.operands[1usize] as usize,
+ op.operands[2usize] as usize,
+ )),
+ }
+ }
+ pub fn function(&self) -> &HighLevelILFunction {
+ use HighLevelILInstruction::*;
+ match self {
+ Adc(op) => &op.function,
+ Sbb(op) => &op.function,
+ Rlc(op) => &op.function,
+ Rrc(op) => &op.function,
+ Add(op) => &op.function,
+ Sub(op) => &op.function,
+ And(op) => &op.function,
+ Or(op) => &op.function,
+ Xor(op) => &op.function,
+ Lsl(op) => &op.function,
+ Lsr(op) => &op.function,
+ Asr(op) => &op.function,
+ Rol(op) => &op.function,
+ Ror(op) => &op.function,
+ Mul(op) => &op.function,
+ MuluDp(op) => &op.function,
+ MulsDp(op) => &op.function,
+ Divu(op) => &op.function,
+ DivuDp(op) => &op.function,
+ Divs(op) => &op.function,
+ DivsDp(op) => &op.function,
+ Modu(op) => &op.function,
+ ModuDp(op) => &op.function,
+ Mods(op) => &op.function,
+ ModsDp(op) => &op.function,
+ CmpE(op) => &op.function,
+ CmpNe(op) => &op.function,
+ CmpSlt(op) => &op.function,
+ CmpUlt(op) => &op.function,
+ CmpSle(op) => &op.function,
+ CmpUle(op) => &op.function,
+ CmpSge(op) => &op.function,
+ CmpUge(op) => &op.function,
+ CmpSgt(op) => &op.function,
+ CmpUgt(op) => &op.function,
+ TestBit(op) => &op.function,
+ AddOverflow(op) => &op.function,
+ Fadd(op) => &op.function,
+ Fsub(op) => &op.function,
+ Fmul(op) => &op.function,
+ Fdiv(op) => &op.function,
+ FcmpE(op) => &op.function,
+ FcmpNe(op) => &op.function,
+ FcmpLt(op) => &op.function,
+ FcmpLe(op) => &op.function,
+ FcmpGe(op) => &op.function,
+ FcmpGt(op) => &op.function,
+ FcmpO(op) => &op.function,
+ FcmpUo(op) => &op.function,
+ ArrayIndex(op) => &op.function,
+ ArrayIndexSsa(op) => &op.function,
+ Assign(op) => &op.function,
+ AssignMemSsa(op) => &op.function,
+ AssignUnpack(op) => &op.function,
+ AssignUnpackMemSsa(op) => &op.function,
+ Block(op) => &op.function,
+ Call(op) => &op.function,
+ Tailcall(op) => &op.function,
+ CallSsa(op) => &op.function,
+ Case(op) => &op.function,
+ Const(op) => &op.function,
+ ConstPtr(op) => &op.function,
+ Import(op) => &op.function,
+ ConstData(op) => &op.function,
+ Deref(op) => &op.function,
+ AddressOf(op) => &op.function,
+ Neg(op) => &op.function,
+ Not(op) => &op.function,
+ Sx(op) => &op.function,
+ Zx(op) => &op.function,
+ LowPart(op) => &op.function,
+ BoolToInt(op) => &op.function,
+ UnimplMem(op) => &op.function,
+ Fsqrt(op) => &op.function,
+ Fneg(op) => &op.function,
+ Fabs(op) => &op.function,
+ FloatToInt(op) => &op.function,
+ IntToFloat(op) => &op.function,
+ FloatConv(op) => &op.function,
+ RoundToInt(op) => &op.function,
+ Floor(op) => &op.function,
+ Ceil(op) => &op.function,
+ Ftrunc(op) => &op.function,
+ DerefFieldSsa(op) => &op.function,
+ DerefSsa(op) => &op.function,
+ ExternPtr(op) => &op.function,
+ FloatConst(op) => &op.function,
+ For(op) => &op.function,
+ ForSsa(op) => &op.function,
+ Goto(op) => &op.function,
+ Label(op) => &op.function,
+ If(op) => &op.function,
+ Intrinsic(op) => &op.function,
+ IntrinsicSsa(op) => &op.function,
+ Jump(op) => &op.function,
+ MemPhi(op) => &op.function,
+ Nop(op) => &op.function,
+ Break(op) => &op.function,
+ Continue(op) => &op.function,
+ Noret(op) => &op.function,
+ Unreachable(op) => &op.function,
+ Bp(op) => &op.function,
+ Undef(op) => &op.function,
+ Unimpl(op) => &op.function,
+ Ret(op) => &op.function,
+ Split(op) => &op.function,
+ StructField(op) => &op.function,
+ DerefField(op) => &op.function,
+ Switch(op) => &op.function,
+ Syscall(op) => &op.function,
+ SyscallSsa(op) => &op.function,
+ Trap(op) => &op.function,
+ VarDeclare(op) => &op.function,
+ Var(op) => &op.function,
+ VarInit(op) => &op.function,
+ VarInitSsa(op) => &op.function,
+ VarPhi(op) => &op.function,
+ VarSsa(op) => &op.function,
+ While(op) => &op.function,
+ DoWhile(op) => &op.function,
+ WhileSsa(op) => &op.function,
+ DoWhileSsa(op) => &op.function,
+ }
+ }
+ pub fn address(&self) -> u64 {
+ use HighLevelILInstruction::*;
+ match self {
+ Adc(op) => op.address,
+ Sbb(op) => op.address,
+ Rlc(op) => op.address,
+ Rrc(op) => op.address,
+ Add(op) => op.address,
+ Sub(op) => op.address,
+ And(op) => op.address,
+ Or(op) => op.address,
+ Xor(op) => op.address,
+ Lsl(op) => op.address,
+ Lsr(op) => op.address,
+ Asr(op) => op.address,
+ Rol(op) => op.address,
+ Ror(op) => op.address,
+ Mul(op) => op.address,
+ MuluDp(op) => op.address,
+ MulsDp(op) => op.address,
+ Divu(op) => op.address,
+ DivuDp(op) => op.address,
+ Divs(op) => op.address,
+ DivsDp(op) => op.address,
+ Modu(op) => op.address,
+ ModuDp(op) => op.address,
+ Mods(op) => op.address,
+ ModsDp(op) => op.address,
+ CmpE(op) => op.address,
+ CmpNe(op) => op.address,
+ CmpSlt(op) => op.address,
+ CmpUlt(op) => op.address,
+ CmpSle(op) => op.address,
+ CmpUle(op) => op.address,
+ CmpSge(op) => op.address,
+ CmpUge(op) => op.address,
+ CmpSgt(op) => op.address,
+ CmpUgt(op) => op.address,
+ TestBit(op) => op.address,
+ AddOverflow(op) => op.address,
+ Fadd(op) => op.address,
+ Fsub(op) => op.address,
+ Fmul(op) => op.address,
+ Fdiv(op) => op.address,
+ FcmpE(op) => op.address,
+ FcmpNe(op) => op.address,
+ FcmpLt(op) => op.address,
+ FcmpLe(op) => op.address,
+ FcmpGe(op) => op.address,
+ FcmpGt(op) => op.address,
+ FcmpO(op) => op.address,
+ FcmpUo(op) => op.address,
+ ArrayIndex(op) => op.address,
+ ArrayIndexSsa(op) => op.address,
+ Assign(op) => op.address,
+ AssignMemSsa(op) => op.address,
+ AssignUnpack(op) => op.address,
+ AssignUnpackMemSsa(op) => op.address,
+ Block(op) => op.address,
+ Call(op) => op.address,
+ Tailcall(op) => op.address,
+ CallSsa(op) => op.address,
+ Case(op) => op.address,
+ Const(op) => op.address,
+ ConstPtr(op) => op.address,
+ Import(op) => op.address,
+ ConstData(op) => op.address,
+ Deref(op) => op.address,
+ AddressOf(op) => op.address,
+ Neg(op) => op.address,
+ Not(op) => op.address,
+ Sx(op) => op.address,
+ Zx(op) => op.address,
+ LowPart(op) => op.address,
+ BoolToInt(op) => op.address,
+ UnimplMem(op) => op.address,
+ Fsqrt(op) => op.address,
+ Fneg(op) => op.address,
+ Fabs(op) => op.address,
+ FloatToInt(op) => op.address,
+ IntToFloat(op) => op.address,
+ FloatConv(op) => op.address,
+ RoundToInt(op) => op.address,
+ Floor(op) => op.address,
+ Ceil(op) => op.address,
+ Ftrunc(op) => op.address,
+ DerefFieldSsa(op) => op.address,
+ DerefSsa(op) => op.address,
+ ExternPtr(op) => op.address,
+ FloatConst(op) => op.address,
+ For(op) => op.address,
+ ForSsa(op) => op.address,
+ Goto(op) => op.address,
+ Label(op) => op.address,
+ If(op) => op.address,
+ Intrinsic(op) => op.address,
+ IntrinsicSsa(op) => op.address,
+ Jump(op) => op.address,
+ MemPhi(op) => op.address,
+ Nop(op) => op.address,
+ Break(op) => op.address,
+ Continue(op) => op.address,
+ Noret(op) => op.address,
+ Unreachable(op) => op.address,
+ Bp(op) => op.address,
+ Undef(op) => op.address,
+ Unimpl(op) => op.address,
+ Ret(op) => op.address,
+ Split(op) => op.address,
+ StructField(op) => op.address,
+ DerefField(op) => op.address,
+ Switch(op) => op.address,
+ Syscall(op) => op.address,
+ SyscallSsa(op) => op.address,
+ Trap(op) => op.address,
+ VarDeclare(op) => op.address,
+ Var(op) => op.address,
+ VarInit(op) => op.address,
+ VarInitSsa(op) => op.address,
+ VarPhi(op) => op.address,
+ VarSsa(op) => op.address,
+ While(op) => op.address,
+ DoWhile(op) => op.address,
+ WhileSsa(op) => op.address,
+ DoWhileSsa(op) => op.address,
+ }
+ }
+ pub fn lift(&self) -> HighLevelILLiftedInstruction {
+ use HighLevelILInstruction::*;
+ use HighLevelILLiftedInstruction as Lifted;
+ match self {
+ Nop(op) => Lifted::Nop(op.clone()),
+ Block(op) => Lifted::Block(op.lift()),
+ If(op) => Lifted::If(op.lift()),
+ While(op) => Lifted::While(op.lift()),
+ WhileSsa(op) => Lifted::WhileSsa(op.lift()),
+ DoWhile(op) => Lifted::DoWhile(op.lift()),
+ DoWhileSsa(op) => Lifted::DoWhileSsa(op.lift()),
+ For(op) => Lifted::For(op.lift()),
+ ForSsa(op) => Lifted::ForSsa(op.lift()),
+ Switch(op) => Lifted::Switch(op.lift()),
+ Case(op) => Lifted::Case(op.lift()),
+ Break(op) => Lifted::Break(op.clone()),
+ Continue(op) => Lifted::Continue(op.clone()),
+ Jump(op) => Lifted::Jump(op.clone()),
+ Ret(op) => Lifted::Ret(op.lift()),
+ Noret(op) => Lifted::Noret(op.clone()),
+ Unreachable(op) => Lifted::Unreachable(op.clone()),
+ Goto(op) => Lifted::Goto(op.clone()),
+ Label(op) => Lifted::Label(op.clone()),
+ VarDeclare(op) => Lifted::VarDeclare(op.clone()),
+ VarInit(op) => Lifted::VarInit(op.lift()),
+ VarInitSsa(op) => Lifted::VarInitSsa(op.lift()),
+ Assign(op) => Lifted::Assign(op.lift()),
+ AssignUnpack(op) => Lifted::AssignUnpack(op.lift()),
+ AssignMemSsa(op) => Lifted::AssignMemSsa(op.lift()),
+ AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(op.lift()),
+ Var(op) => Lifted::Var(op.clone()),
+ VarSsa(op) => Lifted::VarSsa(op.clone()),
+ VarPhi(op) => Lifted::VarPhi(op.lift()),
+ MemPhi(op) => Lifted::MemPhi(op.lift()),
+ ArrayIndex(op) => Lifted::ArrayIndex(op.lift()),
+ ArrayIndexSsa(op) => Lifted::ArrayIndexSsa(op.lift()),
+ Split(op) => Lifted::Split(op.lift()),
+ Deref(op) => Lifted::Deref(op.lift()),
+ StructField(op) => Lifted::StructField(op.lift()),
+ DerefField(op) => Lifted::DerefField(op.lift()),
+ DerefSsa(op) => Lifted::DerefSsa(op.lift()),
+ DerefFieldSsa(op) => Lifted::DerefFieldSsa(op.lift()),
+ AddressOf(op) => Lifted::AddressOf(op.lift()),
+ Const(op) => Lifted::Const(op.clone()),
+ ConstPtr(op) => Lifted::ConstPtr(op.clone()),
+ ExternPtr(op) => Lifted::ExternPtr(op.clone()),
+ FloatConst(op) => Lifted::FloatConst(op.clone()),
+ Import(op) => Lifted::Import(op.clone()),
+ ConstData(op) => Lifted::ConstData(op.lift()),
+ Add(op) => Lifted::Add(op.lift()),
+ Adc(op) => Lifted::Adc(op.lift()),
+ Sub(op) => Lifted::Sub(op.lift()),
+ Sbb(op) => Lifted::Sbb(op.lift()),
+ And(op) => Lifted::And(op.lift()),
+ Or(op) => Lifted::Or(op.lift()),
+ Xor(op) => Lifted::Xor(op.lift()),
+ Lsl(op) => Lifted::Lsl(op.lift()),
+ Lsr(op) => Lifted::Lsr(op.lift()),
+ Asr(op) => Lifted::Asr(op.lift()),
+ Rol(op) => Lifted::Rol(op.lift()),
+ Rlc(op) => Lifted::Rlc(op.lift()),
+ Ror(op) => Lifted::Ror(op.lift()),
+ Rrc(op) => Lifted::Rrc(op.lift()),
+ Mul(op) => Lifted::Mul(op.lift()),
+ MuluDp(op) => Lifted::MuluDp(op.lift()),
+ MulsDp(op) => Lifted::MulsDp(op.lift()),
+ Divu(op) => Lifted::Divu(op.lift()),
+ DivuDp(op) => Lifted::DivuDp(op.lift()),
+ Divs(op) => Lifted::Divs(op.lift()),
+ DivsDp(op) => Lifted::DivsDp(op.lift()),
+ Modu(op) => Lifted::Modu(op.lift()),
+ ModuDp(op) => Lifted::ModuDp(op.lift()),
+ Mods(op) => Lifted::Mods(op.lift()),
+ ModsDp(op) => Lifted::ModsDp(op.lift()),
+ Neg(op) => Lifted::Neg(op.lift()),
+ Not(op) => Lifted::Not(op.lift()),
+ Sx(op) => Lifted::Sx(op.lift()),
+ Zx(op) => Lifted::Zx(op.lift()),
+ LowPart(op) => Lifted::LowPart(op.lift()),
+ Call(op) => Lifted::Call(op.lift()),
+ CallSsa(op) => Lifted::CallSsa(op.lift()),
+ CmpE(op) => Lifted::CmpE(op.lift()),
+ CmpNe(op) => Lifted::CmpNe(op.lift()),
+ CmpSlt(op) => Lifted::CmpSlt(op.lift()),
+ CmpUlt(op) => Lifted::CmpUlt(op.lift()),
+ CmpSle(op) => Lifted::CmpSle(op.lift()),
+ CmpUle(op) => Lifted::CmpUle(op.lift()),
+ CmpSge(op) => Lifted::CmpSge(op.lift()),
+ CmpUge(op) => Lifted::CmpUge(op.lift()),
+ CmpSgt(op) => Lifted::CmpSgt(op.lift()),
+ CmpUgt(op) => Lifted::CmpUgt(op.lift()),
+ TestBit(op) => Lifted::TestBit(op.lift()),
+ BoolToInt(op) => Lifted::BoolToInt(op.lift()),
+ AddOverflow(op) => Lifted::AddOverflow(op.lift()),
+ Syscall(op) => Lifted::Syscall(op.lift()),
+ SyscallSsa(op) => Lifted::SyscallSsa(op.lift()),
+ Tailcall(op) => Lifted::Tailcall(op.lift()),
+ Bp(op) => Lifted::Bp(op.clone()),
+ Trap(op) => Lifted::Trap(op.clone()),
+ Intrinsic(op) => Lifted::Intrinsic(op.lift()),
+ IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift()),
+ Undef(op) => Lifted::Undef(op.clone()),
+ Unimpl(op) => Lifted::Unimpl(op.clone()),
+ UnimplMem(op) => Lifted::UnimplMem(op.lift()),
+ Fadd(op) => Lifted::Fadd(op.lift()),
+ Fsub(op) => Lifted::Fsub(op.lift()),
+ Fmul(op) => Lifted::Fmul(op.lift()),
+ Fdiv(op) => Lifted::Fdiv(op.lift()),
+ Fsqrt(op) => Lifted::Fsqrt(op.lift()),
+ Fneg(op) => Lifted::Fneg(op.lift()),
+ Fabs(op) => Lifted::Fabs(op.lift()),
+ FloatToInt(op) => Lifted::FloatToInt(op.lift()),
+ IntToFloat(op) => Lifted::IntToFloat(op.lift()),
+ FloatConv(op) => Lifted::FloatConv(op.lift()),
+ RoundToInt(op) => Lifted::RoundToInt(op.lift()),
+ Floor(op) => Lifted::Floor(op.lift()),
+ Ceil(op) => Lifted::Ceil(op.lift()),
+ Ftrunc(op) => Lifted::Ftrunc(op.lift()),
+ FcmpE(op) => Lifted::FcmpE(op.lift()),
+ FcmpNe(op) => Lifted::FcmpNe(op.lift()),
+ FcmpLt(op) => Lifted::FcmpLt(op.lift()),
+ FcmpLe(op) => Lifted::FcmpLe(op.lift()),
+ FcmpGe(op) => Lifted::FcmpGe(op.lift()),
+ FcmpGt(op) => Lifted::FcmpGt(op.lift()),
+ FcmpO(op) => Lifted::FcmpO(op.lift()),
+ FcmpUo(op) => Lifted::FcmpUo(op.lift()),
+ }
+ }
+ pub fn operands<'a>(
+ &'a self,
+ ) -> Box<dyn Iterator<Item = (&'static str, HighLevelILOperand)> + 'a> {
+ use HighLevelILInstruction::*;
+ match self {
+ Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands()),
+ Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
+ | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
+ | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
+ | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
+ | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | Fadd(op)
+ | Fsub(op) | Fmul(op) | Fdiv(op) | FcmpE(op) | FcmpNe(op) | FcmpLt(op) | FcmpLe(op)
+ | FcmpGe(op) | FcmpGt(op) | FcmpO(op) | FcmpUo(op) => Box::new(op.operands()),
+ ArrayIndex(op) => Box::new(op.operands()),
+ ArrayIndexSsa(op) => Box::new(op.operands()),
+ Assign(op) => Box::new(op.operands()),
+ AssignMemSsa(op) => Box::new(op.operands()),
+ AssignUnpack(op) => Box::new(op.operands()),
+ AssignUnpackMemSsa(op) => Box::new(op.operands()),
+ Block(op) => Box::new(op.operands()),
+ Call(op) | Tailcall(op) => Box::new(op.operands()),
+ CallSsa(op) => Box::new(op.operands()),
+ Case(op) => Box::new(op.operands()),
+ Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()),
+ ConstData(op) => Box::new(op.operands()),
+ Deref(op) | AddressOf(op) | Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op)
+ | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op)
+ | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op)
+ | Ftrunc(op) => Box::new(op.operands()),
+ DerefFieldSsa(op) => Box::new(op.operands()),
+ DerefSsa(op) => Box::new(op.operands()),
+ ExternPtr(op) => Box::new(op.operands()),
+ FloatConst(op) => Box::new(op.operands()),
+ For(op) => Box::new(op.operands()),
+ ForSsa(op) => Box::new(op.operands()),
+ Goto(op) | Label(op) => Box::new(op.operands()),
+ If(op) => Box::new(op.operands()),
+ Intrinsic(op) => Box::new(op.operands()),
+ IntrinsicSsa(op) => Box::new(op.operands()),
+ Jump(op) => Box::new(op.operands()),
+ MemPhi(op) => Box::new(op.operands()),
+ Nop(op) | Break(op) | Continue(op) | Noret(op) | Unreachable(op) | Bp(op)
+ | Undef(op) | Unimpl(op) => Box::new(op.operands()),
+ Ret(op) => Box::new(op.operands()),
+ Split(op) => Box::new(op.operands()),
+ StructField(op) | DerefField(op) => Box::new(op.operands()),
+ Switch(op) => Box::new(op.operands()),
+ Syscall(op) => Box::new(op.operands()),
+ SyscallSsa(op) => Box::new(op.operands()),
+ Trap(op) => Box::new(op.operands()),
+ VarDeclare(op) | Var(op) => Box::new(op.operands()),
+ VarInit(op) => Box::new(op.operands()),
+ VarInitSsa(op) => Box::new(op.operands()),
+ VarPhi(op) => Box::new(op.operands()),
+ VarSsa(op) => Box::new(op.operands()),
+ While(op) | DoWhile(op) => Box::new(op.operands()),
+ WhileSsa(op) | DoWhileSsa(op) => Box::new(op.operands()),
+ }
+ }
+}
+
+impl core::fmt::Debug for HighLevelILInstruction {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(
+ f,
+ "<{} at 0x{:08}>",
+ core::any::type_name::<Self>(),
+ self.address(),
+ )
+ }
+}
diff --git a/rust/src/hlil/lift.rs b/rust/src/hlil/lift.rs
new file mode 100644
index 00000000..5ed7a33c
--- /dev/null
+++ b/rust/src/hlil/lift.rs
@@ -0,0 +1,385 @@
+use super::{operation::*, HighLevelILFunction};
+
+#[derive(Clone, Debug, PartialEq)]
+pub enum HighLevelILLiftedInstruction {
+ Adc(LiftedBinaryOpCarry),
+ Sbb(LiftedBinaryOpCarry),
+ Rlc(LiftedBinaryOpCarry),
+ Rrc(LiftedBinaryOpCarry),
+ 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),
+ Fadd(LiftedBinaryOp),
+ Fsub(LiftedBinaryOp),
+ Fmul(LiftedBinaryOp),
+ Fdiv(LiftedBinaryOp),
+ FcmpE(LiftedBinaryOp),
+ FcmpNe(LiftedBinaryOp),
+ FcmpLt(LiftedBinaryOp),
+ FcmpLe(LiftedBinaryOp),
+ FcmpGe(LiftedBinaryOp),
+ FcmpGt(LiftedBinaryOp),
+ FcmpO(LiftedBinaryOp),
+ FcmpUo(LiftedBinaryOp),
+ ArrayIndex(LiftedArrayIndex),
+ ArrayIndexSsa(LiftedArrayIndexSsa),
+ Assign(LiftedAssign),
+ AssignMemSsa(LiftedAssignMemSsa),
+ AssignUnpack(LiftedAssignUnpack),
+ AssignUnpackMemSsa(LiftedAssignUnpackMemSsa),
+ Block(LiftedBlock),
+ Call(LiftedCall),
+ Tailcall(LiftedCall),
+ CallSsa(LiftedCallSsa),
+ Case(LiftedCase),
+ Const(Const),
+ ConstPtr(Const),
+ Import(Const),
+ ConstData(LiftedConstantData),
+ Deref(LiftedUnaryOp),
+ AddressOf(LiftedUnaryOp),
+ 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),
+ DerefFieldSsa(LiftedDerefFieldSsa),
+ DerefSsa(LiftedDerefSsa),
+ ExternPtr(ExternPtr),
+ FloatConst(FloatConst),
+ For(LiftedForLoop),
+ ForSsa(LiftedForLoopSsa),
+ Goto(Label),
+ Label(Label),
+ If(LiftedIf),
+ Intrinsic(LiftedIntrinsic),
+ IntrinsicSsa(LiftedIntrinsicSsa),
+ Jump(Jump),
+ MemPhi(LiftedMemPhi),
+ Nop(NoArgs),
+ Break(NoArgs),
+ Continue(NoArgs),
+ Noret(NoArgs),
+ Unreachable(NoArgs),
+ Bp(NoArgs),
+ Undef(NoArgs),
+ Unimpl(NoArgs),
+ Ret(LiftedRet),
+ Split(LiftedSplit),
+ StructField(LiftedStructField),
+ DerefField(LiftedStructField),
+ Switch(LiftedSwitch),
+ Syscall(LiftedSyscall),
+ SyscallSsa(LiftedSyscallSsa),
+ Trap(Trap),
+ VarDeclare(Var),
+ Var(Var),
+ VarInit(LiftedVarInit),
+ VarInitSsa(LiftedVarInitSsa),
+ VarPhi(LiftedVarPhi),
+ VarSsa(VarSsa),
+ While(LiftedWhile),
+ DoWhile(LiftedWhile),
+ WhileSsa(LiftedWhileSsa),
+ DoWhileSsa(LiftedWhileSsa),
+}
+
+impl HighLevelILLiftedInstruction {
+ pub fn address(&self) -> u64 {
+ use HighLevelILLiftedInstruction::*;
+ match self {
+ Adc(op) => op.address,
+ Sbb(op) => op.address,
+ Rlc(op) => op.address,
+ Rrc(op) => op.address,
+ Add(op) => op.address,
+ Sub(op) => op.address,
+ And(op) => op.address,
+ Or(op) => op.address,
+ Xor(op) => op.address,
+ Lsl(op) => op.address,
+ Lsr(op) => op.address,
+ Asr(op) => op.address,
+ Rol(op) => op.address,
+ Ror(op) => op.address,
+ Mul(op) => op.address,
+ MuluDp(op) => op.address,
+ MulsDp(op) => op.address,
+ Divu(op) => op.address,
+ DivuDp(op) => op.address,
+ Divs(op) => op.address,
+ DivsDp(op) => op.address,
+ Modu(op) => op.address,
+ ModuDp(op) => op.address,
+ Mods(op) => op.address,
+ ModsDp(op) => op.address,
+ CmpE(op) => op.address,
+ CmpNe(op) => op.address,
+ CmpSlt(op) => op.address,
+ CmpUlt(op) => op.address,
+ CmpSle(op) => op.address,
+ CmpUle(op) => op.address,
+ CmpSge(op) => op.address,
+ CmpUge(op) => op.address,
+ CmpSgt(op) => op.address,
+ CmpUgt(op) => op.address,
+ TestBit(op) => op.address,
+ AddOverflow(op) => op.address,
+ Fadd(op) => op.address,
+ Fsub(op) => op.address,
+ Fmul(op) => op.address,
+ Fdiv(op) => op.address,
+ FcmpE(op) => op.address,
+ FcmpNe(op) => op.address,
+ FcmpLt(op) => op.address,
+ FcmpLe(op) => op.address,
+ FcmpGe(op) => op.address,
+ FcmpGt(op) => op.address,
+ FcmpO(op) => op.address,
+ FcmpUo(op) => op.address,
+ ArrayIndex(op) => op.address,
+ ArrayIndexSsa(op) => op.address,
+ Assign(op) => op.address,
+ AssignMemSsa(op) => op.address,
+ AssignUnpack(op) => op.address,
+ AssignUnpackMemSsa(op) => op.address,
+ Block(op) => op.address,
+ Call(op) => op.address,
+ Tailcall(op) => op.address,
+ CallSsa(op) => op.address,
+ Case(op) => op.address,
+ Const(op) => op.address,
+ ConstPtr(op) => op.address,
+ Import(op) => op.address,
+ ConstData(op) => op.address,
+ Deref(op) => op.address,
+ AddressOf(op) => op.address,
+ Neg(op) => op.address,
+ Not(op) => op.address,
+ Sx(op) => op.address,
+ Zx(op) => op.address,
+ LowPart(op) => op.address,
+ BoolToInt(op) => op.address,
+ UnimplMem(op) => op.address,
+ Fsqrt(op) => op.address,
+ Fneg(op) => op.address,
+ Fabs(op) => op.address,
+ FloatToInt(op) => op.address,
+ IntToFloat(op) => op.address,
+ FloatConv(op) => op.address,
+ RoundToInt(op) => op.address,
+ Floor(op) => op.address,
+ Ceil(op) => op.address,
+ Ftrunc(op) => op.address,
+ DerefFieldSsa(op) => op.address,
+ DerefSsa(op) => op.address,
+ ExternPtr(op) => op.address,
+ FloatConst(op) => op.address,
+ For(op) => op.address,
+ ForSsa(op) => op.address,
+ Goto(op) => op.address,
+ Label(op) => op.address,
+ If(op) => op.address,
+ Intrinsic(op) => op.address,
+ IntrinsicSsa(op) => op.address,
+ Jump(op) => op.address,
+ MemPhi(op) => op.address,
+ Nop(op) => op.address,
+ Break(op) => op.address,
+ Continue(op) => op.address,
+ Noret(op) => op.address,
+ Unreachable(op) => op.address,
+ Bp(op) => op.address,
+ Undef(op) => op.address,
+ Unimpl(op) => op.address,
+ Ret(op) => op.address,
+ Split(op) => op.address,
+ StructField(op) => op.address,
+ DerefField(op) => op.address,
+ Switch(op) => op.address,
+ Syscall(op) => op.address,
+ SyscallSsa(op) => op.address,
+ Trap(op) => op.address,
+ VarDeclare(op) => op.address,
+ Var(op) => op.address,
+ VarInit(op) => op.address,
+ VarInitSsa(op) => op.address,
+ VarPhi(op) => op.address,
+ VarSsa(op) => op.address,
+ While(op) => op.address,
+ DoWhile(op) => op.address,
+ WhileSsa(op) => op.address,
+ DoWhileSsa(op) => op.address,
+ }
+ }
+
+ pub fn function(&self) -> &HighLevelILFunction {
+ use HighLevelILLiftedInstruction::*;
+ match self {
+ Adc(op) => &op.function,
+ Sbb(op) => &op.function,
+ Rlc(op) => &op.function,
+ Rrc(op) => &op.function,
+ Add(op) => &op.function,
+ Sub(op) => &op.function,
+ And(op) => &op.function,
+ Or(op) => &op.function,
+ Xor(op) => &op.function,
+ Lsl(op) => &op.function,
+ Lsr(op) => &op.function,
+ Asr(op) => &op.function,
+ Rol(op) => &op.function,
+ Ror(op) => &op.function,
+ Mul(op) => &op.function,
+ MuluDp(op) => &op.function,
+ MulsDp(op) => &op.function,
+ Divu(op) => &op.function,
+ DivuDp(op) => &op.function,
+ Divs(op) => &op.function,
+ DivsDp(op) => &op.function,
+ Modu(op) => &op.function,
+ ModuDp(op) => &op.function,
+ Mods(op) => &op.function,
+ ModsDp(op) => &op.function,
+ CmpE(op) => &op.function,
+ CmpNe(op) => &op.function,
+ CmpSlt(op) => &op.function,
+ CmpUlt(op) => &op.function,
+ CmpSle(op) => &op.function,
+ CmpUle(op) => &op.function,
+ CmpSge(op) => &op.function,
+ CmpUge(op) => &op.function,
+ CmpSgt(op) => &op.function,
+ CmpUgt(op) => &op.function,
+ TestBit(op) => &op.function,
+ AddOverflow(op) => &op.function,
+ Fadd(op) => &op.function,
+ Fsub(op) => &op.function,
+ Fmul(op) => &op.function,
+ Fdiv(op) => &op.function,
+ FcmpE(op) => &op.function,
+ FcmpNe(op) => &op.function,
+ FcmpLt(op) => &op.function,
+ FcmpLe(op) => &op.function,
+ FcmpGe(op) => &op.function,
+ FcmpGt(op) => &op.function,
+ FcmpO(op) => &op.function,
+ FcmpUo(op) => &op.function,
+ ArrayIndex(op) => &op.function,
+ ArrayIndexSsa(op) => &op.function,
+ Assign(op) => &op.function,
+ AssignMemSsa(op) => &op.function,
+ AssignUnpack(op) => &op.function,
+ AssignUnpackMemSsa(op) => &op.function,
+ Block(op) => &op.function,
+ Call(op) => &op.function,
+ Tailcall(op) => &op.function,
+ CallSsa(op) => &op.function,
+ Case(op) => &op.function,
+ Const(op) => &op.function,
+ ConstPtr(op) => &op.function,
+ Import(op) => &op.function,
+ ConstData(op) => &op.function,
+ Deref(op) => &op.function,
+ AddressOf(op) => &op.function,
+ Neg(op) => &op.function,
+ Not(op) => &op.function,
+ Sx(op) => &op.function,
+ Zx(op) => &op.function,
+ LowPart(op) => &op.function,
+ BoolToInt(op) => &op.function,
+ UnimplMem(op) => &op.function,
+ Fsqrt(op) => &op.function,
+ Fneg(op) => &op.function,
+ Fabs(op) => &op.function,
+ FloatToInt(op) => &op.function,
+ IntToFloat(op) => &op.function,
+ FloatConv(op) => &op.function,
+ RoundToInt(op) => &op.function,
+ Floor(op) => &op.function,
+ Ceil(op) => &op.function,
+ Ftrunc(op) => &op.function,
+ DerefFieldSsa(op) => &op.function,
+ DerefSsa(op) => &op.function,
+ ExternPtr(op) => &op.function,
+ FloatConst(op) => &op.function,
+ For(op) => &op.function,
+ ForSsa(op) => &op.function,
+ Goto(op) => &op.function,
+ Label(op) => &op.function,
+ If(op) => &op.function,
+ Intrinsic(op) => &op.function,
+ IntrinsicSsa(op) => &op.function,
+ Jump(op) => &op.function,
+ MemPhi(op) => &op.function,
+ Nop(op) => &op.function,
+ Break(op) => &op.function,
+ Continue(op) => &op.function,
+ Noret(op) => &op.function,
+ Unreachable(op) => &op.function,
+ Bp(op) => &op.function,
+ Undef(op) => &op.function,
+ Unimpl(op) => &op.function,
+ Ret(op) => &op.function,
+ Split(op) => &op.function,
+ StructField(op) => &op.function,
+ DerefField(op) => &op.function,
+ Switch(op) => &op.function,
+ Syscall(op) => &op.function,
+ SyscallSsa(op) => &op.function,
+ Trap(op) => &op.function,
+ VarDeclare(op) => &op.function,
+ Var(op) => &op.function,
+ VarInit(op) => &op.function,
+ VarInitSsa(op) => &op.function,
+ VarPhi(op) => &op.function,
+ VarSsa(op) => &op.function,
+ While(op) => &op.function,
+ DoWhile(op) => &op.function,
+ WhileSsa(op) => &op.function,
+ DoWhileSsa(op) => &op.function,
+ }
+ }
+}
diff --git a/rust/src/hlil/mod.rs b/rust/src/hlil/mod.rs
new file mode 100644
index 00000000..8a9103ac
--- /dev/null
+++ b/rust/src/hlil/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/hlil/operation.rs b/rust/src/hlil/operation.rs
new file mode 100644
index 00000000..769861e0
--- /dev/null
+++ b/rust/src/hlil/operation.rs
@@ -0,0 +1,2373 @@
+use binaryninjacore_sys::BNFromVariableIdentifier;
+use binaryninjacore_sys::BNGetGotoLabelName;
+use binaryninjacore_sys::BNGetHighLevelILByIndex;
+use binaryninjacore_sys::BNHighLevelILInstruction;
+use binaryninjacore_sys::BNHighLevelILOperation;
+
+use crate::function::Function;
+use crate::rc::Ref;
+use crate::types::{
+ ConstantData, ILIntrinsic, RegisterValue, RegisterValueType, SSAVariable, Variable,
+};
+
+use super::{HighLevelILFunction, HighLevelILInstruction, HighLevelILLiftedInstruction};
+
+pub enum HighLevelILOperand {
+ ConstantData(ConstantData),
+ Expr(HighLevelILInstruction),
+ ExprList(OperandExprList),
+ Float(f64),
+ Int(u64),
+ IntList(OperandList),
+ Intrinsic(ILIntrinsic),
+ Label(GotoLabel),
+ MemberIndex(Option<usize>),
+ Var(Variable),
+ VarSsa(SSAVariable),
+ VarSsaList(OperandSSAVariableList),
+}
+
+// Iterator for the get_list, this is better then a inline iterator because
+// this also implement ExactSizeIterator, what a inline iterator does not.
+pub struct OperandList {
+ function: Ref<HighLevelILFunction>,
+ remaining: usize,
+ next_node_idx: Option<usize>,
+
+ current_node: core::array::IntoIter<u64, 4>,
+}
+impl OperandList {
+ fn new(function: &HighLevelILFunction, idx: usize, number: usize) -> Self {
+ // alternative to core::array::IntoIter::empty();
+ let mut iter = [0; 4].into_iter();
+ for _ in 0..4 {
+ let _ = iter.next();
+ }
+ Self {
+ function: function.to_owned(),
+ remaining: number,
+ next_node_idx: Some(idx),
+ current_node: iter,
+ }
+ }
+ fn double(self) -> OperandDubleList {
+ assert_eq!(self.len() % 2, 0);
+ OperandDubleList(self)
+ }
+ fn map_expr(self) -> OperandExprList {
+ OperandExprList(self)
+ }
+ fn map_ssa_var(self) -> OperandSSAVariableList {
+ OperandSSAVariableList(self.double())
+ }
+}
+impl Iterator for OperandList {
+ type Item = u64;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // if there is an item in this node, return it
+ if let Some(current_node) = self.current_node.next() {
+ return Some(current_node);
+ }
+
+ // no more items to fetch
+ if self.remaining == 0 {
+ return None;
+ }
+
+ // otherwise get the next node
+ let next_idx = self.next_node_idx?;
+ let node = get_raw_operation(&self.function, next_idx);
+ assert_eq!(node.operation, BNHighLevelILOperation::HLIL_UNDEF);
+
+ // each node contains at most 4, the last is reserved to next node idx
+ let consume = if self.remaining > 4 {
+ // there are more nodes after this one
+ self.next_node_idx = Some(node.operands[4] as usize);
+ self.remaining -= 4;
+ &node.operands[0..4]
+ } else {
+ // last part of the list, there is no next node
+ self.next_node_idx = None;
+ let nodes = &node.operands[0..self.remaining];
+ self.remaining = 0;
+ nodes
+ };
+ // the iter need to have a space of 4, but we may have less then that,
+ // solution is create a dummy elements at the start and discard it
+ let mut nodes = [0; 4];
+ let dummy_values = 4 - consume.len();
+ nodes[dummy_values..4].copy_from_slice(consume);
+ self.current_node = nodes.into_iter();
+ for _ in 0..dummy_values {
+ let _ = self.current_node.next();
+ }
+
+ self.current_node.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+impl ExactSizeIterator for OperandList {
+ fn len(&self) -> usize {
+ self.remaining + self.current_node.len()
+ }
+}
+
+// Iterator similar to OperationList, but returns two elements
+pub struct OperandDubleList(OperandList);
+impl Iterator for OperandDubleList {
+ type Item = (u64, u64);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let first = self.0.next()?;
+ let second = self.0.next().unwrap();
+ Some((first, second))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+impl ExactSizeIterator for OperandDubleList {
+ fn len(&self) -> usize {
+ self.0.len() / 2
+ }
+}
+
+pub struct OperandExprList(OperandList);
+impl Iterator for OperandExprList {
+ type Item = HighLevelILInstruction;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0
+ .next()
+ .map(|idx| get_instruction(&self.0.function, idx as usize))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.0.len(), Some(self.0.len()))
+ }
+}
+impl ExactSizeIterator for OperandExprList {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+pub struct OperandVariableList(OperandList);
+impl Iterator for OperandVariableList {
+ type Item = Variable;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next().map(get_var)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.0.len(), Some(self.0.len()))
+ }
+}
+impl ExactSizeIterator for OperandVariableList {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+pub struct OperandSSAVariableList(OperandDubleList);
+impl Iterator for OperandSSAVariableList {
+ type Item = SSAVariable;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next().map(|(id, version)| {
+ let raw = unsafe { BNFromVariableIdentifier(id) };
+ let var = unsafe { Variable::from_raw(raw) };
+ SSAVariable::new(var, version as usize)
+ })
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+impl ExactSizeIterator for OperandSSAVariableList {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+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),
+ }
+}
+
+fn get_instruction(function: &HighLevelILFunction, idx: usize) -> HighLevelILInstruction {
+ function.instruction_from_idx(idx)
+}
+
+fn get_instruction_list(function: &HighLevelILFunction, list: (usize, usize)) -> OperandExprList {
+ OperandList::new(function, list.1, list.0).map_expr()
+}
+
+fn get_int_list(function: &HighLevelILFunction, list: (usize, usize)) -> OperandList {
+ OperandList::new(function, list.1, list.0)
+}
+
+fn get_raw_operation(function: &HighLevelILFunction, idx: usize) -> BNHighLevelILInstruction {
+ unsafe { BNGetHighLevelILByIndex(function.handle, idx, function.full_ast) }
+}
+
+fn get_var(id: u64) -> Variable {
+ unsafe { Variable::from_raw(BNFromVariableIdentifier(id)) }
+}
+
+fn get_member_index(idx: u64) -> Option<usize> {
+ (idx as i64 > 0).then_some(idx as usize)
+}
+
+fn get_var_ssa(input: (u64, usize)) -> SSAVariable {
+ let raw = unsafe { BNFromVariableIdentifier(input.0) };
+ let var = unsafe { Variable::from_raw(raw) };
+ SSAVariable::new(var, input.1)
+}
+
+fn get_var_ssa_list(
+ function: &HighLevelILFunction,
+ list: (usize, usize),
+) -> OperandSSAVariableList {
+ OperandList::new(function, list.1, list.0).map_ssa_var()
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct GotoLabel {
+ function: Ref<Function>,
+ target: u64,
+}
+
+impl GotoLabel {
+ pub fn name(&self) -> &str {
+ let raw_str = unsafe { BNGetGotoLabelName(self.function.handle, self.target) };
+ let c_str = unsafe { core::ffi::CStr::from_ptr(raw_str) };
+ c_str.to_str().unwrap()
+ }
+}
+
+// ADC, SBB, RLC, RRC
+#[derive(Clone)]
+pub struct BinaryOpCarry {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ left: usize,
+ right: usize,
+ carry: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedBinaryOpCarry {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub left: Box<HighLevelILLiftedInstruction>,
+ pub right: Box<HighLevelILLiftedInstruction>,
+ pub carry: Box<HighLevelILLiftedInstruction>,
+}
+impl BinaryOpCarry {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ left: usize,
+ right: usize,
+ carry: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ left,
+ right,
+ carry,
+ }
+ }
+ pub fn left(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.left)
+ }
+ pub fn right(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.right)
+ }
+ pub fn carry(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.carry)
+ }
+ pub fn lift(&self) -> LiftedBinaryOpCarry {
+ LiftedBinaryOpCarry {
+ function: self.function.to_owned(),
+ address: self.address,
+ left: Box::new(self.left().lift()),
+ right: Box::new(self.right().lift()),
+ carry: Box::new(self.carry().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("left", Expr(self.left())),
+ 1usize => ("right", Expr(self.right())),
+ 2usize => ("carry", Expr(self.carry())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ADD, SUB, AND, OR, XOR, LSL, LSR, ASR, ROL, ROR, MUL, MULU_DP, MULS_DP, DIVU, DIVU_DP, DIVS, DIVS_DP, MODU, MODU_DP, MODS, MODS_DP, CMP_E, CMP_NE, CMP_SLT, CMP_ULT, CMP_SLE, CMP_ULE, CMP_SGE, CMP_UGE, CMP_SGT, CMP_UGT, TEST_BIT, ADD_OVERFLOW, FADD, FSUB, FMUL, FDIV, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO
+#[derive(Clone)]
+pub struct BinaryOp {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ left: usize,
+ right: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedBinaryOp {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub left: Box<HighLevelILLiftedInstruction>,
+ pub right: Box<HighLevelILLiftedInstruction>,
+}
+impl BinaryOp {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ left: usize,
+ right: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ left,
+ right,
+ }
+ }
+ pub fn left(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.left)
+ }
+ pub fn right(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.right)
+ }
+ pub fn lift(&self) -> LiftedBinaryOp {
+ LiftedBinaryOp {
+ function: self.function.to_owned(),
+ address: self.address,
+ left: Box::new(self.left().lift()),
+ right: Box::new(self.right().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("left", Expr(self.left())),
+ 1usize => ("right", Expr(self.right())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ARRAY_INDEX
+#[derive(Clone)]
+pub struct ArrayIndex {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: usize,
+ index: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedArrayIndex {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub index: Box<HighLevelILLiftedInstruction>,
+}
+impl ArrayIndex {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ src: usize,
+ index: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ index,
+ }
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn index(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.index)
+ }
+ pub fn lift(&self) -> LiftedArrayIndex {
+ LiftedArrayIndex {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
+ index: Box::new(self.index().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("src", Expr(self.src())),
+ 1usize => ("index", Expr(self.index())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ARRAY_INDEX_SSA
+#[derive(Clone)]
+pub struct ArrayIndexSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: usize,
+ src_memory: u64,
+ index: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedArrayIndexSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub src_memory: u64,
+ pub index: Box<HighLevelILLiftedInstruction>,
+}
+impl ArrayIndexSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ src: usize,
+ src_memory: u64,
+ index: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ src_memory,
+ index,
+ }
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn index(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.index)
+ }
+ pub fn lift(&self) -> LiftedArrayIndexSsa {
+ LiftedArrayIndexSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
+ src_memory: self.src_memory,
+ index: Box::new(self.index().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("src", Expr(self.src())),
+ 1usize => ("src_memory", Int(self.src_memory())),
+ 2usize => ("index", Expr(self.index())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ASSIGN
+#[derive(Clone)]
+pub struct Assign {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: usize,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedAssign {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Box<HighLevelILLiftedInstruction>,
+ pub src: Box<HighLevelILLiftedInstruction>,
+}
+impl Assign {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: usize,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ src,
+ }
+ }
+ pub fn dest(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.dest)
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedAssign {
+ LiftedAssign {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
+ src: Box::new(self.src().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", Expr(self.dest())),
+ 1usize => ("src", Expr(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ASSIGN_MEM_SSA
+#[derive(Clone)]
+pub struct AssignMemSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: usize,
+ dest_memory: u64,
+ src: usize,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedAssignMemSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Box<HighLevelILLiftedInstruction>,
+ pub dest_memory: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub src_memory: u64,
+}
+impl AssignMemSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: usize,
+ dest_memory: u64,
+ src: usize,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ dest_memory,
+ src,
+ src_memory,
+ }
+ }
+ pub fn dest(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.dest)
+ }
+ pub fn dest_memory(&self) -> u64 {
+ self.dest_memory
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self) -> LiftedAssignMemSsa {
+ LiftedAssignMemSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
+ dest_memory: self.dest_memory,
+ src: Box::new(self.src().lift()),
+ src_memory: self.src_memory,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..4usize).map(move |i| match i {
+ 0usize => ("dest", Expr(self.dest())),
+ 1usize => ("dest_memory", Int(self.dest_memory())),
+ 2usize => ("src", Expr(self.src())),
+ 3usize => ("src_memory", Int(self.src_memory())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ASSIGN_UNPACK
+#[derive(Clone)]
+pub struct AssignUnpack {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: (usize, usize),
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedAssignUnpack {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Vec<HighLevelILLiftedInstruction>,
+ pub src: Box<HighLevelILLiftedInstruction>,
+}
+impl AssignUnpack {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: (usize, usize),
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ src,
+ }
+ }
+ pub fn dest(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.dest)
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedAssignUnpack {
+ LiftedAssignUnpack {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: self.dest().map(|x| x.lift()).collect(),
+ src: Box::new(self.src().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", ExprList(self.dest())),
+ 1usize => ("src", Expr(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// ASSIGN_UNPACK_MEM_SSA
+#[derive(Clone)]
+pub struct AssignUnpackMemSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: (usize, usize),
+ dest_memory: u64,
+ src: usize,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedAssignUnpackMemSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Vec<HighLevelILLiftedInstruction>,
+ pub dest_memory: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub src_memory: u64,
+}
+impl AssignUnpackMemSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: (usize, usize),
+ dest_memory: u64,
+ src: usize,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ dest_memory,
+ src,
+ src_memory,
+ }
+ }
+ pub fn dest(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.dest)
+ }
+ pub fn dest_memory(&self) -> u64 {
+ self.dest_memory
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self) -> LiftedAssignUnpackMemSsa {
+ LiftedAssignUnpackMemSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: self.dest().map(|x| x.lift()).collect(),
+ dest_memory: self.dest_memory,
+ src: Box::new(self.src().lift()),
+ src_memory: self.src_memory,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..4usize).map(move |i| match i {
+ 0usize => ("dest", ExprList(self.dest())),
+ 1usize => ("dest_memory", Int(self.dest_memory())),
+ 2usize => ("src", Expr(self.src())),
+ 3usize => ("src_memory", Int(self.src_memory())),
+ _ => unreachable!(),
+ })
+ }
+}
+// BLOCK
+#[derive(Clone)]
+pub struct Block {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ body: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedBlock {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub body: Vec<HighLevelILLiftedInstruction>,
+}
+impl Block {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ body: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ body,
+ }
+ }
+ pub fn body(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.body)
+ }
+ pub fn lift(&self) -> LiftedBlock {
+ LiftedBlock {
+ function: self.function.to_owned(),
+ address: self.address,
+ body: self.body().map(|x| x.lift()).collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("body", ExprList(self.body())),
+ _ => unreachable!(),
+ })
+ }
+}
+// CALL, TAILCALL
+#[derive(Clone)]
+pub struct Call {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: usize,
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCall {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Box<HighLevelILLiftedInstruction>,
+ pub params: Vec<HighLevelILLiftedInstruction>,
+}
+impl Call {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: usize,
+ params: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ params,
+ }
+ }
+ pub fn dest(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.dest)
+ }
+ pub fn params(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.params)
+ }
+ pub fn lift(&self) -> LiftedCall {
+ LiftedCall {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
+ params: self.params().map(|x| x.lift()).collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", Expr(self.dest())),
+ 1usize => ("params", ExprList(self.params())),
+ _ => unreachable!(),
+ })
+ }
+}
+// CALL_SSA
+#[derive(Clone)]
+pub struct CallSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: usize,
+ params: (usize, usize),
+ dest_memory: u64,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCallSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Box<HighLevelILLiftedInstruction>,
+ pub params: Vec<HighLevelILLiftedInstruction>,
+ pub dest_memory: u64,
+ pub src_memory: u64,
+}
+impl CallSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: usize,
+ params: (usize, usize),
+ dest_memory: u64,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ params,
+ dest_memory,
+ src_memory,
+ }
+ }
+ pub fn dest(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.dest)
+ }
+ pub fn params(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.params)
+ }
+ pub fn dest_memory(&self) -> u64 {
+ self.dest_memory
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self) -> LiftedCallSsa {
+ LiftedCallSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
+ params: self.params().map(|x| x.lift()).collect(),
+ dest_memory: self.dest_memory,
+ src_memory: self.src_memory,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..4usize).map(move |i| match i {
+ 0usize => ("dest", Expr(self.dest())),
+ 1usize => ("params", ExprList(self.params())),
+ 2usize => ("dest_memory", Int(self.dest_memory())),
+ 3usize => ("src_memory", Int(self.src_memory())),
+ _ => unreachable!(),
+ })
+ }
+}
+// CASE
+#[derive(Clone)]
+pub struct Case {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ values: (usize, usize),
+ body: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedCase {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub values: Vec<HighLevelILLiftedInstruction>,
+ pub body: Box<HighLevelILLiftedInstruction>,
+}
+impl Case {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ values: (usize, usize),
+ body: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ values,
+ body,
+ }
+ }
+ pub fn values(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.values)
+ }
+ pub fn body(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.body)
+ }
+ pub fn lift(&self) -> LiftedCase {
+ LiftedCase {
+ function: self.function.to_owned(),
+ address: self.address,
+ values: self.values().map(|x| x.lift()).collect(),
+ body: Box::new(self.body().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("values", ExprList(self.values())),
+ 1usize => ("body", Expr(self.body())),
+ _ => unreachable!(),
+ })
+ }
+}
+// CONST, CONST_PTR, IMPORT
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Const {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub constant: u64,
+}
+impl Const {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, constant: u64) -> Self {
+ Self {
+ function,
+ address,
+ constant,
+ }
+ }
+ pub fn constant(&self) -> u64 {
+ self.constant
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("constant", Int(self.constant())),
+ _ => unreachable!(),
+ })
+ }
+}
+// CONST_DATA
+#[derive(Clone)]
+pub struct ConstData {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ constant_data: (u32, u64, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedConstantData {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub constant_data: ConstantData,
+}
+impl ConstData {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ constant_data: (u32, u64, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ constant_data,
+ }
+ }
+ pub fn constant_data(&self) -> ConstantData {
+ let register_value = RegisterValue {
+ state: RegisterValueType::from_raw_value(self.constant_data.0).unwrap(),
+ value: self.constant_data.1 as i64,
+ offset: 0,
+ size: self.constant_data.2,
+ };
+ ConstantData::new(self.function.get_function(), register_value)
+ }
+ pub fn lift(&self) -> LiftedConstantData {
+ LiftedConstantData {
+ function: self.function.to_owned(),
+ address: self.address,
+ constant_data: self.constant_data(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("constant_data", ConstantData(self.constant_data())),
+ _ => unreachable!(),
+ })
+ }
+}
+// DEREF, ADDRESS_OF, NEG, NOT, SX, ZX, LOW_PART, BOOL_TO_INT, UNIMPL_MEM, FSQRT, FNEG, FABS, FLOAT_TO_INT, INT_TO_FLOAT, FLOAT_CONV, ROUND_TO_INT, FLOOR, CEIL, FTRUNC
+#[derive(Clone)]
+pub struct UnaryOp {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedUnaryOp {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+}
+impl UnaryOp {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, src: usize) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ }
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedUnaryOp {
+ LiftedUnaryOp {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("src", Expr(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// DEREF_FIELD_SSA
+#[derive(Clone)]
+pub struct DerefFieldSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: usize,
+ src_memory: u64,
+ offset: u64,
+ member_index: Option<usize>,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedDerefFieldSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub src_memory: u64,
+ pub offset: u64,
+ pub member_index: Option<usize>,
+}
+impl DerefFieldSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ src: usize,
+ src_memory: u64,
+ offset: u64,
+ member_index: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ src_memory,
+ offset,
+ member_index: get_member_index(member_index),
+ }
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn member_index(&self) -> Option<usize> {
+ self.member_index
+ }
+ pub fn lift(&self) -> LiftedDerefFieldSsa {
+ LiftedDerefFieldSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
+ src_memory: self.src_memory,
+ offset: self.offset,
+ member_index: self.member_index,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..4usize).map(move |i| match i {
+ 0usize => ("src", Expr(self.src())),
+ 1usize => ("src_memory", Int(self.src_memory())),
+ 2usize => ("offset", Int(self.offset())),
+ 3usize => ("member_index", MemberIndex(self.member_index())),
+ _ => unreachable!(),
+ })
+ }
+}
+// DEREF_SSA
+#[derive(Clone)]
+pub struct DerefSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: usize,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedDerefSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub src_memory: u64,
+}
+impl DerefSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ src: usize,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ src_memory,
+ }
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self) -> LiftedDerefSsa {
+ LiftedDerefSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
+ src_memory: self.src_memory,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("src", Expr(self.src())),
+ 1usize => ("src_memory", Int(self.src_memory())),
+ _ => unreachable!(),
+ })
+ }
+}
+// EXTERN_PTR
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct ExternPtr {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub constant: u64,
+ pub offset: u64,
+}
+impl ExternPtr {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ constant: u64,
+ offset: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ constant,
+ offset,
+ }
+ }
+ pub fn constant(&self) -> u64 {
+ self.constant
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("constant", Int(self.constant())),
+ 1usize => ("offset", Int(self.offset())),
+ _ => unreachable!(),
+ })
+ }
+}
+// FLOAT_CONST
+#[derive(Clone, Debug, PartialEq)]
+pub struct FloatConst {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub constant: f64,
+}
+impl FloatConst {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ constant: u64,
+ size: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ constant: get_float(constant, size),
+ }
+ }
+ pub fn constant(&self) -> f64 {
+ self.constant
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("constant", Float(self.constant())),
+ _ => unreachable!(),
+ })
+ }
+}
+// FOR
+#[derive(Clone)]
+pub struct ForLoop {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ init: usize,
+ condition: usize,
+ update: usize,
+ body: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedForLoop {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub init: Box<HighLevelILLiftedInstruction>,
+ pub condition: Box<HighLevelILLiftedInstruction>,
+ pub update: Box<HighLevelILLiftedInstruction>,
+ pub body: Box<HighLevelILLiftedInstruction>,
+}
+impl ForLoop {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ init: usize,
+ condition: usize,
+ update: usize,
+ body: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ init,
+ condition,
+ update,
+ body,
+ }
+ }
+ pub fn init(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.init)
+ }
+ pub fn condition(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition)
+ }
+ pub fn update(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.update)
+ }
+ pub fn body(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.body)
+ }
+ pub fn lift(&self) -> LiftedForLoop {
+ LiftedForLoop {
+ function: self.function.to_owned(),
+ address: self.address,
+ init: Box::new(self.init().lift()),
+ condition: Box::new(self.condition().lift()),
+ update: Box::new(self.update().lift()),
+ body: Box::new(self.body().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..4usize).map(move |i| match i {
+ 0usize => ("init", Expr(self.init())),
+ 1usize => ("condition", Expr(self.condition())),
+ 2usize => ("update", Expr(self.update())),
+ 3usize => ("body", Expr(self.body())),
+ _ => unreachable!(),
+ })
+ }
+}
+// FOR_SSA
+#[derive(Clone)]
+pub struct ForLoopSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ init: usize,
+ condition_phi: usize,
+ condition: usize,
+ update: usize,
+ body: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedForLoopSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub init: Box<HighLevelILLiftedInstruction>,
+ pub condition_phi: Box<HighLevelILLiftedInstruction>,
+ pub condition: Box<HighLevelILLiftedInstruction>,
+ pub update: Box<HighLevelILLiftedInstruction>,
+ pub body: Box<HighLevelILLiftedInstruction>,
+}
+impl ForLoopSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ init: usize,
+ condition_phi: usize,
+ condition: usize,
+ update: usize,
+ body: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ init,
+ condition_phi,
+ condition,
+ update,
+ body,
+ }
+ }
+ pub fn init(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.init)
+ }
+ pub fn condition_phi(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition_phi)
+ }
+ pub fn condition(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition)
+ }
+ pub fn update(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.update)
+ }
+ pub fn body(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.body)
+ }
+ pub fn lift(&self) -> LiftedForLoopSsa {
+ LiftedForLoopSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ init: Box::new(self.init().lift()),
+ condition_phi: Box::new(self.condition_phi().lift()),
+ condition: Box::new(self.condition().lift()),
+ update: Box::new(self.update().lift()),
+ body: Box::new(self.body().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..5usize).map(move |i| match i {
+ 0usize => ("init", Expr(self.init())),
+ 1usize => ("condition_phi", Expr(self.condition_phi())),
+ 2usize => ("condition", Expr(self.condition())),
+ 3usize => ("update", Expr(self.update())),
+ 4usize => ("body", Expr(self.body())),
+ _ => unreachable!(),
+ })
+ }
+}
+// GOTO, LABEL
+#[derive(Clone, Debug, PartialEq)]
+pub struct Label {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub target: u64,
+}
+impl Label {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, target: u64) -> Self {
+ Self {
+ function,
+ address,
+ target,
+ }
+ }
+ pub fn target(&self) -> GotoLabel {
+ GotoLabel {
+ function: self.function.get_function(),
+ target: self.target,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("target", Label(self.target())),
+ _ => unreachable!(),
+ })
+ }
+}
+// IF
+#[derive(Clone)]
+pub struct If {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ condition: usize,
+ cond_true: usize,
+ cond_false: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedIf {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub condition: Box<HighLevelILLiftedInstruction>,
+ pub cond_true: Box<HighLevelILLiftedInstruction>,
+ pub cond_false: Box<HighLevelILLiftedInstruction>,
+}
+impl If {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ condition: usize,
+ cond_true: usize,
+ cond_false: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ condition,
+ cond_true,
+ cond_false,
+ }
+ }
+ pub fn condition(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition)
+ }
+ pub fn cond_true(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.cond_true)
+ }
+ pub fn cond_false(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.cond_false)
+ }
+ pub fn lift(&self) -> LiftedIf {
+ LiftedIf {
+ function: self.function.to_owned(),
+ address: self.address,
+ condition: Box::new(self.condition().lift()),
+ cond_true: Box::new(self.cond_true().lift()),
+ cond_false: Box::new(self.cond_false().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("condition", Expr(self.condition())),
+ 1usize => ("cond_true", Expr(self.cond_true())),
+ 2usize => ("cond_false", Expr(self.cond_false())),
+ _ => unreachable!(),
+ })
+ }
+}
+// INTRINSIC
+#[derive(Clone)]
+pub struct Intrinsic {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ intrinsic: u32,
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedIntrinsic {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub intrinsic: ILIntrinsic,
+ pub params: Vec<HighLevelILLiftedInstruction>,
+}
+impl Intrinsic {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ intrinsic: u32,
+ params: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ intrinsic,
+ params,
+ }
+ }
+ pub fn intrinsic(&self) -> ILIntrinsic {
+ ILIntrinsic::new(self.function.get_function().arch(), self.intrinsic)
+ }
+ pub fn params(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.params)
+ }
+ pub fn lift(&self) -> LiftedIntrinsic {
+ LiftedIntrinsic {
+ function: self.function.to_owned(),
+ address: self.address,
+ intrinsic: self.intrinsic(),
+ params: self.params().map(|x| x.lift()).collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("intrinsic", Intrinsic(self.intrinsic())),
+ 1usize => ("params", ExprList(self.params())),
+ _ => unreachable!(),
+ })
+ }
+}
+// INTRINSIC_SSA
+#[derive(Clone)]
+pub struct IntrinsicSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ intrinsic: u32,
+ params: (usize, usize),
+ dest_memory: u64,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedIntrinsicSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub intrinsic: ILIntrinsic,
+ pub params: Vec<HighLevelILLiftedInstruction>,
+ pub dest_memory: u64,
+ pub src_memory: u64,
+}
+impl IntrinsicSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ intrinsic: u32,
+ params: (usize, usize),
+ dest_memory: u64,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ intrinsic,
+ params,
+ dest_memory,
+ src_memory,
+ }
+ }
+ pub fn intrinsic(&self) -> ILIntrinsic {
+ ILIntrinsic::new(self.function.get_function().arch(), self.intrinsic)
+ }
+ pub fn params(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.params)
+ }
+ pub fn dest_memory(&self) -> u64 {
+ self.dest_memory
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self) -> LiftedIntrinsicSsa {
+ LiftedIntrinsicSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ intrinsic: self.intrinsic(),
+ params: self.params().map(|x| x.lift()).collect(),
+ dest_memory: self.dest_memory,
+ src_memory: self.src_memory,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..4usize).map(move |i| match i {
+ 0usize => ("intrinsic", Intrinsic(self.intrinsic())),
+ 1usize => ("params", ExprList(self.params())),
+ 2usize => ("dest_memory", Int(self.dest_memory())),
+ 3usize => ("src_memory", Int(self.src_memory())),
+ _ => unreachable!(),
+ })
+ }
+}
+// JUMP
+#[derive(Clone, Debug, PartialEq)]
+pub struct Jump {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: usize,
+}
+impl Jump {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, dest: usize) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ }
+ }
+ pub fn dest(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.dest)
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("dest", Expr(self.dest())),
+ _ => unreachable!(),
+ })
+ }
+}
+// MEM_PHI
+#[derive(Clone)]
+pub struct MemPhi {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: u64,
+ src: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedMemPhi {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: u64,
+ pub src: Vec<u64>,
+}
+impl MemPhi {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: u64,
+ src: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ src,
+ }
+ }
+ pub fn dest(&self) -> u64 {
+ self.dest
+ }
+ pub fn src(&self) -> OperandList {
+ get_int_list(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedMemPhi {
+ LiftedMemPhi {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: self.dest,
+ src: self.src().collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", Int(self.dest())),
+ 1usize => ("src", IntList(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// NOP, BREAK, CONTINUE, NORET, UNREACHABLE, BP, UNDEF, UNIMPL
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct NoArgs {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+}
+impl NoArgs {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64) -> Self {
+ Self { function, address }
+ }
+ // NOTE self is not required, it's present just in case data is added to
+ // the struct in the future
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ [].into_iter()
+ }
+}
+// RET
+#[derive(Clone)]
+pub struct Ret {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedRet {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Vec<HighLevelILLiftedInstruction>,
+}
+impl Ret {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ src: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ }
+ }
+ pub fn src(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedRet {
+ LiftedRet {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: self.src().map(|x| x.lift()).collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("src", ExprList(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// SPLIT
+#[derive(Clone)]
+pub struct Split {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ high: usize,
+ low: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSplit {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub high: Box<HighLevelILLiftedInstruction>,
+ pub low: Box<HighLevelILLiftedInstruction>,
+}
+impl Split {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ high: usize,
+ low: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ high,
+ low,
+ }
+ }
+ pub fn high(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.high)
+ }
+ pub fn low(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.low)
+ }
+ pub fn lift(&self) -> LiftedSplit {
+ LiftedSplit {
+ function: self.function.to_owned(),
+ address: self.address,
+ high: Box::new(self.high().lift()),
+ low: Box::new(self.low().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("high", Expr(self.high())),
+ 1usize => ("low", Expr(self.low())),
+ _ => unreachable!(),
+ })
+ }
+}
+// STRUCT_FIELD, DEREF_FIELD
+#[derive(Clone)]
+pub struct StructField {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ src: usize,
+ offset: u64,
+ member_index: Option<usize>,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedStructField {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub src: Box<HighLevelILLiftedInstruction>,
+ pub offset: u64,
+ pub member_index: Option<usize>,
+}
+impl StructField {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ src: usize,
+ offset: u64,
+ member_index: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ offset,
+ member_index: get_member_index(member_index),
+ }
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn offset(&self) -> u64 {
+ self.offset
+ }
+ pub fn member_index(&self) -> Option<usize> {
+ self.member_index
+ }
+ pub fn lift(&self) -> LiftedStructField {
+ LiftedStructField {
+ function: self.function.to_owned(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
+ offset: self.offset,
+ member_index: self.member_index,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("src", Expr(self.src())),
+ 1usize => ("offset", Int(self.offset())),
+ 2usize => ("member_index", MemberIndex(self.member_index())),
+ _ => unreachable!(),
+ })
+ }
+}
+// SWITCH
+#[derive(Clone)]
+pub struct Switch {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ condition: usize,
+ default: usize,
+ cases: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSwitch {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub condition: Box<HighLevelILLiftedInstruction>,
+ pub default: Box<HighLevelILLiftedInstruction>,
+ pub cases: Vec<HighLevelILLiftedInstruction>,
+}
+impl Switch {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ condition: usize,
+ default: usize,
+ cases: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ condition,
+ default,
+ cases,
+ }
+ }
+ pub fn condition(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition)
+ }
+ pub fn default(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.default)
+ }
+ pub fn cases(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.cases)
+ }
+ pub fn lift(&self) -> LiftedSwitch {
+ LiftedSwitch {
+ function: self.function.to_owned(),
+ address: self.address,
+ condition: Box::new(self.condition().lift()),
+ default: Box::new(self.default().lift()),
+ cases: self.cases().map(|x| x.lift()).collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("condition", Expr(self.condition())),
+ 1usize => ("default", Expr(self.default())),
+ 2usize => ("cases", ExprList(self.cases())),
+ _ => unreachable!(),
+ })
+ }
+}
+// SYSCALL
+#[derive(Clone)]
+pub struct Syscall {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ params: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSyscall {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub params: Vec<HighLevelILLiftedInstruction>,
+}
+impl Syscall {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ params: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ params,
+ }
+ }
+ pub fn params(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.params)
+ }
+ pub fn lift(&self) -> LiftedSyscall {
+ LiftedSyscall {
+ function: self.function.to_owned(),
+ address: self.address,
+ params: self.params().map(|x| x.lift()).collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("params", ExprList(self.params())),
+ _ => unreachable!(),
+ })
+ }
+}
+// SYSCALL_SSA
+#[derive(Clone)]
+pub struct SyscallSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ params: (usize, usize),
+ dest_memory: u64,
+ src_memory: u64,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedSyscallSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub params: Vec<HighLevelILLiftedInstruction>,
+ pub dest_memory: u64,
+ pub src_memory: u64,
+}
+impl SyscallSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ params: (usize, usize),
+ dest_memory: u64,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ params,
+ dest_memory,
+ src_memory,
+ }
+ }
+ pub fn params(&self) -> OperandExprList {
+ get_instruction_list(&self.function, self.params)
+ }
+ pub fn dest_memory(&self) -> u64 {
+ self.dest_memory
+ }
+ pub fn src_memory(&self) -> u64 {
+ self.src_memory
+ }
+ pub fn lift(&self) -> LiftedSyscallSsa {
+ LiftedSyscallSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ params: self.params().map(|x| x.lift()).collect(),
+ dest_memory: self.dest_memory,
+ src_memory: self.src_memory,
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("params", ExprList(self.params())),
+ 1usize => ("dest_memory", Int(self.dest_memory())),
+ 2usize => ("src_memory", Int(self.src_memory())),
+ _ => unreachable!(),
+ })
+ }
+}
+// TRAP
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Trap {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub vector: u64,
+}
+impl Trap {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, vector: u64) -> Self {
+ Self {
+ function,
+ address,
+ vector,
+ }
+ }
+ pub fn vector(&self) -> u64 {
+ self.vector
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("vector", Int(self.vector())),
+ _ => unreachable!(),
+ })
+ }
+}
+// VAR_DECLARE, VAR
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct Var {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub var: Variable,
+}
+impl Var {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, var: u64) -> Self {
+ Self {
+ function,
+ address,
+ var: get_var(var),
+ }
+ }
+ pub fn var(&self) -> Variable {
+ self.var
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("var", Var(self.var())),
+ _ => unreachable!(),
+ })
+ }
+}
+// VAR_INIT
+#[derive(Clone)]
+pub struct VarInit {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: Variable,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedVarInit {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: Variable,
+ pub src: Box<HighLevelILLiftedInstruction>,
+}
+impl VarInit {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: u64,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest: get_var(dest),
+ src,
+ }
+ }
+ pub fn dest(&self) -> Variable {
+ self.dest
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedVarInit {
+ LiftedVarInit {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: self.dest,
+ src: Box::new(self.src().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", Var(self.dest())),
+ 1usize => ("src", Expr(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// VAR_INIT_SSA
+#[derive(Clone)]
+pub struct VarInitSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: SSAVariable,
+ src: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedVarInitSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: SSAVariable,
+ pub src: Box<HighLevelILLiftedInstruction>,
+}
+impl VarInitSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest: get_var_ssa(dest),
+ src,
+ }
+ }
+ pub fn dest(&self) -> SSAVariable {
+ self.dest
+ }
+ pub fn src(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedVarInitSsa {
+ LiftedVarInitSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: self.dest,
+ src: Box::new(self.src().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", VarSsa(self.dest())),
+ 1usize => ("src", Expr(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// VAR_PHI
+#[derive(Clone)]
+pub struct VarPhi {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ dest: SSAVariable,
+ src: (usize, usize),
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedVarPhi {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub dest: SSAVariable,
+ pub src: Vec<SSAVariable>,
+}
+impl VarPhi {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ src: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest: get_var_ssa(dest),
+ src,
+ }
+ }
+ pub fn dest(&self) -> SSAVariable {
+ self.dest
+ }
+ pub fn src(&self) -> OperandSSAVariableList {
+ get_var_ssa_list(&self.function, self.src)
+ }
+ pub fn lift(&self) -> LiftedVarPhi {
+ LiftedVarPhi {
+ function: self.function.to_owned(),
+ address: self.address,
+ dest: self.dest,
+ src: self.src().collect(),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("dest", VarSsa(self.dest())),
+ 1usize => ("src", VarSsaList(self.src())),
+ _ => unreachable!(),
+ })
+ }
+}
+// VAR_SSA
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct VarSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub var: SSAVariable,
+}
+impl VarSsa {
+ pub(crate) fn new(function: Ref<HighLevelILFunction>, address: u64, var: (u64, usize)) -> Self {
+ Self {
+ function,
+ address,
+ var: get_var_ssa(var),
+ }
+ }
+ pub fn var(&self) -> SSAVariable {
+ self.var
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..1usize).map(move |i| match i {
+ 0usize => ("var", VarSsa(self.var())),
+ _ => unreachable!(),
+ })
+ }
+}
+// WHILE, DO_WHILE
+#[derive(Clone)]
+pub struct While {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ condition: usize,
+ body: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedWhile {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub condition: Box<HighLevelILLiftedInstruction>,
+ pub body: Box<HighLevelILLiftedInstruction>,
+}
+impl While {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ condition: usize,
+ body: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ condition,
+ body,
+ }
+ }
+ pub fn condition(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition)
+ }
+ pub fn body(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.body)
+ }
+ pub fn lift(&self) -> LiftedWhile {
+ LiftedWhile {
+ function: self.function.to_owned(),
+ address: self.address,
+ condition: Box::new(self.condition().lift()),
+ body: Box::new(self.body().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..2usize).map(move |i| match i {
+ 0usize => ("condition", Expr(self.condition())),
+ 1usize => ("body", Expr(self.body())),
+ _ => unreachable!(),
+ })
+ }
+}
+// WHILE_SSA, DO_WHILE_SSA
+#[derive(Clone)]
+pub struct WhileSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ condition_phi: usize,
+ condition: usize,
+ body: usize,
+}
+#[derive(Clone, Debug, PartialEq)]
+pub struct LiftedWhileSsa {
+ pub function: Ref<HighLevelILFunction>,
+ pub address: u64,
+ pub condition_phi: Box<HighLevelILLiftedInstruction>,
+ pub condition: Box<HighLevelILLiftedInstruction>,
+ pub body: Box<HighLevelILLiftedInstruction>,
+}
+impl WhileSsa {
+ pub(crate) fn new(
+ function: Ref<HighLevelILFunction>,
+ address: u64,
+ condition_phi: usize,
+ condition: usize,
+ body: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ condition_phi,
+ condition,
+ body,
+ }
+ }
+ pub fn condition_phi(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition_phi)
+ }
+ pub fn condition(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.condition)
+ }
+ pub fn body(&self) -> HighLevelILInstruction {
+ get_instruction(&self.function, self.body)
+ }
+ pub fn lift(&self) -> LiftedWhileSsa {
+ LiftedWhileSsa {
+ function: self.function.to_owned(),
+ address: self.address,
+ condition_phi: Box::new(self.condition_phi().lift()),
+ condition: Box::new(self.condition().lift()),
+ body: Box::new(self.body().lift()),
+ }
+ }
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, HighLevelILOperand)> + '_ {
+ use HighLevelILOperand::*;
+ (0..3usize).map(move |i| match i {
+ 0usize => ("condition_phi", Expr(self.condition_phi())),
+ 1usize => ("condition", Expr(self.condition())),
+ 2usize => ("body", Expr(self.body())),
+ _ => unreachable!(),
+ })
+ }
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index fa33439f..d5190890 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -145,6 +145,7 @@ pub mod flowgraph;
pub mod function;
pub mod functionrecognizer;
pub mod headless;
+pub mod hlil;
pub mod interaction;
pub mod linearview;
pub mod llil;
diff --git a/rust/src/llil/function.rs b/rust/src/llil/function.rs
index 46d3e6d1..f0aba63a 100644
--- a/rust/src/llil/function.rs
+++ b/rust/src/llil/function.rs
@@ -13,6 +13,7 @@
// limitations under the License.
use binaryninjacore_sys::BNFreeLowLevelILFunction;
+use binaryninjacore_sys::BNGetLowLevelILOwnerFunction;
use binaryninjacore_sys::BNLowLevelILFunction;
use binaryninjacore_sys::BNNewLowLevelILFunctionReference;
@@ -65,14 +66,14 @@ unsafe impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Sync for Fu
impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Eq for Function<A, M, F> {}
impl<A: Architecture, M: FunctionMutability, F: FunctionForm> PartialEq for Function<A, M, F> {
fn eq(&self, rhs: &Self) -> bool {
- self.handle == rhs.handle
+ self.get_function().eq(&rhs.get_function())
}
}
use std::hash::{Hash, Hasher};
impl<A: Architecture, M: FunctionMutability, F: FunctionForm> Hash for Function<A, M, F> {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.handle.hash(state);
+ self.get_function().hash(state)
}
}
@@ -82,7 +83,10 @@ where
M: FunctionMutability,
F: FunctionForm,
{
- pub(crate) unsafe fn from_raw(borrower: A::Handle, handle: *mut BNLowLevelILFunction) -> Self {
+ pub(crate) unsafe fn from_raw(
+ borrower: A::Handle,
+ handle: *mut BNLowLevelILFunction,
+ ) -> Ref<Self> {
debug_assert!(!handle.is_null());
Self {
@@ -92,6 +96,7 @@ where
_mutability: PhantomData,
_form: PhantomData,
}
+ .to_owned()
}
pub(crate) fn arch(&self) -> &A {
@@ -139,6 +144,13 @@ where
BNGetLowLevelILInstructionCount(self.handle)
}
}
+
+ pub fn get_function(&self) -> Ref<crate::function::Function> {
+ unsafe {
+ let func = BNGetLowLevelILOwnerFunction(self.handle);
+ crate::function::Function::from_raw(func)
+ }
+ }
}
// LLIL basic blocks are not available until the function object
diff --git a/rust/src/mlil/block.rs b/rust/src/mlil/block.rs
index 734d6512..015c7ba4 100644
--- a/rust/src/mlil/block.rs
+++ b/rust/src/mlil/block.rs
@@ -21,7 +21,7 @@ impl Iterator for MediumLevelILBlockIter {
.map(|i| unsafe {
BNGetMediumLevelILIndexForInstruction(self.function.handle, i as usize)
})
- .map(|i| MediumLevelILInstruction::new(&self.function, i))
+ .map(|i| MediumLevelILInstruction::new(self.function.to_owned(), i))
}
}
@@ -43,7 +43,7 @@ impl BlockContext for MediumLevelILBlock {
let expr_idx = unsafe {
BNGetMediumLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize)
};
- MediumLevelILInstruction::new(&self.function, expr_idx)
+ MediumLevelILInstruction::new(self.function.to_owned(), expr_idx)
}
fn iter(&self, block: &BasicBlock<Self>) -> MediumLevelILBlockIter {
diff --git a/rust/src/mlil/function.rs b/rust/src/mlil/function.rs
index 63c63a34..8f5ed73d 100644
--- a/rust/src/mlil/function.rs
+++ b/rust/src/mlil/function.rs
@@ -26,21 +26,21 @@ unsafe impl Sync for MediumLevelILFunction {}
impl Eq for MediumLevelILFunction {}
impl PartialEq for MediumLevelILFunction {
fn eq(&self, rhs: &Self) -> bool {
- self.handle == rhs.handle
+ self.get_function().eq(&rhs.get_function())
}
}
impl Hash for MediumLevelILFunction {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.handle.hash(state);
+ self.get_function().hash(state)
}
}
impl MediumLevelILFunction {
- pub(crate) unsafe fn from_raw(handle: *mut BNMediumLevelILFunction) -> Self {
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNMediumLevelILFunction) -> Ref<Self> {
debug_assert!(!handle.is_null());
- Self { handle }
+ Self { handle }.to_owned()
}
pub fn instruction_at<L: Into<Location>>(&self, loc: L) -> Option<MediumLevelILInstruction> {
@@ -53,12 +53,12 @@ impl MediumLevelILFunction {
if expr_idx >= self.instruction_count() {
None
} else {
- Some(MediumLevelILInstruction::new(self, expr_idx))
+ Some(MediumLevelILInstruction::new(self.to_owned(), expr_idx))
}
}
pub fn instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILInstruction {
- MediumLevelILInstruction::new(self, expr_idx)
+ MediumLevelILInstruction::new(self.to_owned(), expr_idx)
}
pub fn instruction_count(&self) -> usize {
diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs
index 139abe20..438708db 100644
--- a/rust/src/mlil/instruction.rs
+++ b/rust/src/mlil/instruction.rs
@@ -1,21 +1,14 @@
use binaryninjacore_sys::BNGetMediumLevelILByIndex;
use binaryninjacore_sys::BNMediumLevelILOperation;
-use crate::mlil::MediumLevelILLiftedOperation;
+use crate::mlil::MediumLevelILLiftedInstruction;
use crate::rc::Ref;
use super::operation::*;
-use super::{MediumLevelILFunction, MediumLevelILLiftedInstruction};
+use super::MediumLevelILFunction;
#[derive(Clone)]
-pub struct MediumLevelILInstruction {
- pub(crate) function: Ref<MediumLevelILFunction>,
- pub(crate) address: u64,
- pub(crate) operation: MediumLevelILOperation,
-}
-
-#[derive(Copy, Clone)]
-pub enum MediumLevelILOperation {
+pub enum MediumLevelILInstruction {
Nop(NoArgs),
Noret(NoArgs),
Bp(NoArgs),
@@ -27,7 +20,7 @@ pub enum MediumLevelILOperation {
ConstPtr(Constant),
Import(Constant),
ExternPtr(ExternPtr),
- ConstData(ConstData),
+ ConstData(ConstantData),
Jump(Jump),
RetHint(Jump),
StoreSsa(StoreSsa),
@@ -154,42 +147,63 @@ impl core::fmt::Debug for MediumLevelILInstruction {
f,
"<{} at 0x{:08}>",
core::any::type_name::<Self>(),
- self.address,
+ self.address(),
)
}
}
impl MediumLevelILInstruction {
- pub(crate) fn new(function: &MediumLevelILFunction, idx: usize) -> Self {
+ pub(crate) fn new(function: Ref<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()),
+ use MediumLevelILInstruction as Op;
+ match op.operation {
+ MLIL_NOP => Op::Nop(NoArgs::new(function, op.address)),
+ MLIL_NORET => Op::Noret(NoArgs::new(function, op.address)),
+ MLIL_BP => Op::Bp(NoArgs::new(function, op.address)),
+ MLIL_UNDEF => Op::Undef(NoArgs::new(function, op.address)),
+ MLIL_UNIMPL => Op::Unimpl(NoArgs::new(function, op.address)),
MLIL_IF => Op::If(MediumLevelILOperationIf::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
)),
- MLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(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_FLOAT_CONST => Op::FloatConst(FloatConst::new(
+ function,
+ op.address,
+ op.operands[0],
+ op.size,
+ )),
+ MLIL_CONST => Op::Const(Constant::new(function, op.address, op.operands[0])),
+ MLIL_CONST_PTR => Op::ConstPtr(Constant::new(function, op.address, op.operands[0])),
+ MLIL_IMPORT => Op::Import(Constant::new(function, op.address, op.operands[0])),
+ MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(
+ function,
+ op.address,
+ op.operands[0],
+ op.operands[1],
+ )),
+ MLIL_CONST_DATA => Op::ConstData(ConstantData::new(
+ function,
+ op.address,
+ (op.operands[0], op.operands[1]),
+ op.size,
+ )),
+ MLIL_JUMP => Op::Jump(Jump::new(function, op.address, op.operands[0] as usize)),
+ MLIL_RET_HINT => Op::RetHint(Jump::new(function, op.address, op.operands[0] as usize)),
MLIL_STORE_SSA => Op::StoreSsa(StoreSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
op.operands[3] as usize,
)),
MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
@@ -197,623 +211,1093 @@ impl MediumLevelILInstruction {
op.operands[4] as usize,
)),
MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2] as usize,
)),
- MLIL_STORE => Op::Store(Store::new(op.operands[0] as usize, op.operands[1] as usize)),
+ MLIL_STORE => Op::Store(Store::new(
+ function,
+ op.address,
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ )),
MLIL_JUMP_TO => Op::JumpTo(JumpTo::new(
+ function,
+ op.address,
op.operands[0] as usize,
(op.operands[1] as usize, op.operands[2] as usize),
)),
- MLIL_GOTO => Op::Goto(Goto::new(op.operands[0])),
- MLIL_FREE_VAR_SLOT => Op::FreeVarSlot(FreeVarSlot::new(op.operands[0])),
+ MLIL_GOTO => Op::Goto(Goto::new(function, op.address, op.operands[0])),
+ MLIL_FREE_VAR_SLOT => {
+ Op::FreeVarSlot(FreeVarSlot::new(function, op.address, op.operands[0]))
+ }
MLIL_SET_VAR_FIELD => Op::SetVarField(SetVarField::new(
+ function,
+ op.address,
op.operands[0],
op.operands[1],
op.operands[2] as usize,
)),
- MLIL_SET_VAR => Op::SetVar(SetVar::new(op.operands[0], op.operands[1] as usize)),
+ MLIL_SET_VAR => Op::SetVar(SetVar::new(
+ function,
+ op.address,
+ op.operands[0],
+ op.operands[1] as usize,
+ )),
MLIL_FREE_VAR_SLOT_SSA => Op::FreeVarSlotSsa(FreeVarSlotSsa::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
)),
MLIL_SET_VAR_SSA_FIELD => Op::SetVarSsaField(SetVarSsaField::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
op.operands[3],
op.operands[4] as usize,
)),
MLIL_SET_VAR_ALIASED_FIELD => Op::SetVarAliasedField(SetVarSsaField::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
op.operands[3],
op.operands[4] as usize,
)),
MLIL_SET_VAR_ALIASED => Op::SetVarAliased(SetVarAliased::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
op.operands[3] as usize,
)),
MLIL_SET_VAR_SSA => Op::SetVarSsa(SetVarSsa::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
op.operands[2] as usize,
)),
MLIL_VAR_PHI => Op::VarPhi(VarPhi::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[2] as usize, op.operands[3] as usize),
)),
MLIL_MEM_PHI => Op::MemPhi(MemPhi::new(
+ function,
+ op.address,
op.operands[0],
(op.operands[1] as usize, op.operands[2] as usize),
)),
- MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new(op.operands[0], op.operands[1])),
+ MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new(
+ function,
+ op.address,
+ op.operands[0],
+ op.operands[1],
+ )),
MLIL_SET_VAR_SPLIT => Op::SetVarSplit(SetVarSplit::new(
+ function,
+ op.address,
op.operands[0],
op.operands[1],
op.operands[2] as usize,
)),
MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[2], op.operands[3] as usize),
)),
MLIL_SET_VAR_SPLIT_SSA => Op::SetVarSplitSsa(SetVarSplitSsa::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[2], op.operands[3] as usize),
op.operands[4] as usize,
)),
MLIL_ADD => Op::Add(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_SUB => Op::Sub(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_AND => Op::And(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_OR => Op::Or(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_XOR => Op::Xor(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_LSL => Op::Lsl(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_LSR => Op::Lsr(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ASR => Op::Asr(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ROL => Op::Rol(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ROR => Op::Ror(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MUL => Op::Mul(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MULU_DP => Op::MuluDp(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MULS_DP => Op::MulsDp(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVU => Op::Divu(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVU_DP => Op::DivuDp(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVS => Op::Divs(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVS_DP => Op::DivsDp(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODU => Op::Modu(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODU_DP => Op::ModuDp(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODS => Op::Mods(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODS_DP => Op::ModsDp(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_E => Op::CmpE(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_NE => Op::CmpNe(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SLE => Op::CmpSle(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_ULE => Op::CmpUle(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SGE => Op::CmpSge(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_UGE => Op::CmpUge(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_TEST_BIT => Op::TestBit(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_E => Op::FcmpE(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_O => Op::FcmpO(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FADD => Op::Fadd(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FSUB => Op::Fsub(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FMUL => Op::Fmul(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FDIV => Op::Fdiv(BinaryOp::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ADC => Op::Adc(BinaryOpCarry::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_SBB => Op::Sbb(BinaryOpCarry::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_RLC => Op::Rlc(BinaryOpCarry::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_RRC => Op::Rrc(BinaryOpCarry::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_CALL => Op::Call(Call::new(
+ function,
+ op.address,
(op.operands[0] as usize, op.operands[1] as usize),
op.operands[2] as usize,
(op.operands[3] as usize, op.operands[4] as usize),
)),
MLIL_TAILCALL => Op::Tailcall(Call::new(
+ function,
+ op.address,
(op.operands[0] as usize, op.operands[1] as usize),
op.operands[2] as usize,
(op.operands[3] as usize, op.operands[4] as usize),
)),
MLIL_SYSCALL => Op::Syscall(Syscall::new(
+ function,
+ op.address,
(op.operands[0] as usize, op.operands[1] as usize),
(op.operands[2] as usize, op.operands[3] as usize),
)),
MLIL_INTRINSIC => Op::Intrinsic(Intrinsic::new(
+ function,
+ op.address,
(op.operands[0] as usize, op.operands[1] as usize),
- op.operands[2] as usize,
+ op.operands[2] as u32,
(op.operands[3] as usize, op.operands[4] as usize),
)),
MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new(
+ function,
+ op.address,
(op.operands[0] as usize, op.operands[1] as usize),
- op.operands[2] as usize,
+ op.operands[2] as u32,
(op.operands[3] as usize, op.operands[4] as usize),
)),
MLIL_CALL_SSA => Op::CallSsa(CallSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
(op.operands[2] as usize, op.operands[3] as usize),
op.operands[4],
)),
MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
(op.operands[2] as usize, op.operands[3] as usize),
op.operands[4],
)),
MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_TAILCALL_UNTYPED_SSA => Op::TailcallUntypedSsa(CallUntypedSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
(op.operands[1] as usize, op.operands[2] as usize),
op.operands[3],
)),
MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList::new(
- (op.operands[0] as usize, op.operands[1] as usize)
+ function,
+ op.address,
+ (op.operands[0] as usize, op.operands[1] as usize),
)),
MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot::new(
- (op.operands[0] as usize, op.operands[1] as usize)
+ function,
+ op.address,
+ (op.operands[0] as usize, op.operands[1] 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_NEG => Op::Neg(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_NOT => Op::Not(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_SX => Op::Sx(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_ZX => Op::Zx(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_LOW_PART => {
+ Op::LowPart(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ }
+ MLIL_BOOL_TO_INT => {
+ Op::BoolToInt(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ }
+ MLIL_UNIMPL_MEM => {
+ Op::UnimplMem(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ }
+ MLIL_FSQRT => Op::Fsqrt(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_FNEG => Op::Fneg(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_FABS => Op::Fabs(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_FLOAT_TO_INT => {
+ Op::FloatToInt(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ }
+ MLIL_INT_TO_FLOAT => {
+ Op::IntToFloat(UnaryOp::new(function, op.address, op.operands[0] as usize))
}
+ MLIL_FLOAT_CONV => {
+ Op::FloatConv(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ }
+ MLIL_ROUND_TO_INT => {
+ Op::RoundToInt(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ }
+ MLIL_FLOOR => Op::Floor(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_CEIL => Op::Ceil(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_LOAD => Op::Load(UnaryOp::new(function, op.address, op.operands[0] as usize)),
+ MLIL_LOAD_STRUCT => Op::LoadStruct(LoadStruct::new(
+ function,
+ op.address,
+ op.operands[0] as usize,
+ op.operands[1],
+ )),
MLIL_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa::new(
+ function,
+ op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
)),
- MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa::new(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_LOAD_SSA => Op::LoadSsa(LoadSsa::new(
+ function,
+ op.address,
+ op.operands[0] as usize,
+ op.operands[1],
+ )),
+ MLIL_RET => Op::Ret(Ret::new(
+ function,
+ op.address,
+ (op.operands[0] as usize, op.operands[1] as usize),
+ )),
+ MLIL_VAR => Op::Var(Var::new(function, op.address, op.operands[0])),
+ MLIL_ADDRESS_OF => Op::AddressOf(Var::new(function, op.address, op.operands[0])),
+ MLIL_VAR_FIELD => Op::VarField(Field::new(
+ function,
+ op.address,
+ op.operands[0],
+ op.operands[1],
+ )),
+ MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field::new(
+ function,
+ op.address,
+ op.operands[0],
+ op.operands[1],
+ )),
+ MLIL_VAR_SSA => Op::VarSsa(VarSsa::new(
+ function,
+ op.address,
+ (op.operands[0], op.operands[1] as usize),
+ )),
+ MLIL_VAR_ALIASED => Op::VarAliased(VarSsa::new(
+ function,
+ op.address,
+ (op.operands[0], op.operands[1] as usize),
+ )),
MLIL_VAR_SSA_FIELD => Op::VarSsaField(VarSsaField::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
op.operands[2],
)),
MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField::new(
+ function,
+ op.address,
(op.operands[0], op.operands[1] as usize),
op.operands[2],
)),
- MLIL_TRAP => Op::Trap(Trap::new(op.operands[0])),
+ MLIL_TRAP => Op::Trap(Trap::new(function, op.address, 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
+ use MediumLevelILInstruction::*;
+ match self {
+ Nop(op) => &op.function,
+ Noret(op) => &op.function,
+ Bp(op) => &op.function,
+ Undef(op) => &op.function,
+ Unimpl(op) => &op.function,
+ If(op) => &op.function,
+ FloatConst(op) => &op.function,
+ Const(op) => &op.function,
+ ConstPtr(op) => &op.function,
+ Import(op) => &op.function,
+ ExternPtr(op) => &op.function,
+ ConstData(op) => &op.function,
+ Jump(op) => &op.function,
+ RetHint(op) => &op.function,
+ StoreSsa(op) => &op.function,
+ StoreStructSsa(op) => &op.function,
+ StoreStruct(op) => &op.function,
+ Store(op) => &op.function,
+ JumpTo(op) => &op.function,
+ Goto(op) => &op.function,
+ FreeVarSlot(op) => &op.function,
+ SetVarField(op) => &op.function,
+ SetVar(op) => &op.function,
+ FreeVarSlotSsa(op) => &op.function,
+ SetVarSsaField(op) => &op.function,
+ SetVarAliasedField(op) => &op.function,
+ SetVarAliased(op) => &op.function,
+ SetVarSsa(op) => &op.function,
+ VarPhi(op) => &op.function,
+ MemPhi(op) => &op.function,
+ VarSplit(op) => &op.function,
+ SetVarSplit(op) => &op.function,
+ VarSplitSsa(op) => &op.function,
+ SetVarSplitSsa(op) => &op.function,
+ Add(op) => &op.function,
+ Sub(op) => &op.function,
+ And(op) => &op.function,
+ Or(op) => &op.function,
+ Xor(op) => &op.function,
+ Lsl(op) => &op.function,
+ Lsr(op) => &op.function,
+ Asr(op) => &op.function,
+ Rol(op) => &op.function,
+ Ror(op) => &op.function,
+ Mul(op) => &op.function,
+ MuluDp(op) => &op.function,
+ MulsDp(op) => &op.function,
+ Divu(op) => &op.function,
+ DivuDp(op) => &op.function,
+ Divs(op) => &op.function,
+ DivsDp(op) => &op.function,
+ Modu(op) => &op.function,
+ ModuDp(op) => &op.function,
+ Mods(op) => &op.function,
+ ModsDp(op) => &op.function,
+ CmpE(op) => &op.function,
+ CmpNe(op) => &op.function,
+ CmpSlt(op) => &op.function,
+ CmpUlt(op) => &op.function,
+ CmpSle(op) => &op.function,
+ CmpUle(op) => &op.function,
+ CmpSge(op) => &op.function,
+ CmpUge(op) => &op.function,
+ CmpSgt(op) => &op.function,
+ CmpUgt(op) => &op.function,
+ TestBit(op) => &op.function,
+ AddOverflow(op) => &op.function,
+ FcmpE(op) => &op.function,
+ FcmpNe(op) => &op.function,
+ FcmpLt(op) => &op.function,
+ FcmpLe(op) => &op.function,
+ FcmpGe(op) => &op.function,
+ FcmpGt(op) => &op.function,
+ FcmpO(op) => &op.function,
+ FcmpUo(op) => &op.function,
+ Fadd(op) => &op.function,
+ Fsub(op) => &op.function,
+ Fmul(op) => &op.function,
+ Fdiv(op) => &op.function,
+ Adc(op) => &op.function,
+ Sbb(op) => &op.function,
+ Rlc(op) => &op.function,
+ Rrc(op) => &op.function,
+ Call(op) => &op.function,
+ Tailcall(op) => &op.function,
+ Syscall(op) => &op.function,
+ Intrinsic(op) => &op.function,
+ IntrinsicSsa(op) => &op.function,
+ CallSsa(op) => &op.function,
+ TailcallSsa(op) => &op.function,
+ CallUntypedSsa(op) => &op.function,
+ TailcallUntypedSsa(op) => &op.function,
+ SyscallSsa(op) => &op.function,
+ SyscallUntypedSsa(op) => &op.function,
+ CallUntyped(op) => &op.function,
+ TailcallUntyped(op) => &op.function,
+ SyscallUntyped(op) => &op.function,
+ SeparateParamList(op) => &op.function,
+ SharedParamSlot(op) => &op.function,
+ Neg(op) => &op.function,
+ Not(op) => &op.function,
+ Sx(op) => &op.function,
+ Zx(op) => &op.function,
+ LowPart(op) => &op.function,
+ BoolToInt(op) => &op.function,
+ UnimplMem(op) => &op.function,
+ Fsqrt(op) => &op.function,
+ Fneg(op) => &op.function,
+ Fabs(op) => &op.function,
+ FloatToInt(op) => &op.function,
+ IntToFloat(op) => &op.function,
+ FloatConv(op) => &op.function,
+ RoundToInt(op) => &op.function,
+ Floor(op) => &op.function,
+ Ceil(op) => &op.function,
+ Ftrunc(op) => &op.function,
+ Load(op) => &op.function,
+ LoadStruct(op) => &op.function,
+ LoadStructSsa(op) => &op.function,
+ LoadSsa(op) => &op.function,
+ Ret(op) => &op.function,
+ Var(op) => &op.function,
+ AddressOf(op) => &op.function,
+ VarField(op) => &op.function,
+ AddressOfField(op) => &op.function,
+ VarSsa(op) => &op.function,
+ VarAliased(op) => &op.function,
+ VarSsaField(op) => &op.function,
+ VarAliasedField(op) => &op.function,
+ Trap(op) => &op.function,
+ }
}
pub fn address(&self) -> u64 {
- self.address
- }
-
- pub fn operation(&self) -> &MediumLevelILOperation {
- &self.operation
+ use MediumLevelILInstruction::*;
+ match self {
+ Nop(op) => op.address,
+ Noret(op) => op.address,
+ Bp(op) => op.address,
+ Undef(op) => op.address,
+ Unimpl(op) => op.address,
+ If(op) => op.address,
+ FloatConst(op) => op.address,
+ Const(op) => op.address,
+ ConstPtr(op) => op.address,
+ Import(op) => op.address,
+ ExternPtr(op) => op.address,
+ ConstData(op) => op.address,
+ Jump(op) => op.address,
+ RetHint(op) => op.address,
+ StoreSsa(op) => op.address,
+ StoreStructSsa(op) => op.address,
+ StoreStruct(op) => op.address,
+ Store(op) => op.address,
+ JumpTo(op) => op.address,
+ Goto(op) => op.address,
+ FreeVarSlot(op) => op.address,
+ SetVarField(op) => op.address,
+ SetVar(op) => op.address,
+ FreeVarSlotSsa(op) => op.address,
+ SetVarSsaField(op) => op.address,
+ SetVarAliasedField(op) => op.address,
+ SetVarAliased(op) => op.address,
+ SetVarSsa(op) => op.address,
+ VarPhi(op) => op.address,
+ MemPhi(op) => op.address,
+ VarSplit(op) => op.address,
+ SetVarSplit(op) => op.address,
+ VarSplitSsa(op) => op.address,
+ SetVarSplitSsa(op) => op.address,
+ Add(op) => op.address,
+ Sub(op) => op.address,
+ And(op) => op.address,
+ Or(op) => op.address,
+ Xor(op) => op.address,
+ Lsl(op) => op.address,
+ Lsr(op) => op.address,
+ Asr(op) => op.address,
+ Rol(op) => op.address,
+ Ror(op) => op.address,
+ Mul(op) => op.address,
+ MuluDp(op) => op.address,
+ MulsDp(op) => op.address,
+ Divu(op) => op.address,
+ DivuDp(op) => op.address,
+ Divs(op) => op.address,
+ DivsDp(op) => op.address,
+ Modu(op) => op.address,
+ ModuDp(op) => op.address,
+ Mods(op) => op.address,
+ ModsDp(op) => op.address,
+ CmpE(op) => op.address,
+ CmpNe(op) => op.address,
+ CmpSlt(op) => op.address,
+ CmpUlt(op) => op.address,
+ CmpSle(op) => op.address,
+ CmpUle(op) => op.address,
+ CmpSge(op) => op.address,
+ CmpUge(op) => op.address,
+ CmpSgt(op) => op.address,
+ CmpUgt(op) => op.address,
+ TestBit(op) => op.address,
+ AddOverflow(op) => op.address,
+ FcmpE(op) => op.address,
+ FcmpNe(op) => op.address,
+ FcmpLt(op) => op.address,
+ FcmpLe(op) => op.address,
+ FcmpGe(op) => op.address,
+ FcmpGt(op) => op.address,
+ FcmpO(op) => op.address,
+ FcmpUo(op) => op.address,
+ Fadd(op) => op.address,
+ Fsub(op) => op.address,
+ Fmul(op) => op.address,
+ Fdiv(op) => op.address,
+ Adc(op) => op.address,
+ Sbb(op) => op.address,
+ Rlc(op) => op.address,
+ Rrc(op) => op.address,
+ Call(op) => op.address,
+ Tailcall(op) => op.address,
+ Syscall(op) => op.address,
+ Intrinsic(op) => op.address,
+ IntrinsicSsa(op) => op.address,
+ CallSsa(op) => op.address,
+ TailcallSsa(op) => op.address,
+ CallUntypedSsa(op) => op.address,
+ TailcallUntypedSsa(op) => op.address,
+ SyscallSsa(op) => op.address,
+ SyscallUntypedSsa(op) => op.address,
+ CallUntyped(op) => op.address,
+ TailcallUntyped(op) => op.address,
+ SyscallUntyped(op) => op.address,
+ SeparateParamList(op) => op.address,
+ SharedParamSlot(op) => op.address,
+ Neg(op) => op.address,
+ Not(op) => op.address,
+ Sx(op) => op.address,
+ Zx(op) => op.address,
+ LowPart(op) => op.address,
+ BoolToInt(op) => op.address,
+ UnimplMem(op) => op.address,
+ Fsqrt(op) => op.address,
+ Fneg(op) => op.address,
+ Fabs(op) => op.address,
+ FloatToInt(op) => op.address,
+ IntToFloat(op) => op.address,
+ FloatConv(op) => op.address,
+ RoundToInt(op) => op.address,
+ Floor(op) => op.address,
+ Ceil(op) => op.address,
+ Ftrunc(op) => op.address,
+ Load(op) => op.address,
+ LoadStruct(op) => op.address,
+ LoadStructSsa(op) => op.address,
+ LoadSsa(op) => op.address,
+ Ret(op) => op.address,
+ Var(op) => op.address,
+ AddressOf(op) => op.address,
+ VarField(op) => op.address,
+ AddressOfField(op) => op.address,
+ VarSsa(op) => op.address,
+ VarAliased(op) => op.address,
+ VarSsaField(op) => op.address,
+ VarAliasedField(op) => op.address,
+ Trap(op) => op.address,
+ }
}
pub fn lift(&self) -> MediumLevelILLiftedInstruction {
- use MediumLevelILLiftedOperation as Lifted;
- use MediumLevelILOperation::*;
+ use MediumLevelILInstruction::*;
+ use MediumLevelILLiftedInstruction as Lifted;
- 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)),
+ match self {
+ Nop(op) => Lifted::Nop(op.clone()),
+ Noret(op) => Lifted::Noret(op.clone()),
+ Bp(op) => Lifted::Bp(op.clone()),
+ Undef(op) => Lifted::Undef(op.clone()),
+ Unimpl(op) => Lifted::Unimpl(op.clone()),
+ If(op) => Lifted::If(op.lift()),
+ FloatConst(op) => Lifted::FloatConst(op.clone()),
+ Const(op) => Lifted::Const(op.clone()),
+ ConstPtr(op) => Lifted::ConstPtr(op.clone()),
+ Import(op) => Lifted::Import(op.clone()),
+ ExternPtr(op) => Lifted::ExternPtr(op.clone()),
+ ConstData(op) => Lifted::ConstData(op.lift()),
+ Jump(op) => Lifted::Jump(op.lift()),
+ RetHint(op) => Lifted::RetHint(op.lift()),
+ StoreSsa(op) => Lifted::StoreSsa(op.lift()),
+ StoreStructSsa(op) => Lifted::StoreStructSsa(op.lift()),
+ StoreStruct(op) => Lifted::StoreStruct(op.lift()),
+ Store(op) => Lifted::Store(op.lift()),
+ JumpTo(op) => Lifted::JumpTo(op.lift()),
+ Goto(op) => Lifted::Goto(op.clone()),
+ FreeVarSlot(op) => Lifted::FreeVarSlot(op.clone()),
+ SetVarField(op) => Lifted::SetVarField(op.lift()),
+ SetVar(op) => Lifted::SetVar(op.lift()),
FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op.lift()),
- SetVarSsaField(op) => Lifted::SetVarSsaField(op.lift(&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)),
+ SetVarSsaField(op) => Lifted::SetVarSsaField(op.lift()),
+ SetVarAliasedField(op) => Lifted::SetVarAliasedField(op.lift()),
+ SetVarAliased(op) => Lifted::SetVarAliased(op.lift()),
+ SetVarSsa(op) => Lifted::SetVarSsa(op.lift()),
+ VarPhi(op) => Lifted::VarPhi(op.lift()),
+ MemPhi(op) => Lifted::MemPhi(op.lift()),
VarSplit(op) => Lifted::VarSplit(op.lift()),
- SetVarSplit(op) => Lifted::SetVarSplit(op.lift(&self.function)),
+ SetVarSplit(op) => Lifted::SetVarSplit(op.lift()),
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)),
- SeparateParamList(op) => Lifted::SeparateParamList(op.lift(&self.function)),
- SharedParamSlot(op) => Lifted::SharedParamSlot(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,
+ SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(op.lift()),
+ Add(op) => Lifted::Add(op.lift()),
+ Sub(op) => Lifted::Sub(op.lift()),
+ And(op) => Lifted::And(op.lift()),
+ Or(op) => Lifted::Or(op.lift()),
+ Xor(op) => Lifted::Xor(op.lift()),
+ Lsl(op) => Lifted::Lsl(op.lift()),
+ Lsr(op) => Lifted::Lsr(op.lift()),
+ Asr(op) => Lifted::Asr(op.lift()),
+ Rol(op) => Lifted::Rol(op.lift()),
+ Ror(op) => Lifted::Ror(op.lift()),
+ Mul(op) => Lifted::Mul(op.lift()),
+ MuluDp(op) => Lifted::MuluDp(op.lift()),
+ MulsDp(op) => Lifted::MulsDp(op.lift()),
+ Divu(op) => Lifted::Divu(op.lift()),
+ DivuDp(op) => Lifted::DivuDp(op.lift()),
+ Divs(op) => Lifted::Divs(op.lift()),
+ DivsDp(op) => Lifted::DivsDp(op.lift()),
+ Modu(op) => Lifted::Modu(op.lift()),
+ ModuDp(op) => Lifted::ModuDp(op.lift()),
+ Mods(op) => Lifted::Mods(op.lift()),
+ ModsDp(op) => Lifted::ModsDp(op.lift()),
+ CmpE(op) => Lifted::CmpE(op.lift()),
+ CmpNe(op) => Lifted::CmpNe(op.lift()),
+ CmpSlt(op) => Lifted::CmpSlt(op.lift()),
+ CmpUlt(op) => Lifted::CmpUlt(op.lift()),
+ CmpSle(op) => Lifted::CmpSle(op.lift()),
+ CmpUle(op) => Lifted::CmpUle(op.lift()),
+ CmpSge(op) => Lifted::CmpSge(op.lift()),
+ CmpUge(op) => Lifted::CmpUge(op.lift()),
+ CmpSgt(op) => Lifted::CmpSgt(op.lift()),
+ CmpUgt(op) => Lifted::CmpUgt(op.lift()),
+ TestBit(op) => Lifted::TestBit(op.lift()),
+ AddOverflow(op) => Lifted::AddOverflow(op.lift()),
+ FcmpE(op) => Lifted::FcmpE(op.lift()),
+ FcmpNe(op) => Lifted::FcmpNe(op.lift()),
+ FcmpLt(op) => Lifted::FcmpLt(op.lift()),
+ FcmpLe(op) => Lifted::FcmpLe(op.lift()),
+ FcmpGe(op) => Lifted::FcmpGe(op.lift()),
+ FcmpGt(op) => Lifted::FcmpGt(op.lift()),
+ FcmpO(op) => Lifted::FcmpO(op.lift()),
+ FcmpUo(op) => Lifted::FcmpUo(op.lift()),
+ Fadd(op) => Lifted::Fadd(op.lift()),
+ Fsub(op) => Lifted::Fsub(op.lift()),
+ Fmul(op) => Lifted::Fmul(op.lift()),
+ Fdiv(op) => Lifted::Fdiv(op.lift()),
+ Adc(op) => Lifted::Adc(op.lift()),
+ Sbb(op) => Lifted::Sbb(op.lift()),
+ Rlc(op) => Lifted::Rlc(op.lift()),
+ Rrc(op) => Lifted::Rrc(op.lift()),
+ Call(op) => Lifted::Call(op.lift()),
+ Tailcall(op) => Lifted::Tailcall(op.lift()),
+ Intrinsic(op) => Lifted::Intrinsic(op.lift()),
+ Syscall(op) => Lifted::Syscall(op.lift()),
+ IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift()),
+ CallSsa(op) => Lifted::CallSsa(op.lift()),
+ TailcallSsa(op) => Lifted::TailcallSsa(op.lift()),
+ CallUntypedSsa(op) => Lifted::CallUntypedSsa(op.lift()),
+ TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(op.lift()),
+ SyscallSsa(op) => Lifted::SyscallSsa(op.lift()),
+ SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(op.lift()),
+ CallUntyped(op) => Lifted::CallUntyped(op.lift()),
+ TailcallUntyped(op) => Lifted::TailcallUntyped(op.lift()),
+ SyscallUntyped(op) => Lifted::SyscallUntyped(op.lift()),
+ SeparateParamList(op) => Lifted::SeparateParamList(op.lift()),
+ SharedParamSlot(op) => Lifted::SharedParamSlot(op.lift()),
+ Neg(op) => Lifted::Neg(op.lift()),
+ Not(op) => Lifted::Not(op.lift()),
+ Sx(op) => Lifted::Sx(op.lift()),
+ Zx(op) => Lifted::Zx(op.lift()),
+ LowPart(op) => Lifted::LowPart(op.lift()),
+ BoolToInt(op) => Lifted::BoolToInt(op.lift()),
+ UnimplMem(op) => Lifted::UnimplMem(op.lift()),
+ Fsqrt(op) => Lifted::Fsqrt(op.lift()),
+ Fneg(op) => Lifted::Fneg(op.lift()),
+ Fabs(op) => Lifted::Fabs(op.lift()),
+ FloatToInt(op) => Lifted::FloatToInt(op.lift()),
+ IntToFloat(op) => Lifted::IntToFloat(op.lift()),
+ FloatConv(op) => Lifted::FloatConv(op.lift()),
+ RoundToInt(op) => Lifted::RoundToInt(op.lift()),
+ Floor(op) => Lifted::Floor(op.lift()),
+ Ceil(op) => Lifted::Ceil(op.lift()),
+ Ftrunc(op) => Lifted::Ftrunc(op.lift()),
+ Load(op) => Lifted::Load(op.lift()),
+ LoadStruct(op) => Lifted::LoadStruct(op.lift()),
+ LoadStructSsa(op) => Lifted::LoadStructSsa(op.lift()),
+ LoadSsa(op) => Lifted::LoadSsa(op.lift()),
+ Ret(op) => Lifted::Ret(op.lift()),
+ Var(op) => Lifted::Var(op.clone()),
+ AddressOf(op) => Lifted::AddressOf(op.clone()),
+ VarField(op) => Lifted::VarField(op.clone()),
+ AddressOfField(op) => Lifted::AddressOfField(op.clone()),
+ VarSsa(op) => Lifted::VarSsa(op.clone()),
+ VarAliased(op) => Lifted::VarAliased(op.clone()),
+ VarSsaField(op) => Lifted::VarSsaField(op.clone()),
+ VarAliasedField(op) => Lifted::VarAliasedField(op.clone()),
+ Trap(op) => Lifted::Trap(op.clone()),
}
}
- pub fn operands(&self) -> Box<dyn Iterator<Item = (&'static str, MediumLevelILOperand)>> {
- use MediumLevelILOperation::*;
- match &self.operation {
+ pub fn operands(&self) -> Box<dyn Iterator<Item = (&'static str, MediumLevelILOperand)> + '_> {
+ use MediumLevelILInstruction::*;
+ match self {
Nop(_op) | Noret(_op) | Bp(_op) | Undef(_op) | Unimpl(_op) => Box::new([].into_iter()),
- If(op) => Box::new(op.operands(&self.function)),
+ If(op) => Box::new(op.operands()),
FloatConst(op) => Box::new(op.operands()),
Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()),
- ExternPtr(op) => Box::new(op.operands(&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)),
+ ExternPtr(op) => Box::new(op.operands()),
+ ConstData(op) => Box::new(op.operands()),
+ Jump(op) | RetHint(op) => Box::new(op.operands()),
+ StoreSsa(op) => Box::new(op.operands()),
+ StoreStructSsa(op) => Box::new(op.operands()),
+ StoreStruct(op) => Box::new(op.operands()),
+ Store(op) => Box::new(op.operands()),
+ JumpTo(op) => Box::new(op.operands()),
Goto(op) => Box::new(op.operands()),
FreeVarSlot(op) => Box::new(op.operands()),
- SetVarField(op) => Box::new(op.operands(&self.function)),
- SetVar(op) => Box::new(op.operands(&self.function)),
+ SetVarField(op) => Box::new(op.operands()),
+ SetVar(op) => Box::new(op.operands()),
FreeVarSlotSsa(op) => Box::new(op.operands()),
- SetVarSsaField(op) | SetVarAliasedField(op) => Box::new(op.operands(&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)),
+ SetVarSsaField(op) | SetVarAliasedField(op) => Box::new(op.operands()),
+ SetVarAliased(op) => Box::new(op.operands()),
+ SetVarSsa(op) => Box::new(op.operands()),
+ VarPhi(op) => Box::new(op.operands()),
+ MemPhi(op) => Box::new(op.operands()),
VarSplit(op) => Box::new(op.operands()),
- SetVarSplit(op) => Box::new(op.operands(&self.function)),
+ SetVarSplit(op) => Box::new(op.operands()),
VarSplitSsa(op) => Box::new(op.operands()),
- SetVarSplitSsa(op) => Box::new(op.operands(&self.function)),
+ SetVarSplitSsa(op) => Box::new(op.operands()),
Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
| Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
| Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
| CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
| CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
| FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
- | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => {
- Box::new(op.operands(&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)),
- SeparateParamList(op) => Box::new(op.operands(&self.function)),
- SharedParamSlot(op) => Box::new(op.operands(&self.function)),
+ | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => Box::new(op.operands()),
+ Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands()),
+ Call(op) | Tailcall(op) => Box::new(op.operands()),
+ Syscall(op) => Box::new(op.operands()),
+ Intrinsic(op) => Box::new(op.operands()),
+ IntrinsicSsa(op) => Box::new(op.operands()),
+ CallSsa(op) | TailcallSsa(op) => Box::new(op.operands()),
+ CallUntypedSsa(op) | TailcallUntypedSsa(op) => Box::new(op.operands()),
+ SyscallSsa(op) => Box::new(op.operands()),
+ SyscallUntypedSsa(op) => Box::new(op.operands()),
+ CallUntyped(op) | TailcallUntyped(op) => Box::new(op.operands()),
+ SyscallUntyped(op) => Box::new(op.operands()),
+ SeparateParamList(op) => Box::new(op.operands()),
+ SharedParamSlot(op) => Box::new(op.operands()),
Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
| Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
| RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
- Box::new(op.operands(&self.function))
+ Box::new(op.operands())
}
- 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)),
+ LoadStruct(op) => Box::new(op.operands()),
+ LoadStructSsa(op) => Box::new(op.operands()),
+ LoadSsa(op) => Box::new(op.operands()),
+ Ret(op) => Box::new(op.operands()),
Var(op) | AddressOf(op) => Box::new(op.operands()),
VarField(op) | AddressOfField(op) => Box::new(op.operands()),
VarSsa(op) | VarAliased(op) => Box::new(op.operands()),
diff --git a/rust/src/mlil/lift.rs b/rust/src/mlil/lift.rs
index fc996cb4..bf7f16db 100644
--- a/rust/src/mlil/lift.rs
+++ b/rust/src/mlil/lift.rs
@@ -1,13 +1,7 @@
use super::operation::*;
#[derive(Clone, Debug, PartialEq)]
-pub struct MediumLevelILLiftedInstruction {
- pub address: u64,
- pub operation: MediumLevelILLiftedOperation,
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub enum MediumLevelILLiftedOperation {
+pub enum MediumLevelILLiftedInstruction {
Nop(NoArgs),
Noret(NoArgs),
Bp(NoArgs),
@@ -19,7 +13,7 @@ pub enum MediumLevelILLiftedOperation {
ConstPtr(Constant),
Import(Constant),
ExternPtr(ExternPtr),
- ConstData(ConstantData),
+ ConstData(LiftedConstantData),
Jump(LiftedJump),
RetHint(LiftedJump),
StoreSsa(LiftedStoreSsa),
@@ -93,8 +87,8 @@ pub enum MediumLevelILLiftedOperation {
Rrc(LiftedBinaryOpCarry),
Call(LiftedCall),
Tailcall(LiftedCall),
- Intrinsic(LiftedInnerCall),
- Syscall(LiftedInnerCall),
+ Intrinsic(LiftedIntrinsic),
+ Syscall(LiftedSyscallCall),
IntrinsicSsa(LiftedIntrinsicSsa),
CallSsa(LiftedCallSsa),
TailcallSsa(LiftedCallSsa),
diff --git a/rust/src/mlil/operation.rs b/rust/src/mlil/operation.rs
index 880155e3..876337dd 100644
--- a/rust/src/mlil/operation.rs
+++ b/rust/src/mlil/operation.rs
@@ -6,15 +6,17 @@ use binaryninjacore_sys::BNMediumLevelILInstruction;
use binaryninjacore_sys::BNMediumLevelILOperation;
use crate::rc::Ref;
+use crate::types;
+use crate::types::ILIntrinsic;
+use crate::types::RegisterValue;
+use crate::types::RegisterValueType;
use crate::types::{SSAVariable, Variable};
use super::{MediumLevelILFunction, MediumLevelILInstruction, MediumLevelILLiftedInstruction};
pub enum MediumLevelILOperand {
- //TODO
- //ConstantData(!),
- //TODO
- //Intrinsic(!),
+ ConstantData(types::ConstantData),
+ Intrinsic(ILIntrinsic),
Expr(MediumLevelILInstruction),
ExprList(OperandExprList),
Float(f64),
@@ -209,19 +211,25 @@ fn get_float(value: u64, size: usize) -> f64 {
}
}
-// TODO implement ConstantData
fn get_constant_data(
- _function: &MediumLevelILFunction,
- _value: u64,
- _state: u64,
- _size: usize,
-) -> ! {
- todo!()
+ function: &MediumLevelILFunction,
+ state: u64,
+ value: u64,
+ size: usize,
+) -> types::ConstantData {
+ types::ConstantData::new(
+ function.get_function(),
+ RegisterValue::new(
+ RegisterValueType::from_raw_value(state as u32).unwrap(),
+ value as i64,
+ 0,
+ size,
+ ),
+ )
}
-// TODO implement Intrinsic
-fn get_intrinsic(_function: &MediumLevelILFunction, _idx: usize) -> ! {
- todo!()
+fn get_intrinsic(function: &MediumLevelILFunction, idx: u32) -> ILIntrinsic {
+ ILIntrinsic::new(function.get_function().arch(), idx)
}
fn get_operation(function: &MediumLevelILFunction, idx: usize) -> MediumLevelILInstruction {
@@ -303,32 +311,58 @@ fn get_call_params_ssa(function: &MediumLevelILFunction, idx: usize) -> OperandE
}
// NOP, NORET, BP, UNDEF, UNIMPL
-#[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub struct NoArgs {}
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
+pub struct NoArgs {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
+}
+
+impl NoArgs {
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64) -> Self {
+ Self { function, address }
+ }
+ // NOTE self is not required, it's present just in case data is added to
+ // the struct in the future
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
+ [].into_iter()
+ }
+}
// IF
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct MediumLevelILOperationIf {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
condition: usize,
dest_true: u64,
dest_false: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedIf {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub condition: Box<MediumLevelILLiftedInstruction>,
pub dest_true: u64,
pub dest_false: u64,
}
impl MediumLevelILOperationIf {
- pub fn new(condition: usize, dest_true: u64, dest_false: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ condition: usize,
+ dest_true: u64,
+ dest_false: u64,
+ ) -> Self {
Self {
+ function,
+ address,
condition,
dest_true,
dest_false,
}
}
- pub fn condition(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.condition)
+ pub fn condition(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.condition)
}
pub fn dest_true(&self) -> u64 {
self.dest_true
@@ -336,20 +370,19 @@ impl MediumLevelILOperationIf {
pub fn dest_false(&self) -> u64 {
self.dest_false
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedIf {
+ pub fn lift(&self) -> LiftedIf {
LiftedIf {
- condition: Box::new(self.condition(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ condition: Box::new(self.condition().lift()),
dest_true: self.dest_true(),
dest_false: self.dest_false(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("condition", Expr(self.condition(function))),
+ ("condition", Expr(self.condition())),
("dest_true", Int(self.dest_true())),
("dest_false", Int(self.dest_false())),
]
@@ -358,50 +391,77 @@ impl MediumLevelILOperationIf {
}
// FLOAT_CONST
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub struct FloatConst {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub constant: f64,
}
impl FloatConst {
- pub fn new(constant: u64, size: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ constant: u64,
+ size: usize,
+ ) -> Self {
Self {
+ function,
+ address,
constant: get_float(constant, size),
}
}
pub fn constant(&self) -> f64 {
self.constant
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ 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)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Constant {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub constant: u64,
}
impl Constant {
- pub fn new(constant: u64) -> Self {
- Self { constant }
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, constant: u64) -> Self {
+ Self {
+ function,
+ address,
+ constant,
+ }
}
pub fn constant(&self) -> u64 {
self.constant
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ 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)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct ExternPtr {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub constant: u64,
pub offset: u64,
}
impl ExternPtr {
- pub fn new(constant: u64, offset: u64) -> Self {
- Self { constant, offset }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ constant: u64,
+ offset: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ constant,
+ offset,
+ }
}
pub fn constant(&self) -> u64 {
self.constant
@@ -409,10 +469,7 @@ impl ExternPtr {
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn operands(
- &self,
- _function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("constant", MediumLevelILOperand::Int(self.constant())),
("offset", MediumLevelILOperand::Int(self.offset())),
@@ -422,70 +479,99 @@ impl ExternPtr {
}
// CONST_DATA
-#[derive(Copy, Clone)]
-pub struct ConstData {
+#[derive(Clone)]
+pub struct ConstantData {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
constant_data: (u64, u64),
+ size: usize,
}
-#[derive(Clone, Debug, Hash, PartialEq, Eq)]
-pub struct ConstantData {
- //pub constant_data: !,
+#[derive(Clone, Debug, Hash, PartialEq)]
+pub struct LiftedConstantData {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
+ pub constant_data: types::ConstantData,
}
-impl ConstData {
- pub fn new(constant_data: (u64, u64)) -> Self {
- Self { constant_data }
+impl ConstantData {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ constant_data: (u64, u64),
+ size: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ constant_data,
+ size,
+ }
}
- pub fn constant_data(&self, function: &MediumLevelILFunction, size: usize) -> ! {
- get_constant_data(function, self.constant_data.0, self.constant_data.1, size)
+ pub fn constant_data(&self) -> types::ConstantData {
+ get_constant_data(
+ &self.function,
+ self.constant_data.0,
+ self.constant_data.1,
+ self.size,
+ )
}
- pub fn lift(&self, _function: &MediumLevelILFunction) -> ConstantData {
- ConstantData {
- // TODO
+
+ pub fn lift(&self) -> LiftedConstantData {
+ LiftedConstantData {
+ function: self.function.clone(),
+ address: self.address,
+ constant_data: self.constant_data(),
}
}
- pub fn operands(
- &self,
- _function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
- // TODO
- [
- //("contant_data", MediumLevelILOperand::ConstData(_self.constant_data(function, self.size)))
- ]
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
+ [(
+ "contant_data",
+ MediumLevelILOperand::ConstantData(self.constant_data()),
+ )]
.into_iter()
}
}
// JUMP, RET_HINT
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct Jump {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedJump {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Box<MediumLevelILLiftedInstruction>,
}
impl Jump {
- pub fn new(dest: usize) -> Self {
- Self { dest }
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, dest: usize) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ }
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedJump {
+ pub fn lift(&self) -> LiftedJump {
LiftedJump {
- dest: Box::new(self.dest(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
- [("dest", MediumLevelILOperand::Expr(self.dest(function)))].into_iter()
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
+ [("dest", MediumLevelILOperand::Expr(self.dest()))].into_iter()
}
}
// STORE_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct StoreSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: usize,
dest_memory: u64,
src_memory: u64,
@@ -493,22 +579,33 @@ pub struct StoreSsa {
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedStoreSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub dest_memory: u64,
pub src_memory: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl StoreSsa {
- pub fn new(dest: usize, dest_memory: u64, src_memory: u64, src: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: usize,
+ dest_memory: u64,
+ src_memory: u64,
+ src: usize,
+ ) -> Self {
Self {
+ function,
+ address,
dest,
dest_memory,
src_memory,
src,
}
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
pub fn dest_memory(&self) -> u64 {
self.dest_memory
@@ -516,34 +613,35 @@ impl StoreSsa {
pub fn src_memory(&self) -> u64 {
self.src_memory
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreSsa {
+ pub fn lift(&self) -> LiftedStoreSsa {
LiftedStoreSsa {
- dest: Box::new(self.dest(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
dest_memory: self.dest_memory(),
src_memory: self.src_memory(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ ("dest", MediumLevelILOperand::Expr(self.dest())),
("dest_memory", MediumLevelILOperand::Int(self.dest_memory())),
("src_memory", MediumLevelILOperand::Int(self.src_memory())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// STORE_STRUCT_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct StoreStructSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: usize,
offset: u64,
dest_memory: u64,
@@ -552,6 +650,8 @@ pub struct StoreStructSsa {
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedStoreStructSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub offset: u64,
pub dest_memory: u64,
@@ -559,8 +659,18 @@ pub struct LiftedStoreStructSsa {
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl StoreStructSsa {
- pub fn new(dest: usize, offset: u64, dest_memory: u64, src_memory: u64, src: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: usize,
+ offset: u64,
+ dest_memory: u64,
+ src_memory: u64,
+ src: usize,
+ ) -> Self {
Self {
+ function,
+ address,
dest,
offset,
dest_memory,
@@ -568,8 +678,8 @@ impl StoreStructSsa {
src,
}
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
pub fn offset(&self) -> u64 {
self.offset
@@ -580,210 +690,276 @@ impl StoreStructSsa {
pub fn src_memory(&self) -> u64 {
self.src_memory
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreStructSsa {
+ pub fn lift(&self) -> LiftedStoreStructSsa {
LiftedStoreStructSsa {
- dest: Box::new(self.dest(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
offset: self.offset(),
dest_memory: self.dest_memory(),
src_memory: self.src_memory(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ ("dest", MediumLevelILOperand::Expr(self.dest())),
("offset", MediumLevelILOperand::Int(self.offset())),
("dest_memory", MediumLevelILOperand::Int(self.dest_memory())),
("src_memory", MediumLevelILOperand::Int(self.src_memory())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// STORE_STRUCT
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct StoreStruct {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: usize,
offset: u64,
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedStoreStruct {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub offset: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl StoreStruct {
- pub fn new(dest: usize, offset: u64, src: usize) -> Self {
- Self { dest, offset, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: usize,
+ offset: u64,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ offset,
+ src,
+ }
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStoreStruct {
+ pub fn lift(&self) -> LiftedStoreStruct {
LiftedStoreStruct {
- dest: Box::new(self.dest(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
offset: self.offset(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("dest", MediumLevelILOperand::Expr(self.dest(function))),
+ ("dest", MediumLevelILOperand::Expr(self.dest())),
("offset", MediumLevelILOperand::Int(self.offset())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// STORE
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct Store {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: usize,
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedStore {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl Store {
- pub fn new(dest: usize, src: usize) -> Self {
- Self { dest, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: usize,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ src,
+ }
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedStore {
+ pub fn lift(&self) -> LiftedStore {
LiftedStore {
- dest: Box::new(self.dest(function).lift()),
- src: Box::new(self.src(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("dest", MediumLevelILOperand::Expr(self.dest(function))),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("dest", MediumLevelILOperand::Expr(self.dest())),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// JUMP_TO
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct JumpTo {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: usize,
targets: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedJumpTo {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub targets: HashMap<u64, u64>,
}
impl JumpTo {
- pub fn new(dest: usize, targets: (usize, usize)) -> Self {
- Self { dest, targets }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: usize,
+ targets: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ targets,
+ }
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn targets(&self, function: &MediumLevelILFunction) -> OperandDubleList {
- OperandList::new(function, self.targets.1, self.targets.0).duble()
+ pub fn targets(&self) -> OperandDubleList {
+ OperandList::new(&self.function, self.targets.1, self.targets.0).duble()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedJumpTo {
+ pub fn lift(&self) -> LiftedJumpTo {
LiftedJumpTo {
- dest: Box::new(self.dest(function).lift()),
- targets: self.targets(function).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ dest: Box::new(self.dest().lift()),
+ targets: self.targets().collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("dest", Expr(self.dest(function))),
- ("targets", TargetMap(self.targets(function))),
+ ("dest", Expr(self.dest())),
+ ("targets", TargetMap(self.targets())),
]
.into_iter()
}
}
// GOTO
-#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Goto {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: u64,
}
impl Goto {
- pub fn new(dest: u64) -> Self {
- Self { dest }
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, dest: u64) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ }
}
pub fn dest(&self) -> u64 {
self.dest
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ 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)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct FreeVarSlot {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Variable,
}
impl FreeVarSlot {
- pub fn new(dest: u64) -> Self {
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, dest: u64) -> Self {
Self {
+ function,
+ address,
dest: get_var(dest),
}
}
pub fn dest(&self) -> Variable {
self.dest
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[("dest", MediumLevelILOperand::Var(self.dest()))].into_iter()
}
}
// SET_VAR_FIELD
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVarField {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: u64,
offset: u64,
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVarField {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Variable,
pub offset: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVarField {
- pub fn new(dest: u64, offset: u64, src: usize) -> Self {
- Self { dest, offset, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: u64,
+ offset: u64,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ offset,
+ src,
+ }
}
pub fn dest(&self) -> Variable {
get_var(self.dest)
@@ -791,77 +967,98 @@ impl SetVarField {
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarField {
+ pub fn lift(&self) -> LiftedSetVarField {
LiftedSetVarField {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
offset: self.offset(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::Var(self.dest())),
("offset", MediumLevelILOperand::Int(self.offset())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// SET_VAR
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVar {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: u64,
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVar {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: Variable,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVar {
- pub fn new(dest: u64, src: usize) -> Self {
- Self { dest, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: u64,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ 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 src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVar {
+ pub fn lift(&self) -> LiftedSetVar {
LiftedSetVar {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::Var(self.dest())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// FREE_VAR_SLOT_SSA
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct FreeVarSlotSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: SSAVariable,
pub prev: SSAVariable,
}
impl FreeVarSlotSsa {
- pub fn new(dest: (u64, usize), prev: (u64, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ prev: (u64, usize),
+ ) -> Self {
Self {
+ function,
+ address,
dest: get_var_ssa(dest.0, dest.1),
prev: get_var_ssa(prev.0, prev.1),
}
@@ -872,13 +1069,15 @@ impl FreeVarSlotSsa {
pub fn prev(&self) -> SSAVariable {
self.prev
}
- pub fn lift(self) -> FreeVarSlotSsa {
+ pub fn lift(&self) -> FreeVarSlotSsa {
FreeVarSlotSsa {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
prev: self.prev(),
}
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::VarSsa(self.dest())),
("prev", MediumLevelILOperand::VarSsa(self.prev())),
@@ -888,8 +1087,10 @@ impl FreeVarSlotSsa {
}
// SET_VAR_SSA_FIELD, SET_VAR_ALIASED_FIELD
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVarSsaField {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: (u64, usize),
prev: (u64, usize),
offset: u64,
@@ -897,14 +1098,25 @@ pub struct SetVarSsaField {
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVarSsaField {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: SSAVariable,
pub prev: SSAVariable,
pub offset: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVarSsaField {
- pub fn new(dest: (u64, usize), prev: (u64, usize), offset: u64, src: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ prev: (u64, usize),
+ offset: u64,
+ src: usize,
+ ) -> Self {
Self {
+ function,
+ address,
dest,
prev,
offset,
@@ -920,47 +1132,62 @@ impl SetVarSsaField {
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSsaField {
+ pub fn lift(&self) -> LiftedSetVarSsaField {
LiftedSetVarSsaField {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
prev: self.prev(),
offset: self.offset(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::VarSsa(self.dest())),
("prev", MediumLevelILOperand::VarSsa(self.prev())),
("offset", MediumLevelILOperand::Int(self.offset())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// SET_VAR_ALIASED
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVarAliased {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: (u64, usize),
prev: (u64, usize),
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVarAliased {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: SSAVariable,
pub prev: SSAVariable,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVarAliased {
- pub fn new(dest: (u64, usize), prev: (u64, usize), src: usize) -> Self {
- Self { dest, prev, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ prev: (u64, usize),
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ prev,
+ src,
+ }
}
pub fn dest(&self) -> SSAVariable {
get_var_ssa(self.dest.0, self.dest.1)
@@ -968,121 +1195,157 @@ impl SetVarAliased {
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 src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarAliased {
+ pub fn lift(&self) -> LiftedSetVarAliased {
LiftedSetVarAliased {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
prev: self.prev(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::VarSsa(self.dest())),
("prev", MediumLevelILOperand::VarSsa(self.prev())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// SET_VAR_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVarSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: (u64, usize),
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVarSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: SSAVariable,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVarSsa {
- pub fn new(dest: (u64, usize), src: usize) -> Self {
- Self { dest, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ src,
+ }
}
pub fn dest(&self) -> SSAVariable {
get_var_ssa(self.dest.0, self.dest.1)
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSsa {
+ pub fn lift(&self) -> LiftedSetVarSsa {
LiftedSetVarSsa {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::VarSsa(self.dest())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// VAR_PHI
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct VarPhi {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest: (u64, usize),
src: (usize, usize),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct LiftedVarPhi {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest: SSAVariable,
pub src: Vec<SSAVariable>,
}
impl VarPhi {
- pub fn new(dest: (u64, usize), src: (usize, usize)) -> Self {
- Self { dest, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest: (u64, usize),
+ src: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ dest,
+ src,
+ }
}
pub fn dest(&self) -> SSAVariable {
get_var_ssa(self.dest.0, self.dest.1)
}
- pub fn src(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
- OperandList::new(function, self.src.1, self.src.0).map_ssa_var()
+ pub fn src(&self) -> OperandSSAVariableList {
+ OperandList::new(&self.function, self.src.1, self.src.0).map_ssa_var()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedVarPhi {
+ pub fn lift(&self) -> LiftedVarPhi {
LiftedVarPhi {
+ function: self.function.clone(),
+ address: self.address,
dest: self.dest(),
- src: self.src(function).collect(),
+ src: self.src().collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("dest", MediumLevelILOperand::VarSsa(self.dest())),
- ("src", MediumLevelILOperand::VarSsaList(self.src(function))),
+ ("src", MediumLevelILOperand::VarSsaList(self.src())),
]
.into_iter()
}
}
// MEM_PHI
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct MemPhi {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
dest_memory: u64,
src_memory: (usize, usize),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct LiftedMemPhi {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub dest_memory: u64,
pub src_memory: Vec<u64>,
}
impl MemPhi {
- pub fn new(dest_memory: u64, src_memory: (usize, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ dest_memory: u64,
+ src_memory: (usize, usize),
+ ) -> Self {
Self {
+ function,
+ address,
dest_memory,
src_memory,
}
@@ -1090,37 +1353,45 @@ impl MemPhi {
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 src_memory(&self) -> OperandList {
+ OperandList::new(&self.function, self.src_memory.1, self.src_memory.0)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedMemPhi {
+ pub fn lift(&self) -> LiftedMemPhi {
LiftedMemPhi {
+ function: self.function.clone(),
+ address: self.address,
dest_memory: self.dest_memory(),
- src_memory: self.src_memory(function).collect(),
+ src_memory: self.src_memory().collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
("dest_memory", Int(self.dest_memory())),
- ("src_memory", IntList(self.src_memory(function))),
+ ("src_memory", IntList(self.src_memory())),
]
.into_iter()
}
}
// VAR_SPLIT
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct VarSplit {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub high: Variable,
pub low: Variable,
}
impl VarSplit {
- pub fn new(high: u64, low: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ high: u64,
+ low: u64,
+ ) -> Self {
Self {
+ function,
+ address,
high: get_var(high),
low: get_var(low),
}
@@ -1131,13 +1402,15 @@ impl VarSplit {
pub fn low(&self) -> Variable {
self.low
}
- pub fn lift(self) -> VarSplit {
+ pub fn lift(&self) -> VarSplit {
VarSplit {
+ function: self.function.clone(),
+ address: self.address,
high: self.high(),
low: self.low(),
}
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("high", MediumLevelILOperand::Var(self.high())),
("low", MediumLevelILOperand::Var(self.low())),
@@ -1147,21 +1420,37 @@ impl VarSplit {
}
// SET_VAR_SPLIT
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVarSplit {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
high: u64,
low: u64,
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVarSplit {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub high: Variable,
pub low: Variable,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVarSplit {
- pub fn new(high: u64, low: u64, src: usize) -> Self {
- Self { high, low, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ high: u64,
+ low: u64,
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ high,
+ low,
+ src,
+ }
}
pub fn high(&self) -> Variable {
get_var(self.high)
@@ -1169,38 +1458,46 @@ impl SetVarSplit {
pub fn low(&self) -> Variable {
get_var(self.low)
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSplit {
+ pub fn lift(&self) -> LiftedSetVarSplit {
LiftedSetVarSplit {
+ function: self.function.clone(),
+ address: self.address,
high: self.high(),
low: self.low(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("high", MediumLevelILOperand::Var(self.high())),
("low", MediumLevelILOperand::Var(self.low())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// VAR_SPLIT_SSA
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct VarSplitSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub high: SSAVariable,
pub low: SSAVariable,
}
impl VarSplitSsa {
- pub fn new(high: (u64, usize), low: (u64, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ high: (u64, usize),
+ low: (u64, usize),
+ ) -> Self {
Self {
+ function,
+ address,
high: get_var_ssa(high.0, high.1),
low: get_var_ssa(low.0, low.1),
}
@@ -1211,13 +1508,15 @@ impl VarSplitSsa {
pub fn low(&self) -> SSAVariable {
self.low
}
- pub fn lift(self) -> VarSplitSsa {
+ pub fn lift(&self) -> VarSplitSsa {
VarSplitSsa {
+ function: self.function.clone(),
+ address: self.address,
high: self.high(),
low: self.low(),
}
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("high", MediumLevelILOperand::VarSsa(self.high())),
("low", MediumLevelILOperand::VarSsa(self.low())),
@@ -1227,21 +1526,37 @@ impl VarSplitSsa {
}
// SET_VAR_SPLIT_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SetVarSplitSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
high: (u64, usize),
low: (u64, usize),
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSetVarSplitSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub high: SSAVariable,
pub low: SSAVariable,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl SetVarSplitSsa {
- pub fn new(high: (u64, usize), low: (u64, usize), src: usize) -> Self {
- Self { high, low, src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ high: (u64, usize),
+ low: (u64, usize),
+ src: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ high,
+ low,
+ src,
+ }
}
pub fn high(&self) -> SSAVariable {
get_var_ssa(self.high.0, self.high.1)
@@ -1249,314 +1564,384 @@ impl SetVarSplitSsa {
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 src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSetVarSplitSsa {
+ pub fn lift(&self) -> LiftedSetVarSplitSsa {
LiftedSetVarSplitSsa {
+ function: self.function.clone(),
+ address: self.address,
high: self.high(),
low: self.low(),
- src: Box::new(self.src(function).lift()),
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("high", MediumLevelILOperand::VarSsa(self.high())),
("low", MediumLevelILOperand::VarSsa(self.low())),
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
]
.into_iter()
}
}
// ADD, SUB, AND, OR, XOR, LSL, LSR, ASR, ROL, ROR, MUL, MULU_DP, MULS_DP, DIVU, DIVU_DP, DIVS, DIVS_DP, MODU, MODU_DP, MODS, MODS_DP, CMP_E, CMP_NE, CMP_SLT, CMP_ULT, CMP_SLE, CMP_ULE, CMP_SGE, CMP_UGE, CMP_SGT, CMP_UGT, TEST_BIT, ADD_OVERFLOW, FCMP_E, FCMP_NE, FCMP_LT, FCMP_LE, FCMP_GE, FCMP_GT, FCMP_O, FCMP_UO, FADD, FSUB, FMUL, FDIV
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct BinaryOp {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
left: usize,
right: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedBinaryOp {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub left: Box<MediumLevelILLiftedInstruction>,
pub right: Box<MediumLevelILLiftedInstruction>,
}
impl BinaryOp {
- pub fn new(left: usize, right: usize) -> Self {
- Self { left, right }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ left: usize,
+ right: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ left,
+ right,
+ }
}
- pub fn left(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.left)
+ pub fn left(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.left)
}
- pub fn right(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.right)
+ pub fn right(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.right)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedBinaryOp {
+ pub fn lift(&self) -> LiftedBinaryOp {
LiftedBinaryOp {
- left: Box::new(self.left(function).lift()),
- right: Box::new(self.right(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ left: Box::new(self.left().lift()),
+ right: Box::new(self.right().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("left", MediumLevelILOperand::Expr(self.left(function))),
- ("right", MediumLevelILOperand::Expr(self.right(function))),
+ ("left", MediumLevelILOperand::Expr(self.left())),
+ ("right", MediumLevelILOperand::Expr(self.right())),
]
.into_iter()
}
}
// ADC, SBB, RLC, RRC
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct BinaryOpCarry {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
left: usize,
right: usize,
carry: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedBinaryOpCarry {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub left: Box<MediumLevelILLiftedInstruction>,
pub right: Box<MediumLevelILLiftedInstruction>,
pub carry: Box<MediumLevelILLiftedInstruction>,
}
impl BinaryOpCarry {
- pub fn new(left: usize, right: usize, carry: usize) -> Self {
- Self { left, right, carry }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ left: usize,
+ right: usize,
+ carry: usize,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ left,
+ right,
+ carry,
+ }
}
- pub fn left(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.left)
+ pub fn left(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.left)
}
- pub fn right(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.right)
+ pub fn right(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.right)
}
- pub fn carry(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.carry)
+ pub fn carry(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.carry)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedBinaryOpCarry {
+ pub fn lift(&self) -> LiftedBinaryOpCarry {
LiftedBinaryOpCarry {
- left: Box::new(self.left(function).lift()),
- right: Box::new(self.right(function).lift()),
- carry: Box::new(self.carry(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ left: Box::new(self.left().lift()),
+ right: Box::new(self.right().lift()),
+ carry: Box::new(self.carry().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("left", MediumLevelILOperand::Expr(self.left(function))),
- ("right", MediumLevelILOperand::Expr(self.right(function))),
- ("carry", MediumLevelILOperand::Expr(self.carry(function))),
+ ("left", MediumLevelILOperand::Expr(self.left())),
+ ("right", MediumLevelILOperand::Expr(self.right())),
+ ("carry", MediumLevelILOperand::Expr(self.carry())),
]
.into_iter()
}
}
// CALL, TAILCALL
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct Call {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: (usize, usize),
dest: usize,
params: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedCall {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<Variable>,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub params: Vec<MediumLevelILLiftedInstruction>,
}
impl Call {
- pub fn new(output: (usize, usize), dest: usize, params: (usize, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: (usize, usize),
+ dest: usize,
+ params: (usize, usize),
+ ) -> Self {
Self {
+ function,
+ address,
output,
dest,
params,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
- OperandList::new(function, self.output.1, self.output.0).map_var()
+ pub fn output(&self) -> OperandVariableList {
+ OperandList::new(&self.function, self.output.1, self.output.0).map_var()
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.params.1, self.params.0).map_expr()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCall {
+ pub fn lift(&self) -> LiftedCall {
LiftedCall {
- output: self.output(function).collect(),
- dest: Box::new(self.dest(function).lift()),
- params: self.params(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ dest: Box::new(self.dest().lift()),
+ params: self.params().map(|instr| instr.lift()).collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- (
- "output",
- MediumLevelILOperand::VarList(self.output(function)),
- ),
- ("dest", MediumLevelILOperand::Expr(self.dest(function))),
- (
- "params",
- MediumLevelILOperand::ExprList(self.params(function)),
- ),
+ ("output", MediumLevelILOperand::VarList(self.output())),
+ ("dest", MediumLevelILOperand::Expr(self.dest())),
+ ("params", MediumLevelILOperand::ExprList(self.params())),
]
.into_iter()
}
}
// SYSCALL
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct Syscall {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: (usize, usize),
params: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
-pub struct LiftedInnerCall {
+pub struct LiftedSyscallCall {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<Variable>,
pub params: Vec<MediumLevelILLiftedInstruction>,
}
impl Syscall {
- pub fn new(output: (usize, usize), params: (usize, usize)) -> Self {
- Self { output, params }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: (usize, usize),
+ params: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ output,
+ params,
+ }
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
- OperandList::new(function, self.output.1, self.output.0).map_var()
+ pub fn output(&self) -> OperandVariableList {
+ OperandList::new(&self.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 params(&self) -> OperandExprList {
+ OperandList::new(&self.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 lift(&self) -> LiftedSyscallCall {
+ LiftedSyscallCall {
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ params: self.params().map(|instr| instr.lift()).collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarList(self.output(function))),
- ("params", ExprList(self.params(function))),
+ ("output", VarList(self.output())),
+ ("params", ExprList(self.params())),
]
.into_iter()
}
}
// INTRINSIC
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct Intrinsic {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: (usize, usize),
- intrinsic: usize,
+ intrinsic: u32,
params: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
-pub struct MediumLevelILLiftedIntrinsic {
+pub struct LiftedIntrinsic {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<Variable>,
- //pub intrinsic: !,
+ pub intrinsic: ILIntrinsic,
pub params: Vec<MediumLevelILLiftedInstruction>,
}
impl Intrinsic {
- pub fn new(output: (usize, usize), intrinsic: usize, params: (usize, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: (usize, usize),
+ intrinsic: u32,
+ params: (usize, usize),
+ ) -> Self {
Self {
+ function,
+ address,
output,
intrinsic,
params,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
- OperandList::new(function, self.output.1, self.output.0).map_var()
+ pub fn output(&self) -> OperandVariableList {
+ OperandList::new(&self.function, self.output.1, self.output.0).map_var()
}
- pub fn intrinsic(&self, function: &MediumLevelILFunction) -> ! {
- get_intrinsic(function, self.intrinsic)
+ pub fn intrinsic(&self) -> ILIntrinsic {
+ get_intrinsic(&self.function, self.intrinsic)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.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 lift(&self) -> LiftedIntrinsic {
+ LiftedIntrinsic {
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ intrinsic: self.intrinsic(),
+ params: self.params().map(|instr| instr.lift()).collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarList(self.output(function))),
- //("intrinsic", VarList(self.output(function))),
- ("params", ExprList(self.params(function))),
+ ("output", VarList(self.output())),
+ ("intrinsic", Intrinsic(self.intrinsic())),
+ ("params", ExprList(self.params())),
]
.into_iter()
}
}
// INTRINSIC_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct IntrinsicSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: (usize, usize),
- intrinsic: usize,
+ intrinsic: u32,
params: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedIntrinsicSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<SSAVariable>,
- //pub intrinsic: !,
+ pub intrinsic: ILIntrinsic,
pub params: Vec<MediumLevelILLiftedInstruction>,
}
impl IntrinsicSsa {
- pub fn new(output: (usize, usize), intrinsic: usize, params: (usize, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: (usize, usize),
+ intrinsic: u32,
+ params: (usize, usize),
+ ) -> Self {
Self {
+ function,
+ address,
output,
intrinsic,
params,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
- OperandList::new(function, self.output.1, self.output.0).map_ssa_var()
+ pub fn output(&self) -> OperandSSAVariableList {
+ OperandList::new(&self.function, self.output.1, self.output.0).map_ssa_var()
}
- pub fn intrinsic(&self, function: &MediumLevelILFunction) -> ! {
- get_intrinsic(function, self.intrinsic)
+ pub fn intrinsic(&self) -> ILIntrinsic {
+ get_intrinsic(&self.function, self.intrinsic)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.params.1, self.params.0).map_expr()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedIntrinsicSsa {
+ pub fn lift(&self) -> LiftedIntrinsicSsa {
LiftedIntrinsicSsa {
- output: self.output(function).collect(),
- //intrinsic: get_intrinsic(function, self.intrinsic),
- params: self.params(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ intrinsic: get_intrinsic(&self.function, self.intrinsic),
+ params: self.params().map(|instr| instr.lift()).collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarSsaList(self.output(function))),
- ("params", ExprList(self.params(function))),
+ ("output", VarSsaList(self.output())),
+ ("intrinsic", Intrinsic(self.intrinsic())),
+ ("params", ExprList(self.params())),
]
.into_iter()
}
}
// CALL_SSA, TAILCALL_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct CallSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: usize,
dest: usize,
params: (usize, usize),
@@ -1564,49 +1949,59 @@ pub struct CallSsa {
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedCallSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<SSAVariable>,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub params: Vec<MediumLevelILLiftedInstruction>,
pub src_memory: u64,
}
impl CallSsa {
- pub fn new(output: usize, dest: usize, params: (usize, usize), src_memory: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: usize,
+ dest: usize,
+ params: (usize, usize),
+ src_memory: u64,
+ ) -> Self {
Self {
+ function,
+ address,
output,
dest,
params,
src_memory,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
- get_call_output_ssa(function, self.output)
+ pub fn output(&self) -> OperandSSAVariableList {
+ get_call_output_ssa(&self.function, self.output)
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.params.1, self.params.0).map_expr()
}
pub fn src_memory(&self) -> u64 {
self.src_memory
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallSsa {
+ pub fn lift(&self) -> LiftedCallSsa {
LiftedCallSsa {
- output: self.output(function).collect(),
- dest: Box::new(self.dest(function).lift()),
- params: self.params(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ dest: Box::new(self.dest().lift()),
+ params: self.params().map(|instr| instr.lift()).collect(),
src_memory: self.src_memory(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarSsaList(self.output(function))),
- ("dest", Expr(self.dest(function))),
- ("params", ExprList(self.params(function))),
+ ("output", VarSsaList(self.output())),
+ ("dest", Expr(self.dest())),
+ ("params", ExprList(self.params())),
("src_memory", Int(self.src_memory())),
]
.into_iter()
@@ -1614,8 +2009,10 @@ impl CallSsa {
}
// CALL_UNTYPED_SSA, TAILCALL_UNTYPED_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct CallUntypedSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: usize,
dest: usize,
params: usize,
@@ -1623,100 +2020,121 @@ pub struct CallUntypedSsa {
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedCallUntypedSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<SSAVariable>,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub params: Vec<MediumLevelILLiftedInstruction>,
pub stack: Box<MediumLevelILLiftedInstruction>,
}
impl CallUntypedSsa {
- pub fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: usize,
+ dest: usize,
+ params: usize,
+ stack: usize,
+ ) -> Self {
Self {
+ function,
+ address,
output,
dest,
params,
stack,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
- get_call_output_ssa(function, self.output)
+ pub fn output(&self) -> OperandSSAVariableList {
+ get_call_output_ssa(&self.function, self.output)
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- get_call_params_ssa(function, self.params)
+ pub fn params(&self) -> OperandExprList {
+ get_call_params_ssa(&self.function, self.params)
}
- pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.stack)
+ pub fn stack(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.stack)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallUntypedSsa {
+ pub fn lift(&self) -> LiftedCallUntypedSsa {
LiftedCallUntypedSsa {
- output: self.output(function).collect(),
- dest: Box::new(self.dest(function).lift()),
- params: self.params(function).map(|instr| instr.lift()).collect(),
- stack: Box::new(self.stack(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ dest: Box::new(self.dest().lift()),
+ params: self.params().map(|instr| instr.lift()).collect(),
+ stack: Box::new(self.stack().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarSsaList(self.output(function))),
- ("dest", Expr(self.dest(function))),
- ("params", ExprList(self.params(function))),
- ("stack", Expr(self.stack(function))),
+ ("output", VarSsaList(self.output())),
+ ("dest", Expr(self.dest())),
+ ("params", ExprList(self.params())),
+ ("stack", Expr(self.stack())),
]
.into_iter()
}
}
// SYSCALL_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SyscallSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: usize,
params: (usize, usize),
src_memory: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSyscallSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<SSAVariable>,
pub params: Vec<MediumLevelILLiftedInstruction>,
pub src_memory: u64,
}
impl SyscallSsa {
- pub fn new(output: usize, params: (usize, usize), src_memory: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: usize,
+ params: (usize, usize),
+ src_memory: u64,
+ ) -> Self {
Self {
+ function,
+ address,
output,
params,
src_memory,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
- get_call_output_ssa(function, self.output)
+ pub fn output(&self) -> OperandSSAVariableList {
+ get_call_output_ssa(&self.function, self.output)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.params.1, self.params.0).map_expr()
}
pub fn src_memory(&self) -> u64 {
self.src_memory
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallSsa {
+ pub fn lift(&self) -> LiftedSyscallSsa {
LiftedSyscallSsa {
- output: self.output(function).collect(),
- params: self.params(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ params: self.params().map(|instr| instr.lift()).collect(),
src_memory: self.src_memory(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarSsaList(self.output(function))),
- ("params", ExprList(self.params(function))),
+ ("output", VarSsaList(self.output())),
+ ("params", ExprList(self.params())),
("src_memory", MediumLevelILOperand::Int(self.src_memory())),
]
.into_iter()
@@ -1724,59 +2142,72 @@ impl SyscallSsa {
}
// SYSCALL_UNTYPED_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SyscallUntypedSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: usize,
params: usize,
stack: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSyscallUntypedSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<SSAVariable>,
pub params: Vec<MediumLevelILLiftedInstruction>,
pub stack: Box<MediumLevelILLiftedInstruction>,
}
impl SyscallUntypedSsa {
- pub fn new(output: usize, params: usize, stack: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: usize,
+ params: usize,
+ stack: usize,
+ ) -> Self {
Self {
+ function,
+ address,
output,
params,
stack,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandSSAVariableList {
- get_call_output_ssa(function, self.output)
+ pub fn output(&self) -> OperandSSAVariableList {
+ get_call_output_ssa(&self.function, self.output)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- get_call_params_ssa(function, self.params)
+ pub fn params(&self) -> OperandExprList {
+ get_call_params_ssa(&self.function, self.params)
}
- pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.stack)
+ pub fn stack(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.stack)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallUntypedSsa {
+ pub fn lift(&self) -> LiftedSyscallUntypedSsa {
LiftedSyscallUntypedSsa {
- output: self.output(function).collect(),
- params: self.params(function).map(|instr| instr.lift()).collect(),
- stack: Box::new(self.stack(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ params: self.params().map(|instr| instr.lift()).collect(),
+ stack: Box::new(self.stack().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarSsaList(self.output(function))),
- ("params", ExprList(self.params(function))),
- ("stack", Expr(self.stack(function))),
+ ("output", VarSsaList(self.output())),
+ ("params", ExprList(self.params())),
+ ("stack", Expr(self.stack())),
]
.into_iter()
}
}
// CALL_UNTYPED, TAILCALL_UNTYPED
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct CallUntyped {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: usize,
dest: usize,
params: usize,
@@ -1784,168 +2215,209 @@ pub struct CallUntyped {
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedCallUntyped {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<Variable>,
pub dest: Box<MediumLevelILLiftedInstruction>,
pub params: Vec<MediumLevelILLiftedInstruction>,
pub stack: Box<MediumLevelILLiftedInstruction>,
}
impl CallUntyped {
- pub fn new(output: usize, dest: usize, params: usize, stack: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: usize,
+ dest: usize,
+ params: usize,
+ stack: usize,
+ ) -> Self {
Self {
+ function,
+ address,
output,
dest,
params,
stack,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
- get_call_output(function, self.output)
+ pub fn output(&self) -> OperandVariableList {
+ get_call_output(&self.function, self.output)
}
- pub fn dest(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.dest)
+ pub fn dest(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.dest)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- get_call_params(function, self.params)
+ pub fn params(&self) -> OperandExprList {
+ get_call_params(&self.function, self.params)
}
- pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.stack)
+ pub fn stack(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.stack)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedCallUntyped {
+ pub fn lift(&self) -> LiftedCallUntyped {
LiftedCallUntyped {
- output: self.output(function).collect(),
- dest: Box::new(self.dest(function).lift()),
- params: self.params(function).map(|instr| instr.lift()).collect(),
- stack: Box::new(self.stack(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ dest: Box::new(self.dest().lift()),
+ params: self.params().map(|instr| instr.lift()).collect(),
+ stack: Box::new(self.stack().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarList(self.output(function))),
- ("dest", Expr(self.dest(function))),
- ("params", ExprList(self.params(function))),
- ("stack", Expr(self.stack(function))),
+ ("output", VarList(self.output())),
+ ("dest", Expr(self.dest())),
+ ("params", ExprList(self.params())),
+ ("stack", Expr(self.stack())),
]
.into_iter()
}
}
// SYSCALL_UNTYPED
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SyscallUntyped {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
output: usize,
params: usize,
stack: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSyscallUntyped {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub output: Vec<Variable>,
pub params: Vec<MediumLevelILLiftedInstruction>,
pub stack: Box<MediumLevelILLiftedInstruction>,
}
impl SyscallUntyped {
- pub fn new(output: usize, params: usize, stack: usize) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ output: usize,
+ params: usize,
+ stack: usize,
+ ) -> Self {
Self {
+ function,
+ address,
output,
params,
stack,
}
}
- pub fn output(&self, function: &MediumLevelILFunction) -> OperandVariableList {
- get_call_output(function, self.output)
+ pub fn output(&self) -> OperandVariableList {
+ get_call_output(&self.function, self.output)
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- get_call_params(function, self.params)
+ pub fn params(&self) -> OperandExprList {
+ get_call_params(&self.function, self.params)
}
- pub fn stack(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.stack)
+ pub fn stack(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.stack)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSyscallUntyped {
+ pub fn lift(&self) -> LiftedSyscallUntyped {
LiftedSyscallUntyped {
- output: self.output(function).collect(),
- params: self.params(function).map(|instr| instr.lift()).collect(),
- stack: Box::new(self.stack(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ output: self.output().collect(),
+ params: self.params().map(|instr| instr.lift()).collect(),
+ stack: Box::new(self.stack().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
use MediumLevelILOperand::*;
[
- ("output", VarList(self.output(function))),
- ("params", ExprList(self.params(function))),
- ("stack", Expr(self.stack(function))),
+ ("output", VarList(self.output())),
+ ("params", ExprList(self.params())),
+ ("stack", Expr(self.stack())),
]
.into_iter()
}
}
// NEG, NOT, SX, ZX, LOW_PART, BOOL_TO_INT, UNIMPL_MEM, FSQRT, FNEG, FABS, FLOAT_TO_INT, INT_TO_FLOAT, FLOAT_CONV, ROUND_TO_INT, FLOOR, CEIL, FTRUNC, LOAD
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct UnaryOp {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
src: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedUnaryOp {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
}
impl UnaryOp {
- pub fn new(src: usize) -> Self {
- Self { src }
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, src: usize) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ }
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedUnaryOp {
+ pub fn lift(&self) -> LiftedUnaryOp {
LiftedUnaryOp {
- src: Box::new(self.src(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
- [("src", MediumLevelILOperand::Expr(self.src(function)))].into_iter()
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
+ [("src", MediumLevelILOperand::Expr(self.src()))].into_iter()
}
}
// LOAD_STRUCT
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct LoadStruct {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
src: usize,
offset: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedLoadStruct {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
pub offset: u64,
}
impl LoadStruct {
- pub fn new(src: usize, offset: u64) -> Self {
- Self { src, offset }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: usize,
+ offset: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ offset,
+ }
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadStruct {
+ pub fn lift(&self) -> LiftedLoadStruct {
LiftedLoadStruct {
- src: Box::new(self.src(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
offset: self.offset(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
("offset", MediumLevelILOperand::Int(self.offset())),
]
.into_iter()
@@ -1953,28 +2425,40 @@ impl LoadStruct {
}
// LOAD_STRUCT_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct LoadStructSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
src: usize,
offset: u64,
src_memory: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedLoadStructSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
pub offset: u64,
pub src_memory: u64,
}
impl LoadStructSsa {
- pub fn new(src: usize, offset: u64, src_memory: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: usize,
+ offset: u64,
+ src_memory: u64,
+ ) -> Self {
Self {
+ function,
+ address,
src,
offset,
src_memory,
}
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
pub fn offset(&self) -> u64 {
self.offset
@@ -1982,19 +2466,18 @@ impl LoadStructSsa {
pub fn src_memory(&self) -> u64 {
self.src_memory
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadStructSsa {
+ pub fn lift(&self) -> LiftedLoadStructSsa {
LiftedLoadStructSsa {
- src: Box::new(self.src(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
offset: self.offset(),
src_memory: self.src_memory(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
("offset", MediumLevelILOperand::Int(self.offset())),
("src_memory", MediumLevelILOperand::Int(self.src_memory())),
]
@@ -2003,38 +2486,51 @@ impl LoadStructSsa {
}
// LOAD_SSA
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct LoadSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
src: usize,
src_memory: u64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedLoadSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Box<MediumLevelILLiftedInstruction>,
pub src_memory: u64,
}
impl LoadSsa {
- pub fn new(src: usize, src_memory: u64) -> Self {
- Self { src, src_memory }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: usize,
+ src_memory: u64,
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ src_memory,
+ }
}
- pub fn src(&self, function: &MediumLevelILFunction) -> MediumLevelILInstruction {
- get_operation(function, self.src)
+ pub fn src(&self) -> MediumLevelILInstruction {
+ get_operation(&self.function, self.src)
}
pub fn src_memory(&self) -> u64 {
self.src_memory
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedLoadSsa {
+ pub fn lift(&self) -> LiftedLoadSsa {
LiftedLoadSsa {
- src: Box::new(self.src(function).lift()),
+ function: self.function.clone(),
+ address: self.address,
+ src: Box::new(self.src().lift()),
src_memory: self.src_memory(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
- ("src", MediumLevelILOperand::Expr(self.src(function))),
+ ("src", MediumLevelILOperand::Expr(self.src())),
("src_memory", MediumLevelILOperand::Int(self.src_memory())),
]
.into_iter()
@@ -2042,118 +2538,158 @@ impl LoadSsa {
}
// RET
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct Ret {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
src: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedRet {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Vec<MediumLevelILLiftedInstruction>,
}
impl Ret {
- pub fn new(src: (usize, usize)) -> Self {
- Self { src }
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: (usize, usize),
+ ) -> Self {
+ Self {
+ function,
+ address,
+ src,
+ }
}
- pub fn src(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.src.1, self.src.0).map_expr()
+ pub fn src(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.src.1, self.src.0).map_expr()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedRet {
+ pub fn lift(&self) -> LiftedRet {
LiftedRet {
- src: self.src(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ src: self.src().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()
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
+ [("src", MediumLevelILOperand::ExprList(self.src()))].into_iter()
}
}
// SEPARATE_PARAM_LIST
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SeparateParamList {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
params: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSeparateParamList {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub params: Vec<MediumLevelILLiftedInstruction>,
}
impl SeparateParamList {
- pub fn new(params: (usize, usize)) -> Self {
- Self { params }
+ pub fn new(function: Ref<MediumLevelILFunction>, address: u64, params: (usize, usize)) -> Self {
+ Self {
+ function,
+ address,
+ params,
+ }
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.params.1, self.params.0).map_expr()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSeparateParamList {
+ pub fn lift(&self) -> LiftedSeparateParamList {
LiftedSeparateParamList {
- params: self.params(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ params: self.params().map(|instr| instr.lift()).collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
- [("params", MediumLevelILOperand::ExprList(self.params(function)))].into_iter()
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [("params", MediumLevelILOperand::ExprList(self.params()))].into_iter()
}
}
// SHARED_PARAM_SLOT
-#[derive(Copy, Clone)]
+#[derive(Clone)]
pub struct SharedParamSlot {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
params: (usize, usize),
}
#[derive(Clone, Debug, PartialEq)]
pub struct LiftedSharedParamSlot {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub params: Vec<MediumLevelILLiftedInstruction>,
}
impl SharedParamSlot {
- pub fn new(params: (usize, usize)) -> Self {
- Self { params }
+ pub fn new(function: Ref<MediumLevelILFunction>, address: u64, params: (usize, usize)) -> Self {
+ Self {
+ function,
+ address,
+ params,
+ }
}
- pub fn params(&self, function: &MediumLevelILFunction) -> OperandExprList {
- OperandList::new(function, self.params.1, self.params.0).map_expr()
+ pub fn params(&self) -> OperandExprList {
+ OperandList::new(&self.function, self.params.1, self.params.0).map_expr()
}
- pub fn lift(&self, function: &MediumLevelILFunction) -> LiftedSharedParamSlot {
+ pub fn lift(&self) -> LiftedSharedParamSlot {
LiftedSharedParamSlot {
- params: self.params(function).map(|instr| instr.lift()).collect(),
+ function: self.function.clone(),
+ address: self.address,
+ params: self.params().map(|instr| instr.lift()).collect(),
}
}
- pub fn operands(
- &self,
- function: &MediumLevelILFunction,
- ) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
- [("params", MediumLevelILOperand::ExprList(self.params(function)))].into_iter()
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ [("params", MediumLevelILOperand::ExprList(self.params()))].into_iter()
}
}
// VAR, ADDRESS_OF
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Var {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Variable,
}
impl Var {
- pub fn new(src: u64) -> Self {
- Self { src: get_var(src) }
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, src: u64) -> Self {
+ Self {
+ function,
+ address,
+ src: get_var(src),
+ }
}
pub fn src(&self) -> Variable {
self.src
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ 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)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Field {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: Variable,
pub offset: u64,
}
impl Field {
- pub fn new(src: u64, offset: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: u64,
+ offset: u64,
+ ) -> Self {
Self {
+ function,
+ address,
src: get_var(src),
offset,
}
@@ -2164,7 +2700,7 @@ impl Field {
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("src", MediumLevelILOperand::Var(self.src())),
("offset", MediumLevelILOperand::Int(self.offset())),
@@ -2174,33 +2710,50 @@ impl Field {
}
// VAR_SSA, VAR_ALIASED
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct VarSsa {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: SSAVariable,
}
impl VarSsa {
- pub fn new(src: (u64, usize)) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: (u64, usize),
+ ) -> Self {
Self {
+ function,
+ address,
src: get_var_ssa(src.0, src.1),
}
}
pub fn src(&self) -> SSAVariable {
self.src
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ 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)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct VarSsaField {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub src: SSAVariable,
pub offset: u64,
}
impl VarSsaField {
- pub fn new(src: (u64, usize), offset: u64) -> Self {
+ pub(crate) fn new(
+ function: Ref<MediumLevelILFunction>,
+ address: u64,
+ src: (u64, usize),
+ offset: u64,
+ ) -> Self {
Self {
+ function,
+ address,
src: get_var_ssa(src.0, src.1),
offset,
}
@@ -2211,7 +2764,7 @@ impl VarSsaField {
pub fn offset(&self) -> u64 {
self.offset
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> + '_ {
[
("src", MediumLevelILOperand::VarSsa(self.src())),
("offset", MediumLevelILOperand::Int(self.offset())),
@@ -2221,18 +2774,24 @@ impl VarSsaField {
}
// TRAP
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Trap {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
pub vector: u64,
}
impl Trap {
- pub fn new(vector: u64) -> Self {
- Self { vector }
+ pub(crate) fn new(function: Ref<MediumLevelILFunction>, address: u64, vector: u64) -> Self {
+ Self {
+ function,
+ address,
+ vector,
+ }
}
pub fn vector(&self) -> u64 {
self.vector
}
- pub fn operands(&self) -> impl Iterator<Item = (&'static str, MediumLevelILOperand)> {
+ 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 2d67522d..5463ce39 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -23,6 +23,7 @@ use crate::{
binaryview::{BinaryView, BinaryViewExt},
callingconvention::CallingConvention,
filemetadata::FileMetadata,
+ function::Function,
rc::*,
string::{raw_to_string, BnStr, BnStrCompatible, BnString},
symbol::Symbol,
@@ -2585,6 +2586,161 @@ impl<S: BnStrCompatible> DataVariableAndName<S> {
}
}
+/////////////////////////
+// ILIntrinsic
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub struct ILIntrinsic {
+ arch: CoreArchitecture,
+ index: u32,
+}
+
+impl ILIntrinsic {
+ pub(crate) fn new(arch: CoreArchitecture, index: u32) -> Self {
+ Self { arch, index }
+ }
+
+ pub fn name(&self) -> &str {
+ let name_ptr = unsafe { BNGetArchitectureIntrinsicName(self.arch.0, self.index) };
+ let name_raw = unsafe { core::ffi::CStr::from_ptr(name_ptr) };
+ name_raw.to_str().unwrap()
+ }
+
+ // TODO impl inputs and outputs function
+}
+
+/////////////////////////
+// RegisterValueType
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub enum RegisterValueType {
+ UndeterminedValue,
+ EntryValue,
+ ConstantValue,
+ ConstantPointerValue,
+ ExternalPointerValue,
+ StackFrameOffset,
+ ReturnAddressValue,
+ ImportedAddressValue,
+ SignedRangeValue,
+ UnsignedRangeValue,
+ LookupTableValue,
+ InSetOfValues,
+ NotInSetOfValues,
+ ConstantDataValue,
+ ConstantDataZeroExtendValue,
+ ConstantDataSignExtendValue,
+ ConstantDataAggregateValue,
+}
+
+impl RegisterValueType {
+ pub(crate) fn from_raw_value(value: u32) -> Option<Self> {
+ use BNRegisterValueType::*;
+ Some(match value {
+ x if x == UndeterminedValue as u32 => Self::UndeterminedValue,
+ x if x == EntryValue as u32 => Self::EntryValue,
+ x if x == ConstantValue as u32 => Self::ConstantValue,
+ x if x == ConstantPointerValue as u32 => Self::ConstantPointerValue,
+ x if x == ExternalPointerValue as u32 => Self::ExternalPointerValue,
+ x if x == StackFrameOffset as u32 => Self::StackFrameOffset,
+ x if x == ReturnAddressValue as u32 => Self::ReturnAddressValue,
+ x if x == ImportedAddressValue as u32 => Self::ImportedAddressValue,
+ x if x == SignedRangeValue as u32 => Self::SignedRangeValue,
+ x if x == UnsignedRangeValue as u32 => Self::UnsignedRangeValue,
+ x if x == LookupTableValue as u32 => Self::LookupTableValue,
+ x if x == InSetOfValues as u32 => Self::InSetOfValues,
+ x if x == NotInSetOfValues as u32 => Self::NotInSetOfValues,
+ x if x == ConstantDataValue as u32 => Self::ConstantDataValue,
+ x if x == ConstantDataZeroExtendValue as u32 => Self::ConstantDataZeroExtendValue,
+ x if x == ConstantDataSignExtendValue as u32 => Self::ConstantDataSignExtendValue,
+ x if x == ConstantDataAggregateValue as u32 => Self::ConstantDataAggregateValue,
+ _ => return None,
+ })
+ }
+
+ pub(crate) fn into_raw_value(self) -> BNRegisterValueType {
+ use BNRegisterValueType::*;
+ match self {
+ Self::UndeterminedValue => UndeterminedValue,
+ Self::EntryValue => EntryValue,
+ Self::ConstantValue => ConstantValue,
+ Self::ConstantPointerValue => ConstantPointerValue,
+ Self::ExternalPointerValue => ExternalPointerValue,
+ Self::StackFrameOffset => StackFrameOffset,
+ Self::ReturnAddressValue => ReturnAddressValue,
+ Self::ImportedAddressValue => ImportedAddressValue,
+ Self::SignedRangeValue => SignedRangeValue,
+ Self::UnsignedRangeValue => UnsignedRangeValue,
+ Self::LookupTableValue => LookupTableValue,
+ Self::InSetOfValues => InSetOfValues,
+ Self::NotInSetOfValues => NotInSetOfValues,
+ Self::ConstantDataValue => ConstantDataValue,
+ Self::ConstantDataZeroExtendValue => ConstantDataZeroExtendValue,
+ Self::ConstantDataSignExtendValue => ConstantDataSignExtendValue,
+ Self::ConstantDataAggregateValue => ConstantDataAggregateValue,
+ }
+ }
+}
+
+/////////////////////////
+// RegisterValue
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct RegisterValue {
+ pub(crate) state: RegisterValueType,
+ pub(crate) value: i64,
+ pub(crate) offset: i64,
+ pub(crate) size: usize,
+}
+
+impl RegisterValue {
+ pub fn new(state: RegisterValueType, value: i64, offset: i64, size: usize) -> Self {
+ Self {
+ state,
+ value,
+ offset,
+ size,
+ }
+ }
+}
+
+impl From<BNRegisterValue> for RegisterValue {
+ fn from(value: BNRegisterValue) -> Self {
+ Self {
+ state: RegisterValueType::from_raw_value(value.state as u32).unwrap(),
+ value: value.value,
+ offset: value.offset,
+ size: value.size,
+ }
+ }
+}
+
+impl From<RegisterValue> for BNRegisterValue {
+ fn from(value: RegisterValue) -> Self {
+ Self {
+ state: value.state.into_raw_value(),
+ value: value.value,
+ offset: value.offset,
+ size: value.size,
+ }
+ }
+}
+
+/////////////////////////
+// ConstantData
+
+#[derive(Clone, Debug, PartialEq, Hash)]
+pub struct ConstantData {
+ function: Ref<Function>,
+ value: RegisterValue,
+}
+
+impl ConstantData {
+ pub(crate) fn new(function: Ref<Function>, value: RegisterValue) -> Self {
+ Self { function, value }
+ }
+}
+
// unsafe impl<S: BnStrCompatible> CoreArrayProvider for DataVariableAndName<S> {
// type Raw = BNDataVariableAndName;
// type Context = ();