diff options
Diffstat (limited to 'rust/src/llil/expression.rs')
| -rw-r--r-- | rust/src/llil/expression.rs | 851 |
1 files changed, 0 insertions, 851 deletions
diff --git a/rust/src/llil/expression.rs b/rust/src/llil/expression.rs deleted file mode 100644 index f04368a7..00000000 --- a/rust/src/llil/expression.rs +++ /dev/null @@ -1,851 +0,0 @@ -// Copyright 2021-2024 Vector 35 Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use binaryninjacore_sys::BNGetLowLevelILByIndex; -use binaryninjacore_sys::BNLowLevelILInstruction; - -use std::fmt; -use std::marker::PhantomData; - -use super::operation; -use super::operation::Operation; -use super::*; - -use crate::architecture::Architecture; -use crate::architecture::RegisterInfo; - -// used as a marker for Expressions that can produce a value -#[derive(Copy, Clone, Debug)] -pub struct ValueExpr; - -// used as a marker for Expressions that can not produce a value -#[derive(Copy, Clone, Debug)] -pub struct VoidExpr; - -pub trait ExpressionResultType: 'static {} -impl ExpressionResultType for ValueExpr {} -impl ExpressionResultType for VoidExpr {} - -pub struct Expression<'func, A, M, F, R> -where - A: 'func + Architecture, - M: FunctionMutability, - F: FunctionForm, - R: ExpressionResultType, -{ - pub(crate) function: &'func Function<A, M, F>, - pub(crate) expr_idx: usize, - - // tag the 'return' type of this expression - pub(crate) _ty: PhantomData<R>, -} - -impl<'func, A, M, F, R> Expression<'func, A, M, F, R> -where - A: 'func + Architecture, - M: FunctionMutability, - F: FunctionForm, - R: ExpressionResultType, -{ - pub(crate) fn new(function: &'func Function<A, M, F>, expr_idx: usize) -> Self { - Self { - function, - expr_idx, - _ty: PhantomData, - } - } - - pub fn index(&self) -> usize { - self.expr_idx - } -} - -impl<'func, A, M, V> fmt::Debug for Expression<'func, A, M, NonSSA<V>, ValueExpr> -where - A: 'func + Architecture, - M: FunctionMutability, - V: NonSSAVariant, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let op_info = self.info(); - write!(f, "<expr {}: {:?}>", self.expr_idx, op_info) - } -} - -fn common_info<'func, A, M, F>( - function: &'func Function<A, M, F>, - op: BNLowLevelILInstruction, -) -> ExprInfo<'func, A, M, F> -where - A: 'func + Architecture, - M: FunctionMutability, - F: FunctionForm, -{ - use binaryninjacore_sys::BNLowLevelILOperation::*; - - match op.operation { - LLIL_CONST => ExprInfo::Const(Operation::new(function, op)), - LLIL_CONST_PTR => ExprInfo::ConstPtr(Operation::new(function, op)), - - LLIL_EXTERN_PTR => ExprInfo::ExternPtr(Operation::new(function, op)), - - LLIL_ADD => ExprInfo::Add(Operation::new(function, op)), - LLIL_ADC => ExprInfo::Adc(Operation::new(function, op)), - LLIL_SUB => ExprInfo::Sub(Operation::new(function, op)), - LLIL_SBB => ExprInfo::Sbb(Operation::new(function, op)), - LLIL_AND => ExprInfo::And(Operation::new(function, op)), - LLIL_OR => ExprInfo::Or(Operation::new(function, op)), - LLIL_XOR => ExprInfo::Xor(Operation::new(function, op)), - LLIL_LSL => ExprInfo::Lsl(Operation::new(function, op)), - LLIL_LSR => ExprInfo::Lsr(Operation::new(function, op)), - LLIL_ASR => ExprInfo::Asr(Operation::new(function, op)), - LLIL_ROL => ExprInfo::Rol(Operation::new(function, op)), - LLIL_RLC => ExprInfo::Rlc(Operation::new(function, op)), - LLIL_ROR => ExprInfo::Ror(Operation::new(function, op)), - LLIL_RRC => ExprInfo::Rrc(Operation::new(function, op)), - LLIL_MUL => ExprInfo::Mul(Operation::new(function, op)), - - LLIL_MULU_DP => ExprInfo::MuluDp(Operation::new(function, op)), - LLIL_MULS_DP => ExprInfo::MulsDp(Operation::new(function, op)), - - LLIL_DIVU => ExprInfo::Divu(Operation::new(function, op)), - LLIL_DIVS => ExprInfo::Divs(Operation::new(function, op)), - - LLIL_DIVU_DP => ExprInfo::DivuDp(Operation::new(function, op)), - LLIL_DIVS_DP => ExprInfo::DivsDp(Operation::new(function, op)), - - LLIL_MODU => ExprInfo::Modu(Operation::new(function, op)), - LLIL_MODS => ExprInfo::Mods(Operation::new(function, op)), - - LLIL_MODU_DP => ExprInfo::ModuDp(Operation::new(function, op)), - LLIL_MODS_DP => ExprInfo::ModsDp(Operation::new(function, op)), - - LLIL_NEG => ExprInfo::Neg(Operation::new(function, op)), - LLIL_NOT => ExprInfo::Not(Operation::new(function, op)), - - LLIL_SX => ExprInfo::Sx(Operation::new(function, op)), - LLIL_ZX => ExprInfo::Zx(Operation::new(function, op)), - LLIL_LOW_PART => ExprInfo::LowPart(Operation::new(function, op)), - - LLIL_REG_SPLIT => ExprInfo::RegSplit(Operation::new(function, op)), - - LLIL_CMP_E => ExprInfo::CmpE(Operation::new(function, op)), - LLIL_CMP_NE => ExprInfo::CmpNe(Operation::new(function, op)), - LLIL_CMP_SLT => ExprInfo::CmpSlt(Operation::new(function, op)), - LLIL_CMP_ULT => ExprInfo::CmpUlt(Operation::new(function, op)), - LLIL_CMP_SLE => ExprInfo::CmpSle(Operation::new(function, op)), - LLIL_CMP_ULE => ExprInfo::CmpUle(Operation::new(function, op)), - LLIL_CMP_SGE => ExprInfo::CmpSge(Operation::new(function, op)), - LLIL_CMP_UGE => ExprInfo::CmpUge(Operation::new(function, op)), - LLIL_CMP_SGT => ExprInfo::CmpSgt(Operation::new(function, op)), - LLIL_CMP_UGT => ExprInfo::CmpUgt(Operation::new(function, op)), - - LLIL_BOOL_TO_INT => ExprInfo::BoolToInt(Operation::new(function, op)), - - LLIL_FADD => ExprInfo::Fadd(Operation::new(function, op)), - LLIL_FSUB => ExprInfo::Fsub(Operation::new(function, op)), - LLIL_FMUL => ExprInfo::Fmul(Operation::new(function, op)), - LLIL_FDIV => ExprInfo::Fdiv(Operation::new(function, op)), - - LLIL_FSQRT => ExprInfo::Fsqrt(Operation::new(function, op)), - LLIL_FNEG => ExprInfo::Fneg(Operation::new(function, op)), - LLIL_FABS => ExprInfo::Fabs(Operation::new(function, op)), - LLIL_FLOAT_TO_INT => ExprInfo::FloatToInt(Operation::new(function, op)), - LLIL_INT_TO_FLOAT => ExprInfo::IntToFloat(Operation::new(function, op)), - LLIL_FLOAT_CONV => ExprInfo::FloatConv(Operation::new(function, op)), - LLIL_ROUND_TO_INT => ExprInfo::RoundToInt(Operation::new(function, op)), - LLIL_FLOOR => ExprInfo::Floor(Operation::new(function, op)), - LLIL_CEIL => ExprInfo::Ceil(Operation::new(function, op)), - LLIL_FTRUNC => ExprInfo::Ftrunc(Operation::new(function, op)), - - LLIL_FCMP_E => ExprInfo::FcmpE(Operation::new(function, op)), - LLIL_FCMP_NE => ExprInfo::FcmpNE(Operation::new(function, op)), - LLIL_FCMP_LT => ExprInfo::FcmpLT(Operation::new(function, op)), - LLIL_FCMP_LE => ExprInfo::FcmpLE(Operation::new(function, op)), - LLIL_FCMP_GT => ExprInfo::FcmpGT(Operation::new(function, op)), - LLIL_FCMP_GE => ExprInfo::FcmpGE(Operation::new(function, op)), - LLIL_FCMP_O => ExprInfo::FcmpO(Operation::new(function, op)), - LLIL_FCMP_UO => ExprInfo::FcmpUO(Operation::new(function, op)), - - LLIL_UNIMPL => ExprInfo::Unimpl(Operation::new(function, op)), - LLIL_UNIMPL_MEM => ExprInfo::UnimplMem(Operation::new(function, op)), - - // TODO TEST_BIT ADD_OVERFLOW LLIL_REG_STACK_PUSH LLIL_REG_STACK_POP - _ => { - #[cfg(debug_assertions)] - { - error!( - "Got unexpected operation {:?} in value expr at 0x{:x}", - op.operation, op.address - ); - } - - ExprInfo::Undef(Operation::new(function, op)) - } - } -} - -use super::VisitorAction; - -macro_rules! visit { - ($f:expr, $($e:expr),*) => { - if let VisitorAction::Halt = $f($($e,)*) { - return VisitorAction::Halt; - } - } -} - -fn common_visit<'func, A, M, F, CB>(info: &ExprInfo<'func, A, M, F>, f: &mut CB) -> VisitorAction -where - A: 'func + Architecture, - M: FunctionMutability, - F: FunctionForm, - CB: FnMut(&Expression<'func, A, M, F, ValueExpr>) -> VisitorAction, -{ - use self::ExprInfo::*; - - match *info { - CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op) - | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op) | CmpUgt(ref op) - | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op) | FcmpGE(ref op) - | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => { - visit!(f, &op.left()); - visit!(f, &op.right()); - } - - Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => { - visit!(f, &op.left()); - visit!(f, &op.right()); - visit!(f, &op.carry()); - } - - Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op) - | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op) | MulsDp(ref op) - | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op) | Mods(ref op) - | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op) => { - visit!(f, &op.left()); - visit!(f, &op.right()); - } - - DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => { - visit!(f, &op.high()); - visit!(f, &op.low()); - visit!(f, &op.right()); - } - - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) - | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) | FloatToInt(ref op) - | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) | Floor(ref op) - | Ceil(ref op) | Ftrunc(ref op) => { - visit!(f, &op.operand()); - } - - UnimplMem(ref op) => { - visit!(f, &op.mem_expr()); - } - - _ => {} - }; - - VisitorAction::Sibling -} - -impl<'func, A, M, V> Expression<'func, A, M, NonSSA<V>, ValueExpr> -where - A: 'func + Architecture, - M: FunctionMutability, - V: NonSSAVariant, -{ - pub(crate) unsafe fn info_from_op( - &self, - op: BNLowLevelILInstruction, - ) -> ExprInfo<'func, A, M, NonSSA<V>> { - use binaryninjacore_sys::BNLowLevelILOperation::*; - - match op.operation { - LLIL_LOAD => ExprInfo::Load(Operation::new(self.function, op)), - LLIL_POP => ExprInfo::Pop(Operation::new(self.function, op)), - LLIL_REG => ExprInfo::Reg(Operation::new(self.function, op)), - LLIL_REG_SPLIT => ExprInfo::RegSplit(Operation::new(self.function, op)), - LLIL_FLAG => ExprInfo::Flag(Operation::new(self.function, op)), - LLIL_FLAG_BIT => ExprInfo::FlagBit(Operation::new(self.function, op)), - LLIL_FLAG_COND => ExprInfo::FlagCond(Operation::new(self.function, op)), // TODO lifted only - LLIL_FLAG_GROUP => ExprInfo::FlagGroup(Operation::new(self.function, op)), // TODO lifted only - _ => common_info(self.function, op), - } - } - - pub fn info(&self) -> ExprInfo<'func, A, M, NonSSA<V>> { - unsafe { - let op = BNGetLowLevelILByIndex(self.function.handle, self.expr_idx); - self.info_from_op(op) - } - } - - pub fn visit_tree<F>(&self, f: &mut F) -> VisitorAction - where - F: FnMut(&Self, &ExprInfo<'func, A, M, NonSSA<V>>) -> VisitorAction, - { - use self::ExprInfo::*; - - let info = self.info(); - - match f(self, &info) { - VisitorAction::Descend => {} - action => return action, - }; - - match info { - Load(ref op) => visit!(Self::visit_tree, &op.source_mem_expr(), f), - _ => { - let mut fb = |e: &Self| e.visit_tree(f); - visit!(common_visit, &info, &mut fb); - } - }; - - VisitorAction::Sibling - } -} - -impl<'func, A, M> Expression<'func, A, M, SSA, ValueExpr> -where - A: 'func + Architecture, - M: FunctionMutability, -{ - pub(crate) unsafe fn info_from_op( - &self, - op: BNLowLevelILInstruction, - ) -> ExprInfo<'func, A, M, SSA> { - use binaryninjacore_sys::BNLowLevelILOperation::*; - - match op.operation { - LLIL_LOAD_SSA => ExprInfo::Load(Operation::new(self.function, op)), - LLIL_REG_SSA | LLIL_REG_SSA_PARTIAL => ExprInfo::Reg(Operation::new(self.function, op)), - LLIL_REG_SPLIT_SSA => ExprInfo::RegSplit(Operation::new(self.function, op)), - LLIL_FLAG_SSA => ExprInfo::Flag(Operation::new(self.function, op)), - LLIL_FLAG_BIT_SSA => ExprInfo::FlagBit(Operation::new(self.function, op)), - _ => common_info(self.function, op), - } - } - - pub fn info(&self) -> ExprInfo<'func, A, M, SSA> { - unsafe { - let op = BNGetLowLevelILByIndex(self.function.handle, self.expr_idx); - self.info_from_op(op) - } - } - - pub fn visit_tree<F>(&self, f: &mut F) -> VisitorAction - where - F: FnMut(&Self, &ExprInfo<'func, A, M, SSA>) -> VisitorAction, - { - use self::ExprInfo::*; - - let info = self.info(); - - match f(self, &info) { - VisitorAction::Descend => {} - action => return action, - }; - - match info { - // TODO ssa - Load(ref _op) => {} //visit!(Self::visit_tree, &op.source_mem_expr(), f), - _ => { - let mut fb = |e: &Self| e.visit_tree(f); - visit!(common_visit, &info, &mut fb); - } - }; - - VisitorAction::Sibling - } -} - -impl<'func, A, F> Expression<'func, A, Finalized, F, ValueExpr> -where - A: 'func + Architecture, - F: FunctionForm, -{ - // TODO possible values -} - -pub enum ExprInfo<'func, A, M, F> -where - A: 'func + Architecture, - M: FunctionMutability, - F: FunctionForm, -{ - Load(Operation<'func, A, M, F, operation::Load>), - Pop(Operation<'func, A, M, F, operation::Pop>), - Reg(Operation<'func, A, M, F, operation::Reg>), - RegSplit(Operation<'func, A, M, F, operation::RegSplit>), - Const(Operation<'func, A, M, F, operation::Const>), - ConstPtr(Operation<'func, A, M, F, operation::Const>), - Flag(Operation<'func, A, M, F, operation::Flag>), - FlagBit(Operation<'func, A, M, F, operation::FlagBit>), - ExternPtr(Operation<'func, A, M, F, operation::Extern>), - - Add(Operation<'func, A, M, F, operation::BinaryOp>), - Adc(Operation<'func, A, M, F, operation::BinaryOpCarry>), - Sub(Operation<'func, A, M, F, operation::BinaryOp>), - Sbb(Operation<'func, A, M, F, operation::BinaryOpCarry>), - And(Operation<'func, A, M, F, operation::BinaryOp>), - Or(Operation<'func, A, M, F, operation::BinaryOp>), - Xor(Operation<'func, A, M, F, operation::BinaryOp>), - Lsl(Operation<'func, A, M, F, operation::BinaryOp>), - Lsr(Operation<'func, A, M, F, operation::BinaryOp>), - Asr(Operation<'func, A, M, F, operation::BinaryOp>), - Rol(Operation<'func, A, M, F, operation::BinaryOp>), - Rlc(Operation<'func, A, M, F, operation::BinaryOpCarry>), - Ror(Operation<'func, A, M, F, operation::BinaryOp>), - Rrc(Operation<'func, A, M, F, operation::BinaryOpCarry>), - Mul(Operation<'func, A, M, F, operation::BinaryOp>), - - MulsDp(Operation<'func, A, M, F, operation::BinaryOp>), - MuluDp(Operation<'func, A, M, F, operation::BinaryOp>), - - Divu(Operation<'func, A, M, F, operation::BinaryOp>), - Divs(Operation<'func, A, M, F, operation::BinaryOp>), - - DivuDp(Operation<'func, A, M, F, operation::DoublePrecDivOp>), - DivsDp(Operation<'func, A, M, F, operation::DoublePrecDivOp>), - - Modu(Operation<'func, A, M, F, operation::BinaryOp>), - Mods(Operation<'func, A, M, F, operation::BinaryOp>), - - ModuDp(Operation<'func, A, M, F, operation::DoublePrecDivOp>), - ModsDp(Operation<'func, A, M, F, operation::DoublePrecDivOp>), - - Neg(Operation<'func, A, M, F, operation::UnaryOp>), - Not(Operation<'func, A, M, F, operation::UnaryOp>), - Sx(Operation<'func, A, M, F, operation::UnaryOp>), - Zx(Operation<'func, A, M, F, operation::UnaryOp>), - LowPart(Operation<'func, A, M, F, operation::UnaryOp>), - - FlagCond(Operation<'func, A, M, F, operation::FlagCond>), - FlagGroup(Operation<'func, A, M, F, operation::FlagGroup>), - - CmpE(Operation<'func, A, M, F, operation::Condition>), - CmpNe(Operation<'func, A, M, F, operation::Condition>), - CmpSlt(Operation<'func, A, M, F, operation::Condition>), - CmpUlt(Operation<'func, A, M, F, operation::Condition>), - CmpSle(Operation<'func, A, M, F, operation::Condition>), - CmpUle(Operation<'func, A, M, F, operation::Condition>), - CmpSge(Operation<'func, A, M, F, operation::Condition>), - CmpUge(Operation<'func, A, M, F, operation::Condition>), - CmpSgt(Operation<'func, A, M, F, operation::Condition>), - CmpUgt(Operation<'func, A, M, F, operation::Condition>), - - //TestBit(Operation<'func, A, M, F, operation::TestBit>), // TODO - BoolToInt(Operation<'func, A, M, F, operation::UnaryOp>), - - Fadd(Operation<'func, A, M, F, operation::BinaryOp>), - Fsub(Operation<'func, A, M, F, operation::BinaryOp>), - Fmul(Operation<'func, A, M, F, operation::BinaryOp>), - Fdiv(Operation<'func, A, M, F, operation::BinaryOp>), - Fsqrt(Operation<'func, A, M, F, operation::UnaryOp>), - Fneg(Operation<'func, A, M, F, operation::UnaryOp>), - Fabs(Operation<'func, A, M, F, operation::UnaryOp>), - FloatToInt(Operation<'func, A, M, F, operation::UnaryOp>), - IntToFloat(Operation<'func, A, M, F, operation::UnaryOp>), - FloatConv(Operation<'func, A, M, F, operation::UnaryOp>), - RoundToInt(Operation<'func, A, M, F, operation::UnaryOp>), - Floor(Operation<'func, A, M, F, operation::UnaryOp>), - Ceil(Operation<'func, A, M, F, operation::UnaryOp>), - Ftrunc(Operation<'func, A, M, F, operation::UnaryOp>), - - FcmpE(Operation<'func, A, M, F, operation::Condition>), - FcmpNE(Operation<'func, A, M, F, operation::Condition>), - FcmpLT(Operation<'func, A, M, F, operation::Condition>), - FcmpLE(Operation<'func, A, M, F, operation::Condition>), - FcmpGE(Operation<'func, A, M, F, operation::Condition>), - FcmpGT(Operation<'func, A, M, F, operation::Condition>), - FcmpO(Operation<'func, A, M, F, operation::Condition>), - FcmpUO(Operation<'func, A, M, F, operation::Condition>), - - // TODO ADD_OVERFLOW - Unimpl(Operation<'func, A, M, F, operation::NoArgs>), - UnimplMem(Operation<'func, A, M, F, operation::UnimplMem>), - - Undef(Operation<'func, A, M, F, operation::NoArgs>), -} - -impl<'func, A, M, F> ExprInfo<'func, A, M, F> -where - A: 'func + Architecture, - M: FunctionMutability, - F: FunctionForm, -{ - /// Returns the size of the result of this expression - /// - /// If the expression is malformed or is `Unimpl` there - /// is no meaningful size associated with the result. - pub fn size(&self) -> Option<usize> { - use self::ExprInfo::*; - - match *self { - Undef(..) | Unimpl(..) => None, - - FlagCond(..) | FlagGroup(..) | CmpE(..) | CmpNe(..) | CmpSlt(..) | CmpUlt(..) - | CmpSle(..) | CmpUle(..) | CmpSge(..) | CmpUge(..) | CmpSgt(..) | CmpUgt(..) => { - Some(0) - } - - _ => Some(self.raw_struct().size), - //TestBit(Operation<'func, A, M, F, operation::TestBit>), // TODO - } - } - - pub fn address(&self) -> u64 { - self.raw_struct().address - } - - /// Determines if the expressions represent the same operation - /// - /// It does not examine the operands for equality. - pub fn is_same_op_as(&self, other: &Self) -> bool { - use self::ExprInfo::*; - - match (self, other) { - (&Reg(..), &Reg(..)) => true, - _ => self.raw_struct().operation == other.raw_struct().operation, - } - } - - pub fn as_cmp_op(&self) -> Option<&Operation<'func, A, M, F, operation::Condition>> { - use self::ExprInfo::*; - - match *self { - CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op) - | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op) - | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op) - | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => Some(op), - _ => None, - } - } - - pub fn as_binary_op(&self) -> Option<&Operation<'func, A, M, F, operation::BinaryOp>> { - use self::ExprInfo::*; - - match *self { - Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op) - | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op) - | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op) - | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op) => Some(op), - _ => None, - } - } - - pub fn as_binary_op_carry( - &self, - ) -> Option<&Operation<'func, A, M, F, operation::BinaryOpCarry>> { - use self::ExprInfo::*; - - match *self { - Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => Some(op), - _ => None, - } - } - - pub fn as_double_prec_div_op( - &self, - ) -> Option<&Operation<'func, A, M, F, operation::DoublePrecDivOp>> { - use self::ExprInfo::*; - - match *self { - DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => Some(op), - _ => None, - } - } - - pub fn as_unary_op(&self) -> Option<&Operation<'func, A, M, F, operation::UnaryOp>> { - use self::ExprInfo::*; - - match *self { - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) - | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) - | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) - | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => Some(op), - _ => None, - } - } - - pub(crate) fn raw_struct(&self) -> &BNLowLevelILInstruction { - use self::ExprInfo::*; - - match *self { - Undef(ref op) => &op.op, - - Unimpl(ref op) => &op.op, - - FlagCond(ref op) => &op.op, - FlagGroup(ref op) => &op.op, - - CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op) - | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op) - | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op) - | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => &op.op, - - Load(ref op) => &op.op, - - Pop(ref op) => &op.op, - - Reg(ref op) => &op.op, - - RegSplit(ref op) => &op.op, - - Flag(ref op) => &op.op, - - FlagBit(ref op) => &op.op, - - Const(ref op) | ConstPtr(ref op) => &op.op, - - ExternPtr(ref op) => &op.op, - - Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => &op.op, - - Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op) - | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op) - | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op) - | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op) => &op.op, - - DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => &op.op, - - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) - | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) - | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) - | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => &op.op, - - UnimplMem(ref op) => &op.op, - //TestBit(Operation<'func, A, M, F, operation::TestBit>), // TODO - } - } -} - -impl<'func, A> ExprInfo<'func, A, Mutable, NonSSA<LiftedNonSSA>> -where - A: 'func + Architecture, -{ - pub fn flag_write(&self) -> Option<A::FlagWrite> { - use self::ExprInfo::*; - - match *self { - Undef(ref _op) => None, - - Unimpl(ref _op) => None, - - FlagCond(ref _op) => None, - FlagGroup(ref _op) => None, - - CmpE(ref _op) | CmpNe(ref _op) | CmpSlt(ref _op) | CmpUlt(ref _op) - | CmpSle(ref _op) | CmpUle(ref _op) | CmpSge(ref _op) | CmpUge(ref _op) - | CmpSgt(ref _op) | CmpUgt(ref _op) | FcmpE(ref _op) | FcmpNE(ref _op) - | FcmpLT(ref _op) | FcmpLE(ref _op) | FcmpGE(ref _op) | FcmpGT(ref _op) - | FcmpO(ref _op) | FcmpUO(ref _op) => None, - - Load(ref op) => op.flag_write(), - - Pop(ref op) => op.flag_write(), - - Reg(ref op) => op.flag_write(), - - RegSplit(ref op) => op.flag_write(), - - Flag(ref op) => op.flag_write(), - - FlagBit(ref op) => op.flag_write(), - - Const(ref op) | ConstPtr(ref op) => op.flag_write(), - - ExternPtr(ref op) => op.flag_write(), - - Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => op.flag_write(), - - Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op) - | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op) - | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op) - | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op) => { - op.flag_write() - } - - DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => op.flag_write(), - - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) - | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) - | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) - | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => op.flag_write(), - - UnimplMem(ref op) => op.flag_write(), - //TestBit(Operation<'func, A, M, F, operation::TestBit>), // TODO - } - } -} - -impl<'func, A, M, V> fmt::Debug for ExprInfo<'func, A, M, NonSSA<V>> -where - A: 'func + Architecture, - M: FunctionMutability, - V: NonSSAVariant, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::ExprInfo::*; - - match *self { - Undef(..) => f.write_str("undefined"), - - Unimpl(..) => f.write_str("unimplemented"), - - FlagCond(..) => f.write_str("some_flag_cond"), - FlagGroup(..) => f.write_str("some_flag_group"), - - CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op) - | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op) - | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op) - | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => { - let left = op.left(); - let right = op.right(); - - write!( - f, - "{:?}({}, {:?}, {:?})", - op.op.operation, - op.size(), - left, - right - ) - } - - Load(ref op) => { - let source = op.source_mem_expr(); - let size = op.size(); - - write!(f, "[{:?}].{}", source, size) - } - - Pop(ref op) => write!(f, "pop.{}", op.size()), - - Reg(ref op) => { - let reg = op.source_reg(); - let size = op.size(); - - let size = match reg { - Register::Temp(_) => Some(size), - Register::ArchReg(ref r) if r.info().size() != size => Some(size), - _ => None, - }; - - match size { - Some(s) => write!(f, "{:?}.{}", reg, s), - _ => write!(f, "{:?}", reg), - } - } - - RegSplit(ref op) => { - let low_reg = op.low_reg(); - let high_reg = op.high_reg(); - let size = op.size(); - - let low_size = match low_reg { - Register::Temp(_) => Some(size), - Register::ArchReg(ref r) if r.info().size() != size => Some(size), - _ => None, - }; - - let high_size = match high_reg { - Register::Temp(_) => Some(size), - Register::ArchReg(ref r) if r.info().size() != size => Some(size), - _ => None, - }; - - match (low_size, high_size) { - (Some(ls), Some(hs)) => write!(f, "{:?}.{}:{:?}.{}", high_reg, hs, low_reg, ls), - (Some(ls), None) => write!(f, "{:?}:{:?}.{}", high_reg, low_reg, ls), - (None, Some(hs)) => write!(f, "{:?}.{}:{:?}", high_reg, hs, low_reg), - _ => write!(f, "{:?}:{:?}", high_reg, low_reg), - } - } - - Flag(ref _op) => write!(f, "flag"), // TODO - - FlagBit(ref _op) => write!(f, "flag_bit"), // TODO - - Const(ref op) | ConstPtr(ref op) => write!(f, "0x{:x}", op.value()), - - ExternPtr(ref op) => write!(f, "0x{:x}", op.value()), - - Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => { - let left = op.left(); - let right = op.right(); - let carry = op.carry(); - - write!( - f, - "{:?}({}, {:?}, {:?}, carry: {:?})", - op.op.operation, - op.size(), - left, - right, - carry - ) - } - - Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op) - | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op) - | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op) - | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op) => { - let left = op.left(); - let right = op.right(); - - write!( - f, - "{:?}({}, {:?}, {:?})", - op.op.operation, - op.size(), - left, - right - ) - } - - DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => { - let high = op.high(); - let low = op.low(); - let right = op.right(); - - write!( - f, - "{:?}({}, {:?}:{:?},{:?})", - op.op.operation, - op.size(), - high, - low, - right - ) - } - - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) - | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) - | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) - | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => write!( - f, - "{:?}({}, {:?})", - op.op.operation, - op.size(), - op.operand() - ), - - UnimplMem(ref op) => write!(f, "unimplemented_mem({:?})", op.mem_expr()), - //TestBit(Operation<'func, A, M, F, operation::TestBit>), // TODO - } - } -} |
