summaryrefslogtreecommitdiff
path: root/rust/src/mlil/instruction.rs
diff options
context:
space:
mode:
authorMichael Krasnitski <michael.krasnitski@gmail.com>2024-02-07 11:44:06 -0500
committerKyle Martin <krm504@nyu.edu>2024-03-18 17:46:37 -0400
commit5fcf6bc59ebc2110d053360d223e6570cdd2272c (patch)
treeed6eafd132cf53fd9e7105f541967324b4165db0 /rust/src/mlil/instruction.rs
parentbdd012af7941c7d17b97b3e69628a7bc7cc2411e (diff)
Refactor MLIL instructions
* Turn `MediumLevelILInstruction` into a struct with a `kind` field to indicate the instruction variant, and pull out the `function` and `address` fields from each variant to live in the top-level struct. * Make variant fields public, remove field getter methods and centralize lifting logic to happen all at once. Split tuple fields into individual named fields. * Move the `operands` method to `MediumLevelILLiftedInstruction`, and make it return an owned `Vec` of operands rather than a borrowed iterator.
Diffstat (limited to 'rust/src/mlil/instruction.rs')
-rw-r--r--rust/src/mlil/instruction.rs1255
1 files changed, 475 insertions, 780 deletions
diff --git a/rust/src/mlil/instruction.rs b/rust/src/mlil/instruction.rs
index 306a1352..50154f34 100644
--- a/rust/src/mlil/instruction.rs
+++ b/rust/src/mlil/instruction.rs
@@ -1,19 +1,27 @@
use binaryninjacore_sys::BNGetMediumLevelILByIndex;
use binaryninjacore_sys::BNMediumLevelILOperation;
-use crate::mlil::MediumLevelILLiftedInstruction;
use crate::rc::Ref;
+use crate::types::ILIntrinsic;
+use super::lift::*;
use super::operation::*;
use super::MediumLevelILFunction;
#[derive(Clone)]
-pub enum MediumLevelILInstruction {
- Nop(NoArgs),
- Noret(NoArgs),
- Bp(NoArgs),
- Undef(NoArgs),
- Unimpl(NoArgs),
+pub struct MediumLevelILInstruction {
+ pub function: Ref<MediumLevelILFunction>,
+ pub address: u64,
+ pub kind: MediumLevelILInstructionKind,
+}
+
+#[derive(Copy, Clone)]
+pub enum MediumLevelILInstructionKind {
+ Nop,
+ Noret,
+ Bp,
+ Undef,
+ Unimpl,
If(MediumLevelILOperationIf),
FloatConst(FloatConst),
Const(Constant),
@@ -147,7 +155,7 @@ impl core::fmt::Debug for MediumLevelILInstruction {
f,
"<{} at 0x{:08}>",
core::any::type_name::<Self>(),
- self.address(),
+ self.address,
)
}
}
@@ -156,54 +164,37 @@ impl MediumLevelILInstruction {
pub(crate) fn new(function: Ref<MediumLevelILFunction>, idx: usize) -> Self {
let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) };
use BNMediumLevelILOperation::*;
- use MediumLevelILInstruction as Op;
- match op.operation {
- MLIL_NOP => Op::Nop(NoArgs::new(function, op.address)),
- MLIL_NORET => Op::Noret(NoArgs::new(function, op.address)),
- MLIL_BP => Op::Bp(NoArgs::new(function, op.address)),
- MLIL_UNDEF => Op::Undef(NoArgs::new(function, op.address)),
- MLIL_UNIMPL => Op::Unimpl(NoArgs::new(function, op.address)),
+ use MediumLevelILInstructionKind as Op;
+ let kind = match op.operation {
+ MLIL_NOP => Op::Nop,
+ MLIL_NORET => Op::Noret,
+ MLIL_BP => Op::Bp,
+ MLIL_UNDEF => Op::Undef,
+ MLIL_UNIMPL => Op::Unimpl,
MLIL_IF => Op::If(MediumLevelILOperationIf::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
)),
- MLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(
- function,
- op.address,
- op.operands[0],
- op.size,
- )),
- MLIL_CONST => Op::Const(Constant::new(function, op.address, op.operands[0])),
- MLIL_CONST_PTR => Op::ConstPtr(Constant::new(function, op.address, op.operands[0])),
- MLIL_IMPORT => Op::Import(Constant::new(function, op.address, op.operands[0])),
- MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(
- function,
- op.address,
- op.operands[0],
- op.operands[1],
- )),
+ MLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(op.operands[0], op.size)),
+ MLIL_CONST => Op::Const(Constant::new(op.operands[0])),
+ MLIL_CONST_PTR => Op::ConstPtr(Constant::new(op.operands[0])),
+ MLIL_IMPORT => Op::Import(Constant::new(op.operands[0])),
+ MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(op.operands[0], op.operands[1])),
MLIL_CONST_DATA => Op::ConstData(ConstantData::new(
- function,
- op.address,
- (op.operands[0], op.operands[1]),
+ op.operands[0] as u32,
+ op.operands[1] as i64,
op.size,
)),
- MLIL_JUMP => Op::Jump(Jump::new(function, op.address, op.operands[0] as usize)),
- MLIL_RET_HINT => Op::RetHint(Jump::new(function, op.address, op.operands[0] as usize)),
+ MLIL_JUMP => Op::Jump(Jump::new(op.operands[0] as usize)),
+ MLIL_RET_HINT => Op::RetHint(Jump::new(op.operands[0] as usize)),
MLIL_STORE_SSA => Op::StoreSsa(StoreSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
op.operands[3] as usize,
)),
MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
@@ -211,1099 +202,803 @@ impl MediumLevelILInstruction {
op.operands[4] as usize,
)),
MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2] as usize,
)),
- MLIL_STORE => Op::Store(Store::new(
- function,
- op.address,
- op.operands[0] as usize,
- op.operands[1] as usize,
- )),
+ MLIL_STORE => Op::Store(Store::new(op.operands[0] as usize, op.operands[1] as usize)),
MLIL_JUMP_TO => Op::JumpTo(JumpTo::new(
- function,
- op.address,
op.operands[0] as usize,
- (op.operands[1] as usize, op.operands[2] as usize),
+ op.operands[1] as usize,
+ op.operands[2] as usize,
)),
- MLIL_GOTO => Op::Goto(Goto::new(function, op.address, op.operands[0])),
- MLIL_FREE_VAR_SLOT => {
- Op::FreeVarSlot(FreeVarSlot::new(function, op.address, op.operands[0]))
- }
+ MLIL_GOTO => Op::Goto(Goto::new(op.operands[0])),
+ MLIL_FREE_VAR_SLOT => Op::FreeVarSlot(FreeVarSlot::new(op.operands[0])),
MLIL_SET_VAR_FIELD => Op::SetVarField(SetVarField::new(
- function,
- op.address,
op.operands[0],
op.operands[1],
op.operands[2] as usize,
)),
- MLIL_SET_VAR => Op::SetVar(SetVar::new(
- function,
- op.address,
- op.operands[0],
- op.operands[1] as usize,
- )),
+ MLIL_SET_VAR => Op::SetVar(SetVar::new(op.operands[0], op.operands[1] as usize)),
MLIL_FREE_VAR_SLOT_SSA => Op::FreeVarSlotSsa(FreeVarSlotSsa::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
)),
MLIL_SET_VAR_SSA_FIELD => Op::SetVarSsaField(SetVarSsaField::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
op.operands[3],
op.operands[4] as usize,
)),
MLIL_SET_VAR_ALIASED_FIELD => Op::SetVarAliasedField(SetVarSsaField::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
op.operands[3],
op.operands[4] as usize,
)),
MLIL_SET_VAR_ALIASED => Op::SetVarAliased(SetVarAliased::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[0], op.operands[2] as usize),
op.operands[3] as usize,
)),
MLIL_SET_VAR_SSA => Op::SetVarSsa(SetVarSsa::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
op.operands[2] as usize,
)),
MLIL_VAR_PHI => Op::VarPhi(VarPhi::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
- (op.operands[2] as usize, op.operands[3] as usize),
+ op.operands[2] as usize,
+ op.operands[3] as usize,
)),
MLIL_MEM_PHI => Op::MemPhi(MemPhi::new(
- function,
- op.address,
- op.operands[0],
- (op.operands[1] as usize, op.operands[2] as usize),
- )),
- MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new(
- function,
- op.address,
op.operands[0],
- op.operands[1],
+ op.operands[1] as usize,
+ op.operands[2] as usize,
)),
+ MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new(op.operands[0], op.operands[1])),
MLIL_SET_VAR_SPLIT => Op::SetVarSplit(SetVarSplit::new(
- function,
- op.address,
op.operands[0],
op.operands[1],
op.operands[2] as usize,
)),
MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[2], op.operands[3] as usize),
)),
MLIL_SET_VAR_SPLIT_SSA => Op::SetVarSplitSsa(SetVarSplitSsa::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
(op.operands[2], op.operands[3] as usize),
op.operands[4] as usize,
)),
MLIL_ADD => Op::Add(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_SUB => Op::Sub(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_AND => Op::And(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_OR => Op::Or(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_XOR => Op::Xor(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_LSL => Op::Lsl(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_LSR => Op::Lsr(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ASR => Op::Asr(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ROL => Op::Rol(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ROR => Op::Ror(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MUL => Op::Mul(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MULU_DP => Op::MuluDp(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MULS_DP => Op::MulsDp(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVU => Op::Divu(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVU_DP => Op::DivuDp(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVS => Op::Divs(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_DIVS_DP => Op::DivsDp(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODU => Op::Modu(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODU_DP => Op::ModuDp(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODS => Op::Mods(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_MODS_DP => Op::ModsDp(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_E => Op::CmpE(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_NE => Op::CmpNe(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SLE => Op::CmpSle(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_ULE => Op::CmpUle(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SGE => Op::CmpSge(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_UGE => Op::CmpUge(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_TEST_BIT => Op::TestBit(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_E => Op::FcmpE(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_O => Op::FcmpO(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FADD => Op::Fadd(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FSUB => Op::Fsub(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FMUL => Op::Fmul(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_FDIV => Op::Fdiv(BinaryOp::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
)),
MLIL_ADC => Op::Adc(BinaryOpCarry::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_SBB => Op::Sbb(BinaryOpCarry::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_RLC => Op::Rlc(BinaryOpCarry::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_RRC => Op::Rrc(BinaryOpCarry::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_CALL => Op::Call(Call::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
+ op.operands[0] as usize,
+ op.operands[1] as usize,
op.operands[2] as usize,
- (op.operands[3] as usize, op.operands[4] as usize),
+ op.operands[3] as usize,
+ op.operands[4] as usize,
)),
MLIL_TAILCALL => Op::Tailcall(Call::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
+ op.operands[0] as usize,
+ op.operands[1] as usize,
op.operands[2] as usize,
- (op.operands[3] as usize, op.operands[4] as usize),
+ op.operands[3] as usize,
+ op.operands[4] as usize,
)),
MLIL_SYSCALL => Op::Syscall(Syscall::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
- (op.operands[2] as usize, op.operands[3] as usize),
+ op.operands[0] as usize,
+ op.operands[1] as usize,
+ op.operands[2] as usize,
+ op.operands[3] as usize,
)),
MLIL_INTRINSIC => Op::Intrinsic(Intrinsic::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
+ op.operands[0] as usize,
+ op.operands[1] as usize,
op.operands[2] as u32,
- (op.operands[3] as usize, op.operands[4] as usize),
+ op.operands[3] as usize,
+ op.operands[4] as usize,
)),
MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
+ op.operands[0] as usize,
+ op.operands[1] as usize,
op.operands[2] as u32,
- (op.operands[3] as usize, op.operands[4] as usize),
+ op.operands[3] as usize,
+ op.operands[4] as usize,
)),
MLIL_CALL_SSA => Op::CallSsa(CallSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
- (op.operands[2] as usize, op.operands[3] as usize),
+ op.operands[2] as usize,
+ op.operands[3] as usize,
op.operands[4],
)),
MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
- (op.operands[2] as usize, op.operands[3] as usize),
+ op.operands[2] as usize,
+ op.operands[3] as usize,
op.operands[4],
)),
MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_TAILCALL_UNTYPED_SSA => Op::TailcallUntypedSsa(CallUntypedSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa::new(
- function,
- op.address,
op.operands[0] as usize,
- (op.operands[1] as usize, op.operands[2] as usize),
+ op.operands[1] as usize,
+ op.operands[2] as usize,
op.operands[3],
)),
MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
op.operands[3] as usize,
)),
MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1] as usize,
op.operands[2] as usize,
)),
- MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
- )),
- MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
- )),
- MLIL_NEG => Op::Neg(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_NOT => Op::Not(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_SX => Op::Sx(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_ZX => Op::Zx(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_LOW_PART => {
- Op::LowPart(UnaryOp::new(function, op.address, op.operands[0] as usize))
- }
- MLIL_BOOL_TO_INT => {
- Op::BoolToInt(UnaryOp::new(function, op.address, op.operands[0] as usize))
- }
- MLIL_UNIMPL_MEM => {
- Op::UnimplMem(UnaryOp::new(function, op.address, op.operands[0] as usize))
+ MLIL_NEG => Op::Neg(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_NOT => Op::Not(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_SX => Op::Sx(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_ZX => Op::Zx(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_LOW_PART => Op::LowPart(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FSQRT => Op::Fsqrt(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FNEG => Op::Fneg(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FABS => Op::Fabs(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FLOAT_CONV => Op::FloatConv(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FLOOR => Op::Floor(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_CEIL => Op::Ceil(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_LOAD => Op::Load(UnaryOp::new(op.operands[0] as usize)),
+ MLIL_LOAD_STRUCT => {
+ Op::LoadStruct(LoadStruct::new(op.operands[0] as usize, op.operands[1]))
}
- MLIL_FSQRT => Op::Fsqrt(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_FNEG => Op::Fneg(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_FABS => Op::Fabs(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_FLOAT_TO_INT => {
- Op::FloatToInt(UnaryOp::new(function, op.address, op.operands[0] as usize))
- }
- MLIL_INT_TO_FLOAT => {
- Op::IntToFloat(UnaryOp::new(function, op.address, op.operands[0] as usize))
- }
- MLIL_FLOAT_CONV => {
- Op::FloatConv(UnaryOp::new(function, op.address, op.operands[0] as usize))
- }
- MLIL_ROUND_TO_INT => {
- Op::RoundToInt(UnaryOp::new(function, op.address, op.operands[0] as usize))
- }
- MLIL_FLOOR => Op::Floor(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_CEIL => Op::Ceil(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_LOAD => Op::Load(UnaryOp::new(function, op.address, op.operands[0] as usize)),
- MLIL_LOAD_STRUCT => Op::LoadStruct(LoadStruct::new(
- function,
- op.address,
- op.operands[0] as usize,
- op.operands[1],
- )),
MLIL_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa::new(
- function,
- op.address,
op.operands[0] as usize,
op.operands[1],
op.operands[2],
)),
- MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa::new(
- function,
- op.address,
+ MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa::new(op.operands[0] as usize, op.operands[1])),
+ MLIL_RET => Op::Ret(Ret::new(op.operands[0] as usize, op.operands[1] as usize)),
+ MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList::new(
op.operands[0] as usize,
- op.operands[1],
- )),
- MLIL_RET => Op::Ret(Ret::new(
- function,
- op.address,
- (op.operands[0] as usize, op.operands[1] as usize),
- )),
- MLIL_VAR => Op::Var(Var::new(function, op.address, op.operands[0])),
- MLIL_ADDRESS_OF => Op::AddressOf(Var::new(function, op.address, op.operands[0])),
- MLIL_VAR_FIELD => Op::VarField(Field::new(
- function,
- op.address,
- op.operands[0],
- op.operands[1],
- )),
- MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field::new(
- function,
- op.address,
- op.operands[0],
- op.operands[1],
- )),
- MLIL_VAR_SSA => Op::VarSsa(VarSsa::new(
- function,
- op.address,
- (op.operands[0], op.operands[1] as usize),
+ op.operands[1] as usize,
)),
- MLIL_VAR_ALIASED => Op::VarAliased(VarSsa::new(
- function,
- op.address,
- (op.operands[0], op.operands[1] as usize),
+ MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot::new(
+ op.operands[0] as usize,
+ op.operands[1] as usize,
)),
+ MLIL_VAR => Op::Var(Var::new(op.operands[0])),
+ MLIL_ADDRESS_OF => Op::AddressOf(Var::new(op.operands[0])),
+ MLIL_VAR_FIELD => Op::VarField(Field::new(op.operands[0], op.operands[1])),
+ MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field::new(op.operands[0], op.operands[1])),
+ MLIL_VAR_SSA => Op::VarSsa(VarSsa::new((op.operands[0], op.operands[1] as usize))),
+ MLIL_VAR_ALIASED => {
+ Op::VarAliased(VarSsa::new((op.operands[0], op.operands[1] as usize)))
+ }
MLIL_VAR_SSA_FIELD => Op::VarSsaField(VarSsaField::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
op.operands[2],
)),
MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField::new(
- function,
- op.address,
(op.operands[0], op.operands[1] as usize),
op.operands[2],
)),
- MLIL_TRAP => Op::Trap(Trap::new(function, op.address, op.operands[0])),
+ MLIL_TRAP => Op::Trap(Trap::new(op.operands[0])),
// translated directly into a list for Expression or Variables
// TODO MLIL_MEMORY_INTRINSIC_SSA needs to be handled properly
MLIL_CALL_OUTPUT | MLIL_CALL_PARAM | MLIL_CALL_PARAM_SSA | MLIL_CALL_OUTPUT_SSA | MLIL_MEMORY_INTRINSIC_OUTPUT_SSA | MLIL_MEMORY_INTRINSIC_SSA => {
unreachable!()
}
+ };
+
+ Self {
+ function,
+ address: op.address,
+ kind,
}
}
- pub fn function(&self) -> &MediumLevelILFunction {
- use MediumLevelILInstruction::*;
- match self {
- Nop(op) => &op.function,
- Noret(op) => &op.function,
- Bp(op) => &op.function,
- Undef(op) => &op.function,
- Unimpl(op) => &op.function,
- If(op) => &op.function,
- FloatConst(op) => &op.function,
- Const(op) => &op.function,
- ConstPtr(op) => &op.function,
- Import(op) => &op.function,
- ExternPtr(op) => &op.function,
- ConstData(op) => &op.function,
- Jump(op) => &op.function,
- RetHint(op) => &op.function,
- StoreSsa(op) => &op.function,
- StoreStructSsa(op) => &op.function,
- StoreStruct(op) => &op.function,
- Store(op) => &op.function,
- JumpTo(op) => &op.function,
- Goto(op) => &op.function,
- FreeVarSlot(op) => &op.function,
- SetVarField(op) => &op.function,
- SetVar(op) => &op.function,
- FreeVarSlotSsa(op) => &op.function,
- SetVarSsaField(op) => &op.function,
- SetVarAliasedField(op) => &op.function,
- SetVarAliased(op) => &op.function,
- SetVarSsa(op) => &op.function,
- VarPhi(op) => &op.function,
- MemPhi(op) => &op.function,
- VarSplit(op) => &op.function,
- SetVarSplit(op) => &op.function,
- VarSplitSsa(op) => &op.function,
- SetVarSplitSsa(op) => &op.function,
- Add(op) => &op.function,
- Sub(op) => &op.function,
- And(op) => &op.function,
- Or(op) => &op.function,
- Xor(op) => &op.function,
- Lsl(op) => &op.function,
- Lsr(op) => &op.function,
- Asr(op) => &op.function,
- Rol(op) => &op.function,
- Ror(op) => &op.function,
- Mul(op) => &op.function,
- MuluDp(op) => &op.function,
- MulsDp(op) => &op.function,
- Divu(op) => &op.function,
- DivuDp(op) => &op.function,
- Divs(op) => &op.function,
- DivsDp(op) => &op.function,
- Modu(op) => &op.function,
- ModuDp(op) => &op.function,
- Mods(op) => &op.function,
- ModsDp(op) => &op.function,
- CmpE(op) => &op.function,
- CmpNe(op) => &op.function,
- CmpSlt(op) => &op.function,
- CmpUlt(op) => &op.function,
- CmpSle(op) => &op.function,
- CmpUle(op) => &op.function,
- CmpSge(op) => &op.function,
- CmpUge(op) => &op.function,
- CmpSgt(op) => &op.function,
- CmpUgt(op) => &op.function,
- TestBit(op) => &op.function,
- AddOverflow(op) => &op.function,
- FcmpE(op) => &op.function,
- FcmpNe(op) => &op.function,
- FcmpLt(op) => &op.function,
- FcmpLe(op) => &op.function,
- FcmpGe(op) => &op.function,
- FcmpGt(op) => &op.function,
- FcmpO(op) => &op.function,
- FcmpUo(op) => &op.function,
- Fadd(op) => &op.function,
- Fsub(op) => &op.function,
- Fmul(op) => &op.function,
- Fdiv(op) => &op.function,
- Adc(op) => &op.function,
- Sbb(op) => &op.function,
- Rlc(op) => &op.function,
- Rrc(op) => &op.function,
- Call(op) => &op.function,
- Tailcall(op) => &op.function,
- Syscall(op) => &op.function,
- Intrinsic(op) => &op.function,
- IntrinsicSsa(op) => &op.function,
- CallSsa(op) => &op.function,
- TailcallSsa(op) => &op.function,
- CallUntypedSsa(op) => &op.function,
- TailcallUntypedSsa(op) => &op.function,
- SyscallSsa(op) => &op.function,
- SyscallUntypedSsa(op) => &op.function,
- CallUntyped(op) => &op.function,
- TailcallUntyped(op) => &op.function,
- SyscallUntyped(op) => &op.function,
- SeparateParamList(op) => &op.function,
- SharedParamSlot(op) => &op.function,
- Neg(op) => &op.function,
- Not(op) => &op.function,
- Sx(op) => &op.function,
- Zx(op) => &op.function,
- LowPart(op) => &op.function,
- BoolToInt(op) => &op.function,
- UnimplMem(op) => &op.function,
- Fsqrt(op) => &op.function,
- Fneg(op) => &op.function,
- Fabs(op) => &op.function,
- FloatToInt(op) => &op.function,
- IntToFloat(op) => &op.function,
- FloatConv(op) => &op.function,
- RoundToInt(op) => &op.function,
- Floor(op) => &op.function,
- Ceil(op) => &op.function,
- Ftrunc(op) => &op.function,
- Load(op) => &op.function,
- LoadStruct(op) => &op.function,
- LoadStructSsa(op) => &op.function,
- LoadSsa(op) => &op.function,
- Ret(op) => &op.function,
- Var(op) => &op.function,
- AddressOf(op) => &op.function,
- VarField(op) => &op.function,
- AddressOfField(op) => &op.function,
- VarSsa(op) => &op.function,
- VarAliased(op) => &op.function,
- VarSsaField(op) => &op.function,
- VarAliasedField(op) => &op.function,
- Trap(op) => &op.function,
+ pub fn lift(&self) -> MediumLevelILLiftedInstruction {
+ use MediumLevelILInstructionKind::*;
+ use MediumLevelILLiftedInstructionKind as Lifted;
+
+ let kind = match self.kind {
+ Nop => Lifted::Nop,
+ Noret => Lifted::Noret,
+ Bp => Lifted::Bp,
+ Undef => Lifted::Undef,
+ Unimpl => Lifted::Unimpl,
+ If(op) => Lifted::If(LiftedIf {
+ condition: self.lift_operand(op.condition),
+ dest_true: op.dest_true,
+ dest_false: op.dest_false,
+ }),
+
+ FloatConst(op) => Lifted::FloatConst(op),
+ Const(op) => Lifted::Const(op),
+ ConstPtr(op) => Lifted::ConstPtr(op),
+ Import(op) => Lifted::Import(op),
+ ExternPtr(op) => Lifted::ExternPtr(op),
+
+ ConstData(op) => Lifted::ConstData(LiftedConstantData {
+ constant_data: get_constant_data(
+ &self.function,
+ op.constant_data_kind,
+ op.constant_data_value,
+ op.size,
+ ),
+ }),
+ Jump(op) => Lifted::Jump(LiftedJump {
+ dest: self.lift_operand(op.dest),
+ }),
+ RetHint(op) => Lifted::RetHint(LiftedJump {
+ dest: self.lift_operand(op.dest),
+ }),
+ StoreSsa(op) => Lifted::StoreSsa(LiftedStoreSsa {
+ dest: self.lift_operand(op.dest),
+ dest_memory: op.dest_memory,
+ src_memory: op.src_memory,
+ src: self.lift_operand(op.src),
+ }),
+ StoreStructSsa(op) => Lifted::StoreStructSsa(LiftedStoreStructSsa {
+ dest: self.lift_operand(op.dest),
+ offset: op.offset,
+ dest_memory: op.dest_memory,
+ src_memory: op.src_memory,
+ src: self.lift_operand(op.src),
+ }),
+ StoreStruct(op) => Lifted::StoreStruct(LiftedStoreStruct {
+ dest: self.lift_operand(op.dest),
+ offset: op.offset,
+ src: self.lift_operand(op.src),
+ }),
+ Store(op) => Lifted::Store(LiftedStore {
+ dest: self.lift_operand(op.dest),
+ src: self.lift_operand(op.src),
+ }),
+ JumpTo(op) => Lifted::JumpTo(LiftedJumpTo {
+ dest: self.lift_operand(op.dest),
+ targets: OperandIter::new(&self.function, op.first_operand, op.num_operands)
+ .as_pairs()
+ .collect(),
+ }),
+ Goto(op) => Lifted::Goto(op),
+ FreeVarSlot(op) => Lifted::FreeVarSlot(op),
+ SetVarField(op) => Lifted::SetVarField(LiftedSetVarField {
+ dest: op.dest,
+ offset: op.offset,
+ src: self.lift_operand(op.src),
+ }),
+ SetVar(op) => Lifted::SetVar(LiftedSetVar {
+ dest: op.dest,
+ src: self.lift_operand(op.src),
+ }),
+ FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op),
+ SetVarSsaField(op) => Lifted::SetVarSsaField(LiftedSetVarSsaField {
+ dest: op.dest,
+ prev: op.prev,
+ offset: op.offset,
+ src: self.lift_operand(op.src),
+ }),
+ SetVarAliasedField(op) => Lifted::SetVarAliasedField(LiftedSetVarSsaField {
+ dest: op.dest,
+ prev: op.prev,
+ offset: op.offset,
+ src: self.lift_operand(op.src),
+ }),
+ SetVarAliased(op) => Lifted::SetVarAliased(LiftedSetVarAliased {
+ dest: op.dest,
+ prev: op.prev,
+ src: self.lift_operand(op.src),
+ }),
+ SetVarSsa(op) => Lifted::SetVarSsa(LiftedSetVarSsa {
+ dest: op.dest,
+ src: self.lift_operand(op.src),
+ }),
+ VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
+ dest: op.dest,
+ src: OperandIter::new(&self.function, op.first_operand, op.num_operands)
+ .as_ssa_vars()
+ .collect(),
+ }),
+ MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
+ dest_memory: op.dest_memory,
+ src_memory: OperandIter::new(&self.function, op.first_operand, op.num_operands)
+ .collect(),
+ }),
+ VarSplit(op) => Lifted::VarSplit(op),
+ SetVarSplit(op) => Lifted::SetVarSplit(LiftedSetVarSplit {
+ high: op.high,
+ low: op.low,
+ src: self.lift_operand(op.src),
+ }),
+ VarSplitSsa(op) => Lifted::VarSplitSsa(op),
+ SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(LiftedSetVarSplitSsa {
+ high: op.high,
+ low: op.low,
+ src: self.lift_operand(op.src),
+ }),
+
+ Add(op) => Lifted::Add(self.lift_binary_op(op)),
+ Sub(op) => Lifted::Sub(self.lift_binary_op(op)),
+ And(op) => Lifted::And(self.lift_binary_op(op)),
+ Or(op) => Lifted::Or(self.lift_binary_op(op)),
+ Xor(op) => Lifted::Xor(self.lift_binary_op(op)),
+ Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)),
+ Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)),
+ Asr(op) => Lifted::Asr(self.lift_binary_op(op)),
+ Rol(op) => Lifted::Rol(self.lift_binary_op(op)),
+ Ror(op) => Lifted::Ror(self.lift_binary_op(op)),
+ Mul(op) => Lifted::Mul(self.lift_binary_op(op)),
+ MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)),
+ MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)),
+ Divu(op) => Lifted::Divu(self.lift_binary_op(op)),
+ DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)),
+ Divs(op) => Lifted::Divs(self.lift_binary_op(op)),
+ DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)),
+ Modu(op) => Lifted::Modu(self.lift_binary_op(op)),
+ ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)),
+ Mods(op) => Lifted::Mods(self.lift_binary_op(op)),
+ ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)),
+ CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)),
+ CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)),
+ CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)),
+ CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)),
+ CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)),
+ CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)),
+ CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)),
+ CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)),
+ CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)),
+ CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)),
+ TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)),
+ AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)),
+ FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)),
+ FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)),
+ FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)),
+ FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)),
+ FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)),
+ FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)),
+ FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)),
+ FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)),
+ Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)),
+ Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)),
+ Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)),
+ Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)),
+
+ Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)),
+ Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)),
+ Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)),
+ Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)),
+
+ Call(op) => Lifted::Call(self.lift_call(op)),
+ Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
+
+ Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic {
+ output: OperandIter::new(&self.function, op.first_output, op.num_outputs)
+ .as_vars()
+ .collect(),
+ intrinsic: ILIntrinsic::new(self.function.get_function().arch(), op.intrinsic),
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }),
+ Syscall(op) => Lifted::Syscall(LiftedSyscallCall {
+ output: OperandIter::new(&self.function, op.first_output, op.num_outputs)
+ .as_vars()
+ .collect(),
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }),
+ IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
+ output: OperandIter::new(&self.function, op.first_output, op.num_outputs)
+ .as_ssa_vars()
+ .collect(),
+ intrinsic: ILIntrinsic::new(self.function.get_function().arch(), op.intrinsic),
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }),
+
+ CallSsa(op) => Lifted::CallSsa(self.lift_call_ssa(op)),
+ TailcallSsa(op) => Lifted::TailcallSsa(self.lift_call_ssa(op)),
+
+ CallUntypedSsa(op) => Lifted::CallUntypedSsa(self.lift_call_untyped_ssa(op)),
+ TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(self.lift_call_untyped_ssa(op)),
+
+ SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa {
+ output: get_call_output_ssa(&self.function, op.output).collect(),
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ src_memory: op.src_memory,
+ }),
+ SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(LiftedSyscallUntypedSsa {
+ output: get_call_output_ssa(&self.function, op.output).collect(),
+ params: get_call_params_ssa(&self.function, op.params)
+ .map(|param| param.lift())
+ .collect(),
+ stack: self.lift_operand(op.stack),
+ }),
+
+ CallUntyped(op) => Lifted::CallUntyped(self.lift_call_untyped(op)),
+ TailcallUntyped(op) => Lifted::TailcallUntyped(self.lift_call_untyped(op)),
+ SyscallUntyped(op) => Lifted::SyscallUntyped(LiftedSyscallUntyped {
+ output: get_call_output(&self.function, op.output).collect(),
+ params: get_call_params(&self.function, op.params)
+ .map(|param| param.lift())
+ .collect(),
+ stack: self.lift_operand(op.stack),
+ }),
+
+ Neg(op) => Lifted::Neg(self.lift_unary_op(op)),
+ Not(op) => Lifted::Not(self.lift_unary_op(op)),
+ Sx(op) => Lifted::Sx(self.lift_unary_op(op)),
+ Zx(op) => Lifted::Zx(self.lift_unary_op(op)),
+ LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)),
+ BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)),
+ UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)),
+ Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)),
+ Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)),
+ Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)),
+ FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)),
+ IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)),
+ FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)),
+ RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)),
+ Floor(op) => Lifted::Floor(self.lift_unary_op(op)),
+ Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)),
+ Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)),
+ Load(op) => Lifted::Load(self.lift_unary_op(op)),
+
+ LoadStruct(op) => Lifted::LoadStruct(LiftedLoadStruct {
+ src: self.lift_operand(op.src),
+ offset: op.offset,
+ }),
+ LoadStructSsa(op) => Lifted::LoadStructSsa(LiftedLoadStructSsa {
+ src: self.lift_operand(op.src),
+ offset: op.offset,
+ src_memory: op.src_memory,
+ }),
+ LoadSsa(op) => Lifted::LoadSsa(LiftedLoadSsa {
+ src: self.lift_operand(op.src),
+ src_memory: op.src_memory,
+ }),
+ Ret(op) => Lifted::Ret(LiftedRet {
+ src: OperandIter::new(&self.function, op.first_operand, op.num_operands)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }),
+ SeparateParamList(op) => Lifted::SeparateParamList(LiftedSeparateParamList {
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }),
+ SharedParamSlot(op) => Lifted::SharedParamSlot(LiftedSharedParamSlot {
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }),
+ Var(op) => Lifted::Var(op),
+ AddressOf(op) => Lifted::AddressOf(op),
+ VarField(op) => Lifted::VarField(op),
+ AddressOfField(op) => Lifted::AddressOfField(op),
+ VarSsa(op) => Lifted::VarSsa(op),
+ VarAliased(op) => Lifted::VarAliased(op),
+ VarSsaField(op) => Lifted::VarSsaField(op),
+ VarAliasedField(op) => Lifted::VarAliasedField(op),
+ Trap(op) => Lifted::Trap(op),
+ };
+
+ MediumLevelILLiftedInstruction {
+ function: self.function.clone(),
+ address: self.address,
+ kind,
}
}
- pub fn address(&self) -> u64 {
- use MediumLevelILInstruction::*;
- match self {
- Nop(op) => op.address,
- Noret(op) => op.address,
- Bp(op) => op.address,
- Undef(op) => op.address,
- Unimpl(op) => op.address,
- If(op) => op.address,
- FloatConst(op) => op.address,
- Const(op) => op.address,
- ConstPtr(op) => op.address,
- Import(op) => op.address,
- ExternPtr(op) => op.address,
- ConstData(op) => op.address,
- Jump(op) => op.address,
- RetHint(op) => op.address,
- StoreSsa(op) => op.address,
- StoreStructSsa(op) => op.address,
- StoreStruct(op) => op.address,
- Store(op) => op.address,
- JumpTo(op) => op.address,
- Goto(op) => op.address,
- FreeVarSlot(op) => op.address,
- SetVarField(op) => op.address,
- SetVar(op) => op.address,
- FreeVarSlotSsa(op) => op.address,
- SetVarSsaField(op) => op.address,
- SetVarAliasedField(op) => op.address,
- SetVarAliased(op) => op.address,
- SetVarSsa(op) => op.address,
- VarPhi(op) => op.address,
- MemPhi(op) => op.address,
- VarSplit(op) => op.address,
- SetVarSplit(op) => op.address,
- VarSplitSsa(op) => op.address,
- SetVarSplitSsa(op) => op.address,
- Add(op) => op.address,
- Sub(op) => op.address,
- And(op) => op.address,
- Or(op) => op.address,
- Xor(op) => op.address,
- Lsl(op) => op.address,
- Lsr(op) => op.address,
- Asr(op) => op.address,
- Rol(op) => op.address,
- Ror(op) => op.address,
- Mul(op) => op.address,
- MuluDp(op) => op.address,
- MulsDp(op) => op.address,
- Divu(op) => op.address,
- DivuDp(op) => op.address,
- Divs(op) => op.address,
- DivsDp(op) => op.address,
- Modu(op) => op.address,
- ModuDp(op) => op.address,
- Mods(op) => op.address,
- ModsDp(op) => op.address,
- CmpE(op) => op.address,
- CmpNe(op) => op.address,
- CmpSlt(op) => op.address,
- CmpUlt(op) => op.address,
- CmpSle(op) => op.address,
- CmpUle(op) => op.address,
- CmpSge(op) => op.address,
- CmpUge(op) => op.address,
- CmpSgt(op) => op.address,
- CmpUgt(op) => op.address,
- TestBit(op) => op.address,
- AddOverflow(op) => op.address,
- FcmpE(op) => op.address,
- FcmpNe(op) => op.address,
- FcmpLt(op) => op.address,
- FcmpLe(op) => op.address,
- FcmpGe(op) => op.address,
- FcmpGt(op) => op.address,
- FcmpO(op) => op.address,
- FcmpUo(op) => op.address,
- Fadd(op) => op.address,
- Fsub(op) => op.address,
- Fmul(op) => op.address,
- Fdiv(op) => op.address,
- Adc(op) => op.address,
- Sbb(op) => op.address,
- Rlc(op) => op.address,
- Rrc(op) => op.address,
- Call(op) => op.address,
- Tailcall(op) => op.address,
- Syscall(op) => op.address,
- Intrinsic(op) => op.address,
- IntrinsicSsa(op) => op.address,
- CallSsa(op) => op.address,
- TailcallSsa(op) => op.address,
- CallUntypedSsa(op) => op.address,
- TailcallUntypedSsa(op) => op.address,
- SyscallSsa(op) => op.address,
- SyscallUntypedSsa(op) => op.address,
- CallUntyped(op) => op.address,
- TailcallUntyped(op) => op.address,
- SyscallUntyped(op) => op.address,
- SeparateParamList(op) => op.address,
- SharedParamSlot(op) => op.address,
- Neg(op) => op.address,
- Not(op) => op.address,
- Sx(op) => op.address,
- Zx(op) => op.address,
- LowPart(op) => op.address,
- BoolToInt(op) => op.address,
- UnimplMem(op) => op.address,
- Fsqrt(op) => op.address,
- Fneg(op) => op.address,
- Fabs(op) => op.address,
- FloatToInt(op) => op.address,
- IntToFloat(op) => op.address,
- FloatConv(op) => op.address,
- RoundToInt(op) => op.address,
- Floor(op) => op.address,
- Ceil(op) => op.address,
- Ftrunc(op) => op.address,
- Load(op) => op.address,
- LoadStruct(op) => op.address,
- LoadStructSsa(op) => op.address,
- LoadSsa(op) => op.address,
- Ret(op) => op.address,
- Var(op) => op.address,
- AddressOf(op) => op.address,
- VarField(op) => op.address,
- AddressOfField(op) => op.address,
- VarSsa(op) => op.address,
- VarAliased(op) => op.address,
- VarSsaField(op) => op.address,
- VarAliasedField(op) => op.address,
- Trap(op) => op.address,
+ fn lift_operand(&self, expr_idx: usize) -> Box<MediumLevelILLiftedInstruction> {
+ Box::new(self.function.lifted_instruction_from_idx(expr_idx))
+ }
+
+ fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp {
+ LiftedBinaryOp {
+ left: self.lift_operand(op.left),
+ right: self.lift_operand(op.right),
}
}
- pub fn lift(&self) -> MediumLevelILLiftedInstruction {
- use MediumLevelILInstruction::*;
- use MediumLevelILLiftedInstruction as Lifted;
+ fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry {
+ LiftedBinaryOpCarry {
+ left: self.lift_operand(op.left),
+ right: self.lift_operand(op.right),
+ carry: self.lift_operand(op.carry),
+ }
+ }
- match self {
- Nop(op) => Lifted::Nop(op.clone()),
- Noret(op) => Lifted::Noret(op.clone()),
- Bp(op) => Lifted::Bp(op.clone()),
- Undef(op) => Lifted::Undef(op.clone()),
- Unimpl(op) => Lifted::Unimpl(op.clone()),
- If(op) => Lifted::If(op.lift()),
- FloatConst(op) => Lifted::FloatConst(op.clone()),
- Const(op) => Lifted::Const(op.clone()),
- ConstPtr(op) => Lifted::ConstPtr(op.clone()),
- Import(op) => Lifted::Import(op.clone()),
- ExternPtr(op) => Lifted::ExternPtr(op.clone()),
- ConstData(op) => Lifted::ConstData(op.lift()),
- Jump(op) => Lifted::Jump(op.lift()),
- RetHint(op) => Lifted::RetHint(op.lift()),
- StoreSsa(op) => Lifted::StoreSsa(op.lift()),
- StoreStructSsa(op) => Lifted::StoreStructSsa(op.lift()),
- StoreStruct(op) => Lifted::StoreStruct(op.lift()),
- Store(op) => Lifted::Store(op.lift()),
- JumpTo(op) => Lifted::JumpTo(op.lift()),
- Goto(op) => Lifted::Goto(op.clone()),
- FreeVarSlot(op) => Lifted::FreeVarSlot(op.clone()),
- SetVarField(op) => Lifted::SetVarField(op.lift()),
- SetVar(op) => Lifted::SetVar(op.lift()),
- FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op.lift()),
- SetVarSsaField(op) => Lifted::SetVarSsaField(op.lift()),
- SetVarAliasedField(op) => Lifted::SetVarAliasedField(op.lift()),
- SetVarAliased(op) => Lifted::SetVarAliased(op.lift()),
- SetVarSsa(op) => Lifted::SetVarSsa(op.lift()),
- VarPhi(op) => Lifted::VarPhi(op.lift()),
- MemPhi(op) => Lifted::MemPhi(op.lift()),
- VarSplit(op) => Lifted::VarSplit(op.lift()),
- SetVarSplit(op) => Lifted::SetVarSplit(op.lift()),
- VarSplitSsa(op) => Lifted::VarSplitSsa(op.lift()),
- SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(op.lift()),
- Add(op) => Lifted::Add(op.lift()),
- Sub(op) => Lifted::Sub(op.lift()),
- And(op) => Lifted::And(op.lift()),
- Or(op) => Lifted::Or(op.lift()),
- Xor(op) => Lifted::Xor(op.lift()),
- Lsl(op) => Lifted::Lsl(op.lift()),
- Lsr(op) => Lifted::Lsr(op.lift()),
- Asr(op) => Lifted::Asr(op.lift()),
- Rol(op) => Lifted::Rol(op.lift()),
- Ror(op) => Lifted::Ror(op.lift()),
- Mul(op) => Lifted::Mul(op.lift()),
- MuluDp(op) => Lifted::MuluDp(op.lift()),
- MulsDp(op) => Lifted::MulsDp(op.lift()),
- Divu(op) => Lifted::Divu(op.lift()),
- DivuDp(op) => Lifted::DivuDp(op.lift()),
- Divs(op) => Lifted::Divs(op.lift()),
- DivsDp(op) => Lifted::DivsDp(op.lift()),
- Modu(op) => Lifted::Modu(op.lift()),
- ModuDp(op) => Lifted::ModuDp(op.lift()),
- Mods(op) => Lifted::Mods(op.lift()),
- ModsDp(op) => Lifted::ModsDp(op.lift()),
- CmpE(op) => Lifted::CmpE(op.lift()),
- CmpNe(op) => Lifted::CmpNe(op.lift()),
- CmpSlt(op) => Lifted::CmpSlt(op.lift()),
- CmpUlt(op) => Lifted::CmpUlt(op.lift()),
- CmpSle(op) => Lifted::CmpSle(op.lift()),
- CmpUle(op) => Lifted::CmpUle(op.lift()),
- CmpSge(op) => Lifted::CmpSge(op.lift()),
- CmpUge(op) => Lifted::CmpUge(op.lift()),
- CmpSgt(op) => Lifted::CmpSgt(op.lift()),
- CmpUgt(op) => Lifted::CmpUgt(op.lift()),
- TestBit(op) => Lifted::TestBit(op.lift()),
- AddOverflow(op) => Lifted::AddOverflow(op.lift()),
- FcmpE(op) => Lifted::FcmpE(op.lift()),
- FcmpNe(op) => Lifted::FcmpNe(op.lift()),
- FcmpLt(op) => Lifted::FcmpLt(op.lift()),
- FcmpLe(op) => Lifted::FcmpLe(op.lift()),
- FcmpGe(op) => Lifted::FcmpGe(op.lift()),
- FcmpGt(op) => Lifted::FcmpGt(op.lift()),
- FcmpO(op) => Lifted::FcmpO(op.lift()),
- FcmpUo(op) => Lifted::FcmpUo(op.lift()),
- Fadd(op) => Lifted::Fadd(op.lift()),
- Fsub(op) => Lifted::Fsub(op.lift()),
- Fmul(op) => Lifted::Fmul(op.lift()),
- Fdiv(op) => Lifted::Fdiv(op.lift()),
- Adc(op) => Lifted::Adc(op.lift()),
- Sbb(op) => Lifted::Sbb(op.lift()),
- Rlc(op) => Lifted::Rlc(op.lift()),
- Rrc(op) => Lifted::Rrc(op.lift()),
- Call(op) => Lifted::Call(op.lift()),
- Tailcall(op) => Lifted::Tailcall(op.lift()),
- Intrinsic(op) => Lifted::Intrinsic(op.lift()),
- Syscall(op) => Lifted::Syscall(op.lift()),
- IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift()),
- CallSsa(op) => Lifted::CallSsa(op.lift()),
- TailcallSsa(op) => Lifted::TailcallSsa(op.lift()),
- CallUntypedSsa(op) => Lifted::CallUntypedSsa(op.lift()),
- TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(op.lift()),
- SyscallSsa(op) => Lifted::SyscallSsa(op.lift()),
- SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(op.lift()),
- CallUntyped(op) => Lifted::CallUntyped(op.lift()),
- TailcallUntyped(op) => Lifted::TailcallUntyped(op.lift()),
- SyscallUntyped(op) => Lifted::SyscallUntyped(op.lift()),
- SeparateParamList(op) => Lifted::SeparateParamList(op.lift()),
- SharedParamSlot(op) => Lifted::SharedParamSlot(op.lift()),
- Neg(op) => Lifted::Neg(op.lift()),
- Not(op) => Lifted::Not(op.lift()),
- Sx(op) => Lifted::Sx(op.lift()),
- Zx(op) => Lifted::Zx(op.lift()),
- LowPart(op) => Lifted::LowPart(op.lift()),
- BoolToInt(op) => Lifted::BoolToInt(op.lift()),
- UnimplMem(op) => Lifted::UnimplMem(op.lift()),
- Fsqrt(op) => Lifted::Fsqrt(op.lift()),
- Fneg(op) => Lifted::Fneg(op.lift()),
- Fabs(op) => Lifted::Fabs(op.lift()),
- FloatToInt(op) => Lifted::FloatToInt(op.lift()),
- IntToFloat(op) => Lifted::IntToFloat(op.lift()),
- FloatConv(op) => Lifted::FloatConv(op.lift()),
- RoundToInt(op) => Lifted::RoundToInt(op.lift()),
- Floor(op) => Lifted::Floor(op.lift()),
- Ceil(op) => Lifted::Ceil(op.lift()),
- Ftrunc(op) => Lifted::Ftrunc(op.lift()),
- Load(op) => Lifted::Load(op.lift()),
- LoadStruct(op) => Lifted::LoadStruct(op.lift()),
- LoadStructSsa(op) => Lifted::LoadStructSsa(op.lift()),
- LoadSsa(op) => Lifted::LoadSsa(op.lift()),
- Ret(op) => Lifted::Ret(op.lift()),
- Var(op) => Lifted::Var(op.clone()),
- AddressOf(op) => Lifted::AddressOf(op.clone()),
- VarField(op) => Lifted::VarField(op.clone()),
- AddressOfField(op) => Lifted::AddressOfField(op.clone()),
- VarSsa(op) => Lifted::VarSsa(op.clone()),
- VarAliased(op) => Lifted::VarAliased(op.clone()),
- VarSsaField(op) => Lifted::VarSsaField(op.clone()),
- VarAliasedField(op) => Lifted::VarAliasedField(op.clone()),
- Trap(op) => Lifted::Trap(op.clone()),
+ fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp {
+ LiftedUnaryOp {
+ src: self.lift_operand(op.src),
}
}
- pub fn operands(&self) -> Box<dyn Iterator<Item = (&'static str, MediumLevelILOperand)> + '_> {
- use MediumLevelILInstruction::*;
- match self {
- Nop(_op) | Noret(_op) | Bp(_op) | Undef(_op) | Unimpl(_op) => Box::new([].into_iter()),
- If(op) => Box::new(op.operands()),
- FloatConst(op) => Box::new(op.operands()),
- Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()),
- ExternPtr(op) => Box::new(op.operands()),
- ConstData(op) => Box::new(op.operands()),
- Jump(op) | RetHint(op) => Box::new(op.operands()),
- StoreSsa(op) => Box::new(op.operands()),
- StoreStructSsa(op) => Box::new(op.operands()),
- StoreStruct(op) => Box::new(op.operands()),
- Store(op) => Box::new(op.operands()),
- JumpTo(op) => Box::new(op.operands()),
- Goto(op) => Box::new(op.operands()),
- FreeVarSlot(op) => Box::new(op.operands()),
- SetVarField(op) => Box::new(op.operands()),
- SetVar(op) => Box::new(op.operands()),
- FreeVarSlotSsa(op) => Box::new(op.operands()),
- SetVarSsaField(op) | SetVarAliasedField(op) => Box::new(op.operands()),
- SetVarAliased(op) => Box::new(op.operands()),
- SetVarSsa(op) => Box::new(op.operands()),
- VarPhi(op) => Box::new(op.operands()),
- MemPhi(op) => Box::new(op.operands()),
- VarSplit(op) => Box::new(op.operands()),
- SetVarSplit(op) => Box::new(op.operands()),
- VarSplitSsa(op) => Box::new(op.operands()),
- SetVarSplitSsa(op) => Box::new(op.operands()),
- Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
- | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
- | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
- | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
- | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
- | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
- | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => Box::new(op.operands()),
- Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands()),
- Call(op) | Tailcall(op) => Box::new(op.operands()),
- Syscall(op) => Box::new(op.operands()),
- Intrinsic(op) => Box::new(op.operands()),
- IntrinsicSsa(op) => Box::new(op.operands()),
- CallSsa(op) | TailcallSsa(op) => Box::new(op.operands()),
- CallUntypedSsa(op) | TailcallUntypedSsa(op) => Box::new(op.operands()),
- SyscallSsa(op) => Box::new(op.operands()),
- SyscallUntypedSsa(op) => Box::new(op.operands()),
- CallUntyped(op) | TailcallUntyped(op) => Box::new(op.operands()),
- SyscallUntyped(op) => Box::new(op.operands()),
- SeparateParamList(op) => Box::new(op.operands()),
- SharedParamSlot(op) => Box::new(op.operands()),
- Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
- | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
- | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
- Box::new(op.operands())
- }
- LoadStruct(op) => Box::new(op.operands()),
- LoadStructSsa(op) => Box::new(op.operands()),
- LoadSsa(op) => Box::new(op.operands()),
- Ret(op) => Box::new(op.operands()),
- Var(op) | AddressOf(op) => Box::new(op.operands()),
- VarField(op) | AddressOfField(op) => Box::new(op.operands()),
- VarSsa(op) | VarAliased(op) => Box::new(op.operands()),
- VarSsaField(op) | VarAliasedField(op) => Box::new(op.operands()),
- Trap(op) => Box::new(op.operands()),
+ fn lift_call(&self, op: Call) -> LiftedCall {
+ LiftedCall {
+ output: OperandIter::new(&self.function, op.first_output, op.num_outputs)
+ .as_vars()
+ .collect(),
+ dest: self.lift_operand(op.dest),
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ }
+ }
+
+ fn lift_call_untyped(&self, op: CallUntyped) -> LiftedCallUntyped {
+ LiftedCallUntyped {
+ output: get_call_output(&self.function, op.output).collect(),
+ dest: self.lift_operand(op.dest),
+ params: get_call_params(&self.function, op.params)
+ .map(|expr| expr.lift())
+ .collect(),
+ stack: self.lift_operand(op.stack),
+ }
+ }
+
+ fn lift_call_ssa(&self, op: CallSsa) -> LiftedCallSsa {
+ LiftedCallSsa {
+ output: get_call_output_ssa(&self.function, op.output).collect(),
+ dest: self.lift_operand(op.dest),
+ params: OperandIter::new(&self.function, op.first_param, op.num_params)
+ .as_exprs()
+ .map(|expr| expr.lift())
+ .collect(),
+ src_memory: op.src_memory,
+ }
+ }
+
+ fn lift_call_untyped_ssa(&self, op: CallUntypedSsa) -> LiftedCallUntypedSsa {
+ LiftedCallUntypedSsa {
+ output: get_call_output_ssa(&self.function, op.output).collect(),
+ dest: self.lift_operand(op.dest),
+ params: get_call_params_ssa(&self.function, op.params)
+ .map(|param| param.lift())
+ .collect(),
+ stack: self.lift_operand(op.stack),
}
}
}