initial commit
This commit is contained in:
63
src/mlil/block.rs
Normal file
63
src/mlil/block.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use binaryninjacore_sys::BNGetMediumLevelILIndexForInstruction;
|
||||
|
||||
use crate::basicblock::{BasicBlock, BlockContext};
|
||||
use crate::rc::Ref;
|
||||
|
||||
use super::{MediumLevelILFunction, MediumLevelILInstruction};
|
||||
|
||||
pub struct MediumLevelILBlockIter {
|
||||
function: Ref<MediumLevelILFunction>,
|
||||
range: Range<u64>,
|
||||
}
|
||||
|
||||
impl Iterator for MediumLevelILBlockIter {
|
||||
type Item = MediumLevelILInstruction;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.range
|
||||
.next()
|
||||
.map(|i| unsafe {
|
||||
BNGetMediumLevelILIndexForInstruction(self.function.handle, i as usize)
|
||||
})
|
||||
.map(|i| MediumLevelILInstruction::new(&self.function, i))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MediumLevelILBlock {
|
||||
pub(crate) function: Ref<MediumLevelILFunction>,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for MediumLevelILBlock {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "mlil_bb {:?}", self.function)
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockContext for MediumLevelILBlock {
|
||||
type Iter = MediumLevelILBlockIter;
|
||||
type Instruction = MediumLevelILInstruction;
|
||||
|
||||
fn start(&self, block: &BasicBlock<Self>) -> MediumLevelILInstruction {
|
||||
let expr_idx = unsafe {
|
||||
BNGetMediumLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize)
|
||||
};
|
||||
MediumLevelILInstruction::new(&self.function, expr_idx)
|
||||
}
|
||||
|
||||
fn iter(&self, block: &BasicBlock<Self>) -> MediumLevelILBlockIter {
|
||||
MediumLevelILBlockIter {
|
||||
function: self.function.to_owned(),
|
||||
range: block.raw_start()..block.raw_end(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for MediumLevelILBlock {
|
||||
fn clone(&self) -> Self {
|
||||
MediumLevelILBlock {
|
||||
function: self.function.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
116
src/mlil/function.rs
Normal file
116
src/mlil/function.rs
Normal file
@@ -0,0 +1,116 @@
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
use binaryninjacore_sys::BNFreeMediumLevelILFunction;
|
||||
use binaryninjacore_sys::BNGetMediumLevelILBasicBlockList;
|
||||
use binaryninjacore_sys::BNGetMediumLevelILInstructionCount;
|
||||
use binaryninjacore_sys::BNGetMediumLevelILOwnerFunction;
|
||||
use binaryninjacore_sys::BNGetMediumLevelILSSAForm;
|
||||
use binaryninjacore_sys::BNMediumLevelILFunction;
|
||||
use binaryninjacore_sys::BNMediumLevelILGetInstructionStart;
|
||||
use binaryninjacore_sys::BNNewMediumLevelILFunctionReference;
|
||||
|
||||
use crate::basicblock::BasicBlock;
|
||||
use crate::function::Function;
|
||||
use crate::function::Location;
|
||||
use crate::rc::{Array, Ref, RefCountable};
|
||||
|
||||
use super::{MediumLevelILBlock, MediumLevelILInstruction};
|
||||
|
||||
pub struct MediumLevelILFunction {
|
||||
pub(crate) handle: *mut BNMediumLevelILFunction,
|
||||
}
|
||||
|
||||
unsafe impl Send for MediumLevelILFunction {}
|
||||
unsafe impl Sync for MediumLevelILFunction {}
|
||||
|
||||
impl Eq for MediumLevelILFunction {}
|
||||
impl PartialEq for MediumLevelILFunction {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.handle == rhs.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for MediumLevelILFunction {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl MediumLevelILFunction {
|
||||
pub(crate) unsafe fn from_raw(handle: *mut BNMediumLevelILFunction) -> Self {
|
||||
debug_assert!(!handle.is_null());
|
||||
|
||||
Self { handle }
|
||||
}
|
||||
|
||||
pub fn instruction_at<L: Into<Location>>(&self, loc: L) -> Option<MediumLevelILInstruction> {
|
||||
let loc: Location = loc.into();
|
||||
let arch_handle = loc.arch.unwrap();
|
||||
|
||||
let expr_idx =
|
||||
unsafe { BNMediumLevelILGetInstructionStart(self.handle, arch_handle.0, loc.addr) };
|
||||
|
||||
if expr_idx >= self.instruction_count() {
|
||||
None
|
||||
} else {
|
||||
Some(MediumLevelILInstruction::new(self, expr_idx))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILInstruction {
|
||||
MediumLevelILInstruction::new(self, expr_idx)
|
||||
}
|
||||
|
||||
pub fn instruction_count(&self) -> usize {
|
||||
unsafe { BNGetMediumLevelILInstructionCount(self.handle) }
|
||||
}
|
||||
|
||||
pub fn ssa_form(&self) -> MediumLevelILFunction {
|
||||
let ssa = unsafe { BNGetMediumLevelILSSAForm(self.handle) };
|
||||
assert!(!ssa.is_null());
|
||||
MediumLevelILFunction { handle: ssa }
|
||||
}
|
||||
|
||||
pub fn get_function(&self) -> Ref<Function> {
|
||||
unsafe {
|
||||
let func = BNGetMediumLevelILOwnerFunction(self.handle);
|
||||
Function::from_raw(func)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn basic_blocks(&self) -> Array<BasicBlock<MediumLevelILBlock>> {
|
||||
let mut count = 0;
|
||||
let blocks = unsafe { BNGetMediumLevelILBasicBlockList(self.handle, &mut count) };
|
||||
let context = MediumLevelILBlock {
|
||||
function: self.to_owned(),
|
||||
};
|
||||
|
||||
unsafe { Array::new(blocks, count, context) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOwned for MediumLevelILFunction {
|
||||
type Owned = Ref<Self>;
|
||||
|
||||
fn to_owned(&self) -> Self::Owned {
|
||||
unsafe { RefCountable::inc_ref(self) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl RefCountable for MediumLevelILFunction {
|
||||
unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
|
||||
Ref::new(Self {
|
||||
handle: BNNewMediumLevelILFunctionReference(handle.handle),
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn dec_ref(handle: &Self) {
|
||||
BNFreeMediumLevelILFunction(handle.handle);
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for MediumLevelILFunction {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "<mlil func handle {:p}>", self.handle)
|
||||
}
|
||||
}
|
||||
824
src/mlil/instruction.rs
Normal file
824
src/mlil/instruction.rs
Normal file
@@ -0,0 +1,824 @@
|
||||
use binaryninjacore_sys::BNGetMediumLevelILByIndex;
|
||||
use binaryninjacore_sys::BNMediumLevelILOperation;
|
||||
|
||||
use crate::mlil::MediumLevelILLiftedOperation;
|
||||
use crate::rc::Ref;
|
||||
|
||||
use super::operation::*;
|
||||
use super::{MediumLevelILFunction, MediumLevelILLiftedInstruction};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MediumLevelILInstruction {
|
||||
pub(crate) function: Ref<MediumLevelILFunction>,
|
||||
pub(crate) address: u64,
|
||||
pub(crate) operation: MediumLevelILOperation,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum MediumLevelILOperation {
|
||||
Nop(NoArgs),
|
||||
Noret(NoArgs),
|
||||
Bp(NoArgs),
|
||||
Undef(NoArgs),
|
||||
Unimpl(NoArgs),
|
||||
If(MediumLevelILOperationIf),
|
||||
FloatConst(FloatConst),
|
||||
Const(Constant),
|
||||
ConstPtr(Constant),
|
||||
Import(Constant),
|
||||
ExternPtr(ExternPtr),
|
||||
ConstData(ConstData),
|
||||
Jump(Jump),
|
||||
RetHint(Jump),
|
||||
StoreSsa(StoreSsa),
|
||||
StoreStructSsa(StoreStructSsa),
|
||||
StoreStruct(StoreStruct),
|
||||
Store(Store),
|
||||
JumpTo(JumpTo),
|
||||
Goto(Goto),
|
||||
FreeVarSlot(FreeVarSlot),
|
||||
SetVarField(SetVarField),
|
||||
SetVar(SetVar),
|
||||
FreeVarSlotSsa(FreeVarSlotSsa),
|
||||
SetVarSsaField(SetVarSsaField),
|
||||
SetVarAliasedField(SetVarSsaField),
|
||||
SetVarAliased(SetVarAliased),
|
||||
SetVarSsa(SetVarSsa),
|
||||
VarPhi(VarPhi),
|
||||
MemPhi(MemPhi),
|
||||
VarSplit(VarSplit),
|
||||
SetVarSplit(SetVarSplit),
|
||||
VarSplitSsa(VarSplitSsa),
|
||||
SetVarSplitSsa(SetVarSplitSsa),
|
||||
Add(BinaryOp),
|
||||
Sub(BinaryOp),
|
||||
And(BinaryOp),
|
||||
Or(BinaryOp),
|
||||
Xor(BinaryOp),
|
||||
Lsl(BinaryOp),
|
||||
Lsr(BinaryOp),
|
||||
Asr(BinaryOp),
|
||||
Rol(BinaryOp),
|
||||
Ror(BinaryOp),
|
||||
Mul(BinaryOp),
|
||||
MuluDp(BinaryOp),
|
||||
MulsDp(BinaryOp),
|
||||
Divu(BinaryOp),
|
||||
DivuDp(BinaryOp),
|
||||
Divs(BinaryOp),
|
||||
DivsDp(BinaryOp),
|
||||
Modu(BinaryOp),
|
||||
ModuDp(BinaryOp),
|
||||
Mods(BinaryOp),
|
||||
ModsDp(BinaryOp),
|
||||
CmpE(BinaryOp),
|
||||
CmpNe(BinaryOp),
|
||||
CmpSlt(BinaryOp),
|
||||
CmpUlt(BinaryOp),
|
||||
CmpSle(BinaryOp),
|
||||
CmpUle(BinaryOp),
|
||||
CmpSge(BinaryOp),
|
||||
CmpUge(BinaryOp),
|
||||
CmpSgt(BinaryOp),
|
||||
CmpUgt(BinaryOp),
|
||||
TestBit(BinaryOp),
|
||||
AddOverflow(BinaryOp),
|
||||
FcmpE(BinaryOp),
|
||||
FcmpNe(BinaryOp),
|
||||
FcmpLt(BinaryOp),
|
||||
FcmpLe(BinaryOp),
|
||||
FcmpGe(BinaryOp),
|
||||
FcmpGt(BinaryOp),
|
||||
FcmpO(BinaryOp),
|
||||
FcmpUo(BinaryOp),
|
||||
Fadd(BinaryOp),
|
||||
Fsub(BinaryOp),
|
||||
Fmul(BinaryOp),
|
||||
Fdiv(BinaryOp),
|
||||
Adc(BinaryOpCarry),
|
||||
Sbb(BinaryOpCarry),
|
||||
Rlc(BinaryOpCarry),
|
||||
Rrc(BinaryOpCarry),
|
||||
Call(Call),
|
||||
Tailcall(Call),
|
||||
Syscall(Syscall),
|
||||
Intrinsic(Intrinsic),
|
||||
IntrinsicSsa(IntrinsicSsa),
|
||||
CallSsa(CallSsa),
|
||||
TailcallSsa(CallSsa),
|
||||
CallUntypedSsa(CallUntypedSsa),
|
||||
TailcallUntypedSsa(CallUntypedSsa),
|
||||
SyscallSsa(SyscallSsa),
|
||||
SyscallUntypedSsa(SyscallUntypedSsa),
|
||||
CallUntyped(CallUntyped),
|
||||
TailcallUntyped(CallUntyped),
|
||||
SyscallUntyped(SyscallUntyped),
|
||||
SeparateParamList(SeparateParamList),
|
||||
SharedParamSlot(SharedParamSlot),
|
||||
Neg(UnaryOp),
|
||||
Not(UnaryOp),
|
||||
Sx(UnaryOp),
|
||||
Zx(UnaryOp),
|
||||
LowPart(UnaryOp),
|
||||
BoolToInt(UnaryOp),
|
||||
UnimplMem(UnaryOp),
|
||||
Fsqrt(UnaryOp),
|
||||
Fneg(UnaryOp),
|
||||
Fabs(UnaryOp),
|
||||
FloatToInt(UnaryOp),
|
||||
IntToFloat(UnaryOp),
|
||||
FloatConv(UnaryOp),
|
||||
RoundToInt(UnaryOp),
|
||||
Floor(UnaryOp),
|
||||
Ceil(UnaryOp),
|
||||
Ftrunc(UnaryOp),
|
||||
Load(UnaryOp),
|
||||
LoadStruct(LoadStruct),
|
||||
LoadStructSsa(LoadStructSsa),
|
||||
LoadSsa(LoadSsa),
|
||||
Ret(Ret),
|
||||
Var(Var),
|
||||
AddressOf(Var),
|
||||
VarField(Field),
|
||||
AddressOfField(Field),
|
||||
VarSsa(VarSsa),
|
||||
VarAliased(VarSsa),
|
||||
VarSsaField(VarSsaField),
|
||||
VarAliasedField(VarSsaField),
|
||||
Trap(Trap),
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for MediumLevelILInstruction {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"<{} at 0x{:08}>",
|
||||
core::any::type_name::<Self>(),
|
||||
self.address,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl MediumLevelILInstruction {
|
||||
pub(crate) fn new(function: &MediumLevelILFunction, idx: usize) -> Self {
|
||||
let op = unsafe { BNGetMediumLevelILByIndex(function.handle, idx) };
|
||||
use BNMediumLevelILOperation::*;
|
||||
use MediumLevelILOperation as Op;
|
||||
let info = match op.operation {
|
||||
MLIL_NOP => Op::Nop(NoArgs::default()),
|
||||
MLIL_NORET => Op::Noret(NoArgs::default()),
|
||||
MLIL_BP => Op::Bp(NoArgs::default()),
|
||||
MLIL_UNDEF => Op::Undef(NoArgs::default()),
|
||||
MLIL_UNIMPL => Op::Unimpl(NoArgs::default()),
|
||||
MLIL_IF => Op::If(MediumLevelILOperationIf::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1],
|
||||
op.operands[2],
|
||||
)),
|
||||
MLIL_FLOAT_CONST => Op::FloatConst(FloatConst::new(op.operands[0], op.size)),
|
||||
MLIL_CONST => Op::Const(Constant::new(op.operands[0])),
|
||||
MLIL_CONST_PTR => Op::ConstPtr(Constant::new(op.operands[0])),
|
||||
MLIL_IMPORT => Op::Import(Constant::new(op.operands[0])),
|
||||
MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr::new(op.operands[0], op.operands[1])),
|
||||
MLIL_CONST_DATA => Op::ConstData(ConstData::new((op.operands[0], op.operands[1]))),
|
||||
MLIL_JUMP => Op::Jump(Jump::new(op.operands[0] as usize)),
|
||||
MLIL_RET_HINT => Op::RetHint(Jump::new(op.operands[0] as usize)),
|
||||
MLIL_STORE_SSA => Op::StoreSsa(StoreSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1],
|
||||
op.operands[2],
|
||||
op.operands[3] as usize,
|
||||
)),
|
||||
MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1],
|
||||
op.operands[2],
|
||||
op.operands[3],
|
||||
op.operands[4] as usize,
|
||||
)),
|
||||
MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1],
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_STORE => Op::Store(Store::new(op.operands[0] as usize, op.operands[1] as usize)),
|
||||
MLIL_JUMP_TO => Op::JumpTo(JumpTo::new(
|
||||
op.operands[0] as usize,
|
||||
(op.operands[1] as usize, op.operands[2] as usize),
|
||||
)),
|
||||
MLIL_GOTO => Op::Goto(Goto::new(op.operands[0])),
|
||||
MLIL_FREE_VAR_SLOT => Op::FreeVarSlot(FreeVarSlot::new(op.operands[0])),
|
||||
MLIL_SET_VAR_FIELD => Op::SetVarField(SetVarField::new(
|
||||
op.operands[0],
|
||||
op.operands[1],
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_SET_VAR => Op::SetVar(SetVar::new(op.operands[0], op.operands[1] as usize)),
|
||||
MLIL_FREE_VAR_SLOT_SSA => Op::FreeVarSlotSsa(FreeVarSlotSsa::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[0], op.operands[2] as usize),
|
||||
)),
|
||||
MLIL_SET_VAR_SSA_FIELD => Op::SetVarSsaField(SetVarSsaField::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[0], op.operands[2] as usize),
|
||||
op.operands[3],
|
||||
op.operands[4] as usize,
|
||||
)),
|
||||
MLIL_SET_VAR_ALIASED_FIELD => Op::SetVarAliasedField(SetVarSsaField::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[0], op.operands[2] as usize),
|
||||
op.operands[3],
|
||||
op.operands[4] as usize,
|
||||
)),
|
||||
MLIL_SET_VAR_ALIASED => Op::SetVarAliased(SetVarAliased::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[0], op.operands[2] as usize),
|
||||
op.operands[3] as usize,
|
||||
)),
|
||||
MLIL_SET_VAR_SSA => Op::SetVarSsa(SetVarSsa::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_VAR_PHI => Op::VarPhi(VarPhi::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[2] as usize, op.operands[3] as usize),
|
||||
)),
|
||||
MLIL_MEM_PHI => Op::MemPhi(MemPhi::new(
|
||||
op.operands[0],
|
||||
(op.operands[1] as usize, op.operands[2] as usize),
|
||||
)),
|
||||
MLIL_VAR_SPLIT => Op::VarSplit(VarSplit::new(op.operands[0], op.operands[1])),
|
||||
MLIL_SET_VAR_SPLIT => Op::SetVarSplit(SetVarSplit::new(
|
||||
op.operands[0],
|
||||
op.operands[1],
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[2], op.operands[3] as usize),
|
||||
)),
|
||||
MLIL_SET_VAR_SPLIT_SSA => Op::SetVarSplitSsa(SetVarSplitSsa::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
(op.operands[2], op.operands[3] as usize),
|
||||
op.operands[4] as usize,
|
||||
)),
|
||||
MLIL_ADD => Op::Add(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_SUB => Op::Sub(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_AND => Op::And(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_OR => Op::Or(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_XOR => Op::Xor(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_LSL => Op::Lsl(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_LSR => Op::Lsr(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_ASR => Op::Asr(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_ROL => Op::Rol(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_ROR => Op::Ror(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MUL => Op::Mul(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MULU_DP => Op::MuluDp(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MULS_DP => Op::MulsDp(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_DIVU => Op::Divu(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_DIVU_DP => Op::DivuDp(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_DIVS => Op::Divs(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_DIVS_DP => Op::DivsDp(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MODU => Op::Modu(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MODU_DP => Op::ModuDp(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MODS => Op::Mods(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_MODS_DP => Op::ModsDp(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_E => Op::CmpE(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_NE => Op::CmpNe(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_SLT => Op::CmpSlt(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_ULT => Op::CmpUlt(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_SLE => Op::CmpSle(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_ULE => Op::CmpUle(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_SGE => Op::CmpSge(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_UGE => Op::CmpUge(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_SGT => Op::CmpSgt(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_CMP_UGT => Op::CmpUgt(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_TEST_BIT => Op::TestBit(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_E => Op::FcmpE(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_NE => Op::FcmpNe(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_LT => Op::FcmpLt(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_LE => Op::FcmpLe(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_GE => Op::FcmpGe(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_GT => Op::FcmpGt(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_O => Op::FcmpO(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FCMP_UO => Op::FcmpUo(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FADD => Op::Fadd(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FSUB => Op::Fsub(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FMUL => Op::Fmul(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_FDIV => Op::Fdiv(BinaryOp::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
)),
|
||||
MLIL_ADC => Op::Adc(BinaryOpCarry::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_SBB => Op::Sbb(BinaryOpCarry::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_RLC => Op::Rlc(BinaryOpCarry::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_RRC => Op::Rrc(BinaryOpCarry::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_CALL => Op::Call(Call::new(
|
||||
(op.operands[0] as usize, op.operands[1] as usize),
|
||||
op.operands[2] as usize,
|
||||
(op.operands[3] as usize, op.operands[4] as usize),
|
||||
)),
|
||||
MLIL_TAILCALL => Op::Tailcall(Call::new(
|
||||
(op.operands[0] as usize, op.operands[1] as usize),
|
||||
op.operands[2] as usize,
|
||||
(op.operands[3] as usize, op.operands[4] as usize),
|
||||
)),
|
||||
MLIL_SYSCALL => Op::Syscall(Syscall::new(
|
||||
(op.operands[0] as usize, op.operands[1] as usize),
|
||||
(op.operands[2] as usize, op.operands[3] as usize),
|
||||
)),
|
||||
MLIL_INTRINSIC => Op::Intrinsic(Intrinsic::new(
|
||||
(op.operands[0] as usize, op.operands[1] as usize),
|
||||
op.operands[2] as usize,
|
||||
(op.operands[3] as usize, op.operands[4] as usize),
|
||||
)),
|
||||
MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa::new(
|
||||
(op.operands[0] as usize, op.operands[1] as usize),
|
||||
op.operands[2] as usize,
|
||||
(op.operands[3] as usize, op.operands[4] as usize),
|
||||
)),
|
||||
MLIL_CALL_SSA => Op::CallSsa(CallSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
(op.operands[2] as usize, op.operands[3] as usize),
|
||||
op.operands[4],
|
||||
)),
|
||||
MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
(op.operands[2] as usize, op.operands[3] as usize),
|
||||
op.operands[4],
|
||||
)),
|
||||
MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
op.operands[3] as usize,
|
||||
)),
|
||||
MLIL_TAILCALL_UNTYPED_SSA => Op::TailcallUntypedSsa(CallUntypedSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
op.operands[3] as usize,
|
||||
)),
|
||||
MLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa::new(
|
||||
op.operands[0] as usize,
|
||||
(op.operands[1] as usize, op.operands[2] as usize),
|
||||
op.operands[3],
|
||||
)),
|
||||
MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
op.operands[3] as usize,
|
||||
)),
|
||||
MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
op.operands[3] as usize,
|
||||
)),
|
||||
MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1] as usize,
|
||||
op.operands[2] as usize,
|
||||
)),
|
||||
MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList::new(
|
||||
(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)
|
||||
)),
|
||||
MLIL_NEG => Op::Neg(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_NOT => Op::Not(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_SX => Op::Sx(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_ZX => Op::Zx(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_LOW_PART => Op::LowPart(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FSQRT => Op::Fsqrt(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FNEG => Op::Fneg(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FABS => Op::Fabs(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FLOAT_CONV => Op::FloatConv(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FLOOR => Op::Floor(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_CEIL => Op::Ceil(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_FTRUNC => Op::Ftrunc(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_LOAD => Op::Load(UnaryOp::new(op.operands[0] as usize)),
|
||||
MLIL_LOAD_STRUCT => {
|
||||
Op::LoadStruct(LoadStruct::new(op.operands[0] as usize, op.operands[1]))
|
||||
}
|
||||
MLIL_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa::new(
|
||||
op.operands[0] as usize,
|
||||
op.operands[1],
|
||||
op.operands[2],
|
||||
)),
|
||||
MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa::new(op.operands[0] as usize, op.operands[1])),
|
||||
MLIL_RET => Op::Ret(Ret::new((op.operands[0] as usize, op.operands[1] as usize))),
|
||||
MLIL_VAR => Op::Var(Var::new(op.operands[0])),
|
||||
MLIL_ADDRESS_OF => Op::AddressOf(Var::new(op.operands[0])),
|
||||
MLIL_VAR_FIELD => Op::VarField(Field::new(op.operands[0], op.operands[1])),
|
||||
MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field::new(op.operands[0], op.operands[1])),
|
||||
MLIL_VAR_SSA => Op::VarSsa(VarSsa::new((op.operands[0], op.operands[1] as usize))),
|
||||
MLIL_VAR_ALIASED => {
|
||||
Op::VarAliased(VarSsa::new((op.operands[0], op.operands[1] as usize)))
|
||||
}
|
||||
MLIL_VAR_SSA_FIELD => Op::VarSsaField(VarSsaField::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
op.operands[2],
|
||||
)),
|
||||
MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField::new(
|
||||
(op.operands[0], op.operands[1] as usize),
|
||||
op.operands[2],
|
||||
)),
|
||||
MLIL_TRAP => Op::Trap(Trap::new(op.operands[0])),
|
||||
// translated directly into a list for Expression or Variables
|
||||
MLIL_CALL_OUTPUT | MLIL_CALL_PARAM | MLIL_CALL_PARAM_SSA | MLIL_CALL_OUTPUT_SSA => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
Self {
|
||||
function: function.to_owned(),
|
||||
address: op.address,
|
||||
operation: info,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function(&self) -> &MediumLevelILFunction {
|
||||
&self.function
|
||||
}
|
||||
|
||||
pub fn address(&self) -> u64 {
|
||||
self.address
|
||||
}
|
||||
|
||||
pub fn operation(&self) -> &MediumLevelILOperation {
|
||||
&self.operation
|
||||
}
|
||||
|
||||
pub fn lift(&self) -> MediumLevelILLiftedInstruction {
|
||||
use MediumLevelILLiftedOperation as Lifted;
|
||||
use MediumLevelILOperation::*;
|
||||
|
||||
let operation = match self.operation {
|
||||
Nop(op) => Lifted::Nop(op),
|
||||
Noret(op) => Lifted::Noret(op),
|
||||
Bp(op) => Lifted::Bp(op),
|
||||
Undef(op) => Lifted::Undef(op),
|
||||
Unimpl(op) => Lifted::Unimpl(op),
|
||||
If(op) => Lifted::If(op.lift(&self.function)),
|
||||
FloatConst(op) => Lifted::FloatConst(op),
|
||||
Const(op) => Lifted::Const(op),
|
||||
ConstPtr(op) => Lifted::ConstPtr(op),
|
||||
Import(op) => Lifted::Import(op),
|
||||
ExternPtr(op) => Lifted::ExternPtr(op),
|
||||
ConstData(op) => Lifted::ConstData(op.lift(&self.function)),
|
||||
Jump(op) => Lifted::Jump(op.lift(&self.function)),
|
||||
RetHint(op) => Lifted::RetHint(op.lift(&self.function)),
|
||||
StoreSsa(op) => Lifted::StoreSsa(op.lift(&self.function)),
|
||||
StoreStructSsa(op) => Lifted::StoreStructSsa(op.lift(&self.function)),
|
||||
StoreStruct(op) => Lifted::StoreStruct(op.lift(&self.function)),
|
||||
Store(op) => Lifted::Store(op.lift(&self.function)),
|
||||
JumpTo(op) => Lifted::JumpTo(op.lift(&self.function)),
|
||||
Goto(op) => Lifted::Goto(op),
|
||||
FreeVarSlot(op) => Lifted::FreeVarSlot(op),
|
||||
SetVarField(op) => Lifted::SetVarField(op.lift(&self.function)),
|
||||
SetVar(op) => Lifted::SetVar(op.lift(&self.function)),
|
||||
FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op.lift()),
|
||||
SetVarSsaField(op) => Lifted::SetVarSsaField(op.lift(&self.function)),
|
||||
SetVarAliasedField(op) => Lifted::SetVarAliasedField(op.lift(&self.function)),
|
||||
SetVarAliased(op) => Lifted::SetVarAliased(op.lift(&self.function)),
|
||||
SetVarSsa(op) => Lifted::SetVarSsa(op.lift(&self.function)),
|
||||
VarPhi(op) => Lifted::VarPhi(op.lift(&self.function)),
|
||||
MemPhi(op) => Lifted::MemPhi(op.lift(&self.function)),
|
||||
VarSplit(op) => Lifted::VarSplit(op.lift()),
|
||||
SetVarSplit(op) => Lifted::SetVarSplit(op.lift(&self.function)),
|
||||
VarSplitSsa(op) => Lifted::VarSplitSsa(op.lift()),
|
||||
SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(op.lift(&self.function)),
|
||||
Add(op) => Lifted::Add(op.lift(&self.function)),
|
||||
Sub(op) => Lifted::Sub(op.lift(&self.function)),
|
||||
And(op) => Lifted::And(op.lift(&self.function)),
|
||||
Or(op) => Lifted::Or(op.lift(&self.function)),
|
||||
Xor(op) => Lifted::Xor(op.lift(&self.function)),
|
||||
Lsl(op) => Lifted::Lsl(op.lift(&self.function)),
|
||||
Lsr(op) => Lifted::Lsr(op.lift(&self.function)),
|
||||
Asr(op) => Lifted::Asr(op.lift(&self.function)),
|
||||
Rol(op) => Lifted::Rol(op.lift(&self.function)),
|
||||
Ror(op) => Lifted::Ror(op.lift(&self.function)),
|
||||
Mul(op) => Lifted::Mul(op.lift(&self.function)),
|
||||
MuluDp(op) => Lifted::MuluDp(op.lift(&self.function)),
|
||||
MulsDp(op) => Lifted::MulsDp(op.lift(&self.function)),
|
||||
Divu(op) => Lifted::Divu(op.lift(&self.function)),
|
||||
DivuDp(op) => Lifted::DivuDp(op.lift(&self.function)),
|
||||
Divs(op) => Lifted::Divs(op.lift(&self.function)),
|
||||
DivsDp(op) => Lifted::DivsDp(op.lift(&self.function)),
|
||||
Modu(op) => Lifted::Modu(op.lift(&self.function)),
|
||||
ModuDp(op) => Lifted::ModuDp(op.lift(&self.function)),
|
||||
Mods(op) => Lifted::Mods(op.lift(&self.function)),
|
||||
ModsDp(op) => Lifted::ModsDp(op.lift(&self.function)),
|
||||
CmpE(op) => Lifted::CmpE(op.lift(&self.function)),
|
||||
CmpNe(op) => Lifted::CmpNe(op.lift(&self.function)),
|
||||
CmpSlt(op) => Lifted::CmpSlt(op.lift(&self.function)),
|
||||
CmpUlt(op) => Lifted::CmpUlt(op.lift(&self.function)),
|
||||
CmpSle(op) => Lifted::CmpSle(op.lift(&self.function)),
|
||||
CmpUle(op) => Lifted::CmpUle(op.lift(&self.function)),
|
||||
CmpSge(op) => Lifted::CmpSge(op.lift(&self.function)),
|
||||
CmpUge(op) => Lifted::CmpUge(op.lift(&self.function)),
|
||||
CmpSgt(op) => Lifted::CmpSgt(op.lift(&self.function)),
|
||||
CmpUgt(op) => Lifted::CmpUgt(op.lift(&self.function)),
|
||||
TestBit(op) => Lifted::TestBit(op.lift(&self.function)),
|
||||
AddOverflow(op) => Lifted::AddOverflow(op.lift(&self.function)),
|
||||
FcmpE(op) => Lifted::FcmpE(op.lift(&self.function)),
|
||||
FcmpNe(op) => Lifted::FcmpNe(op.lift(&self.function)),
|
||||
FcmpLt(op) => Lifted::FcmpLt(op.lift(&self.function)),
|
||||
FcmpLe(op) => Lifted::FcmpLe(op.lift(&self.function)),
|
||||
FcmpGe(op) => Lifted::FcmpGe(op.lift(&self.function)),
|
||||
FcmpGt(op) => Lifted::FcmpGt(op.lift(&self.function)),
|
||||
FcmpO(op) => Lifted::FcmpO(op.lift(&self.function)),
|
||||
FcmpUo(op) => Lifted::FcmpUo(op.lift(&self.function)),
|
||||
Fadd(op) => Lifted::Fadd(op.lift(&self.function)),
|
||||
Fsub(op) => Lifted::Fsub(op.lift(&self.function)),
|
||||
Fmul(op) => Lifted::Fmul(op.lift(&self.function)),
|
||||
Fdiv(op) => Lifted::Fdiv(op.lift(&self.function)),
|
||||
Adc(op) => Lifted::Adc(op.lift(&self.function)),
|
||||
Sbb(op) => Lifted::Sbb(op.lift(&self.function)),
|
||||
Rlc(op) => Lifted::Rlc(op.lift(&self.function)),
|
||||
Rrc(op) => Lifted::Rrc(op.lift(&self.function)),
|
||||
Call(op) => Lifted::Call(op.lift(&self.function)),
|
||||
Tailcall(op) => Lifted::Tailcall(op.lift(&self.function)),
|
||||
Intrinsic(op) => Lifted::Intrinsic(op.lift(&self.function)),
|
||||
Syscall(op) => Lifted::Syscall(op.lift(&self.function)),
|
||||
IntrinsicSsa(op) => Lifted::IntrinsicSsa(op.lift(&self.function)),
|
||||
CallSsa(op) => Lifted::CallSsa(op.lift(&self.function)),
|
||||
TailcallSsa(op) => Lifted::TailcallSsa(op.lift(&self.function)),
|
||||
CallUntypedSsa(op) => Lifted::CallUntypedSsa(op.lift(&self.function)),
|
||||
TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(op.lift(&self.function)),
|
||||
SyscallSsa(op) => Lifted::SyscallSsa(op.lift(&self.function)),
|
||||
SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(op.lift(&self.function)),
|
||||
CallUntyped(op) => Lifted::CallUntyped(op.lift(&self.function)),
|
||||
TailcallUntyped(op) => Lifted::TailcallUntyped(op.lift(&self.function)),
|
||||
SyscallUntyped(op) => Lifted::SyscallUntyped(op.lift(&self.function)),
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operands(&self) -> Box<dyn Iterator<Item = (&'static str, MediumLevelILOperand)>> {
|
||||
use MediumLevelILOperation::*;
|
||||
match &self.operation {
|
||||
Nop(_op) | Noret(_op) | Bp(_op) | Undef(_op) | Unimpl(_op) => Box::new([].into_iter()),
|
||||
If(op) => Box::new(op.operands(&self.function)),
|
||||
FloatConst(op) => Box::new(op.operands()),
|
||||
Const(op) | ConstPtr(op) | Import(op) => Box::new(op.operands()),
|
||||
ExternPtr(op) => Box::new(op.operands(&self.function)),
|
||||
ConstData(op) => Box::new(op.operands(&self.function)),
|
||||
Jump(op) | RetHint(op) => Box::new(op.operands(&self.function)),
|
||||
StoreSsa(op) => Box::new(op.operands(&self.function)),
|
||||
StoreStructSsa(op) => Box::new(op.operands(&self.function)),
|
||||
StoreStruct(op) => Box::new(op.operands(&self.function)),
|
||||
Store(op) => Box::new(op.operands(&self.function)),
|
||||
JumpTo(op) => Box::new(op.operands(&self.function)),
|
||||
Goto(op) => Box::new(op.operands()),
|
||||
FreeVarSlot(op) => Box::new(op.operands()),
|
||||
SetVarField(op) => Box::new(op.operands(&self.function)),
|
||||
SetVar(op) => Box::new(op.operands(&self.function)),
|
||||
FreeVarSlotSsa(op) => Box::new(op.operands()),
|
||||
SetVarSsaField(op) | SetVarAliasedField(op) => Box::new(op.operands(&self.function)),
|
||||
SetVarAliased(op) => Box::new(op.operands(&self.function)),
|
||||
SetVarSsa(op) => Box::new(op.operands(&self.function)),
|
||||
VarPhi(op) => Box::new(op.operands(&self.function)),
|
||||
MemPhi(op) => Box::new(op.operands(&self.function)),
|
||||
VarSplit(op) => Box::new(op.operands()),
|
||||
SetVarSplit(op) => Box::new(op.operands(&self.function)),
|
||||
VarSplitSsa(op) => Box::new(op.operands()),
|
||||
SetVarSplitSsa(op) => Box::new(op.operands(&self.function)),
|
||||
Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
|
||||
| Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
|
||||
| Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
|
||||
| CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
|
||||
| CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
|
||||
| FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
|
||||
| FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => {
|
||||
Box::new(op.operands(&self.function))
|
||||
}
|
||||
Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => Box::new(op.operands(&self.function)),
|
||||
Call(op) | Tailcall(op) => Box::new(op.operands(&self.function)),
|
||||
Syscall(op) => Box::new(op.operands(&self.function)),
|
||||
Intrinsic(op) => Box::new(op.operands(&self.function)),
|
||||
IntrinsicSsa(op) => Box::new(op.operands(&self.function)),
|
||||
CallSsa(op) | TailcallSsa(op) => Box::new(op.operands(&self.function)),
|
||||
CallUntypedSsa(op) | TailcallUntypedSsa(op) => Box::new(op.operands(&self.function)),
|
||||
SyscallSsa(op) => Box::new(op.operands(&self.function)),
|
||||
SyscallUntypedSsa(op) => Box::new(op.operands(&self.function)),
|
||||
CallUntyped(op) | TailcallUntyped(op) => Box::new(op.operands(&self.function)),
|
||||
SyscallUntyped(op) => Box::new(op.operands(&self.function)),
|
||||
SeparateParamList(op) => Box::new(op.operands(&self.function)),
|
||||
SharedParamSlot(op) => Box::new(op.operands(&self.function)),
|
||||
Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
|
||||
| Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
|
||||
| RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
|
||||
Box::new(op.operands(&self.function))
|
||||
}
|
||||
LoadStruct(op) => Box::new(op.operands(&self.function)),
|
||||
LoadStructSsa(op) => Box::new(op.operands(&self.function)),
|
||||
LoadSsa(op) => Box::new(op.operands(&self.function)),
|
||||
Ret(op) => Box::new(op.operands(&self.function)),
|
||||
Var(op) | AddressOf(op) => Box::new(op.operands()),
|
||||
VarField(op) | AddressOfField(op) => Box::new(op.operands()),
|
||||
VarSsa(op) | VarAliased(op) => Box::new(op.operands()),
|
||||
VarSsaField(op) | VarAliasedField(op) => Box::new(op.operands()),
|
||||
Trap(op) => Box::new(op.operands()),
|
||||
}
|
||||
}
|
||||
}
|
||||
141
src/mlil/lift.rs
Normal file
141
src/mlil/lift.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
use super::operation::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MediumLevelILLiftedInstruction {
|
||||
pub address: u64,
|
||||
pub operation: MediumLevelILLiftedOperation,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum MediumLevelILLiftedOperation {
|
||||
Nop(NoArgs),
|
||||
Noret(NoArgs),
|
||||
Bp(NoArgs),
|
||||
Undef(NoArgs),
|
||||
Unimpl(NoArgs),
|
||||
If(LiftedIf),
|
||||
FloatConst(FloatConst),
|
||||
Const(Constant),
|
||||
ConstPtr(Constant),
|
||||
Import(Constant),
|
||||
ExternPtr(ExternPtr),
|
||||
ConstData(ConstantData),
|
||||
Jump(LiftedJump),
|
||||
RetHint(LiftedJump),
|
||||
StoreSsa(LiftedStoreSsa),
|
||||
StoreStructSsa(LiftedStoreStructSsa),
|
||||
StoreStruct(LiftedStoreStruct),
|
||||
Store(LiftedStore),
|
||||
JumpTo(LiftedJumpTo),
|
||||
Goto(Goto),
|
||||
FreeVarSlot(FreeVarSlot),
|
||||
SetVarField(LiftedSetVarField),
|
||||
SetVar(LiftedSetVar),
|
||||
FreeVarSlotSsa(FreeVarSlotSsa),
|
||||
SetVarSsaField(LiftedSetVarSsaField),
|
||||
SetVarAliasedField(LiftedSetVarSsaField),
|
||||
SetVarAliased(LiftedSetVarAliased),
|
||||
SetVarSsa(LiftedSetVarSsa),
|
||||
VarPhi(LiftedVarPhi),
|
||||
MemPhi(LiftedMemPhi),
|
||||
VarSplit(VarSplit),
|
||||
SetVarSplit(LiftedSetVarSplit),
|
||||
VarSplitSsa(VarSplitSsa),
|
||||
SetVarSplitSsa(LiftedSetVarSplitSsa),
|
||||
Add(LiftedBinaryOp),
|
||||
Sub(LiftedBinaryOp),
|
||||
And(LiftedBinaryOp),
|
||||
Or(LiftedBinaryOp),
|
||||
Xor(LiftedBinaryOp),
|
||||
Lsl(LiftedBinaryOp),
|
||||
Lsr(LiftedBinaryOp),
|
||||
Asr(LiftedBinaryOp),
|
||||
Rol(LiftedBinaryOp),
|
||||
Ror(LiftedBinaryOp),
|
||||
Mul(LiftedBinaryOp),
|
||||
MuluDp(LiftedBinaryOp),
|
||||
MulsDp(LiftedBinaryOp),
|
||||
Divu(LiftedBinaryOp),
|
||||
DivuDp(LiftedBinaryOp),
|
||||
Divs(LiftedBinaryOp),
|
||||
DivsDp(LiftedBinaryOp),
|
||||
Modu(LiftedBinaryOp),
|
||||
ModuDp(LiftedBinaryOp),
|
||||
Mods(LiftedBinaryOp),
|
||||
ModsDp(LiftedBinaryOp),
|
||||
CmpE(LiftedBinaryOp),
|
||||
CmpNe(LiftedBinaryOp),
|
||||
CmpSlt(LiftedBinaryOp),
|
||||
CmpUlt(LiftedBinaryOp),
|
||||
CmpSle(LiftedBinaryOp),
|
||||
CmpUle(LiftedBinaryOp),
|
||||
CmpSge(LiftedBinaryOp),
|
||||
CmpUge(LiftedBinaryOp),
|
||||
CmpSgt(LiftedBinaryOp),
|
||||
CmpUgt(LiftedBinaryOp),
|
||||
TestBit(LiftedBinaryOp),
|
||||
AddOverflow(LiftedBinaryOp),
|
||||
FcmpE(LiftedBinaryOp),
|
||||
FcmpNe(LiftedBinaryOp),
|
||||
FcmpLt(LiftedBinaryOp),
|
||||
FcmpLe(LiftedBinaryOp),
|
||||
FcmpGe(LiftedBinaryOp),
|
||||
FcmpGt(LiftedBinaryOp),
|
||||
FcmpO(LiftedBinaryOp),
|
||||
FcmpUo(LiftedBinaryOp),
|
||||
Fadd(LiftedBinaryOp),
|
||||
Fsub(LiftedBinaryOp),
|
||||
Fmul(LiftedBinaryOp),
|
||||
Fdiv(LiftedBinaryOp),
|
||||
Adc(LiftedBinaryOpCarry),
|
||||
Sbb(LiftedBinaryOpCarry),
|
||||
Rlc(LiftedBinaryOpCarry),
|
||||
Rrc(LiftedBinaryOpCarry),
|
||||
Call(LiftedCall),
|
||||
Tailcall(LiftedCall),
|
||||
Intrinsic(LiftedInnerCall),
|
||||
Syscall(LiftedInnerCall),
|
||||
IntrinsicSsa(LiftedIntrinsicSsa),
|
||||
CallSsa(LiftedCallSsa),
|
||||
TailcallSsa(LiftedCallSsa),
|
||||
CallUntypedSsa(LiftedCallUntypedSsa),
|
||||
TailcallUntypedSsa(LiftedCallUntypedSsa),
|
||||
SyscallSsa(LiftedSyscallSsa),
|
||||
SyscallUntypedSsa(LiftedSyscallUntypedSsa),
|
||||
CallUntyped(LiftedCallUntyped),
|
||||
TailcallUntyped(LiftedCallUntyped),
|
||||
SyscallUntyped(LiftedSyscallUntyped),
|
||||
SeparateParamList(LiftedSeparateParamList),
|
||||
SharedParamSlot(LiftedSharedParamSlot),
|
||||
Neg(LiftedUnaryOp),
|
||||
Not(LiftedUnaryOp),
|
||||
Sx(LiftedUnaryOp),
|
||||
Zx(LiftedUnaryOp),
|
||||
LowPart(LiftedUnaryOp),
|
||||
BoolToInt(LiftedUnaryOp),
|
||||
UnimplMem(LiftedUnaryOp),
|
||||
Fsqrt(LiftedUnaryOp),
|
||||
Fneg(LiftedUnaryOp),
|
||||
Fabs(LiftedUnaryOp),
|
||||
FloatToInt(LiftedUnaryOp),
|
||||
IntToFloat(LiftedUnaryOp),
|
||||
FloatConv(LiftedUnaryOp),
|
||||
RoundToInt(LiftedUnaryOp),
|
||||
Floor(LiftedUnaryOp),
|
||||
Ceil(LiftedUnaryOp),
|
||||
Ftrunc(LiftedUnaryOp),
|
||||
Load(LiftedUnaryOp),
|
||||
LoadStruct(LiftedLoadStruct),
|
||||
LoadStructSsa(LiftedLoadStructSsa),
|
||||
LoadSsa(LiftedLoadSsa),
|
||||
Ret(LiftedRet),
|
||||
Var(Var),
|
||||
AddressOf(Var),
|
||||
VarField(Field),
|
||||
AddressOfField(Field),
|
||||
VarSsa(VarSsa),
|
||||
VarAliased(VarSsa),
|
||||
VarSsaField(VarSsaField),
|
||||
VarAliasedField(VarSsaField),
|
||||
Trap(Trap),
|
||||
}
|
||||
10
src/mlil/mod.rs
Normal file
10
src/mlil/mod.rs
Normal file
@@ -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::*;
|
||||
2238
src/mlil/operation.rs
Normal file
2238
src/mlil/operation.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user