diff options
Diffstat (limited to 'rust/src/llil/lifting.rs')
| -rw-r--r-- | rust/src/llil/lifting.rs | 1492 |
1 files changed, 0 insertions, 1492 deletions
diff --git a/rust/src/llil/lifting.rs b/rust/src/llil/lifting.rs deleted file mode 100644 index 840e029b..00000000 --- a/rust/src/llil/lifting.rs +++ /dev/null @@ -1,1492 +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 std::marker::PhantomData; -use std::mem; - -use crate::architecture::Architecture; -use crate::architecture::Register as ArchReg; -use crate::architecture::{ - Flag, FlagClass, FlagCondition, FlagGroup, FlagRole, FlagWrite, Intrinsic, -}; - -use super::*; - -pub trait Liftable<'func, A: 'func + Architecture> { - type Result: ExpressionResultType; - - fn lift( - il: &'func Function<A, Mutable, NonSSA<LiftedNonSSA>>, - expr: Self, - ) -> Expression<'func, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result>; -} - -pub trait LiftableWithSize<'func, A: 'func + Architecture>: - Liftable<'func, A, Result = ValueExpr> -{ - fn lift_with_size( - il: &'func Function<A, Mutable, NonSSA<LiftedNonSSA>>, - expr: Self, - size: usize, - ) -> Expression<'func, A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr>; -} - -use binaryninjacore_sys::BNRegisterOrConstant; - -#[derive(Copy, Clone)] -pub enum RegisterOrConstant<R: ArchReg> { - Register(usize, Register<R>), - Constant(usize, u64), -} - -impl<R: ArchReg> RegisterOrConstant<R> { - pub(crate) fn into_api(self) -> BNRegisterOrConstant { - match self { - RegisterOrConstant::Register(_, r) => BNRegisterOrConstant { - constant: false, - reg: r.id(), - value: 0, - }, - RegisterOrConstant::Constant(_, value) => BNRegisterOrConstant { - constant: true, - reg: 0, - value, - }, - } - } -} - -// TODO flesh way out -#[derive(Copy, Clone)] -pub enum FlagWriteOp<R: ArchReg> { - SetReg(usize, RegisterOrConstant<R>), - SetRegSplit(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - - Sub(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Add(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - - Load(usize, RegisterOrConstant<R>), - - Push(usize, RegisterOrConstant<R>), - Neg(usize, RegisterOrConstant<R>), - Not(usize, RegisterOrConstant<R>), - Sx(usize, RegisterOrConstant<R>), - Zx(usize, RegisterOrConstant<R>), - LowPart(usize, RegisterOrConstant<R>), - BoolToInt(usize, RegisterOrConstant<R>), - FloatToInt(usize, RegisterOrConstant<R>), - - Store(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - - And(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Or(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Xor(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Lsl(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Lsr(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Asr(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Rol(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Ror(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Mul(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - MuluDp(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - MulsDp(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Divu(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Divs(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Modu(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - Mods(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - DivuDp(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - DivsDp(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - ModuDp(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - ModsDp(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - - TestBit(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - AddOverflow(usize, RegisterOrConstant<R>, RegisterOrConstant<R>), - - Adc( - usize, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - ), - Sbb( - usize, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - ), - Rlc( - usize, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - ), - Rrc( - usize, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - RegisterOrConstant<R>, - ), - - Pop(usize), - // TODO: floating point stuff, llil comparison ops that set flags, intrinsics -} - -impl<R: ArchReg> FlagWriteOp<R> { - pub(crate) fn from_op<A>( - arch: &A, - size: usize, - op: BNLowLevelILOperation, - operands: &[BNRegisterOrConstant], - ) -> Option<Self> - where - A: Architecture<Register = R>, - R: ArchReg<InfoType = A::RegisterInfo>, - { - use self::FlagWriteOp::*; - use binaryninjacore_sys::BNLowLevelILOperation::*; - - fn build_op<A, R>( - arch: &A, - size: usize, - operand: &BNRegisterOrConstant, - ) -> RegisterOrConstant<R> - where - A: Architecture<Register = R>, - R: ArchReg<InfoType = A::RegisterInfo>, - { - if operand.constant { - RegisterOrConstant::Constant(size, operand.value) - } else { - let il_reg = if 0x8000_0000 & operand.reg == 0 { - Register::ArchReg(arch.register_from_id(operand.reg).unwrap()) - } else { - Register::Temp(operand.reg) - }; - - RegisterOrConstant::Register(size, il_reg) - } - } - - macro_rules! op { - ($x:ident, $($ops:expr),*) => { - ( $x(size, $( build_op(arch, size, &operands[$ops]), )* ) ) - }; - } - - Some(match (operands.len(), op) { - (1, LLIL_SET_REG) => op!(SetReg, 0), - (2, LLIL_SET_REG_SPLIT) => op!(SetRegSplit, 0, 1), - - (2, LLIL_SUB) => op!(Sub, 0, 1), - (2, LLIL_ADD) => op!(Add, 0, 1), - - (1, LLIL_LOAD) => op!(Load, 0), - - (1, LLIL_PUSH) => op!(Push, 0), - (1, LLIL_NEG) => op!(Neg, 0), - (1, LLIL_NOT) => op!(Not, 0), - (1, LLIL_SX) => op!(Sx, 0), - (1, LLIL_ZX) => op!(Zx, 0), - (1, LLIL_LOW_PART) => op!(LowPart, 0), - (1, LLIL_BOOL_TO_INT) => op!(BoolToInt, 0), - (1, LLIL_FLOAT_TO_INT) => op!(FloatToInt, 0), - - (2, LLIL_STORE) => op!(Store, 0, 1), - - (2, LLIL_AND) => op!(And, 0, 1), - (2, LLIL_OR) => op!(Or, 0, 1), - (2, LLIL_XOR) => op!(Xor, 0, 1), - (2, LLIL_LSL) => op!(Lsl, 0, 1), - (2, LLIL_LSR) => op!(Lsr, 0, 1), - (2, LLIL_ASR) => op!(Asr, 0, 1), - (2, LLIL_ROL) => op!(Rol, 0, 1), - (2, LLIL_ROR) => op!(Ror, 0, 1), - (2, LLIL_MUL) => op!(Mul, 0, 1), - (2, LLIL_MULU_DP) => op!(MuluDp, 0, 1), - (2, LLIL_MULS_DP) => op!(MulsDp, 0, 1), - (2, LLIL_DIVU) => op!(Divu, 0, 1), - (2, LLIL_DIVS) => op!(Divs, 0, 1), - (2, LLIL_MODU) => op!(Modu, 0, 1), - (2, LLIL_MODS) => op!(Mods, 0, 1), - (2, LLIL_DIVU_DP) => op!(DivuDp, 0, 1), - (2, LLIL_DIVS_DP) => op!(DivsDp, 0, 1), - (2, LLIL_MODU_DP) => op!(ModuDp, 0, 1), - (2, LLIL_MODS_DP) => op!(ModsDp, 0, 1), - - (2, LLIL_TEST_BIT) => op!(TestBit, 0, 1), - (2, LLIL_ADD_OVERFLOW) => op!(AddOverflow, 0, 1), - - (3, LLIL_ADC) => op!(Adc, 0, 1, 2), - (3, LLIL_SBB) => op!(Sbb, 0, 1, 2), - (3, LLIL_RLC) => op!(Rlc, 0, 1, 2), - (3, LLIL_RRC) => op!(Rrc, 0, 1, 2), - - (0, LLIL_POP) => op!(Pop,), - - _ => return None, - }) - } - - pub(crate) fn size_and_op(&self) -> (usize, BNLowLevelILOperation) { - use self::FlagWriteOp::*; - use binaryninjacore_sys::BNLowLevelILOperation::*; - - match *self { - SetReg(size, ..) => (size, LLIL_SET_REG), - SetRegSplit(size, ..) => (size, LLIL_SET_REG_SPLIT), - - Sub(size, ..) => (size, LLIL_SUB), - Add(size, ..) => (size, LLIL_ADD), - - Load(size, ..) => (size, LLIL_LOAD), - - Push(size, ..) => (size, LLIL_PUSH), - Neg(size, ..) => (size, LLIL_NEG), - Not(size, ..) => (size, LLIL_NOT), - Sx(size, ..) => (size, LLIL_SX), - Zx(size, ..) => (size, LLIL_ZX), - LowPart(size, ..) => (size, LLIL_LOW_PART), - BoolToInt(size, ..) => (size, LLIL_BOOL_TO_INT), - FloatToInt(size, ..) => (size, LLIL_FLOAT_TO_INT), - - Store(size, ..) => (size, LLIL_STORE), - - And(size, ..) => (size, LLIL_AND), - Or(size, ..) => (size, LLIL_OR), - Xor(size, ..) => (size, LLIL_XOR), - Lsl(size, ..) => (size, LLIL_LSL), - Lsr(size, ..) => (size, LLIL_LSR), - Asr(size, ..) => (size, LLIL_ASR), - Rol(size, ..) => (size, LLIL_ROL), - Ror(size, ..) => (size, LLIL_ROR), - Mul(size, ..) => (size, LLIL_MUL), - MuluDp(size, ..) => (size, LLIL_MULU_DP), - MulsDp(size, ..) => (size, LLIL_MULS_DP), - Divu(size, ..) => (size, LLIL_DIVU), - Divs(size, ..) => (size, LLIL_DIVS), - Modu(size, ..) => (size, LLIL_MODU), - Mods(size, ..) => (size, LLIL_MODS), - DivuDp(size, ..) => (size, LLIL_DIVU_DP), - DivsDp(size, ..) => (size, LLIL_DIVS_DP), - ModuDp(size, ..) => (size, LLIL_MODU_DP), - ModsDp(size, ..) => (size, LLIL_MODS_DP), - - TestBit(size, ..) => (size, LLIL_TEST_BIT), - AddOverflow(size, ..) => (size, LLIL_ADD_OVERFLOW), - - Adc(size, ..) => (size, LLIL_ADC), - Sbb(size, ..) => (size, LLIL_SBB), - Rlc(size, ..) => (size, LLIL_RLC), - Rrc(size, ..) => (size, LLIL_RRC), - - Pop(size) => (size, LLIL_POP), - } - } - - pub(crate) fn api_operands(&self) -> (usize, [BNRegisterOrConstant; 5]) { - use self::FlagWriteOp::*; - - let mut operands: [BNRegisterOrConstant; 5] = unsafe { mem::zeroed() }; - - let count = match *self { - Pop(_) => 0, - - SetReg(_, op0) - | Load(_, op0) - | Push(_, op0) - | Neg(_, op0) - | Not(_, op0) - | Sx(_, op0) - | Zx(_, op0) - | LowPart(_, op0) - | BoolToInt(_, op0) - | FloatToInt(_, op0) => { - operands[0] = op0.into_api(); - 1 - } - - SetRegSplit(_, op0, op1) - | Sub(_, op0, op1) - | Add(_, op0, op1) - | Store(_, op0, op1) - | And(_, op0, op1) - | Or(_, op0, op1) - | Xor(_, op0, op1) - | Lsl(_, op0, op1) - | Lsr(_, op0, op1) - | Asr(_, op0, op1) - | Rol(_, op0, op1) - | Ror(_, op0, op1) - | Mul(_, op0, op1) - | MuluDp(_, op0, op1) - | MulsDp(_, op0, op1) - | Divu(_, op0, op1) - | Divs(_, op0, op1) - | Modu(_, op0, op1) - | Mods(_, op0, op1) - | DivuDp(_, op0, op1) - | DivsDp(_, op0, op1) - | ModuDp(_, op0, op1) - | ModsDp(_, op0, op1) - | TestBit(_, op0, op1) - | AddOverflow(_, op0, op1) => { - operands[0] = op0.into_api(); - operands[1] = op1.into_api(); - 2 - } - - Adc(_, op0, op1, op2) - | Sbb(_, op0, op1, op2) - | Rlc(_, op0, op1, op2) - | Rrc(_, op0, op1, op2) => { - operands[0] = op0.into_api(); - operands[1] = op1.into_api(); - operands[2] = op2.into_api(); - 3 - } - }; - - (count, operands) - } -} - -pub fn get_default_flag_write_llil<'func, A>( - arch: &A, - role: FlagRole, - op: FlagWriteOp<A::Register>, - il: &'func Lifter<A>, -) -> LiftedExpr<'func, A> -where - A: 'func + Architecture, -{ - let (size, operation) = op.size_and_op(); - let (count, operands) = op.api_operands(); - - let expr_idx = unsafe { - use binaryninjacore_sys::BNGetDefaultArchitectureFlagWriteLowLevelIL; - BNGetDefaultArchitectureFlagWriteLowLevelIL( - arch.as_ref().0, - operation, - size, - role, - operands.as_ptr() as *mut _, - count, - il.handle, - ) - }; - - Expression::new(il, expr_idx) -} - -pub fn get_default_flag_cond_llil<'func, A>( - arch: &A, - cond: FlagCondition, - class: Option<A::FlagClass>, - il: &'func Lifter<A>, -) -> LiftedExpr<'func, A> -where - A: 'func + Architecture, -{ - use binaryninjacore_sys::BNGetDefaultArchitectureFlagConditionLowLevelIL; - - let handle = arch.as_ref(); - let class_id = class.map(|c| c.id()).unwrap_or(0); - - unsafe { - let expr_idx = - BNGetDefaultArchitectureFlagConditionLowLevelIL(handle.0, cond, class_id, il.handle); - - Expression::new(il, expr_idx) - } -} - -macro_rules! prim_int_lifter { - ($x:ty) => { - impl<'a, A: 'a + Architecture> Liftable<'a, A> for $x { - type Result = ValueExpr; - - fn lift(il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, val: Self) - -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result> - { - il.const_int(mem::size_of::<Self>(), val as i64 as u64) - } - } - - impl<'a, A: 'a + Architecture> LiftableWithSize<'a, A> for $x { - fn lift_with_size(il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, val: Self, size: usize) - -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> - { - let raw = val as i64; - - #[cfg(debug_assertions)] - { - let is_safe = match raw.overflowing_shr(size as u32 * 8) { - (_, true) => true, - (res, false) => [-1, 0].contains(&res), - }; - - if !is_safe { - error!("il @ {:x} attempted to lift constant 0x{:x} as {} byte expr (won't fit!)", - il.current_address(), val, size); - } - } - - il.const_int(size, raw as u64) - } - } - } -} - -prim_int_lifter!(i8); -prim_int_lifter!(i16); -prim_int_lifter!(i32); -prim_int_lifter!(i64); - -prim_int_lifter!(u8); -prim_int_lifter!(u16); -prim_int_lifter!(u32); -prim_int_lifter!(u64); - -impl<'a, R: ArchReg, A: 'a + Architecture> Liftable<'a, A> for Register<R> -where - R: Liftable<'a, A, Result = ValueExpr> + Into<Register<R>>, -{ - type Result = ValueExpr; - - fn lift( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - reg: Self, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result> { - match reg { - Register::ArchReg(r) => R::lift(il, r), - Register::Temp(t) => il.reg(il.arch().default_integer_size(), Register::Temp(t)), - } - } -} - -impl<'a, R: ArchReg, A: 'a + Architecture> LiftableWithSize<'a, A> for Register<R> -where - R: LiftableWithSize<'a, A> + Into<Register<R>>, -{ - fn lift_with_size( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - reg: Self, - size: usize, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - match reg { - Register::ArchReg(r) => R::lift_with_size(il, r, size), - Register::Temp(t) => il.reg(size, Register::Temp(t)), - } - } -} - -impl<'a, R: ArchReg, A: 'a + Architecture> Liftable<'a, A> for RegisterOrConstant<R> -where - R: LiftableWithSize<'a, A, Result = ValueExpr> + Into<Register<R>>, -{ - type Result = ValueExpr; - - fn lift( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - reg: Self, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result> { - match reg { - RegisterOrConstant::Register(size, r) => Register::<R>::lift_with_size(il, r, size), - RegisterOrConstant::Constant(size, value) => u64::lift_with_size(il, value, size), - } - } -} - -impl<'a, R: ArchReg, A: 'a + Architecture> LiftableWithSize<'a, A> for RegisterOrConstant<R> -where - R: LiftableWithSize<'a, A> + Into<Register<R>>, -{ - fn lift_with_size( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - reg: Self, - size: usize, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - // TODO ensure requested size is compatible with size of this constant - match reg { - RegisterOrConstant::Register(_, r) => Register::<R>::lift_with_size(il, r, size), - RegisterOrConstant::Constant(_, value) => u64::lift_with_size(il, value, size), - } - } -} - -impl<'a, A, R> Liftable<'a, A> for Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, R> -where - A: 'a + Architecture, - R: ExpressionResultType, -{ - type Result = R; - - fn lift( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - expr: Self, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result> { - debug_assert!(expr.function.handle == il.handle); - expr - } -} - -impl<'a, A: 'a + Architecture> LiftableWithSize<'a, A> - for Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> -{ - fn lift_with_size( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - expr: Self, - _size: usize, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result> { - #[cfg(debug_assertions)] - { - if let Some(expr_size) = expr.info().size() { - if expr_size != _size { - warn!( - "il @ {:x} attempted to lift {} byte expression as {} bytes", - il.current_address(), - expr_size, - _size - ); - } - } - } - - Liftable::lift(il, expr) - } -} - -impl<'func, A, R> Expression<'func, A, Mutable, NonSSA<LiftedNonSSA>, R> -where - A: 'func + Architecture, - R: ExpressionResultType, -{ - pub fn with_source_operand(self, op: u32) -> Self { - use binaryninjacore_sys::BNLowLevelILSetExprSourceOperand; - - unsafe { BNLowLevelILSetExprSourceOperand(self.function.handle, self.expr_idx, op) } - - self - } - - pub fn append(self) { - let il = self.function; - il.instruction(self); - } -} - -use binaryninjacore_sys::BNLowLevelILOperation; -pub struct ExpressionBuilder<'func, A, R> -where - A: 'func + Architecture, - R: ExpressionResultType, -{ - function: &'func Function<A, Mutable, NonSSA<LiftedNonSSA>>, - op: BNLowLevelILOperation, - size: usize, - flags: u32, - op1: u64, - op2: u64, - op3: u64, - op4: u64, - _ty: PhantomData<R>, -} - -impl<'a, A, R> ExpressionBuilder<'a, A, R> -where - A: 'a + Architecture, - R: ExpressionResultType, -{ - pub fn from_expr(expr: Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, R>) -> Self { - use binaryninjacore_sys::BNGetLowLevelILByIndex; - - let instr = unsafe { - BNGetLowLevelILByIndex(expr.function.handle, expr.expr_idx) - }; - - ExpressionBuilder { - function: expr.function, - op: instr.operation, - size: instr.size, - flags: instr.flags, - op1: instr.operands[0], - op2: instr.operands[1], - op3: instr.operands[2], - op4: instr.operands[3], - _ty: PhantomData - } - } - - pub fn with_flag_write(mut self, flag_write: A::FlagWrite) -> Self { - // TODO verify valid id - self.flags = flag_write.id(); - self - } - - pub fn build(self) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, R> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - - let expr_idx = unsafe { - BNLowLevelILAddExpr( - self.function.handle, - self.op, - self.size, - self.flags, - self.op1, - self.op2, - self.op3, - self.op4, - ) - }; - - Expression::new(self.function, expr_idx) - } - - pub fn with_source_operand( - self, - op: u32, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, R> { - self.build().with_source_operand(op) - } - - pub fn append(self) { - let expr = self.build(); - let il = expr.function; - - il.instruction(expr); - } -} - -impl<'a, A, R> Liftable<'a, A> for ExpressionBuilder<'a, A, R> -where - A: 'a + Architecture, - R: ExpressionResultType, -{ - type Result = R; - - fn lift( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - expr: Self, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, Self::Result> { - debug_assert!(expr.function.handle == il.handle); - - expr.build() - } -} - -impl<'a, A> LiftableWithSize<'a, A> for ExpressionBuilder<'a, A, ValueExpr> -where - A: 'a + Architecture, -{ - fn lift_with_size( - il: &'a Function<A, Mutable, NonSSA<LiftedNonSSA>>, - expr: Self, - _size: usize, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - #[cfg(debug_assertions)] - { - use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_UNIMPL, LLIL_UNIMPL_MEM}; - - if expr.size != _size && ![LLIL_UNIMPL, LLIL_UNIMPL_MEM].contains(&expr.op) { - warn!( - "il @ {:x} attempted to lift {} byte expression builder as {} bytes", - il.current_address(), - expr.size, - _size - ); - } - } - - Liftable::lift(il, expr) - } -} - -macro_rules! no_arg_lifter { - ($name:ident, $op:ident, $result:ty) => { - pub fn $name(&self) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, $result> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - let expr_idx = unsafe { BNLowLevelILAddExpr(self.handle, $op, 0, 0, 0, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - }; -} - -macro_rules! sized_no_arg_lifter { - ($name:ident, $op:ident, $result:ty) => { - pub fn $name(&self, size: usize) -> ExpressionBuilder<A, $result> { - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - ExpressionBuilder { - function: self, - op: $op, - size, - flags: 0, - op1: 0, - op2: 0, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - }; -} - -macro_rules! unsized_unary_op_lifter { - ($name:ident, $op:ident, $result:ty) => { - pub fn $name<'a, E>( - &'a self, - expr: E, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, $result> - where - E: Liftable<'a, A, Result = ValueExpr>, - { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - let expr = E::lift(self, expr); - - let expr_idx = unsafe { - BNLowLevelILAddExpr(self.handle, $op, 0, 0, expr.expr_idx as u64, 0, 0, 0) - }; - - Expression::new(self, expr_idx) - } - }; -} - -macro_rules! sized_unary_op_lifter { - ($name:ident, $op:ident, $result:ty) => { - pub fn $name<'a, E>(&'a self, size: usize, expr: E) -> ExpressionBuilder<'a, A, $result> - where - E: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - let expr = E::lift_with_size(self, expr, size); - - ExpressionBuilder { - function: self, - op: $op, - size, - flags: 0, - op1: expr.expr_idx as u64, - op2: 0, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - }; -} - -macro_rules! size_changing_unary_op_lifter { - ($name:ident, $op:ident, $result:ty) => { - pub fn $name<'a, E>(&'a self, size: usize, expr: E) -> ExpressionBuilder<'a, A, $result> - where - E: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - let expr = E::lift(self, expr); - - ExpressionBuilder { - function: self, - op: $op, - size, - flags: 0, - op1: expr.expr_idx as u64, - op2: 0, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - }; -} - -macro_rules! binary_op_lifter { - ($name:ident, $op:ident) => { - pub fn $name<'a, L, R>( - &'a self, - size: usize, - left: L, - right: R, - ) -> ExpressionBuilder<'a, A, ValueExpr> - where - L: LiftableWithSize<'a, A>, - R: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - let left = L::lift_with_size(self, left, size); - let right = R::lift_with_size(self, right, size); - - ExpressionBuilder { - function: self, - op: $op, - size, - flags: 0, - op1: left.expr_idx as u64, - op2: right.expr_idx as u64, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - }; -} - -macro_rules! binary_op_carry_lifter { - ($name:ident, $op:ident) => { - pub fn $name<'a, L, R, C>( - &'a self, - size: usize, - left: L, - right: R, - carry: C, - ) -> ExpressionBuilder<'a, A, ValueExpr> - where - L: LiftableWithSize<'a, A>, - R: LiftableWithSize<'a, A>, - C: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::$op; - - let left = L::lift_with_size(self, left, size); - let right = R::lift_with_size(self, right, size); - let carry = C::lift_with_size(self, carry, 0); - - ExpressionBuilder { - function: self, - op: $op, - size, - flags: 0, - op1: left.expr_idx as u64, - op2: right.expr_idx as u64, - op3: carry.expr_idx as u64, - op4: 0, - _ty: PhantomData, - } - } - }; -} - -impl<A> Function<A, Mutable, NonSSA<LiftedNonSSA>> -where - A: Architecture, -{ - pub const NO_INPUTS: [ExpressionBuilder<'static, A, ValueExpr>; 0] = []; - pub const NO_OUTPUTS: [Register<A::Register>; 0] = []; - - pub fn expression<'a, E: Liftable<'a, A>>( - &'a self, - expr: E, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, E::Result> { - E::lift(self, expr) - } - - pub fn instruction<'a, E: Liftable<'a, A>>(&'a self, expr: E) { - let expr = self.expression(expr); - - unsafe { - use binaryninjacore_sys::BNLowLevelILAddInstruction; - BNLowLevelILAddInstruction(self.handle, expr.expr_idx); - } - } - - pub unsafe fn replace_expression<'a, E: Liftable<'a, A>>( - &'a self, - replaced_expr_index: usize, - replacement: E, - ) { - use binaryninjacore_sys::BNGetLowLevelILExprCount; - use binaryninjacore_sys::BNReplaceLowLevelILExpr; - - if replaced_expr_index >= BNGetLowLevelILExprCount(self.handle) { - panic!( - "bad expr idx used: {} exceeds function bounds", - replaced_expr_index - ); - } - - let expr = self.expression(replacement); - BNReplaceLowLevelILExpr(self.handle, replaced_expr_index, expr.expr_idx); - } - - pub fn const_int( - &self, - size: usize, - val: u64, - ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CONST; - - let expr_idx = - unsafe { BNLowLevelILAddExpr(self.handle, LLIL_CONST, size, 0, val, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - - pub fn const_ptr_sized( - &self, - size: usize, - val: u64, - ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CONST_PTR; - - let expr_idx = - unsafe { BNLowLevelILAddExpr(self.handle, LLIL_CONST_PTR, size, 0, val, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - - pub fn const_ptr(&self, val: u64) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - self.const_ptr_sized(self.arch().address_size(), val) - } - - pub fn trap(&self, val: u64) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, VoidExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_TRAP; - - let expr_idx = unsafe { BNLowLevelILAddExpr(self.handle, LLIL_TRAP, 0, 0, val, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - - no_arg_lifter!(unimplemented, LLIL_UNIMPL, ValueExpr); - no_arg_lifter!(undefined, LLIL_UNDEF, VoidExpr); - no_arg_lifter!(nop, LLIL_NOP, VoidExpr); - - no_arg_lifter!(no_ret, LLIL_NORET, VoidExpr); - no_arg_lifter!(syscall, LLIL_SYSCALL, VoidExpr); - no_arg_lifter!(bp, LLIL_BP, VoidExpr); - - unsized_unary_op_lifter!(call, LLIL_CALL, VoidExpr); - unsized_unary_op_lifter!(ret, LLIL_RET, VoidExpr); - unsized_unary_op_lifter!(jump, LLIL_JUMP, VoidExpr); - // JumpTo TODO - - pub fn if_expr<'a: 'b, 'b, C>( - &'a self, - cond: C, - t: &'b Label, - f: &'b Label, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, VoidExpr> - where - C: Liftable<'b, A, Result = ValueExpr>, - { - use binaryninjacore_sys::BNLowLevelILIf; - - let cond = C::lift(self, cond); - - let expr_idx = unsafe { - BNLowLevelILIf( - self.handle, - cond.expr_idx as u64, - &t.0 as *const _ as *mut _, - &f.0 as *const _ as *mut _, - ) - }; - - Expression::new(self, expr_idx) - } - - pub fn goto<'a: 'b, 'b>( - &'a self, - l: &'b Label, - ) -> Expression<'a, A, Mutable, NonSSA<LiftedNonSSA>, VoidExpr> { - use binaryninjacore_sys::BNLowLevelILGoto; - - let expr_idx = unsafe { BNLowLevelILGoto(self.handle, &l.0 as *const _ as *mut _) }; - - Expression::new(self, expr_idx) - } - - pub fn reg<R: Into<Register<A::Register>>>( - &self, - size: usize, - reg: R, - ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG; - - // TODO verify valid id - let reg = match reg.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - - let expr_idx = - unsafe { BNLowLevelILAddExpr(self.handle, LLIL_REG, size, 0, reg as u64, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - - pub fn reg_split<H: Into<Register<A::Register>>, L: Into<Register<A::Register>>>( - &self, - size: usize, - hi_reg: H, - lo_reg: L, - ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG_SPLIT; - - // TODO verify valid id - let hi_reg = match hi_reg.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - - // TODO verify valid id - let lo_reg = match lo_reg.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - - let expr_idx = unsafe { - BNLowLevelILAddExpr( - self.handle, - LLIL_REG_SPLIT, - size, - 0, - hi_reg as u64, - lo_reg as u64, - 0, - 0, - ) - }; - - Expression::new(self, expr_idx) - } - - pub fn set_reg<'a, R, E>( - &'a self, - size: usize, - dest_reg: R, - expr: E, - ) -> ExpressionBuilder<'a, A, VoidExpr> - where - R: Into<Register<A::Register>>, - E: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG; - - // TODO verify valid id - let dest_reg = match dest_reg.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - - let expr = E::lift_with_size(self, expr, size); - - ExpressionBuilder { - function: self, - op: LLIL_SET_REG, - size, - flags: 0, - op1: dest_reg as u64, - op2: expr.expr_idx as u64, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - - pub fn set_reg_split<'a, H, L, E>( - &'a self, - size: usize, - hi_reg: H, - lo_reg: L, - expr: E, - ) -> ExpressionBuilder<'a, A, VoidExpr> - where - H: Into<Register<A::Register>>, - L: Into<Register<A::Register>>, - E: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG_SPLIT; - - // TODO verify valid id - let hi_reg = match hi_reg.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - - // TODO verify valid id - let lo_reg = match lo_reg.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - - let expr = E::lift_with_size(self, expr, size); - - ExpressionBuilder { - function: self, - op: LLIL_SET_REG_SPLIT, - size, - flags: 0, - op1: hi_reg as u64, - op2: lo_reg as u64, - op3: expr.expr_idx as u64, - op4: 0, - _ty: PhantomData, - } - } - - pub fn flag(&self, flag: A::Flag) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG; - - // TODO verify valid id - let expr_idx = - unsafe { BNLowLevelILAddExpr(self.handle, LLIL_FLAG, 0, 0, flag.id() as u64, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - - pub fn flag_cond( - &self, - cond: FlagCondition, - ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_COND; - - // TODO verify valid id - let expr_idx = - unsafe { BNLowLevelILAddExpr(self.handle, LLIL_FLAG_COND, 0, 0, cond as u64, 0, 0, 0) }; - - Expression::new(self, expr_idx) - } - - pub fn flag_group( - &self, - group: A::FlagGroup, - ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> { - use binaryninjacore_sys::BNLowLevelILAddExpr; - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_GROUP; - - // TODO verify valid id - let expr_idx = unsafe { - BNLowLevelILAddExpr( - self.handle, - LLIL_FLAG_GROUP, - 0, - 0, - group.id() as u64, - 0, - 0, - 0, - ) - }; - - Expression::new(self, expr_idx) - } - - pub fn set_flag<'a, E>( - &'a self, - dest_flag: A::Flag, - expr: E, - ) -> ExpressionBuilder<'a, A, VoidExpr> - where - E: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_FLAG; - - // TODO verify valid id - - let expr = E::lift_with_size(self, expr, 0); - - ExpressionBuilder { - function: self, - op: LLIL_SET_FLAG, - size: 0, - flags: 0, - op1: dest_flag.id() as u64, - op2: expr.expr_idx as u64, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - - /* - * TODO - FlagBit(usize, Flag<A>, u64), - */ - - pub fn load<'a, E>(&'a self, size: usize, source_mem: E) -> ExpressionBuilder<'a, A, ValueExpr> - where - E: Liftable<'a, A, Result = ValueExpr>, - { - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_LOAD; - - let expr = E::lift(self, source_mem); - - ExpressionBuilder { - function: self, - op: LLIL_LOAD, - size, - flags: 0, - op1: expr.expr_idx as u64, - op2: 0, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - - pub fn store<'a, D, V>( - &'a self, - size: usize, - dest_mem: D, - value: V, - ) -> ExpressionBuilder<'a, A, VoidExpr> - where - D: Liftable<'a, A, Result = ValueExpr>, - V: LiftableWithSize<'a, A>, - { - use binaryninjacore_sys::BNLowLevelILOperation::LLIL_STORE; - - let dest_mem = D::lift(self, dest_mem); - let value = V::lift_with_size(self, value, size); - - ExpressionBuilder { - function: self, - op: LLIL_STORE, - size, - flags: 0, - op1: dest_mem.expr_idx as u64, - op2: value.expr_idx as u64, - op3: 0, - op4: 0, - _ty: PhantomData, - } - } - - pub fn intrinsic<'a, O, OL, I, P, PL>( - &'a self, - outputs: OL, - intrinsic: I, - inputs: PL, - ) -> ExpressionBuilder<'a, A, VoidExpr> - where - O: Into<Register<A::Register>>, - OL: IntoIterator<Item = O>, - I: Into<A::Intrinsic>, - P: Liftable<'a, A, Result = ValueExpr>, - PL: IntoIterator<Item = P>, - { - use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_CALL_PARAM, LLIL_INTRINSIC}; - use binaryninjacore_sys::{BNLowLevelILAddExpr, BNLowLevelILAddOperandList}; - - let mut outputs: Vec<u64> = outputs - .into_iter() - .map(|output| { - // TODO verify valid id - let output = match output.into() { - Register::ArchReg(r) => r.id(), - Register::Temp(r) => 0x8000_0000 | r, - }; - output as u64 - }) - .collect(); - let output_expr_idx = - unsafe { BNLowLevelILAddOperandList(self.handle, outputs.as_mut_ptr(), outputs.len()) }; - - let intrinsic: A::Intrinsic = intrinsic.into(); - - let mut inputs: Vec<u64> = inputs - .into_iter() - .map(|input| { - let input = P::lift(self, input); - input.expr_idx as u64 - }) - .collect(); - let input_list_expr_idx = - unsafe { BNLowLevelILAddOperandList(self.handle, inputs.as_mut_ptr(), inputs.len()) }; - let input_expr_idx = unsafe { - BNLowLevelILAddExpr( - self.handle, - LLIL_CALL_PARAM, - 0, - 0, - inputs.len() as u64, - input_list_expr_idx as u64, - 0, - 0, - ) - }; - - ExpressionBuilder { - function: self, - op: LLIL_INTRINSIC, - size: 0, - flags: 0, - op1: outputs.len() as u64, - op2: output_expr_idx as u64, - op3: intrinsic.id() as u64, - op4: input_expr_idx as u64, - _ty: PhantomData, - } - } - - sized_unary_op_lifter!(push, LLIL_PUSH, VoidExpr); - sized_no_arg_lifter!(pop, LLIL_POP, ValueExpr); - - size_changing_unary_op_lifter!(unimplemented_mem, LLIL_UNIMPL_MEM, ValueExpr); - - sized_unary_op_lifter!(neg, LLIL_NEG, ValueExpr); - sized_unary_op_lifter!(not, LLIL_NOT, ValueExpr); - - size_changing_unary_op_lifter!(sx, LLIL_SX, ValueExpr); - size_changing_unary_op_lifter!(zx, LLIL_ZX, ValueExpr); - size_changing_unary_op_lifter!(low_part, LLIL_LOW_PART, ValueExpr); - - binary_op_lifter!(add, LLIL_ADD); - binary_op_lifter!(add_overflow, LLIL_ADD_OVERFLOW); - binary_op_lifter!(sub, LLIL_SUB); - binary_op_lifter!(and, LLIL_AND); - binary_op_lifter!(or, LLIL_OR); - binary_op_lifter!(xor, LLIL_XOR); - binary_op_lifter!(lsl, LLIL_LSL); - binary_op_lifter!(lsr, LLIL_LSR); - binary_op_lifter!(asr, LLIL_ASR); - - binary_op_lifter!(rol, LLIL_ROL); - binary_op_lifter!(rlc, LLIL_RLC); - binary_op_lifter!(ror, LLIL_ROR); - binary_op_lifter!(rrc, LLIL_RRC); - binary_op_lifter!(mul, LLIL_MUL); - binary_op_lifter!(muls_dp, LLIL_MULS_DP); - binary_op_lifter!(mulu_dp, LLIL_MULU_DP); - binary_op_lifter!(divs, LLIL_DIVS); - binary_op_lifter!(divu, LLIL_DIVU); - binary_op_lifter!(mods, LLIL_MODS); - binary_op_lifter!(modu, LLIL_MODU); - - binary_op_carry_lifter!(adc, LLIL_ADC); - binary_op_carry_lifter!(sbb, LLIL_SBB); - - /* - DivsDp(usize, Expr, Expr, Expr, Option<A::FlagWrite>), - DivuDp(usize, Expr, Expr, Expr, Option<A::FlagWrite>), - ModsDp(usize, Expr, Expr, Expr, Option<A::FlagWrite>), - ModuDp(usize, Expr, Expr, Expr, Option<A::FlagWrite>), - */ - - // FlagCond(u32), // TODO - - binary_op_lifter!(cmp_e, LLIL_CMP_E); - binary_op_lifter!(cmp_ne, LLIL_CMP_NE); - binary_op_lifter!(cmp_slt, LLIL_CMP_SLT); - binary_op_lifter!(cmp_ult, LLIL_CMP_ULT); - binary_op_lifter!(cmp_sle, LLIL_CMP_SLE); - binary_op_lifter!(cmp_ule, LLIL_CMP_ULE); - binary_op_lifter!(cmp_sge, LLIL_CMP_SGE); - binary_op_lifter!(cmp_uge, LLIL_CMP_UGE); - binary_op_lifter!(cmp_sgt, LLIL_CMP_SGT); - binary_op_lifter!(cmp_ugt, LLIL_CMP_UGT); - binary_op_lifter!(test_bit, LLIL_TEST_BIT); - - // TODO no flags - size_changing_unary_op_lifter!(bool_to_int, LLIL_BOOL_TO_INT, ValueExpr); - - binary_op_lifter!(fadd, LLIL_FADD); - binary_op_lifter!(fsub, LLIL_FSUB); - binary_op_lifter!(fmul, LLIL_FMUL); - binary_op_lifter!(fdiv, LLIL_FDIV); - sized_unary_op_lifter!(fsqrt, LLIL_FSQRT, ValueExpr); - sized_unary_op_lifter!(fneg, LLIL_FNEG, ValueExpr); - sized_unary_op_lifter!(fabs, LLIL_FABS, ValueExpr); - sized_unary_op_lifter!(float_to_int, LLIL_FLOAT_TO_INT, ValueExpr); - sized_unary_op_lifter!(int_to_float, LLIL_INT_TO_FLOAT, ValueExpr); - sized_unary_op_lifter!(float_conv, LLIL_FLOAT_CONV, ValueExpr); - sized_unary_op_lifter!(round_to_int, LLIL_ROUND_TO_INT, ValueExpr); - sized_unary_op_lifter!(floor, LLIL_FLOOR, ValueExpr); - sized_unary_op_lifter!(ceil, LLIL_CEIL, ValueExpr); - sized_unary_op_lifter!(ftrunc, LLIL_FTRUNC, ValueExpr); - binary_op_lifter!(fcmp_e, LLIL_FCMP_E); - binary_op_lifter!(fcmp_ne, LLIL_FCMP_NE); - binary_op_lifter!(fcmp_lt, LLIL_FCMP_LT); - binary_op_lifter!(fcmp_le, LLIL_FCMP_LE); - binary_op_lifter!(fcmp_ge, LLIL_FCMP_GE); - binary_op_lifter!(fcmp_gt, LLIL_FCMP_GT); - binary_op_lifter!(fcmp_o, LLIL_FCMP_O); - binary_op_lifter!(fcmp_uo, LLIL_FCMP_UO); - - pub fn current_address(&self) -> u64 { - use binaryninjacore_sys::BNLowLevelILGetCurrentAddress; - unsafe { BNLowLevelILGetCurrentAddress(self.handle) } - } - - pub fn set_current_address<L: Into<Location>>(&self, loc: L) { - use binaryninjacore_sys::BNLowLevelILSetCurrentAddress; - - let loc: Location = loc.into(); - let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref()); - - unsafe { - BNLowLevelILSetCurrentAddress(self.handle, arch.0, loc.addr); - } - } - - pub fn label_for_address<L: Into<Location>>(&self, loc: L) -> Option<&Label> { - use binaryninjacore_sys::BNGetLowLevelILLabelForAddress; - - let loc: Location = loc.into(); - let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref()); - - let res = unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.0, loc.addr) }; - - if res.is_null() { - None - } else { - Some(unsafe { &*(res as *mut Label) }) - } - } - - pub fn mark_label(&self, label: &mut Label) { - use binaryninjacore_sys::BNLowLevelILMarkLabel; - - unsafe { - BNLowLevelILMarkLabel(self.handle, &mut label.0 as *mut _); - } - } -} - -use binaryninjacore_sys::BNLowLevelILLabel; - -#[repr(C)] -pub struct Label(BNLowLevelILLabel); -impl Label { - pub fn new() -> Self { - use binaryninjacore_sys::BNLowLevelILInitLabel; - - unsafe { - // This is one instance where it'd be easy to use mem::MaybeUninit, but *shrug* this is easier - let mut res = Label(mem::zeroed()); - BNLowLevelILInitLabel(&mut res.0 as *mut _); - res - } - } -} - -impl Default for Label { - fn default() -> Self { - Self::new() - } -} |
