From c3fdda9727f5507818e3f55576ad32215a22b0f9 Mon Sep 17 00:00:00 2001 From: Mason Reed Date: Wed, 30 Apr 2025 17:38:40 -0400 Subject: [Rust] Remove Architecture trait bound on LLIL related structures --- arch/msp430/src/architecture.rs | 6 +- arch/msp430/src/lift.rs | 11 +- arch/msp430/src/register.rs | 6 +- arch/riscv/disasm/src/lib.rs | 2 +- arch/riscv/src/lib.rs | 209 +++++++++++------- plugins/warp/src/cache.rs | 20 +- plugins/warp/src/lib.rs | 24 +- rust/src/architecture.rs | 65 +++--- rust/src/disassembly.rs | 11 +- rust/src/flowgraph.rs | 11 +- rust/src/function.rs | 23 +- rust/src/function_recognizer.rs | 4 +- rust/src/low_level_il.rs | 129 ++++++++--- rust/src/low_level_il/block.rs | 33 ++- rust/src/low_level_il/expression.rs | 275 +++++++++++------------ rust/src/low_level_il/function.rs | 86 ++++---- rust/src/low_level_il/instruction.rs | 103 ++++----- rust/src/low_level_il/lifting.rs | 309 +++++++++++--------------- rust/src/low_level_il/operation.rs | 415 +++++++++++------------------------ rust/src/relocation.rs | 8 +- rust/src/workflow.rs | 19 +- rust/tests/low_level_il.rs | 14 +- 22 files changed, 807 insertions(+), 976 deletions(-) diff --git a/arch/msp430/src/architecture.rs b/arch/msp430/src/architecture.rs index ccc5ce80..e5815c91 100644 --- a/arch/msp430/src/architecture.rs +++ b/arch/msp430/src/architecture.rs @@ -194,7 +194,7 @@ impl Architecture for Msp430 { &self, data: &[u8], addr: u64, - il: &mut MutableLiftedILFunction, + il: &mut MutableLiftedILFunction, ) -> Option<(usize, bool)> { match msp430_asm::decode(data) { Ok(inst) => { @@ -226,8 +226,8 @@ impl Architecture for Msp430 { fn flag_group_llil<'a>( &self, _group: Self::FlagGroup, - _il: &'a mut MutableLiftedILFunction, - ) -> Option> { + _il: &'a mut MutableLiftedILFunction, + ) -> Option> { None } diff --git a/arch/msp430/src/lift.rs b/arch/msp430/src/lift.rs index 6ad7b67b..124911f0 100644 --- a/arch/msp430/src/lift.rs +++ b/arch/msp430/src/lift.rs @@ -1,7 +1,6 @@ use crate::architecture::offset_to_absolute; use crate::flag::{Flag, FlagWrite}; use crate::register::Register; -use crate::Msp430; use binaryninja::{architecture::FlagCondition, low_level_il::lifting::LowLevelILLabel}; @@ -164,11 +163,7 @@ macro_rules! conditional_jump { }; } -pub(crate) fn lift_instruction( - inst: &Instruction, - addr: u64, - il: &MutableLiftedILFunction, -) { +pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &MutableLiftedILFunction) { match inst { Instruction::Rrc(inst) => { let size = match inst.operand_width() { @@ -628,8 +623,8 @@ pub(crate) fn lift_instruction( fn lift_source_operand<'a>( operand: &Operand, size: usize, - il: &'a MutableLiftedILFunction, -) -> MutableLiftedILExpr<'a, Msp430, ValueExpr> { + il: &'a MutableLiftedILFunction, +) -> MutableLiftedILExpr<'a, ValueExpr> { match operand { Operand::RegisterDirect(r) => il.reg(size, Register::try_from(*r as u32).unwrap()), Operand::Indexed((r, offset)) => il diff --git a/arch/msp430/src/register.rs b/arch/msp430/src/register.rs index 0886e537..31339ea0 100644 --- a/arch/msp430/src/register.rs +++ b/arch/msp430/src/register.rs @@ -1,7 +1,7 @@ use binaryninja::architecture; use binaryninja::architecture::{ImplicitRegisterExtend, RegisterId}; -use binaryninja::low_level_il::LowLevelILRegister; +use binaryninja::low_level_il::LowLevelILRegisterKind; use std::borrow::Cow; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -134,8 +134,8 @@ impl architecture::RegisterInfo for Register { } } -impl From for LowLevelILRegister { +impl From for LowLevelILRegisterKind { fn from(register: Register) -> Self { - LowLevelILRegister::ArchReg(register) + LowLevelILRegisterKind::Arch(register) } } diff --git a/arch/riscv/disasm/src/lib.rs b/arch/riscv/disasm/src/lib.rs index 959952ee..152817c6 100644 --- a/arch/riscv/disasm/src/lib.rs +++ b/arch/riscv/disasm/src/lib.rs @@ -2331,7 +2331,7 @@ impl StandardExtension for ExtensionSupported { } } -pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Sync { +pub trait RiscVDisassembler: 'static + Debug + Sized + Copy + Clone + Send + Sync { type RegFile: RegFile; type MulDivExtension: StandardExtension; type AtomicExtension: StandardExtension; diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs index 6df34fd7..da4c3115 100644 --- a/arch/riscv/src/lib.rs +++ b/arch/riscv/src/lib.rs @@ -43,7 +43,7 @@ use binaryninja::low_level_il::lifting::{ LiftableLowLevelIL, LiftableLowLevelILWithSize, LowLevelILLabel, }; use binaryninja::low_level_il::{ - expression::ExpressionHandler, instruction::InstructionHandler, LowLevelILRegister, + expression::ExpressionHandler, instruction::InstructionHandler, LowLevelILRegisterKind, MutableLiftedILExpr, MutableLiftedILFunction, RegularLowLevelILFunction, }; use riscv_dis::{ @@ -138,9 +138,9 @@ impl From> for Register { } } -impl From> for LowLevelILRegister> { +impl From> for LowLevelILRegisterKind> { fn from(reg: Register) -> Self { - LowLevelILRegister::ArchReg(reg) + LowLevelILRegisterKind::Arch(reg) } } @@ -204,15 +204,10 @@ impl architecture::Register for Register { } } -impl<'a, D: RiscVDisassembler> LiftableLowLevelIL<'a, RiscVArch> - for Register -{ +impl<'a, D: RiscVDisassembler> LiftableLowLevelIL<'a> for Register { type Result = ValueExpr; - fn lift( - il: &'a MutableLiftedILFunction>, - reg: Self, - ) -> MutableLiftedILExpr<'a, RiscVArch, Self::Result> { + fn lift(il: &'a MutableLiftedILFunction, reg: Self) -> MutableLiftedILExpr<'a, Self::Result> { match reg.reg_type() { RegType::Integer(0) => il.const_int(reg.size(), 0), RegType::Integer(_) => il.reg(reg.size(), reg), @@ -221,14 +216,12 @@ impl<'a, D: RiscVDisassembler> LiftableLowLevelIL<'a, RiscVArch> } } -impl<'a, D: RiscVDisassembler> LiftableLowLevelILWithSize<'a, RiscVArch> - for Register -{ +impl<'a, D: RiscVDisassembler> LiftableLowLevelILWithSize<'a> for Register { fn lift_with_size( - il: &'a MutableLiftedILFunction>, + il: &'a MutableLiftedILFunction, reg: Self, size: usize, - ) -> MutableLiftedILExpr<'a, RiscVArch, ValueExpr> { + ) -> MutableLiftedILExpr<'a, ValueExpr> { #[cfg(debug_assertions)] { if reg.size() < size { @@ -1069,7 +1062,7 @@ impl Architecture for RiscVArch { &self, data: &[u8], addr: u64, - il: &mut MutableLiftedILFunction, + il: &mut MutableLiftedILFunction, ) -> Option<(usize, bool)> { let max_width = self.default_integer_size(); @@ -1242,7 +1235,8 @@ impl Architecture for RiscVArch { (0, _, _) => il.jump(target).append(), // indirect jump (rd_id, rs1_id, _) if rd_id == rs1_id => { // store the target in a temporary register so we don't clobber it when rd == rs1 - let tmp_reg: LowLevelILRegister> = LowLevelILRegister::Temp(0); + let tmp_reg: LowLevelILRegisterKind> = + LowLevelILRegisterKind::from_temp(0); il.set_reg(max_width, tmp_reg, target).append(); // indirect jump with storage of next address to non-`ra` register il.set_reg( @@ -1312,42 +1306,42 @@ impl Architecture for RiscVArch { Op::Ebreak => il.bp().append(), Op::Uret => { il.intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Uret, - MutableLiftedILFunction::::NO_INPUTS, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Uret), + MutableLiftedILFunction::NO_INPUTS, ) .append(); il.no_ret().append(); } Op::Sret => { il.intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Sret, - MutableLiftedILFunction::::NO_INPUTS, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Sret), + MutableLiftedILFunction::NO_INPUTS, ) .append(); il.no_ret().append(); } Op::Mret => { il.intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Mret, - MutableLiftedILFunction::::NO_INPUTS, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Mret), + MutableLiftedILFunction::NO_INPUTS, ) .append(); il.no_ret().append(); } Op::Wfi => il .intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Wfi, - MutableLiftedILFunction::::NO_INPUTS, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Wfi), + MutableLiftedILFunction::NO_INPUTS, ) .append(), Op::Fence(i) => il .intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Fence, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Fence), [il.const_int(4, i.imm() as u32 as u64)], ) .append(), @@ -1359,13 +1353,14 @@ impl Architecture for RiscVArch { if i.rd().id() == 0 { il.intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Csrwr, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Csrwr), [csr, rs1], ) .append(); } else { - il.intrinsic([rd], Intrinsic::Csrrw, [rs1]).append(); + il.intrinsic([rd], RiscVIntrinsic::::from(Intrinsic::Csrrw), [rs1]) + .append(); } } Op::Csrrs(i) => { @@ -1374,9 +1369,15 @@ impl Architecture for RiscVArch { let csr = il.const_int(4, i.csr() as u64); if i.rs1().id() == 0 { - il.intrinsic([rd], Intrinsic::Csrrd, [csr]).append(); + il.intrinsic([rd], RiscVIntrinsic::::from(Intrinsic::Csrrd), [csr]) + .append(); } else { - il.intrinsic([rd], Intrinsic::Csrrs, [csr, rs1]).append(); + il.intrinsic( + [rd], + RiscVIntrinsic::::from(Intrinsic::Csrrs), + [csr, rs1], + ) + .append(); } } Op::Csrrc(i) => { @@ -1385,9 +1386,15 @@ impl Architecture for RiscVArch { let csr = il.const_int(4, i.csr() as u64); if i.rs1().id() == 0 { - il.intrinsic([rd], Intrinsic::Csrrd, [csr]).append(); + il.intrinsic([rd], RiscVIntrinsic::::from(Intrinsic::Csrrd), [csr]) + .append(); } else { - il.intrinsic([rd], Intrinsic::Csrrc, [csr, rs1]).append(); + il.intrinsic( + [rd], + RiscVIntrinsic::::from(Intrinsic::Csrrc), + [csr, rs1], + ) + .append(); } } Op::CsrrwI(i) => { @@ -1397,13 +1404,18 @@ impl Architecture for RiscVArch { if i.rd().id() == 0 { il.intrinsic( - MutableLiftedILFunction::::NO_OUTPUTS, - Intrinsic::Csrwr, + MutableLiftedILFunction::NO_OUTPUTS, + RiscVIntrinsic::::from(Intrinsic::Csrwr), [csr, imm], ) .append(); } else { - il.intrinsic([rd], Intrinsic::Csrrw, [csr, imm]).append(); + il.intrinsic( + [rd], + RiscVIntrinsic::::from(Intrinsic::Csrrw), + [csr, imm], + ) + .append(); } } Op::CsrrsI(i) => { @@ -1412,9 +1424,15 @@ impl Architecture for RiscVArch { let imm = il.const_int(max_width, i.imm() as u64); if i.imm() == 0 { - il.intrinsic([rd], Intrinsic::Csrrd, [csr]).append(); + il.intrinsic([rd], RiscVIntrinsic::::from(Intrinsic::Csrrd), [csr]) + .append(); } else { - il.intrinsic([rd], Intrinsic::Csrrs, [csr, imm]).append(); + il.intrinsic( + [rd], + RiscVIntrinsic::::from(Intrinsic::Csrrs), + [csr, imm], + ) + .append(); } } Op::CsrrcI(i) => { @@ -1423,9 +1441,15 @@ impl Architecture for RiscVArch { let imm = il.const_int(max_width, i.imm() as u64); if i.imm() == 0 { - il.intrinsic([rd], Intrinsic::Csrrd, [csr]).append(); + il.intrinsic([rd], RiscVIntrinsic::::from(Intrinsic::Csrrd), [csr]) + .append(); } else { - il.intrinsic([rd], Intrinsic::Csrrc, [csr, imm]).append(); + il.intrinsic( + [rd], + RiscVIntrinsic::::from(Intrinsic::Csrrc), + [csr, imm], + ) + .append(); } } @@ -1444,7 +1468,7 @@ impl Architecture for RiscVArch { let rd = a.rd(); let dest_reg = match rd.id() { - 0 => LowLevelILRegister::Temp(0), + 0 => LowLevelILRegisterKind::from_temp(0), _ => Register::from(rd).into(), }; @@ -1492,14 +1516,14 @@ impl Architecture for RiscVArch { let rs2 = a.rs2(); let dest_reg = match rd.id() { - 0 => LowLevelILRegister::Temp(0), + 0 => LowLevelILRegisterKind::from_temp(0), _ => Register::from(rd).into(), }; let mut next_temp_reg = 1; let mut alloc_reg = |rs: riscv_dis::IntReg| match (rs.id(), rd.id()) { (id, r) if id != 0 && id == r => { - let reg = LowLevelILRegister::Temp(next_temp_reg); + let reg = LowLevelILRegisterKind::from_temp(next_temp_reg); next_temp_reg += 1; il.set_reg(max_width, reg, Register::from(rs)).append(); @@ -1579,10 +1603,11 @@ impl Architecture for RiscVArch { }; il.set_reg(width, rd, result).append(); } else { - let product = LowLevelILRegister::Temp(0); + let product: LowLevelILRegisterKind = + LowLevelILRegisterKind::from_temp(0); il.intrinsic( [product], - Intrinsic::Fmul(f.width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::Fmul(f.width(), f.rm())), [il.reg(width, rs1), il.reg(width, rs2)], ) .append(); @@ -1590,21 +1615,21 @@ impl Architecture for RiscVArch { Op::Fmadd(..) => il .intrinsic( [rd], - Intrinsic::Fmul(f.width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::Fmul(f.width(), f.rm())), [il.reg(width, product), il.reg(width, rs3)], ) .append(), Op::Fmsub(..) => il .intrinsic( [rd], - Intrinsic::Fsub(f.width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::Fsub(f.width(), f.rm())), [il.reg(width, product), il.reg(width, rs3)], ) .append(), Op::Fnmadd(..) => il .intrinsic( [rd], - Intrinsic::Fsub(f.width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::Fsub(f.width(), f.rm())), [ il.fneg(width, il.reg(width, product)).build(), il.reg(width, rs3), @@ -1614,7 +1639,7 @@ impl Architecture for RiscVArch { Op::Fnmsub(..) => il .intrinsic( [rd], - Intrinsic::Fadd(f.width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::Fadd(f.width(), f.rm())), [ il.fneg(width, il.reg(width, product)).build(), il.reg(width, rs3), @@ -1641,10 +1666,18 @@ impl Architecture for RiscVArch { il.set_reg(width, rd, result).append(); } else { let intrinsic = match op { - Op::Fadd(..) => Intrinsic::Fadd(f.width(), f.rm()), - Op::Fsub(..) => Intrinsic::Fsub(f.width(), f.rm()), - Op::Fmul(..) => Intrinsic::Fmul(f.width(), f.rm()), - Op::Fdiv(..) => Intrinsic::Fdiv(f.width(), f.rm()), + Op::Fadd(..) => { + RiscVIntrinsic::::from(Intrinsic::Fadd(f.width(), f.rm())) + } + Op::Fsub(..) => { + RiscVIntrinsic::::from(Intrinsic::Fsub(f.width(), f.rm())) + } + Op::Fmul(..) => { + RiscVIntrinsic::::from(Intrinsic::Fmul(f.width(), f.rm())) + } + Op::Fdiv(..) => { + RiscVIntrinsic::::from(Intrinsic::Fdiv(f.width(), f.rm())) + } _ => unreachable!(), }; il.intrinsic([rd], intrinsic, [il.reg(width, rs1), il.reg(width, rs2)]) @@ -1661,7 +1694,7 @@ impl Architecture for RiscVArch { } else { il.intrinsic( [rd], - Intrinsic::Fsgnj(f.width()), + RiscVIntrinsic::::from(Intrinsic::Fsgnj(f.width())), [il.reg(width, rs1), il.reg(width, rs2)], ) .append(); @@ -1678,7 +1711,7 @@ impl Architecture for RiscVArch { } else { il.intrinsic( [rd], - Intrinsic::Fsgnjn(f.width()), + RiscVIntrinsic::::from(Intrinsic::Fsgnjn(f.width())), [il.reg(width, rs1), il.reg(width, rs2)], ) .append(); @@ -1695,7 +1728,7 @@ impl Architecture for RiscVArch { } else { il.intrinsic( [rd], - Intrinsic::Fsgnjx(f.width()), + RiscVIntrinsic::::from(Intrinsic::Fsgnjx(f.width())), [il.reg(width, rs1), il.reg(width, rs2)], ) .append(); @@ -1715,7 +1748,7 @@ impl Architecture for RiscVArch { let width = f.width() as usize; il.intrinsic( [rd], - Intrinsic::Fmin(f.width()), + RiscVIntrinsic::::from(Intrinsic::Fmin(f.width())), [il.reg(width, rs1), il.reg(width, rs2)], ) .append(); @@ -1727,14 +1760,14 @@ impl Architecture for RiscVArch { let width = f.width() as usize; il.intrinsic( [rd], - Intrinsic::Fmax(f.width()), + RiscVIntrinsic::::from(Intrinsic::Fmax(f.width())), [il.reg(width, rs1), il.reg(width, rs2)], ) .append(); } Op::Fle(f) | Op::Flt(f) | Op::Feq(f) => { let rd = match f.rd().id() { - 0 => LowLevelILRegister::Temp(0), + 0 => LowLevelILRegisterKind::from_temp(0), _ => Register::from(f.rd()).into(), }; let left = Register::from(f.rs1()); @@ -1760,7 +1793,11 @@ impl Architecture for RiscVArch { } else { il.intrinsic( [rd], - Intrinsic::FcvtFToF(f.rs1_width(), f.rd_width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::FcvtFToF( + f.rs1_width(), + f.rd_width(), + f.rm(), + )), [il.reg(rs1_width, rs1)], ) .append(); @@ -1768,7 +1805,7 @@ impl Architecture for RiscVArch { } Op::FcvtToInt(f) => { let rd = match f.rd().id() { - 0 => LowLevelILRegister::Temp(0), + 0 => LowLevelILRegisterKind::from_temp(0), _ => Register::from(f.rd()).into(), }; let rs1 = Register::from(f.rs1()); @@ -1777,14 +1814,22 @@ impl Architecture for RiscVArch { if f.zx() { il.intrinsic( [rd], - Intrinsic::FcvtFToU(f.rs1_width(), f.rd_width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::FcvtFToU( + f.rs1_width(), + f.rd_width(), + f.rm(), + )), [il.reg(rs1_width, rs1)], ) .append(); } else if f.rm() != RoundMode::Dynamic { il.intrinsic( [rd], - Intrinsic::FcvtFToI(f.rs1_width(), f.rd_width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::FcvtFToI( + f.rs1_width(), + f.rd_width(), + f.rm(), + )), [il.reg(rs1_width, rs1)], ) .append(); @@ -1807,14 +1852,22 @@ impl Architecture for RiscVArch { if f.zx() { il.intrinsic( [rd], - Intrinsic::FcvtUToF(f.rs1_width(), f.rd_width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::FcvtUToF( + f.rs1_width(), + f.rd_width(), + f.rm(), + )), [rs1], ) .append(); } else if f.rm() != RoundMode::Dynamic { il.intrinsic( [rd], - Intrinsic::FcvtIToF(f.rs1_width(), f.rd_width(), f.rm()), + RiscVIntrinsic::::from(Intrinsic::FcvtIToF( + f.rs1_width(), + f.rd_width(), + f.rm(), + )), [rs1], ) .append(); @@ -1825,7 +1878,7 @@ impl Architecture for RiscVArch { } Op::FmvToInt(f) => { let rd = match f.rd().id() { - 0 => LowLevelILRegister::Temp(0), + 0 => LowLevelILRegisterKind::from_temp(0), _ => Register::from(f.rd()).into(), }; let rs1 = Register::from(f.rs1()); @@ -1848,8 +1901,12 @@ impl Architecture for RiscVArch { let rd = Register::from(f.rd()); let rs1 = Register::from(f.rs1()); let width = f.width() as usize; - il.intrinsic([rd], Intrinsic::Fclass(f.width()), [il.reg(width, rs1)]) - .append(); + il.intrinsic( + [rd], + RiscVIntrinsic::::from(Intrinsic::Fclass(f.width())), + [il.reg(width, rs1)], + ) + .append(); } _ => il.unimplemented().append(), @@ -2653,9 +2710,7 @@ impl RelocationHandler } } -impl AsRef - for RiscVELFRelocationHandler -{ +impl AsRef for RiscVELFRelocationHandler { fn as_ref(&self) -> &CoreRelocationHandler { &self.handle } @@ -2793,7 +2848,7 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { &self, bv: &BinaryView, func: &Function, - llil: &RegularLowLevelILFunction, + llil: &RegularLowLevelILFunction, ) -> bool { // Look for the following code pattern: // t3 = plt diff --git a/plugins/warp/src/cache.rs b/plugins/warp/src/cache.rs index 4b1df5af..7219b547 100644 --- a/plugins/warp/src/cache.rs +++ b/plugins/warp/src/cache.rs @@ -1,6 +1,5 @@ use crate::convert::{from_bn_symbol, from_bn_type_internal}; use crate::{build_function, function_guid}; -use binaryninja::architecture::Architecture; use binaryninja::binary_view::{BinaryView, BinaryViewExt}; use binaryninja::confidence::MAX_CONFIDENCE; use binaryninja::function::Function as BNFunction; @@ -68,10 +67,7 @@ pub fn try_cached_function_match(function: &BNFunction) -> Option { .to_owned() } -pub fn cached_function( - function: &BNFunction, - llil: &RegularLowLevelILFunction, -) -> Function { +pub fn cached_function(function: &BNFunction, llil: &RegularLowLevelILFunction) -> Function { let view = function.view(); let view_id = ViewID::from(view.as_ref()); let function_cache = FUNCTION_CACHE.get_or_init(Default::default); @@ -122,9 +118,9 @@ where } } -pub fn cached_function_guid( +pub fn cached_function_guid( function: &BNFunction, - llil: &LowLevelILFunction>, + llil: &LowLevelILFunction>, ) -> FunctionGUID { let view = function.view(); let view_id = ViewID::from(view); @@ -202,11 +198,7 @@ pub struct FunctionCache { } impl FunctionCache { - pub fn function( - &self, - function: &BNFunction, - llil: &RegularLowLevelILFunction, - ) -> Function { + pub fn function(&self, function: &BNFunction, llil: &RegularLowLevelILFunction) -> Function { let function_id = FunctionID::from(function); match self.cache.get(&function_id) { Some(function) => function.value().to_owned(), @@ -330,10 +322,10 @@ impl GUIDCache { } } - pub fn function_guid( + pub fn function_guid( &self, function: &BNFunction, - llil: &LowLevelILFunction>, + llil: &LowLevelILFunction>, ) -> FunctionGUID { let function_id = FunctionID::from(function); match self.cache.get(&function_id) { diff --git a/plugins/warp/src/lib.rs b/plugins/warp/src/lib.rs index 3f2fc276..3d68b402 100644 --- a/plugins/warp/src/lib.rs +++ b/plugins/warp/src/lib.rs @@ -16,7 +16,7 @@ use binaryninja::low_level_il::function::{ use binaryninja::low_level_il::instruction::{ InstructionHandler, LowLevelILInstruction, LowLevelILInstructionKind, }; -use binaryninja::low_level_il::{LowLevelILRegister, VisitorAction}; +use binaryninja::low_level_il::{LowLevelILRegisterKind, VisitorAction}; use binaryninja::rc::Ref as BNRef; use std::path::PathBuf; use warp::signature::basic_block::BasicBlockGUID; @@ -44,9 +44,9 @@ pub fn user_signature_dir() -> PathBuf { binaryninja::user_directory().join("signatures/") } -pub fn build_function( +pub fn build_function( func: &BNFunction, - llil: &LowLevelILFunction>, + llil: &LowLevelILFunction>, ) -> Function { let bn_fn_ty = func.function_type(); Function { @@ -76,9 +76,9 @@ pub fn sorted_basic_blocks(func: &BNFunction) -> Vec( +pub fn function_guid( func: &BNFunction, - llil: &LowLevelILFunction>, + llil: &LowLevelILFunction>, ) -> FunctionGUID { let basic_blocks = sorted_basic_blocks(func); let basic_block_guids = basic_blocks @@ -88,9 +88,9 @@ pub fn function_guid( FunctionGUID::from_basic_blocks(&basic_block_guids) } -pub fn basic_block_guid( +pub fn basic_block_guid( basic_block: &BNBasicBlock, - llil: &LowLevelILFunction>, + llil: &LowLevelILFunction>, ) -> BasicBlockGUID { let func = basic_block.function(); let view = func.view(); @@ -98,7 +98,7 @@ pub fn basic_block_guid( let max_instr_len = arch.max_instr_len(); // NOPs and useless moves are blacklisted to allow for hot-patchable functions. - let is_blacklisted_instr = |instr: &LowLevelILInstruction>| { + let is_blacklisted_instr = |instr: &LowLevelILInstruction>| { match instr.kind() { LowLevelILInstructionKind::Nop(_) => true, LowLevelILInstructionKind::SetReg(op) => { @@ -107,7 +107,7 @@ pub fn basic_block_guid( if op.dest_reg() == source_op.source_reg() => { match op.dest_reg() { - LowLevelILRegister::ArchReg(r) => { + LowLevelILRegisterKind::Arch(r) => { // If this register has no implicit extend then we can safely assume it's a NOP. // Ex. on x86_64 we don't want to remove `mov edi, edi` as it will zero the upper 32 bits. // Ex. on x86 we do want to remove `mov edi, edi` as it will not have a side effect like above. @@ -116,7 +116,7 @@ pub fn basic_block_guid( ImplicitRegisterExtend::NoExtend ) } - LowLevelILRegister::Temp(_) => false, + LowLevelILRegisterKind::Temp(_) => false, } } _ => false, @@ -126,8 +126,8 @@ pub fn basic_block_guid( } }; - let is_variant_instr = |instr: &LowLevelILInstruction>| { - let is_variant_expr = |expr: &LowLevelILExpressionKind>| { + let is_variant_instr = |instr: &LowLevelILInstruction>| { + let is_variant_expr = |expr: &LowLevelILExpressionKind>| { // TODO: Checking the section here is slow, we should gather all section ranges outside of this. match expr { LowLevelILExpressionKind::ConstPtr(op) diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 7ad10dfb..c0fe138e 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -80,6 +80,13 @@ macro_rules! newtype { } newtype!(RegisterId, u32); + +impl RegisterId { + pub fn is_temporary(&self) -> bool { + self.0 & 0x8000_0000 != 0 + } +} + newtype!(RegisterStackId, u32); newtype!(FlagId, u32); // TODO: Make this NonZero? @@ -418,7 +425,7 @@ pub trait Intrinsic: Debug + Sized + Clone + Copy { fn outputs(&self) -> Vec>>; } -pub trait Architecture: 'static + Sized + AsRef + Debug { +pub trait Architecture: 'static + Sized + AsRef { type Handle: Borrow + Clone; type RegisterInfo: RegisterInfo; @@ -460,7 +467,7 @@ pub trait Architecture: 'static + Sized + AsRef + Debug { &self, data: &[u8], addr: u64, - il: &mut MutableLiftedILFunction, + il: &mut MutableLiftedILFunction, ) -> Option<(usize, bool)>; /// Fallback flag value calculation path. This method is invoked when the core is unable to @@ -477,8 +484,8 @@ pub trait Architecture: 'static + Sized + AsRef + Debug { flag: Self::Flag, flag_write_type: Self::FlagWrite, op: LowLevelILFlagWriteOp, - il: &'a mut MutableLiftedILFunction, - ) -> Option> { + il: &'a mut MutableLiftedILFunction, + ) -> Option> { let role = flag.role(flag_write_type.class()); Some(get_default_flag_write_llil(self, role, op, il)) } @@ -506,8 +513,8 @@ pub trait Architecture: 'static + Sized + AsRef + Debug { &self, cond: FlagCondition, class: Option, - il: &'a mut MutableLiftedILFunction, - ) -> Option> { + il: &'a mut MutableLiftedILFunction, + ) -> Option> { Some(get_default_flag_cond_llil(self, cond, class, il)) } @@ -528,8 +535,8 @@ pub trait Architecture: 'static + Sized + AsRef + Debug { fn flag_group_llil<'a>( &self, _group: Self::FlagGroup, - _il: &'a mut MutableLiftedILFunction, - ) -> Option> { + _il: &'a mut MutableLiftedILFunction, + ) -> Option> { None } @@ -1505,7 +1512,7 @@ impl Architecture for CoreArchitecture { &self, data: &[u8], addr: u64, - il: &mut MutableLiftedILFunction, + il: &mut MutableLiftedILFunction, ) -> Option<(usize, bool)> { let mut size = data.len(); let success = unsafe { @@ -1530,8 +1537,8 @@ impl Architecture for CoreArchitecture { _flag: Self::Flag, _flag_write: Self::FlagWrite, _op: LowLevelILFlagWriteOp, - _il: &'a mut MutableLiftedILFunction, - ) -> Option> { + _il: &'a mut MutableLiftedILFunction, + ) -> Option> { None } @@ -1567,16 +1574,16 @@ impl Architecture for CoreArchitecture { &self, _cond: FlagCondition, _class: Option, - _il: &'a mut MutableLiftedILFunction, - ) -> Option> { + _il: &'a mut MutableLiftedILFunction, + ) -> Option> { None } fn flag_group_llil<'a>( &self, _group: Self::FlagGroup, - _il: &'a mut MutableLiftedILFunction, - ) -> Option> { + _il: &'a mut MutableLiftedILFunction, + ) -> Option> { None } @@ -2218,12 +2225,9 @@ where A: 'static + Architecture> + Send + Sync, { let custom_arch = unsafe { &*(ctxt as *mut A) }; - let custom_arch_handle = CustomArchitectureHandle { - handle: ctxt as *mut A, - }; - let data = unsafe { std::slice::from_raw_parts(data, *len) }; - let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) }; + let mut lifter = + unsafe { MutableLiftedILFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref())) }; match custom_arch.instruction_llil(data, addr, &mut lifter) { Some((res_len, res_value)) => { @@ -2606,14 +2610,11 @@ where A: 'static + Architecture> + Send + Sync, { let custom_arch = unsafe { &*(ctxt as *mut A) }; - let custom_arch_handle = CustomArchitectureHandle { - handle: ctxt as *mut A, - }; - let flag_write = custom_arch.flag_write_from_id(FlagWriteId(flag_write)); let flag = custom_arch.flag_from_id(FlagId(flag)); let operands = unsafe { std::slice::from_raw_parts(operands_raw, operand_count) }; - let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) }; + let mut lifter = + unsafe { MutableLiftedILFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref())) }; if let (Some(flag_write), Some(flag)) = (flag_write, flag) { if let Some(op) = LowLevelILFlagWriteOp::from_op(custom_arch, size, op, operands) { @@ -2659,13 +2660,10 @@ where A: 'static + Architecture> + Send + Sync, { let custom_arch = unsafe { &*(ctxt as *mut A) }; - let custom_arch_handle = CustomArchitectureHandle { - handle: ctxt as *mut A, - }; - let class = custom_arch.flag_class_from_id(FlagClassId(class)); - let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) }; + let mut lifter = + unsafe { MutableLiftedILFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref())) }; if let Some(expr) = custom_arch.flag_cond_llil(cond, class, &mut lifter) { // TODO verify that returned expr is a bool value return expr.index.0; @@ -2683,11 +2681,8 @@ where A: 'static + Architecture> + Send + Sync, { let custom_arch = unsafe { &*(ctxt as *mut A) }; - let custom_arch_handle = CustomArchitectureHandle { - handle: ctxt as *mut A, - }; - - let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) }; + let mut lifter = + unsafe { MutableLiftedILFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref())) }; if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) { if let Some(expr) = custom_arch.flag_group_llil(group, &mut lifter) { diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs index 9dfd160f..99a6b22e 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -1022,8 +1022,8 @@ impl DisassemblyTextRenderer { unsafe { Self::ref_from_raw(NonNull::new(result).unwrap()) } } - pub fn from_llil( - func: &LowLevelILFunction, + pub fn from_llil( + func: &LowLevelILFunction, settings: Option<&DisassemblySettings>, ) -> Ref { let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut()); @@ -1058,14 +1058,11 @@ impl DisassemblyTextRenderer { unsafe { Function::ref_from_raw(result) } } - pub fn llil( - &self, - ) -> Ref> { - let arch = self.arch(); + pub fn llil(&self) -> Ref> { let result = unsafe { BNGetDisassemblyTextRendererLowLevelILFunction(self.handle.as_ptr()) }; assert!(!result.is_null()); - unsafe { LowLevelILFunction::ref_from_raw(arch.handle(), result) } + unsafe { LowLevelILFunction::ref_from_raw(result) } } pub fn mlil(&self) -> Ref { diff --git a/rust/src/flowgraph.rs b/rust/src/flowgraph.rs index c8a9e4a7..976764eb 100644 --- a/rust/src/flowgraph.rs +++ b/rust/src/flowgraph.rs @@ -14,7 +14,6 @@ //! Interfaces for creating and displaying pretty CFGs in Binary Ninja. -use crate::architecture::CoreArchitecture; use crate::disassembly::DisassemblyTextLine; use crate::rc::*; use binaryninjacore_sys::*; @@ -55,17 +54,11 @@ impl FlowGraph { unsafe { Array::new(nodes_ptr, count, ()) } } - pub fn low_level_il(&self) -> Result>, ()> { + pub fn low_level_il(&self) -> Result, ()> { unsafe { let llil_ptr = BNGetFlowGraphLowLevelILFunction(self.handle); match llil_ptr.is_null() { - false => { - let func_ptr = BNGetLowLevelILOwnerFunction(llil_ptr); - let arch_ptr = BNGetFunctionArchitecture(func_ptr); - let arch = CoreArchitecture::from_raw(arch_ptr); - BNFreeFunction(func_ptr); - Ok(RegularLowLevelILFunction::ref_from_raw(arch, llil_ptr)) - } + false => Ok(RegularLowLevelILFunction::ref_from_raw(llil_ptr)), true => Err(()), } } diff --git a/rust/src/function.rs b/rust/src/function.rs index 7990f109..c882ab08 100644 --- a/rust/src/function.rs +++ b/rust/src/function.rs @@ -529,45 +529,38 @@ impl Function { } } - pub fn low_level_il(&self) -> Result>, ()> { + pub fn low_level_il(&self) -> Result, ()> { unsafe { let llil_ptr = BNGetFunctionLowLevelIL(self.handle); match llil_ptr.is_null() { - false => Ok(RegularLowLevelILFunction::ref_from_raw( - self.arch(), - llil_ptr, - )), + false => Ok(RegularLowLevelILFunction::ref_from_raw(llil_ptr)), true => Err(()), } } } - pub fn low_level_il_if_available( - &self, - ) -> Option>> { + pub fn low_level_il_if_available(&self) -> Option> { let llil_ptr = unsafe { BNGetFunctionLowLevelILIfAvailable(self.handle) }; match llil_ptr.is_null() { - false => { - Some(unsafe { RegularLowLevelILFunction::ref_from_raw(self.arch(), llil_ptr) }) - } + false => Some(unsafe { RegularLowLevelILFunction::ref_from_raw(llil_ptr) }), true => None, } } - pub fn lifted_il(&self) -> Result>, ()> { + pub fn lifted_il(&self) -> Result, ()> { unsafe { let llil_ptr = BNGetFunctionLiftedIL(self.handle); match llil_ptr.is_null() { - false => Ok(LiftedILFunction::ref_from_raw(self.arch(), llil_ptr)), + false => Ok(LiftedILFunction::ref_from_raw(llil_ptr)), true => Err(()), } } } - pub fn lifted_il_if_available(&self) -> Option>> { + pub fn lifted_il_if_available(&self) -> Option> { let llil_ptr = unsafe { BNGetFunctionLiftedILIfAvailable(self.handle) }; match llil_ptr.is_null() { - false => Some(unsafe { LiftedILFunction::ref_from_raw(self.arch(), llil_ptr) }), + false => Some(unsafe { LiftedILFunction::ref_from_raw(llil_ptr) }), true => None, } } diff --git a/rust/src/function_recognizer.rs b/rust/src/function_recognizer.rs index 64e33806..cd5592ee 100644 --- a/rust/src/function_recognizer.rs +++ b/rust/src/function_recognizer.rs @@ -10,7 +10,7 @@ pub trait FunctionRecognizer { &self, _bv: &BinaryView, _func: &Function, - _llil: &RegularLowLevelILFunction, + _llil: &RegularLowLevelILFunction, ) -> bool { false } @@ -49,7 +49,7 @@ where let context = unsafe { &*(ctxt as *mut FunctionRecognizerHandlerContext) }; let bv = unsafe { BinaryView::from_raw(bv).to_owned() }; let func = unsafe { Function::from_raw(func).to_owned() }; - let llil = unsafe { LowLevelILFunction::from_raw(func.arch(), llil).to_owned() }; + let llil = unsafe { LowLevelILFunction::from_raw(llil).to_owned() }; context.recognizer.recognize_low_level_il(&bv, &func, &llil) } diff --git a/rust/src/low_level_il.rs b/rust/src/low_level_il.rs index d6303c13..453e0546 100644 --- a/rust/src/low_level_il.rs +++ b/rust/src/low_level_il.rs @@ -20,8 +20,8 @@ use std::fmt; // requirements on load/store memory address sizes? // can reg/set_reg be used with sizes that differ from what is in BNRegisterInfo? -use crate::architecture::Register as ArchReg; use crate::architecture::{Architecture, RegisterId}; +use crate::architecture::{CoreRegister, Register as ArchReg}; use crate::function::Location; pub mod block; @@ -35,52 +35,123 @@ use self::expression::*; use self::function::*; use self::instruction::*; -pub type MutableLiftedILFunction = LowLevelILFunction>; -pub type LiftedILFunction = LowLevelILFunction>; -pub type MutableLiftedILExpr<'a, Arch, ReturnType> = - LowLevelILExpression<'a, Arch, Mutable, NonSSA, ReturnType>; -pub type RegularLowLevelILFunction = - LowLevelILFunction>; -pub type RegularLowLevelILInstruction<'a, Arch> = - LowLevelILInstruction<'a, Arch, Finalized, NonSSA>; -pub type RegularLowLevelILInstructionKind<'a, Arch> = - LowLevelILInstructionKind<'a, Arch, Finalized, NonSSA>; -pub type RegularLowLevelILExpression<'a, Arch, ReturnType> = - LowLevelILExpression<'a, Arch, Finalized, NonSSA, ReturnType>; -pub type RegularLowLevelILExpressionKind<'a, Arch> = - LowLevelILExpressionKind<'a, Arch, Finalized, NonSSA>; -pub type LowLevelILSSAFunction = LowLevelILFunction; +pub type MutableLiftedILFunction = LowLevelILFunction>; +pub type LiftedILFunction = LowLevelILFunction>; +pub type MutableLiftedILExpr<'a, ReturnType> = + LowLevelILExpression<'a, Mutable, NonSSA, ReturnType>; +pub type RegularLowLevelILFunction = LowLevelILFunction>; +pub type RegularLowLevelILInstruction<'a> = + LowLevelILInstruction<'a, Finalized, NonSSA>; +pub type RegularLowLevelILInstructionKind<'a> = + LowLevelILInstructionKind<'a, Finalized, NonSSA>; +pub type RegularLowLevelILExpression<'a, ReturnType> = + LowLevelILExpression<'a, Finalized, NonSSA, ReturnType>; +pub type RegularLowLevelILExpressionKind<'a> = + LowLevelILExpressionKind<'a, Finalized, NonSSA>; +pub type LowLevelILSSAFunction = LowLevelILFunction; + +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct LowLevelILTempRegister { + /// The temporary id for the register, this will **NOT** be the referenced id in the core. + /// + /// Do not attempt to pass this to the core. Use [`LowLevelILTempRegister::id`] instead. + temp_id: RegisterId, +} + +impl LowLevelILTempRegister { + pub fn new(temp_id: u32) -> Self { + Self { + temp_id: RegisterId(temp_id), + } + } + + pub fn from_id(id: RegisterId) -> Option { + match id.is_temporary() { + true => { + let temp_id = RegisterId(id.0 & 0x7fff_ffff); + Some(Self { temp_id }) + } + false => None, + } + } + + /// The temporary registers core id, with the temporary bit set. + pub fn id(&self) -> RegisterId { + RegisterId(self.temp_id.0 | 0x8000_0000) + } +} + +impl fmt::Debug for LowLevelILTempRegister { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "temp{}", self.temp_id) + } +} + +impl TryFrom for LowLevelILTempRegister { + type Error = (); + + fn try_from(value: RegisterId) -> Result { + Self::from_id(value).ok_or(()) + } +} + +impl From for LowLevelILTempRegister { + fn from(value: u32) -> Self { + Self::new(value) + } +} #[derive(Copy, Clone, PartialEq, Eq)] -pub enum LowLevelILRegister { - ArchReg(R), - // TODO: Might want to be changed to TempRegisterId. - // TODO: If we do that then we would need to get rid of `Register::id()` - Temp(u32), +pub enum LowLevelILRegisterKind { + Arch(R), + Temp(LowLevelILTempRegister), } -impl LowLevelILRegister { +impl LowLevelILRegisterKind { + pub fn from_raw(arch: &impl Architecture, val: RegisterId) -> Option { + match val.is_temporary() { + true => { + let temp_reg = LowLevelILTempRegister::from_id(val)?; + Some(LowLevelILRegisterKind::Temp(temp_reg)) + } + false => { + let arch_reg = arch.register_from_id(val)?; + Some(LowLevelILRegisterKind::Arch(arch_reg)) + } + } + } + + pub fn from_temp(temp: impl Into) -> Self { + LowLevelILRegisterKind::Temp(temp.into()) + } + fn id(&self) -> RegisterId { match *self { - LowLevelILRegister::ArchReg(ref r) => r.id(), - LowLevelILRegister::Temp(id) => RegisterId(0x8000_0000 | id), + LowLevelILRegisterKind::Arch(ref r) => r.id(), + LowLevelILRegisterKind::Temp(temp) => temp.id(), } } } -impl fmt::Debug for LowLevelILRegister { +impl fmt::Debug for LowLevelILRegisterKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - LowLevelILRegister::ArchReg(ref r) => write!(f, "{}", r.name().as_ref()), - LowLevelILRegister::Temp(id) => write!(f, "temp{}", id), + LowLevelILRegisterKind::Arch(ref r) => r.fmt(f), + LowLevelILRegisterKind::Temp(id) => id.fmt(f), } } } +impl From for LowLevelILRegisterKind { + fn from(reg: LowLevelILTempRegister) -> Self { + LowLevelILRegisterKind::Temp(reg) + } +} + #[derive(Copy, Clone, Debug)] pub enum LowLevelILSSARegister { - Full(LowLevelILRegister, u32), // no such thing as partial access to a temp register, I think - Partial(R, u32, R), // partial accesses only possible for arch registers, I think + Full(LowLevelILRegisterKind, u32), // no such thing as partial access to a temp register, I think + Partial(R, u32, R), // partial accesses only possible for arch registers, I think } impl LowLevelILSSARegister { diff --git a/rust/src/low_level_il/block.rs b/rust/src/low_level_il/block.rs index ac0be449..519c707e 100644 --- a/rust/src/low_level_il/block.rs +++ b/rust/src/low_level_il/block.rs @@ -15,38 +15,35 @@ use std::fmt::Debug; use std::ops::Range; -use crate::architecture::Architecture; use crate::basic_block::{BasicBlock, BlockContext}; use super::*; #[derive(Copy)] -pub struct LowLevelILBlock<'func, A, M, F> +pub struct LowLevelILBlock<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { - pub(crate) function: &'func LowLevelILFunction, + pub(crate) function: &'func LowLevelILFunction, } -impl<'func, A, M, F> BlockContext for LowLevelILBlock<'func, A, M, F> +impl<'func, M, F> BlockContext for LowLevelILBlock<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { - type Instruction = LowLevelILInstruction<'func, A, M, F>; + type Instruction = LowLevelILInstruction<'func, M, F>; type InstructionIndex = LowLevelInstructionIndex; - type Iter = LowLevelILBlockIter<'func, A, M, F>; + type Iter = LowLevelILBlockIter<'func, M, F>; - fn start(&self, block: &BasicBlock) -> LowLevelILInstruction<'func, A, M, F> { + fn start(&self, block: &BasicBlock) -> LowLevelILInstruction<'func, M, F> { self.function .instruction_from_index(block.start_index()) .unwrap() } - fn iter(&self, block: &BasicBlock) -> LowLevelILBlockIter<'func, A, M, F> { + fn iter(&self, block: &BasicBlock) -> LowLevelILBlockIter<'func, M, F> { LowLevelILBlockIter { function: self.function, range: (block.start_index().0)..(block.end_index().0), @@ -54,9 +51,8 @@ where } } -impl<'func, A, M, F> Debug for LowLevelILBlock<'func, A, M, F> +impl<'func, M, F> Debug for LowLevelILBlock<'func, M, F> where - A: 'func + Architecture + Debug, M: FunctionMutability, F: FunctionForm, { @@ -67,9 +63,8 @@ where } } -impl<'func, A, M, F> Clone for LowLevelILBlock<'func, A, M, F> +impl<'func, M, F> Clone for LowLevelILBlock<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { @@ -80,24 +75,22 @@ where } } -pub struct LowLevelILBlockIter<'func, A, M, F> +pub struct LowLevelILBlockIter<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { - function: &'func LowLevelILFunction, + function: &'func LowLevelILFunction, // TODO: Once step_trait is stable we can do Range range: Range, } -impl<'func, A, M, F> Iterator for LowLevelILBlockIter<'func, A, M, F> +impl<'func, M, F> Iterator for LowLevelILBlockIter<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { - type Item = LowLevelILInstruction<'func, A, M, F>; + type Item = LowLevelILInstruction<'func, M, F>; fn next(&mut self) -> Option { self.range diff --git a/rust/src/low_level_il/expression.rs b/rust/src/low_level_il/expression.rs index f8fcf9f7..331ab980 100644 --- a/rust/src/low_level_il/expression.rs +++ b/rust/src/low_level_il/expression.rs @@ -19,7 +19,7 @@ use super::operation; use super::operation::Operation; use super::VisitorAction; use super::*; -use crate::architecture::Architecture; +use crate::architecture::CoreFlagWrite; use std::fmt; use std::fmt::{Debug, Display, Formatter}; use std::marker::PhantomData; @@ -47,42 +47,39 @@ impl Display for LowLevelExpressionIndex { } // TODO: Probably want to rename this with a LowLevelIL prefix to avoid collisions when we add handlers for other ILs -pub trait ExpressionHandler<'func, A, M, F> +pub trait ExpressionHandler<'func, M, F> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - fn kind(&self) -> LowLevelILExpressionKind<'func, A, M, F>; + fn kind(&self) -> LowLevelILExpressionKind<'func, M, F>; fn visit_tree(&self, f: &mut T) -> VisitorAction where - T: FnMut(&LowLevelILExpression<'func, A, M, F, ValueExpr>) -> VisitorAction; + T: FnMut(&LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction; } -pub struct LowLevelILExpression<'func, A, M, F, R> +pub struct LowLevelILExpression<'func, M, F, R> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, R: ExpressionResultType, { - pub(crate) function: &'func LowLevelILFunction, + pub(crate) function: &'func LowLevelILFunction, pub index: LowLevelExpressionIndex, // tag the 'return' type of this expression pub(crate) _ty: PhantomData, } -impl<'func, A, M, F, R> LowLevelILExpression<'func, A, M, F, R> +impl<'func, M, F, R> LowLevelILExpression<'func, M, F, R> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, R: ExpressionResultType, { pub(crate) fn new( - function: &'func LowLevelILFunction, + function: &'func LowLevelILFunction, index: LowLevelExpressionIndex, ) -> Self { // TODO: Validate expression here? @@ -94,27 +91,25 @@ where } } -impl<'func, A, M, F, R> fmt::Debug for LowLevelILExpression<'func, A, M, F, R> +impl<'func, M, F, R> fmt::Debug for LowLevelILExpression<'func, M, F, R> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, R: ExpressionResultType, { fn fmt(&self, f: &mut Formatter) -> fmt::Result { let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) }; - let t = unsafe { LowLevelILExpressionKind::from_raw(self.function, op) }; - t.fmt(f) + // SAFETY: This is safe we are not exposing the expression kind to the caller. + let kind = unsafe { LowLevelILExpressionKind::from_raw(self.function, op) }; + kind.fmt(f) } } -impl<'func, A, M> ExpressionHandler<'func, A, M, SSA> - for LowLevelILExpression<'func, A, M, SSA, ValueExpr> +impl<'func, M> ExpressionHandler<'func, M, SSA> for LowLevelILExpression<'func, M, SSA, ValueExpr> where - A: 'func + Architecture, M: FunctionMutability, { - fn kind(&self) -> LowLevelILExpressionKind<'func, A, M, SSA> { + fn kind(&self) -> LowLevelILExpressionKind<'func, M, SSA> { #[allow(unused_imports)] use binaryninjacore_sys::BNLowLevelILOperation::*; let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) }; @@ -128,7 +123,7 @@ where fn visit_tree(&self, f: &mut T) -> VisitorAction where - T: FnMut(&LowLevelILExpression<'func, A, M, SSA, ValueExpr>) -> VisitorAction, + T: FnMut(&LowLevelILExpression<'func, M, SSA, ValueExpr>) -> VisitorAction, { // Visit the current expression. match f(self) { @@ -141,13 +136,12 @@ where } } -impl<'func, A, M> ExpressionHandler<'func, A, M, NonSSA> - for LowLevelILExpression<'func, A, M, NonSSA, ValueExpr> +impl<'func, M> ExpressionHandler<'func, M, NonSSA> + for LowLevelILExpression<'func, M, NonSSA, ValueExpr> where - A: 'func + Architecture, M: FunctionMutability, { - fn kind(&self) -> LowLevelILExpressionKind<'func, A, M, NonSSA> { + fn kind(&self) -> LowLevelILExpressionKind<'func, M, NonSSA> { #[allow(unused_imports)] use binaryninjacore_sys::BNLowLevelILOperation::*; let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) }; @@ -161,9 +155,7 @@ where fn visit_tree(&self, f: &mut T) -> VisitorAction where - T: FnMut( - &LowLevelILExpression<'func, A, M, NonSSA, ValueExpr>, - ) -> VisitorAction, + T: FnMut(&LowLevelILExpression<'func, M, NonSSA, ValueExpr>) -> VisitorAction, { // Visit the current expression. match f(self) { @@ -176,13 +168,12 @@ where } } -impl<'func, A, M> ExpressionHandler<'func, A, M, NonSSA> - for LowLevelILExpression<'func, A, M, NonSSA, ValueExpr> +impl<'func, M> ExpressionHandler<'func, M, NonSSA> + for LowLevelILExpression<'func, M, NonSSA, ValueExpr> where - A: 'func + Architecture, M: FunctionMutability, { - fn kind(&self) -> LowLevelILExpressionKind<'func, A, M, NonSSA> { + fn kind(&self) -> LowLevelILExpressionKind<'func, M, NonSSA> { use binaryninjacore_sys::BNLowLevelILOperation::*; let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) }; match op.operation { @@ -197,7 +188,7 @@ where fn visit_tree(&self, f: &mut T) -> VisitorAction where T: FnMut( - &LowLevelILExpression<'func, A, M, NonSSA, ValueExpr>, + &LowLevelILExpression<'func, M, NonSSA, ValueExpr>, ) -> VisitorAction, { // Visit the current expression. @@ -211,129 +202,126 @@ where } } -impl<'func, A, F> LowLevelILExpression<'func, A, Finalized, F, ValueExpr> +impl<'func, F> LowLevelILExpression<'func, Finalized, F, ValueExpr> where - A: 'func + Architecture, F: FunctionForm, { // TODO possible values } #[derive(Debug)] -pub enum LowLevelILExpressionKind<'func, A, M, F> +pub enum LowLevelILExpressionKind<'func, 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>), - - RegStackPop(Operation<'func, A, M, F, operation::RegStackPop>), - - 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>), + Load(Operation<'func, M, F, operation::Load>), + Pop(Operation<'func, M, F, operation::Pop>), + Reg(Operation<'func, M, F, operation::Reg>), + RegSplit(Operation<'func, M, F, operation::RegSplit>), + Const(Operation<'func, M, F, operation::Const>), + ConstPtr(Operation<'func, M, F, operation::Const>), + Flag(Operation<'func, M, F, operation::Flag>), + FlagBit(Operation<'func, M, F, operation::FlagBit>), + ExternPtr(Operation<'func, M, F, operation::Extern>), + + RegStackPop(Operation<'func, M, F, operation::RegStackPop>), + + Add(Operation<'func, M, F, operation::BinaryOp>), + Adc(Operation<'func, M, F, operation::BinaryOpCarry>), + Sub(Operation<'func, M, F, operation::BinaryOp>), + Sbb(Operation<'func, M, F, operation::BinaryOpCarry>), + And(Operation<'func, M, F, operation::BinaryOp>), + Or(Operation<'func, M, F, operation::BinaryOp>), + Xor(Operation<'func, M, F, operation::BinaryOp>), + Lsl(Operation<'func, M, F, operation::BinaryOp>), + Lsr(Operation<'func, M, F, operation::BinaryOp>), + Asr(Operation<'func, M, F, operation::BinaryOp>), + Rol(Operation<'func, M, F, operation::BinaryOp>), + Rlc(Operation<'func, M, F, operation::BinaryOpCarry>), + Ror(Operation<'func, M, F, operation::BinaryOp>), + Rrc(Operation<'func, M, F, operation::BinaryOpCarry>), + Mul(Operation<'func, M, F, operation::BinaryOp>), + + MulsDp(Operation<'func, M, F, operation::BinaryOp>), + MuluDp(Operation<'func, M, F, operation::BinaryOp>), + + Divu(Operation<'func, M, F, operation::BinaryOp>), + Divs(Operation<'func, M, F, operation::BinaryOp>), + + DivuDp(Operation<'func, M, F, operation::DoublePrecDivOp>), + DivsDp(Operation<'func, M, F, operation::DoublePrecDivOp>), + + Modu(Operation<'func, M, F, operation::BinaryOp>), + Mods(Operation<'func, M, F, operation::BinaryOp>), + + ModuDp(Operation<'func, M, F, operation::DoublePrecDivOp>), + ModsDp(Operation<'func, M, F, operation::DoublePrecDivOp>), + + Neg(Operation<'func, M, F, operation::UnaryOp>), + Not(Operation<'func, M, F, operation::UnaryOp>), + Sx(Operation<'func, M, F, operation::UnaryOp>), + Zx(Operation<'func, M, F, operation::UnaryOp>), + LowPart(Operation<'func, M, F, operation::UnaryOp>), // Valid only in Lifted IL - FlagCond(Operation<'func, A, M, NonSSA, operation::FlagCond>), + FlagCond(Operation<'func, M, NonSSA, operation::FlagCond>), // Valid only in Lifted IL - FlagGroup(Operation<'func, A, M, NonSSA, 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>), + FlagGroup(Operation<'func, M, NonSSA, operation::FlagGroup>), + + CmpE(Operation<'func, M, F, operation::Condition>), + CmpNe(Operation<'func, M, F, operation::Condition>), + CmpSlt(Operation<'func, M, F, operation::Condition>), + CmpUlt(Operation<'func, M, F, operation::Condition>), + CmpSle(Operation<'func, M, F, operation::Condition>), + CmpUle(Operation<'func, M, F, operation::Condition>), + CmpSge(Operation<'func, M, F, operation::Condition>), + CmpUge(Operation<'func, M, F, operation::Condition>), + CmpSgt(Operation<'func, M, F, operation::Condition>), + CmpUgt(Operation<'func, M, F, operation::Condition>), + + //TestBit(Operation<'func, M, F, operation::TestBit>), // TODO + BoolToInt(Operation<'func, M, F, operation::UnaryOp>), + + Fadd(Operation<'func, M, F, operation::BinaryOp>), + Fsub(Operation<'func, M, F, operation::BinaryOp>), + Fmul(Operation<'func, M, F, operation::BinaryOp>), + Fdiv(Operation<'func, M, F, operation::BinaryOp>), + Fsqrt(Operation<'func, M, F, operation::UnaryOp>), + Fneg(Operation<'func, M, F, operation::UnaryOp>), + Fabs(Operation<'func, M, F, operation::UnaryOp>), + FloatToInt(Operation<'func, M, F, operation::UnaryOp>), + IntToFloat(Operation<'func, M, F, operation::UnaryOp>), + FloatConv(Operation<'func, M, F, operation::UnaryOp>), + RoundToInt(Operation<'func, M, F, operation::UnaryOp>), + Floor(Operation<'func, M, F, operation::UnaryOp>), + Ceil(Operation<'func, M, F, operation::UnaryOp>), + Ftrunc(Operation<'func, M, F, operation::UnaryOp>), + + FcmpE(Operation<'func, M, F, operation::Condition>), + FcmpNE(Operation<'func, M, F, operation::Condition>), + FcmpLT(Operation<'func, M, F, operation::Condition>), + FcmpLE(Operation<'func, M, F, operation::Condition>), + FcmpGE(Operation<'func, M, F, operation::Condition>), + FcmpGT(Operation<'func, M, F, operation::Condition>), + FcmpO(Operation<'func, M, F, operation::Condition>), + FcmpUO(Operation<'func, M, F, operation::Condition>), // TODO ADD_OVERFLOW - Unimpl(Operation<'func, A, M, F, operation::NoArgs>), - UnimplMem(Operation<'func, A, M, F, operation::UnimplMem>), + Unimpl(Operation<'func, M, F, operation::NoArgs>), + UnimplMem(Operation<'func, M, F, operation::UnimplMem>), - Undef(Operation<'func, A, M, F, operation::NoArgs>), + Undef(Operation<'func, M, F, operation::NoArgs>), } -impl<'func, A, M, F> LowLevelILExpressionKind<'func, A, M, F> +impl<'func, M, F> LowLevelILExpressionKind<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { // TODO: Document what "unchecked" means and how to consume this safely. pub(crate) unsafe fn from_raw( - function: &'func LowLevelILFunction, + function: &'func LowLevelILFunction, op: BNLowLevelILInstruction, ) -> Self { use binaryninjacore_sys::BNLowLevelILOperation::*; @@ -472,7 +460,7 @@ where } _ => Some(self.raw_struct().size), - //TestBit(Operation<'func, A, M, F, operation::TestBit>), // TODO + //TestBit(Operation<'func, M, F, operation::TestBit>), // TODO } } @@ -492,7 +480,7 @@ where } } - pub fn as_cmp_op(&self) -> Option<&Operation<'func, A, M, F, operation::Condition>> { + pub fn as_cmp_op(&self) -> Option<&Operation<'func, M, F, operation::Condition>> { use self::LowLevelILExpressionKind::*; match *self { @@ -504,7 +492,7 @@ where } } - pub fn as_binary_op(&self) -> Option<&Operation<'func, A, M, F, operation::BinaryOp>> { + pub fn as_binary_op(&self) -> Option<&Operation<'func, M, F, operation::BinaryOp>> { use self::LowLevelILExpressionKind::*; match *self { @@ -516,9 +504,7 @@ where } } - pub fn as_binary_op_carry( - &self, - ) -> Option<&Operation<'func, A, M, F, operation::BinaryOpCarry>> { + pub fn as_binary_op_carry(&self) -> Option<&Operation<'func, M, F, operation::BinaryOpCarry>> { use self::LowLevelILExpressionKind::*; match *self { @@ -529,7 +515,7 @@ where pub fn as_double_prec_div_op( &self, - ) -> Option<&Operation<'func, A, M, F, operation::DoublePrecDivOp>> { + ) -> Option<&Operation<'func, M, F, operation::DoublePrecDivOp>> { use self::LowLevelILExpressionKind::*; match *self { @@ -538,7 +524,7 @@ where } } - pub fn as_unary_op(&self) -> Option<&Operation<'func, A, M, F, operation::UnaryOp>> { + pub fn as_unary_op(&self) -> Option<&Operation<'func, M, F, operation::UnaryOp>> { use self::LowLevelILExpressionKind::*; match *self { @@ -552,7 +538,7 @@ where pub fn visit_sub_expressions(&self, mut visitor: T) -> VisitorAction where - T: FnMut(LowLevelILExpression<'func, A, M, F, ValueExpr>) -> VisitorAction, + T: FnMut(LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction, { use LowLevelILExpressionKind::*; @@ -659,16 +645,13 @@ where | 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 + //TestBit(Operation<'func, M, F, operation::TestBit>), // TODO } } } -impl<'func, A> LowLevelILExpressionKind<'func, A, Mutable, NonSSA> -where - A: 'func + Architecture, -{ - pub fn flag_write(&self) -> Option { +impl<'func> LowLevelILExpressionKind<'func, Mutable, NonSSA> { + pub fn flag_write(&self) -> Option { use self::LowLevelILExpressionKind::*; match *self { @@ -720,7 +703,7 @@ where | 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 + //TestBit(Operation<'func, M, F, operation::TestBit>), // TODO } } } diff --git a/rust/src/low_level_il/function.rs b/rust/src/low_level_il/function.rs index 301c3f09..21eebc3c 100644 --- a/rust/src/low_level_il/function.rs +++ b/rust/src/low_level_il/function.rs @@ -17,7 +17,6 @@ use binaryninjacore_sys::BNGetLowLevelILOwnerFunction; use binaryninjacore_sys::BNLowLevelILFunction; use binaryninjacore_sys::BNNewLowLevelILFunctionReference; -use std::borrow::Borrow; use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; @@ -57,51 +56,56 @@ pub trait FunctionForm: 'static + Debug {} impl FunctionForm for SSA {} impl FunctionForm for NonSSA {} -pub struct LowLevelILFunction { - pub(crate) arch_handle: A::Handle, +pub struct LowLevelILFunction { pub(crate) handle: *mut BNLowLevelILFunction, - _arch: PhantomData<*mut A>, + arch: Option, _mutability: PhantomData, _form: PhantomData, } -impl LowLevelILFunction +impl LowLevelILFunction where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub(crate) unsafe fn from_raw( - arch_handle: A::Handle, + pub(crate) unsafe fn from_raw_with_arch( handle: *mut BNLowLevelILFunction, + arch: Option, ) -> Self { debug_assert!(!handle.is_null()); Self { - arch_handle, handle, - _arch: PhantomData, + arch, _mutability: PhantomData, _form: PhantomData, } } - pub(crate) unsafe fn ref_from_raw( - arch_handle: A::Handle, + pub(crate) unsafe fn from_raw(handle: *mut BNLowLevelILFunction) -> Self { + Self::from_raw_with_arch(handle, None) + } + + pub(crate) unsafe fn ref_from_raw_with_arch( handle: *mut BNLowLevelILFunction, + arch: Option, ) -> Ref { debug_assert!(!handle.is_null()); - Ref::new(Self::from_raw(arch_handle, handle)) + Ref::new(Self::from_raw_with_arch(handle, arch)) } - pub(crate) fn arch(&self) -> &A { - self.arch_handle.borrow() + pub(crate) unsafe fn ref_from_raw(handle: *mut BNLowLevelILFunction) -> Ref { + Self::ref_from_raw_with_arch(handle, None) } - pub fn instruction_at>( - &self, - loc: L, - ) -> Option> { + pub(crate) fn arch(&self) -> CoreArchitecture { + match self.arch { + None => self.function().arch(), + Some(arch) => arch, + } + } + + pub fn instruction_at>(&self, loc: L) -> Option> { Some(LowLevelILInstruction::new( self, self.instruction_index_at(loc)?, @@ -128,7 +132,7 @@ where pub fn instruction_from_index( &self, index: LowLevelInstructionIndex, - ) -> Option> { + ) -> Option> { if index.0 >= self.instruction_count() { None } else { @@ -161,12 +165,8 @@ where // LLIL basic blocks are not available until the function object // is finalized, so ensure we can't try requesting basic blocks // during lifting -impl LowLevelILFunction -where - A: Architecture, - F: FunctionForm, -{ - pub fn basic_blocks(&self) -> Array>> { +impl LowLevelILFunction { + pub fn basic_blocks(&self) -> Array>> { use binaryninjacore_sys::BNGetLowLevelILBasicBlockList; unsafe { @@ -179,7 +179,7 @@ where } // Allow instantiating Lifted IL functions for querying Lifted IL from Architectures -impl LowLevelILFunction> { +impl LowLevelILFunction> { // TODO: Document what happens when you pass None for `source_func`. // TODO: Doing so would construct a LowLevelILFunction with no basic blocks // TODO: Document why you would want to do that. @@ -196,7 +196,7 @@ impl LowLevelILFunction> { // BNCreateLowLevelILFunction should always return a valid object. assert!(!handle.is_null()); - unsafe { Self::ref_from_raw(arch, handle) } + unsafe { Self::ref_from_raw_with_arch(handle, Some(arch)) } } pub fn generate_ssa_form(&self) { @@ -206,9 +206,8 @@ impl LowLevelILFunction> { } } -impl ToOwned for LowLevelILFunction +impl ToOwned for LowLevelILFunction where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -219,17 +218,15 @@ where } } -unsafe impl RefCountable for LowLevelILFunction +unsafe impl RefCountable for LowLevelILFunction where - A: Architecture, M: FunctionMutability, F: FunctionForm, { unsafe fn inc_ref(handle: &Self) -> Ref { Ref::new(Self { - arch_handle: handle.arch_handle.clone(), handle: BNNewLowLevelILFunctionReference(handle.handle), - _arch: PhantomData, + arch: handle.arch, _mutability: PhantomData, _form: PhantomData, }) @@ -240,9 +237,8 @@ where } } -impl Debug for LowLevelILFunction +impl Debug for LowLevelILFunction where - A: Architecture + Debug, M: FunctionMutability, F: FunctionForm, { @@ -255,26 +251,18 @@ where } } -unsafe impl Send - for LowLevelILFunction -{ -} -unsafe impl Sync - for LowLevelILFunction -{ -} +unsafe impl Send for LowLevelILFunction {} +unsafe impl Sync for LowLevelILFunction {} -impl Eq for LowLevelILFunction {} +impl Eq for LowLevelILFunction {} -impl PartialEq - for LowLevelILFunction -{ +impl PartialEq for LowLevelILFunction { fn eq(&self, rhs: &Self) -> bool { self.function().eq(&rhs.function()) } } -impl Hash for LowLevelILFunction { +impl Hash for LowLevelILFunction { fn hash(&self, state: &mut H) { self.function().hash(state) } diff --git a/rust/src/low_level_il/instruction.rs b/rust/src/low_level_il/instruction.rs index 977dcff4..a1253df5 100644 --- a/rust/src/low_level_il/instruction.rs +++ b/rust/src/low_level_il/instruction.rs @@ -16,7 +16,6 @@ use super::operation; use super::operation::Operation; use super::VisitorAction; use super::*; -use crate::architecture::Architecture; use binaryninjacore_sys::BNGetLowLevelILByIndex; use binaryninjacore_sys::BNGetLowLevelILIndexForInstruction; use binaryninjacore_sys::BNLowLevelILInstruction; @@ -51,44 +50,38 @@ impl Display for LowLevelInstructionIndex { } // TODO: Probably want to rename this with a LowLevelIL prefix to avoid collisions when we add handlers for other ILs -pub trait InstructionHandler<'func, A, M, F> +pub trait InstructionHandler<'func, M, F> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - fn kind(&self) -> LowLevelILInstructionKind<'func, A, M, F>; + fn kind(&self) -> LowLevelILInstructionKind<'func, M, F>; /// Visit the sub expressions of this instruction. /// /// NOTE: This does not visit the root expression, i.e. the instruction. fn visit_tree(&self, f: &mut T) -> VisitorAction where - T: FnMut(&LowLevelILExpression<'func, A, M, F, ValueExpr>) -> VisitorAction; + T: FnMut(&LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction; } -pub struct LowLevelILInstruction<'func, A, M, F> +pub struct LowLevelILInstruction<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { - pub(crate) function: &'func LowLevelILFunction, + pub(crate) function: &'func LowLevelILFunction, pub index: LowLevelInstructionIndex, } -impl<'func, A, M, F> LowLevelILInstruction<'func, A, M, F> +impl<'func, M, F> LowLevelILInstruction<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { // TODO: Should we check the instruction count here with BNGetLowLevelILInstructionCount? // TODO: If we _can_ then this should become an Option methinks - pub fn new( - function: &'func LowLevelILFunction, - index: LowLevelInstructionIndex, - ) -> Self { + pub fn new(function: &'func LowLevelILFunction, index: LowLevelInstructionIndex) -> Self { Self { function, index } } @@ -107,9 +100,8 @@ where } } -impl<'func, A, M, F> Debug for LowLevelILInstruction<'func, A, M, F> +impl<'func, M, F> Debug for LowLevelILInstruction<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { @@ -122,12 +114,11 @@ where } } -impl<'func, A, M> InstructionHandler<'func, A, M, SSA> for LowLevelILInstruction<'func, A, M, SSA> +impl<'func, M> InstructionHandler<'func, M, SSA> for LowLevelILInstruction<'func, M, SSA> where - A: 'func + Architecture, M: FunctionMutability, { - fn kind(&self) -> LowLevelILInstructionKind<'func, A, M, SSA> { + fn kind(&self) -> LowLevelILInstructionKind<'func, M, SSA> { #[allow(unused_imports)] use binaryninjacore_sys::BNLowLevelILOperation::*; let raw_op = self.into_raw(); @@ -143,20 +134,19 @@ where fn visit_tree(&self, f: &mut T) -> VisitorAction where - T: FnMut(&LowLevelILExpression<'func, A, M, SSA, ValueExpr>) -> VisitorAction, + T: FnMut(&LowLevelILExpression<'func, M, SSA, ValueExpr>) -> VisitorAction, { // Recursively visit sub expressions. self.kind().visit_sub_expressions(|e| e.visit_tree(f)) } } -impl<'func, A, M> InstructionHandler<'func, A, M, NonSSA> - for LowLevelILInstruction<'func, A, M, NonSSA> +impl<'func, M> InstructionHandler<'func, M, NonSSA> + for LowLevelILInstruction<'func, M, NonSSA> where - A: 'func + Architecture, M: FunctionMutability, { - fn kind(&self) -> LowLevelILInstructionKind<'func, A, M, NonSSA> { + fn kind(&self) -> LowLevelILInstructionKind<'func, M, NonSSA> { #[allow(unused_imports)] use binaryninjacore_sys::BNLowLevelILOperation::*; let raw_op = self.into_raw(); @@ -172,22 +162,19 @@ where fn visit_tree(&self, f: &mut T) -> VisitorAction where - T: FnMut( - &LowLevelILExpression<'func, A, M, NonSSA, ValueExpr>, - ) -> VisitorAction, + T: FnMut(&LowLevelILExpression<'func, M, NonSSA, ValueExpr>) -> VisitorAction, { // Recursively visit sub expressions. self.kind().visit_sub_expressions(|e| e.visit_tree(f)) } } -impl<'func, A, M> InstructionHandler<'func, A, M, NonSSA> - for LowLevelILInstruction<'func, A, M, NonSSA> +impl<'func, M> InstructionHandler<'func, M, NonSSA> + for LowLevelILInstruction<'func, M, NonSSA> where - A: 'func + Architecture, M: FunctionMutability, { - fn kind(&self) -> LowLevelILInstructionKind<'func, A, M, NonSSA> { + fn kind(&self) -> LowLevelILInstructionKind<'func, M, NonSSA> { #[allow(unused_imports)] use binaryninjacore_sys::BNLowLevelILOperation::*; let raw_op = self.into_raw(); @@ -204,7 +191,7 @@ where fn visit_tree(&self, f: &mut T) -> VisitorAction where T: FnMut( - &LowLevelILExpression<'func, A, M, NonSSA, ValueExpr>, + &LowLevelILExpression<'func, M, NonSSA, ValueExpr>, ) -> VisitorAction, { // Recursively visit sub expressions. @@ -213,52 +200,50 @@ where } #[derive(Debug)] -pub enum LowLevelILInstructionKind<'func, A, M, F> +pub enum LowLevelILInstructionKind<'func, M, F> where - A: 'func + Architecture, M: FunctionMutability, F: FunctionForm, { - Nop(Operation<'func, A, M, F, operation::NoArgs>), - SetReg(Operation<'func, A, M, F, operation::SetReg>), - SetRegSplit(Operation<'func, A, M, F, operation::SetRegSplit>), - SetFlag(Operation<'func, A, M, F, operation::SetFlag>), - Store(Operation<'func, A, M, F, operation::Store>), + Nop(Operation<'func, M, F, operation::NoArgs>), + SetReg(Operation<'func, M, F, operation::SetReg>), + SetRegSplit(Operation<'func, M, F, operation::SetRegSplit>), + SetFlag(Operation<'func, M, F, operation::SetFlag>), + Store(Operation<'func, M, F, operation::Store>), // TODO needs a real op - Push(Operation<'func, A, M, F, operation::UnaryOp>), + Push(Operation<'func, M, F, operation::UnaryOp>), - RegStackPush(Operation<'func, A, M, F, operation::RegStackPush>), + RegStackPush(Operation<'func, M, F, operation::RegStackPush>), - Jump(Operation<'func, A, M, F, operation::Jump>), - JumpTo(Operation<'func, A, M, F, operation::JumpTo>), + Jump(Operation<'func, M, F, operation::Jump>), + JumpTo(Operation<'func, M, F, operation::JumpTo>), - Call(Operation<'func, A, M, F, operation::Call>), - TailCall(Operation<'func, A, M, F, operation::Call>), + Call(Operation<'func, M, F, operation::Call>), + TailCall(Operation<'func, M, F, operation::Call>), - Ret(Operation<'func, A, M, F, operation::Ret>), - NoRet(Operation<'func, A, M, F, operation::NoArgs>), + Ret(Operation<'func, M, F, operation::Ret>), + NoRet(Operation<'func, M, F, operation::NoArgs>), - If(Operation<'func, A, M, F, operation::If>), - Goto(Operation<'func, A, M, F, operation::Goto>), + If(Operation<'func, M, F, operation::If>), + Goto(Operation<'func, M, F, operation::Goto>), - Syscall(Operation<'func, A, M, F, operation::Syscall>), - Intrinsic(Operation<'func, A, M, F, operation::Intrinsic>), - Bp(Operation<'func, A, M, F, operation::NoArgs>), - Trap(Operation<'func, A, M, F, operation::Trap>), - Undef(Operation<'func, A, M, F, operation::NoArgs>), + Syscall(Operation<'func, M, F, operation::Syscall>), + Intrinsic(Operation<'func, M, F, operation::Intrinsic>), + Bp(Operation<'func, M, F, operation::NoArgs>), + Trap(Operation<'func, M, F, operation::Trap>), + Undef(Operation<'func, M, F, operation::NoArgs>), /// The instruction is an expression. - Value(LowLevelILExpression<'func, A, M, F, ValueExpr>), + Value(LowLevelILExpression<'func, M, F, ValueExpr>), } -impl<'func, A, M, F> LowLevelILInstructionKind<'func, A, M, F> +impl<'func, M, F> LowLevelILInstructionKind<'func, M, F> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { pub(crate) unsafe fn from_raw( - function: &'func LowLevelILFunction, + function: &'func LowLevelILFunction, expr_index: LowLevelExpressionIndex, op: BNLowLevelILInstruction, ) -> Self { @@ -315,7 +300,7 @@ where fn visit_sub_expressions(&self, mut visitor: T) -> VisitorAction where - T: FnMut(&LowLevelILExpression<'func, A, M, F, ValueExpr>) -> VisitorAction, + T: FnMut(&LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction, { use LowLevelILInstructionKind::*; diff --git a/rust/src/low_level_il/lifting.rs b/rust/src/low_level_il/lifting.rs index 7401c99b..c40f68f2 100644 --- a/rust/src/low_level_il/lifting.rs +++ b/rust/src/low_level_il/lifting.rs @@ -18,35 +18,33 @@ use binaryninjacore_sys::{BNAddLowLevelILLabelForAddress, BNLowLevelILOperation} use binaryninjacore_sys::{BNLowLevelILLabel, BNRegisterOrConstant}; use super::*; -use crate::architecture::Register as ArchReg; use crate::architecture::{Architecture, FlagWriteId, RegisterId}; +use crate::architecture::{CoreRegister, Register as ArchReg}; use crate::architecture::{ Flag, FlagClass, FlagCondition, FlagGroup, FlagRole, FlagWrite, Intrinsic, }; use crate::function::Location; -pub trait LiftableLowLevelIL<'func, A: 'func + Architecture> { +pub trait LiftableLowLevelIL<'func> { type Result: ExpressionResultType; fn lift( - il: &'func MutableLiftedILFunction, + il: &'func MutableLiftedILFunction, expr: Self, - ) -> MutableLiftedILExpr<'func, A, Self::Result>; + ) -> MutableLiftedILExpr<'func, Self::Result>; } -pub trait LiftableLowLevelILWithSize<'func, A: 'func + Architecture>: - LiftableLowLevelIL<'func, A, Result = ValueExpr> -{ +pub trait LiftableLowLevelILWithSize<'func>: LiftableLowLevelIL<'func, Result = ValueExpr> { fn lift_with_size( - il: &'func MutableLiftedILFunction, + il: &'func MutableLiftedILFunction, expr: Self, size: usize, - ) -> MutableLiftedILExpr<'func, A, ValueExpr>; + ) -> MutableLiftedILExpr<'func, ValueExpr>; } #[derive(Copy, Clone)] pub enum LowLevelILRegisterOrConstant { - Register(usize, LowLevelILRegister), + Register(usize, LowLevelILRegisterKind), Constant(usize, u64), } @@ -267,14 +265,9 @@ impl LowLevelILFlagWriteOp { if operand.constant { LowLevelILRegisterOrConstant::Constant(size, operand.value) } else { - let il_reg = if 0x8000_0000 & operand.reg == 0 { - LowLevelILRegister::ArchReg( - arch.register_from_id(RegisterId(operand.reg)).unwrap(), - ) - } else { - LowLevelILRegister::Temp(operand.reg) - }; - + let raw_id = RegisterId(operand.reg); + let il_reg = + LowLevelILRegisterKind::from_raw(arch, raw_id).expect("Bad register ID"); LowLevelILRegisterOrConstant::Register(size, il_reg) } } @@ -466,8 +459,8 @@ pub fn get_default_flag_write_llil<'func, A>( arch: &A, role: FlagRole, op: LowLevelILFlagWriteOp, - il: &'func MutableLiftedILFunction, -) -> MutableLiftedILExpr<'func, A, ValueExpr> + il: &'func MutableLiftedILFunction, +) -> MutableLiftedILExpr<'func, ValueExpr> where A: 'func + Architecture, { @@ -494,8 +487,8 @@ pub fn get_default_flag_cond_llil<'func, A>( arch: &A, cond: FlagCondition, class: Option, - il: &'func MutableLiftedILFunction, -) -> MutableLiftedILExpr<'func, A, ValueExpr> + il: &'func MutableLiftedILFunction, +) -> MutableLiftedILExpr<'func, ValueExpr> where A: 'func + Architecture, { @@ -516,19 +509,19 @@ where macro_rules! prim_int_lifter { ($x:ty) => { - impl<'a, A: 'a + Architecture> LiftableLowLevelIL<'a, A> for $x { + impl<'a> LiftableLowLevelIL<'a> for $x { type Result = ValueExpr; - fn lift(il: &'a MutableLiftedILFunction, val: Self) - -> MutableLiftedILExpr<'a, A, Self::Result> + fn lift(il: &'a MutableLiftedILFunction, val: Self) + -> MutableLiftedILExpr<'a, Self::Result> { il.const_int(std::mem::size_of::(), val as i64 as u64) } } - impl<'a, A: 'a + Architecture> LiftableLowLevelILWithSize<'a, A> for $x { - fn lift_with_size(il: &'a MutableLiftedILFunction, val: Self, size: usize) - -> MutableLiftedILExpr<'a, A, ValueExpr> + impl<'a> LiftableLowLevelILWithSize<'a> for $x { + fn lift_with_size(il: &'a MutableLiftedILFunction, val: Self, size: usize) + -> MutableLiftedILExpr<'a, ValueExpr> { let raw = val as i64; @@ -561,57 +554,51 @@ prim_int_lifter!(u16); prim_int_lifter!(u32); prim_int_lifter!(u64); -impl<'a, R: ArchReg, A: 'a + Architecture> LiftableLowLevelIL<'a, A> for LowLevelILRegister +impl<'a, R> LiftableLowLevelIL<'a> for LowLevelILRegisterKind where - R: LiftableLowLevelIL<'a, A, Result = ValueExpr> + Into>, + R: LiftableLowLevelIL<'a, Result = ValueExpr> + Into> + ArchReg, { type Result = ValueExpr; - fn lift( - il: &'a MutableLiftedILFunction, - reg: Self, - ) -> MutableLiftedILExpr<'a, A, Self::Result> { + fn lift(il: &'a MutableLiftedILFunction, reg: Self) -> MutableLiftedILExpr<'a, Self::Result> { match reg { - LowLevelILRegister::ArchReg(r) => R::lift(il, r), - LowLevelILRegister::Temp(t) => il.reg( + LowLevelILRegisterKind::Arch(r) => R::lift(il, r), + LowLevelILRegisterKind::Temp(t) => il.reg( il.arch().default_integer_size(), - LowLevelILRegister::Temp(t), + LowLevelILRegisterKind::Temp::(t), ), } } } -impl<'a, R: ArchReg, A: 'a + Architecture> LiftableLowLevelILWithSize<'a, A> - for LowLevelILRegister +impl<'a, R> LiftableLowLevelILWithSize<'a> for LowLevelILRegisterKind where - R: LiftableLowLevelILWithSize<'a, A> + Into>, + R: LiftableLowLevelILWithSize<'a> + Into> + ArchReg, { fn lift_with_size( - il: &'a MutableLiftedILFunction, + il: &'a MutableLiftedILFunction, reg: Self, size: usize, - ) -> MutableLiftedILExpr<'a, A, ValueExpr> { + ) -> MutableLiftedILExpr<'a, ValueExpr> { match reg { - LowLevelILRegister::ArchReg(r) => R::lift_with_size(il, r, size), - LowLevelILRegister::Temp(t) => il.reg(size, LowLevelILRegister::Temp(t)), + LowLevelILRegisterKind::Arch(r) => R::lift_with_size(il, r, size), + LowLevelILRegisterKind::Temp(t) => il.reg(size, LowLevelILRegisterKind::::Temp(t)), } } } -impl<'a, R: ArchReg, A: 'a + Architecture> LiftableLowLevelIL<'a, A> - for LowLevelILRegisterOrConstant +impl<'a, R> LiftableLowLevelIL<'a> for LowLevelILRegisterOrConstant where - R: LiftableLowLevelILWithSize<'a, A, Result = ValueExpr> + Into>, + R: LiftableLowLevelILWithSize<'a, Result = ValueExpr> + + Into> + + ArchReg, { type Result = ValueExpr; - fn lift( - il: &'a MutableLiftedILFunction, - reg: Self, - ) -> MutableLiftedILExpr<'a, A, Self::Result> { + fn lift(il: &'a MutableLiftedILFunction, reg: Self) -> MutableLiftedILExpr<'a, Self::Result> { match reg { LowLevelILRegisterOrConstant::Register(size, r) => { - LowLevelILRegister::::lift_with_size(il, r, size) + LowLevelILRegisterKind::::lift_with_size(il, r, size) } LowLevelILRegisterOrConstant::Constant(size, value) => { u64::lift_with_size(il, value, size) @@ -620,20 +607,19 @@ where } } -impl<'a, R: ArchReg, A: 'a + Architecture> LiftableLowLevelILWithSize<'a, A> - for LowLevelILRegisterOrConstant +impl<'a, R> LiftableLowLevelILWithSize<'a> for LowLevelILRegisterOrConstant where - R: LiftableLowLevelILWithSize<'a, A> + Into>, + R: LiftableLowLevelILWithSize<'a> + Into> + ArchReg, { fn lift_with_size( - il: &'a MutableLiftedILFunction, + il: &'a MutableLiftedILFunction, reg: Self, size: usize, - ) -> MutableLiftedILExpr<'a, A, ValueExpr> { + ) -> MutableLiftedILExpr<'a, ValueExpr> { // TODO ensure requested size is compatible with size of this constant match reg { LowLevelILRegisterOrConstant::Register(_, r) => { - LowLevelILRegister::::lift_with_size(il, r, size) + LowLevelILRegisterKind::::lift_with_size(il, r, size) } LowLevelILRegisterOrConstant::Constant(_, value) => { u64::lift_with_size(il, value, size) @@ -642,31 +628,26 @@ where } } -impl<'a, A, R> LiftableLowLevelIL<'a, A> - for LowLevelILExpression<'a, A, Mutable, NonSSA, R> +impl<'a, R> LiftableLowLevelIL<'a> for LowLevelILExpression<'a, Mutable, NonSSA, R> where - A: 'a + Architecture, R: ExpressionResultType, { type Result = R; - fn lift( - il: &'a MutableLiftedILFunction, - expr: Self, - ) -> MutableLiftedILExpr<'a, A, Self::Result> { + fn lift(il: &'a MutableLiftedILFunction, expr: Self) -> MutableLiftedILExpr<'a, Self::Result> { debug_assert!(expr.function.handle == il.handle); expr } } -impl<'a, A: 'a + Architecture> LiftableLowLevelILWithSize<'a, A> - for LowLevelILExpression<'a, A, Mutable, NonSSA, ValueExpr> +impl<'a> LiftableLowLevelILWithSize<'a> + for LowLevelILExpression<'a, Mutable, NonSSA, ValueExpr> { fn lift_with_size( - il: &'a MutableLiftedILFunction, + il: &'a MutableLiftedILFunction, expr: Self, _size: usize, - ) -> MutableLiftedILExpr<'a, A, Self::Result> { + ) -> MutableLiftedILExpr<'a, Self::Result> { #[cfg(debug_assertions)] { use crate::low_level_il::ExpressionHandler; @@ -686,9 +667,8 @@ impl<'a, A: 'a + Architecture> LiftableLowLevelILWithSize<'a, A> } } -impl<'func, A, R> LowLevelILExpression<'func, A, Mutable, NonSSA, R> +impl<'func, R> LowLevelILExpression<'func, Mutable, NonSSA, R> where - A: 'func + Architecture, R: ExpressionResultType, { pub fn with_source_operand(self, op: u32) -> Self { @@ -702,12 +682,11 @@ where } } -pub struct ExpressionBuilder<'func, A, R> +pub struct ExpressionBuilder<'func, R> where - A: 'func + Architecture, R: ExpressionResultType, { - function: &'func LowLevelILFunction>, + function: &'func LowLevelILFunction>, op: BNLowLevelILOperation, size: usize, flag_write: FlagWriteId, @@ -718,12 +697,11 @@ where _ty: PhantomData, } -impl<'a, A, R> ExpressionBuilder<'a, A, R> +impl<'a, R> ExpressionBuilder<'a, R> where - A: 'a + Architecture, R: ExpressionResultType, { - pub fn from_expr(expr: LowLevelILExpression<'a, A, Mutable, NonSSA, R>) -> Self { + pub fn from_expr(expr: LowLevelILExpression<'a, Mutable, NonSSA, R>) -> Self { use binaryninjacore_sys::BNGetLowLevelILByIndex; let instr = unsafe { BNGetLowLevelILByIndex(expr.function.handle, expr.index.0) }; @@ -741,13 +719,13 @@ where } } - pub fn with_flag_write(mut self, flag_write: A::FlagWrite) -> Self { + pub fn with_flag_write(mut self, flag_write: impl FlagWrite) -> Self { // TODO verify valid id self.flag_write = flag_write.id(); self } - pub fn build(self) -> LowLevelILExpression<'a, A, Mutable, NonSSA, R> { + pub fn build(self) -> LowLevelILExpression<'a, Mutable, NonSSA, R> { use binaryninjacore_sys::BNLowLevelILAddExpr; let expr_idx = unsafe { @@ -769,7 +747,7 @@ where pub fn with_source_operand( self, op: u32, - ) -> LowLevelILExpression<'a, A, Mutable, NonSSA, R> { + ) -> LowLevelILExpression<'a, Mutable, NonSSA, R> { self.build().with_source_operand(op) } @@ -779,32 +757,25 @@ where } } -impl<'a, A, R> LiftableLowLevelIL<'a, A> for ExpressionBuilder<'a, A, R> +impl<'a, R> LiftableLowLevelIL<'a> for ExpressionBuilder<'a, R> where - A: 'a + Architecture, R: ExpressionResultType, { type Result = R; - fn lift( - il: &'a MutableLiftedILFunction, - expr: Self, - ) -> MutableLiftedILExpr<'a, A, Self::Result> { + fn lift(il: &'a MutableLiftedILFunction, expr: Self) -> MutableLiftedILExpr<'a, Self::Result> { debug_assert!(expr.function.handle == il.handle); expr.build() } } -impl<'a, A> LiftableLowLevelILWithSize<'a, A> for ExpressionBuilder<'a, A, ValueExpr> -where - A: 'a + Architecture, -{ +impl<'a> LiftableLowLevelILWithSize<'a> for ExpressionBuilder<'a, ValueExpr> { fn lift_with_size( - il: &'a MutableLiftedILFunction, + il: &'a MutableLiftedILFunction, expr: Self, _size: usize, - ) -> MutableLiftedILExpr<'a, A, ValueExpr> { + ) -> MutableLiftedILExpr<'a, ValueExpr> { #[cfg(debug_assertions)] { use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_UNIMPL, LLIL_UNIMPL_MEM}; @@ -825,7 +796,7 @@ where macro_rules! no_arg_lifter { ($name:ident, $op:ident, $result:ty) => { - pub fn $name(&self) -> LowLevelILExpression, $result> { + pub fn $name(&self) -> LowLevelILExpression, $result> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::$op; @@ -838,7 +809,7 @@ macro_rules! no_arg_lifter { macro_rules! sized_no_arg_lifter { ($name:ident, $op:ident, $result:ty) => { - pub fn $name(&self, size: usize) -> ExpressionBuilder { + pub fn $name(&self, size: usize) -> ExpressionBuilder<$result> { use binaryninjacore_sys::BNLowLevelILOperation::$op; ExpressionBuilder { @@ -861,9 +832,9 @@ macro_rules! unsized_unary_op_lifter { pub fn $name<'a, E>( &'a self, expr: E, - ) -> LowLevelILExpression<'a, A, Mutable, NonSSA, $result> + ) -> LowLevelILExpression<'a, Mutable, NonSSA, $result> where - E: LiftableLowLevelIL<'a, A, Result = ValueExpr>, + E: LiftableLowLevelIL<'a, Result = ValueExpr>, { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::$op; @@ -881,9 +852,9 @@ macro_rules! unsized_unary_op_lifter { 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> + pub fn $name<'a, E>(&'a self, size: usize, expr: E) -> ExpressionBuilder<'a, $result> where - E: LiftableLowLevelILWithSize<'a, A>, + E: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::$op; @@ -906,9 +877,9 @@ macro_rules! sized_unary_op_lifter { 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> + pub fn $name<'a, E>(&'a self, size: usize, expr: E) -> ExpressionBuilder<'a, $result> where - E: LiftableLowLevelILWithSize<'a, A>, + E: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::$op; @@ -936,10 +907,10 @@ macro_rules! binary_op_lifter { size: usize, left: L, right: R, - ) -> ExpressionBuilder<'a, A, ValueExpr> + ) -> ExpressionBuilder<'a, ValueExpr> where - L: LiftableLowLevelILWithSize<'a, A>, - R: LiftableLowLevelILWithSize<'a, A>, + L: LiftableLowLevelILWithSize<'a>, + R: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::$op; @@ -969,11 +940,11 @@ macro_rules! binary_op_carry_lifter { left: L, right: R, carry: C, - ) -> ExpressionBuilder<'a, A, ValueExpr> + ) -> ExpressionBuilder<'a, ValueExpr> where - L: LiftableLowLevelILWithSize<'a, A>, - R: LiftableLowLevelILWithSize<'a, A>, - C: LiftableLowLevelILWithSize<'a, A>, + L: LiftableLowLevelILWithSize<'a>, + R: LiftableLowLevelILWithSize<'a>, + C: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::$op; @@ -996,21 +967,18 @@ macro_rules! binary_op_carry_lifter { }; } -impl LowLevelILFunction> -where - A: Architecture, -{ - pub const NO_INPUTS: [ExpressionBuilder<'static, A, ValueExpr>; 0] = []; - pub const NO_OUTPUTS: [LowLevelILRegister; 0] = []; +impl LowLevelILFunction> { + pub const NO_INPUTS: [ExpressionBuilder<'static, ValueExpr>; 0] = []; + pub const NO_OUTPUTS: [LowLevelILRegisterKind; 0] = []; - pub fn expression<'a, E: LiftableLowLevelIL<'a, A>>( + pub fn expression<'a, E: LiftableLowLevelIL<'a>>( &'a self, expr: E, - ) -> LowLevelILExpression<'a, A, Mutable, NonSSA, E::Result> { + ) -> LowLevelILExpression<'a, Mutable, NonSSA, E::Result> { E::lift(self, expr) } - pub fn add_instruction<'a, E: LiftableLowLevelIL<'a, A>>(&'a self, expr: E) { + pub fn add_instruction<'a, E: LiftableLowLevelIL<'a>>(&'a self, expr: E) { let expr = self.expression(expr); unsafe { @@ -1019,7 +987,7 @@ where } } - pub unsafe fn replace_expression<'a, E: LiftableLowLevelIL<'a, A>>( + pub unsafe fn replace_expression<'a, E: LiftableLowLevelIL<'a>>( &'a self, replaced_expr_index: LowLevelExpressionIndex, replacement: E, @@ -1038,7 +1006,7 @@ where &self, size: usize, val: u64, - ) -> LowLevelILExpression, ValueExpr> { + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CONST; @@ -1052,7 +1020,7 @@ where &self, size: usize, val: u64, - ) -> LowLevelILExpression, ValueExpr> { + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CONST_PTR; @@ -1065,14 +1033,11 @@ where pub fn const_ptr( &self, val: u64, - ) -> LowLevelILExpression, ValueExpr> { + ) -> LowLevelILExpression, ValueExpr> { self.const_ptr_sized(self.arch().address_size(), val) } - pub fn trap( - &self, - val: u64, - ) -> LowLevelILExpression, VoidExpr> { + pub fn trap(&self, val: u64) -> LowLevelILExpression, VoidExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_TRAP; @@ -1099,9 +1064,9 @@ where cond: C, true_label: &'b mut LowLevelILLabel, false_label: &'b mut LowLevelILLabel, - ) -> LowLevelILExpression<'a, A, Mutable, NonSSA, VoidExpr> + ) -> LowLevelILExpression<'a, Mutable, NonSSA, VoidExpr> where - C: LiftableLowLevelIL<'b, A, Result = ValueExpr>, + C: LiftableLowLevelIL<'b, Result = ValueExpr>, { use binaryninjacore_sys::BNLowLevelILIf; @@ -1139,7 +1104,7 @@ where pub fn goto<'a: 'b, 'b>( &'a self, label: &'b mut LowLevelILLabel, - ) -> LowLevelILExpression<'a, A, Mutable, NonSSA, VoidExpr> { + ) -> LowLevelILExpression<'a, Mutable, NonSSA, VoidExpr> { use binaryninjacore_sys::BNLowLevelILGoto; let mut raw_label = BNLowLevelILLabel::from(*label); @@ -1156,11 +1121,11 @@ where LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx)) } - pub fn reg>>( + pub fn reg>>( &self, size: usize, - reg: R, - ) -> LowLevelILExpression, ValueExpr> { + reg: LR, + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG; @@ -1173,15 +1138,12 @@ where LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx)) } - pub fn reg_split< - H: Into>, - L: Into>, - >( + pub fn reg_split>>( &self, size: usize, - hi_reg: H, - lo_reg: L, - ) -> LowLevelILExpression, ValueExpr> { + hi_reg: LR, + lo_reg: LR, + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG_SPLIT; @@ -1205,15 +1167,16 @@ where LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx)) } - pub fn set_reg<'a, R, E>( + pub fn set_reg<'a, R, LR, E>( &'a self, size: usize, - dest_reg: R, + dest_reg: LR, expr: E, - ) -> ExpressionBuilder<'a, A, VoidExpr> + ) -> ExpressionBuilder<'a, VoidExpr> where - R: Into>, - E: LiftableLowLevelILWithSize<'a, A>, + R: ArchReg, + LR: Into>, + E: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG; @@ -1236,17 +1199,17 @@ where } } - pub fn set_reg_split<'a, H, L, E>( + pub fn set_reg_split<'a, R, LR, E>( &'a self, size: usize, - hi_reg: H, - lo_reg: L, + hi_reg: LR, + lo_reg: LR, expr: E, - ) -> ExpressionBuilder<'a, A, VoidExpr> + ) -> ExpressionBuilder<'a, VoidExpr> where - H: Into>, - L: Into>, - E: LiftableLowLevelILWithSize<'a, A>, + R: ArchReg, + LR: Into>, + E: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG_SPLIT; @@ -1260,7 +1223,6 @@ where function: self, op: LLIL_SET_REG_SPLIT, size, - // TODO: Make these optional? flag_write: FlagWriteId(0), op1: hi_reg.0 as u64, op2: lo_reg.0 as u64, @@ -1272,8 +1234,8 @@ where pub fn flag( &self, - flag: A::Flag, - ) -> LowLevelILExpression, ValueExpr> { + flag: impl Flag, + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG; @@ -1288,7 +1250,7 @@ where pub fn flag_cond( &self, cond: FlagCondition, - ) -> LowLevelILExpression, ValueExpr> { + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_COND; @@ -1301,8 +1263,8 @@ where pub fn flag_group( &self, - group: A::FlagGroup, - ) -> LowLevelILExpression, ValueExpr> { + group: impl FlagGroup, + ) -> LowLevelILExpression, ValueExpr> { use binaryninjacore_sys::BNLowLevelILAddExpr; use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_GROUP; @@ -1325,11 +1287,11 @@ where pub fn set_flag<'a, E>( &'a self, - dest_flag: A::Flag, + dest_flag: impl Flag, expr: E, - ) -> ExpressionBuilder<'a, A, VoidExpr> + ) -> ExpressionBuilder<'a, VoidExpr> where - E: LiftableLowLevelILWithSize<'a, A>, + E: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_FLAG; @@ -1355,9 +1317,9 @@ where FlagBit(usize, Flag, u64), */ - pub fn load<'a, E>(&'a self, size: usize, source_mem: E) -> ExpressionBuilder<'a, A, ValueExpr> + pub fn load<'a, E>(&'a self, size: usize, source_mem: E) -> ExpressionBuilder<'a, ValueExpr> where - E: LiftableLowLevelIL<'a, A, Result = ValueExpr>, + E: LiftableLowLevelIL<'a, Result = ValueExpr>, { use binaryninjacore_sys::BNLowLevelILOperation::LLIL_LOAD; @@ -1381,10 +1343,10 @@ where size: usize, dest_mem: D, value: V, - ) -> ExpressionBuilder<'a, A, VoidExpr> + ) -> ExpressionBuilder<'a, VoidExpr> where - D: LiftableLowLevelIL<'a, A, Result = ValueExpr>, - V: LiftableLowLevelILWithSize<'a, A>, + D: LiftableLowLevelIL<'a, Result = ValueExpr>, + V: LiftableLowLevelILWithSize<'a>, { use binaryninjacore_sys::BNLowLevelILOperation::LLIL_STORE; @@ -1404,18 +1366,17 @@ where } } - pub fn intrinsic<'a, O, OL, I, P, PL>( + // TODO: Reposition arguments. + pub fn intrinsic<'a, R, O, P>( &'a self, - outputs: OL, - intrinsic: I, - inputs: PL, - ) -> ExpressionBuilder<'a, A, VoidExpr> + outputs: impl IntoIterator, + intrinsic: impl Intrinsic, + inputs: impl IntoIterator, + ) -> ExpressionBuilder<'a, VoidExpr> where - O: Into>, - OL: IntoIterator, - I: Into, - P: LiftableLowLevelIL<'a, A, Result = ValueExpr>, - PL: IntoIterator, + R: ArchReg, + O: Into>, + P: LiftableLowLevelIL<'a, Result = ValueExpr>, { use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_CALL_PARAM, LLIL_INTRINSIC}; use binaryninjacore_sys::{BNLowLevelILAddExpr, BNLowLevelILAddOperandList}; @@ -1427,8 +1388,6 @@ where let output_expr_idx = unsafe { BNLowLevelILAddOperandList(self.handle, outputs.as_mut_ptr(), outputs.len()) }; - let intrinsic: A::Intrinsic = intrinsic.into(); - let mut inputs: Vec = inputs .into_iter() .map(|input| { diff --git a/rust/src/low_level_il/operation.rs b/rust/src/low_level_il/operation.rs index b1bc8ef4..bd68bbb1 100644 --- a/rust/src/low_level_il/operation.rs +++ b/rust/src/low_level_il/operation.rs @@ -15,33 +15,34 @@ use binaryninjacore_sys::{BNGetLowLevelILByIndex, BNLowLevelILInstruction}; use super::*; -use crate::architecture::{FlagGroupId, FlagId, FlagWriteId, IntrinsicId, RegisterStackId}; +use crate::architecture::{ + CoreFlag, CoreFlagGroup, CoreFlagWrite, CoreIntrinsic, CoreRegister, CoreRegisterStack, + FlagGroupId, FlagId, FlagWriteId, IntrinsicId, RegisterStackId, +}; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; use std::mem; -pub struct Operation<'func, A, M, F, O> +pub struct Operation<'func, M, F, O> where - A: Architecture, M: FunctionMutability, F: FunctionForm, O: OperationArguments, { - pub(crate) function: &'func LowLevelILFunction, + pub(crate) function: &'func LowLevelILFunction, pub(crate) op: BNLowLevelILInstruction, _args: PhantomData, } -impl<'func, A, M, F, O> Operation<'func, A, M, F, O> +impl<'func, M, F, O> Operation<'func, M, F, O> where - A: Architecture, M: FunctionMutability, F: FunctionForm, O: OperationArguments, { pub(crate) fn new( - function: &'func LowLevelILFunction, + function: &'func LowLevelILFunction, op: BNLowLevelILInstruction, ) -> Self { Self { @@ -56,13 +57,12 @@ where } } -impl Operation<'_, A, M, NonSSA, O> +impl Operation<'_, M, NonSSA, O> where - A: Architecture, M: FunctionMutability, O: OperationArguments, { - pub fn flag_write(&self) -> Option { + pub fn flag_write(&self) -> Option { match self.op.flags { 0 => None, id => self.function.arch().flag_write_from_id(FlagWriteId(id)), @@ -73,9 +73,8 @@ where // LLIL_NOP, LLIL_NORET, LLIL_BP, LLIL_UNDEF, LLIL_UNIMPL pub struct NoArgs; -impl Debug for Operation<'_, A, M, F, NoArgs> +impl Debug for Operation<'_, M, F, NoArgs> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -87,9 +86,8 @@ where // LLIL_POP pub struct Pop; -impl Operation<'_, A, M, F, Pop> +impl Operation<'_, M, F, Pop> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -98,9 +96,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Pop> +impl Debug for Operation<'_, M, F, Pop> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -115,9 +112,8 @@ where // LLIL_SYSCALL, LLIL_SYSCALL_SSA pub struct Syscall; -impl Debug for Operation<'_, A, M, F, Syscall> +impl Debug for Operation<'_, M, F, Syscall> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -129,22 +125,20 @@ where // LLIL_INTRINSIC, LLIL_INTRINSIC_SSA pub struct Intrinsic; -impl Operation<'_, A, M, F, Intrinsic> +impl Operation<'_, M, F, Intrinsic> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { // TODO: Support register and expression lists - pub fn intrinsic(&self) -> Option { + pub fn intrinsic(&self) -> Option { let raw_id = self.op.operands[2] as u32; self.function.arch().intrinsic_from_id(IntrinsicId(raw_id)) } } -impl Debug for Operation<'_, A, M, F, Intrinsic> +impl Debug for Operation<'_, M, F, Intrinsic> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -159,9 +153,8 @@ where // LLIL_SET_REG, LLIL_SET_REG_SSA, LLIL_SET_REG_PARTIAL_SSA pub struct SetReg; -impl<'func, A, M, F> Operation<'func, A, M, F, SetReg> +impl<'func, M, F> Operation<'func, M, F, SetReg> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -169,28 +162,12 @@ where self.op.size } - pub fn dest_reg(&self) -> LowLevelILRegister { - let raw_id = self.op.operands[0] as u32; - - if raw_id >= 0x8000_0000 { - LowLevelILRegister::Temp(raw_id & 0x7fff_ffff) - } else { - self.function - .arch() - .register_from_id(RegisterId(raw_id)) - .map(LowLevelILRegister::ArchReg) - .unwrap_or_else(|| { - log::error!( - "got garbage register from LLIL_SET_REG @ 0x{:x}", - self.op.address - ); - - LowLevelILRegister::Temp(0) - }) - } + pub fn dest_reg(&self) -> LowLevelILRegisterKind { + let raw_id = RegisterId(self.op.operands[0] as u32); + LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } - pub fn source_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -198,9 +175,8 @@ where } } -impl Debug for Operation<'_, A, M, F, SetReg> +impl Debug for Operation<'_, M, F, SetReg> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -217,9 +193,8 @@ where // LLIL_SET_REG_SPLIT, LLIL_SET_REG_SPLIT_SSA pub struct SetRegSplit; -impl<'func, A, M, F> Operation<'func, A, M, F, SetRegSplit> +impl<'func, M, F> Operation<'func, M, F, SetRegSplit> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -227,49 +202,17 @@ where self.op.size } - pub fn dest_reg_high(&self) -> LowLevelILRegister { - let raw_id = self.op.operands[0] as u32; - - if raw_id >= 0x8000_0000 { - LowLevelILRegister::Temp(raw_id & 0x7fff_ffff) - } else { - self.function - .arch() - .register_from_id(RegisterId(raw_id)) - .map(LowLevelILRegister::ArchReg) - .unwrap_or_else(|| { - log::error!( - "got garbage register from LLIL_SET_REG_SPLIT @ 0x{:x}", - self.op.address - ); - - LowLevelILRegister::Temp(0) - }) - } + pub fn dest_reg_high(&self) -> LowLevelILRegisterKind { + let raw_id = RegisterId(self.op.operands[0] as u32); + LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } - pub fn dest_reg_low(&self) -> LowLevelILRegister { - let raw_id = self.op.operands[1] as u32; - - if raw_id >= 0x8000_0000 { - LowLevelILRegister::Temp(raw_id & 0x7fff_ffff) - } else { - self.function - .arch() - .register_from_id(RegisterId(raw_id)) - .map(LowLevelILRegister::ArchReg) - .unwrap_or_else(|| { - log::error!( - "got garbage register from LLIL_SET_REG_SPLIT @ 0x{:x}", - self.op.address - ); - - LowLevelILRegister::Temp(0) - }) - } + pub fn dest_reg_low(&self) -> LowLevelILRegisterKind { + let raw_id = RegisterId(self.op.operands[1] as u32); + LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } - pub fn source_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[2] as usize), @@ -277,9 +220,8 @@ where } } -impl Debug for Operation<'_, A, M, F, SetRegSplit> +impl Debug for Operation<'_, M, F, SetRegSplit> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -297,13 +239,12 @@ where // LLIL_SET_FLAG, LLIL_SET_FLAG_SSA pub struct SetFlag; -impl<'func, A, M, F> Operation<'func, A, M, F, SetFlag> +impl<'func, M, F> Operation<'func, M, F, SetFlag> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn dest_flag(&self) -> A::Flag { + pub fn dest_flag(&self) -> CoreFlag { // TODO: Error handling? // TODO: Test this. self.function @@ -312,7 +253,7 @@ where .unwrap() } - pub fn source_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -320,9 +261,8 @@ where } } -impl Debug for Operation<'_, A, M, F, SetFlag> +impl Debug for Operation<'_, M, F, SetFlag> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -338,9 +278,8 @@ where // LLIL_LOAD, LLIL_LOAD_SSA pub struct Load; -impl<'func, A, M, F> Operation<'func, A, M, F, Load> +impl<'func, M, F> Operation<'func, M, F, Load> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -348,7 +287,7 @@ where self.op.size } - pub fn source_mem_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn source_mem_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -356,9 +295,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Load> +impl Debug for Operation<'_, M, F, Load> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -374,9 +312,8 @@ where // LLIL_STORE, LLIL_STORE_SSA pub struct Store; -impl<'func, A, M, F> Operation<'func, A, M, F, Store> +impl<'func, M, F> Operation<'func, M, F, Store> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -384,14 +321,14 @@ where self.op.size } - pub fn dest_mem_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn dest_mem_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), ) } - pub fn source_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -399,9 +336,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Store> +impl Debug for Operation<'_, M, F, Store> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -415,12 +351,11 @@ where } } -// LLIL_REG, LLIL_REG_SSA, LLIL_REG_SSA_PARTIAL +// LLIL_REG, LLIL_REG_SSLLIL_REG_SSA_PARTIAL pub struct Reg; -impl Operation<'_, A, M, F, Reg> +impl Operation<'_, M, F, Reg> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -428,31 +363,14 @@ where self.op.size } - pub fn source_reg(&self) -> LowLevelILRegister { - let raw_id = self.op.operands[0] as u32; - - if raw_id >= 0x8000_0000 { - LowLevelILRegister::Temp(raw_id & 0x7fff_ffff) - } else { - self.function - .arch() - .register_from_id(RegisterId(raw_id)) - .map(LowLevelILRegister::ArchReg) - .unwrap_or_else(|| { - log::error!( - "got garbage register from LLIL_REG @ 0x{:x}", - self.op.address - ); - - LowLevelILRegister::Temp(0) - }) - } + pub fn source_reg(&self) -> LowLevelILRegisterKind { + let raw_id = RegisterId(self.op.operands[0] as u32); + LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } } -impl Debug for Operation<'_, A, M, F, Reg> +impl Debug for Operation<'_, M, F, Reg> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -468,9 +386,8 @@ where // LLIL_REG_SPLIT, LLIL_REG_SPLIT_SSA pub struct RegSplit; -impl Operation<'_, A, M, F, RegSplit> +impl Operation<'_, M, F, RegSplit> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -478,52 +395,19 @@ where self.op.size } - pub fn low_reg(&self) -> LowLevelILRegister { - let raw_id = self.op.operands[0] as u32; - - if raw_id >= 0x8000_0000 { - LowLevelILRegister::Temp(raw_id & 0x7fff_ffff) - } else { - self.function - .arch() - .register_from_id(RegisterId(raw_id)) - .map(LowLevelILRegister::ArchReg) - .unwrap_or_else(|| { - log::error!( - "got garbage register from LLIL_REG @ 0x{:x}", - self.op.address - ); - - LowLevelILRegister::Temp(0) - }) - } + pub fn low_reg(&self) -> LowLevelILRegisterKind { + let raw_id = RegisterId(self.op.operands[0] as u32); + LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } - pub fn high_reg(&self) -> LowLevelILRegister { - let raw_id = self.op.operands[1] as u32; - - if raw_id >= 0x8000_0000 { - LowLevelILRegister::Temp(raw_id & 0x7fff_ffff) - } else { - self.function - .arch() - .register_from_id(RegisterId(raw_id)) - .map(LowLevelILRegister::ArchReg) - .unwrap_or_else(|| { - log::error!( - "got garbage register from LLIL_REG @ 0x{:x}", - self.op.address - ); - - LowLevelILRegister::Temp(0) - }) - } + pub fn high_reg(&self) -> LowLevelILRegisterKind { + let raw_id = RegisterId(self.op.operands[1] as u32); + LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID") } } -impl Debug for Operation<'_, A, M, F, RegSplit> +impl Debug for Operation<'_, M, F, RegSplit> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -540,9 +424,8 @@ where // LLIL_REG_STACK_PUSH pub struct RegStackPush; -impl<'func, A, M, F> Operation<'func, A, M, F, RegStackPush> +impl<'func, M, F> Operation<'func, M, F, RegStackPush> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -550,7 +433,7 @@ where self.op.size } - pub fn dest_reg_stack(&self) -> A::RegisterStack { + pub fn dest_reg_stack(&self) -> CoreRegisterStack { let raw_id = self.op.operands[0] as u32; self.function .arch() @@ -558,7 +441,7 @@ where .expect("Bad register stack ID") } - pub fn source_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -566,9 +449,8 @@ where } } -impl Debug for Operation<'_, A, M, F, RegStackPush> +impl Debug for Operation<'_, M, F, RegStackPush> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -585,9 +467,8 @@ where // LLIL_REG_STACK_POP pub struct RegStackPop; -impl Operation<'_, A, M, F, RegStackPop> +impl Operation<'_, M, F, RegStackPop> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -595,7 +476,7 @@ where self.op.size } - pub fn source_reg_stack(&self) -> A::RegisterStack { + pub fn source_reg_stack(&self) -> CoreRegisterStack { let raw_id = self.op.operands[0] as u32; self.function .arch() @@ -604,9 +485,8 @@ where } } -impl Debug for Operation<'_, A, M, F, RegStackPop> +impl Debug for Operation<'_, M, F, RegStackPop> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -622,9 +502,8 @@ where // LLIL_FLAG, LLIL_FLAG_SSA pub struct Flag; -impl Debug for Operation<'_, A, M, F, Flag> +impl Debug for Operation<'_, M, F, Flag> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -636,9 +515,8 @@ where // LLIL_FLAG_BIT, LLIL_FLAG_BIT_SSA pub struct FlagBit; -impl Debug for Operation<'_, A, M, F, FlagBit> +impl Debug for Operation<'_, M, F, FlagBit> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -650,13 +528,12 @@ where // LLIL_JUMP pub struct Jump; -impl<'func, A, M, F> Operation<'func, A, M, F, Jump> +impl<'func, M, F> Operation<'func, M, F, Jump> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn target(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -664,9 +541,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Jump> +impl Debug for Operation<'_, M, F, Jump> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -680,20 +556,18 @@ where // LLIL_JUMP_TO pub struct JumpTo; -struct TargetListIter<'func, A, M, F> +struct TargetListIter<'func, M, F> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - function: &'func LowLevelILFunction, + function: &'func LowLevelILFunction, cursor: BNLowLevelILInstruction, cursor_operand: usize, } -impl TargetListIter<'_, A, M, F> +impl TargetListIter<'_, M, F> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -710,13 +584,12 @@ where } } -impl<'func, A, M, F> Operation<'func, A, M, F, JumpTo> +impl<'func, M, F> Operation<'func, M, F, JumpTo> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn target(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -744,9 +617,8 @@ where } } -impl Debug for Operation<'_, A, M, F, JumpTo> +impl Debug for Operation<'_, M, F, JumpTo> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -761,13 +633,12 @@ where // LLIL_CALL, LLIL_CALL_SSA pub struct Call; -impl<'func, A, M, F> Operation<'func, A, M, F, Call> +impl<'func, M, F> Operation<'func, M, F, Call> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn target(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -785,9 +656,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Call> +impl Debug for Operation<'_, M, F, Call> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -802,13 +672,12 @@ where // LLIL_RET pub struct Ret; -impl<'func, A, M, F> Operation<'func, A, M, F, Ret> +impl<'func, M, F> Operation<'func, M, F, Ret> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn target(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -816,9 +685,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Ret> +impl Debug for Operation<'_, M, F, Ret> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -832,27 +700,26 @@ where // LLIL_IF pub struct If; -impl<'func, A, M, F> Operation<'func, A, M, F, If> +impl<'func, M, F> Operation<'func, M, F, If> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn condition(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn condition(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), ) } - pub fn true_target(&self) -> LowLevelILInstruction<'func, A, M, F> { + pub fn true_target(&self) -> LowLevelILInstruction<'func, M, F> { LowLevelILInstruction::new( self.function, LowLevelInstructionIndex(self.op.operands[1] as usize), ) } - pub fn false_target(&self) -> LowLevelILInstruction<'func, A, M, F> { + pub fn false_target(&self) -> LowLevelILInstruction<'func, M, F> { LowLevelILInstruction::new( self.function, LowLevelInstructionIndex(self.op.operands[2] as usize), @@ -860,9 +727,8 @@ where } } -impl Debug for Operation<'_, A, M, F, If> +impl Debug for Operation<'_, M, F, If> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -878,13 +744,12 @@ where // LLIL_GOTO pub struct Goto; -impl<'func, A, M, F> Operation<'func, A, M, F, Goto> +impl<'func, M, F> Operation<'func, M, F, Goto> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { - pub fn target(&self) -> LowLevelILInstruction<'func, A, M, F> { + pub fn target(&self) -> LowLevelILInstruction<'func, M, F> { LowLevelILInstruction::new( self.function, LowLevelInstructionIndex(self.op.operands[0] as usize), @@ -892,9 +757,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Goto> +impl Debug for Operation<'_, M, F, Goto> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -909,9 +773,8 @@ where // Valid only in Lifted IL pub struct FlagCond; -impl Debug for Operation<'_, A, M, F, FlagCond> +impl Debug for Operation<'_, M, F, FlagCond> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -924,12 +787,11 @@ where // Valid only in Lifted IL pub struct FlagGroup; -impl Operation<'_, A, M, NonSSA, FlagGroup> +impl Operation<'_, M, NonSSA, FlagGroup> where - A: Architecture, M: FunctionMutability, { - pub fn flag_group(&self) -> A::FlagGroup { + pub fn flag_group(&self) -> CoreFlagGroup { let id = self.op.operands[0] as u32; self.function .arch() @@ -938,9 +800,8 @@ where } } -impl Debug for Operation<'_, A, M, NonSSA, FlagGroup> +impl Debug for Operation<'_, M, NonSSA, FlagGroup> where - A: Architecture, M: FunctionMutability, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -950,9 +811,8 @@ where } } -impl Debug for Operation<'_, A, M, SSA, FlagGroup> +impl Debug for Operation<'_, M, SSA, FlagGroup> where - A: Architecture, M: FunctionMutability, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -963,9 +823,8 @@ where // LLIL_TRAP pub struct Trap; -impl Operation<'_, A, M, F, Trap> +impl Operation<'_, M, F, Trap> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -974,9 +833,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Trap> +impl Debug for Operation<'_, M, F, Trap> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -990,9 +848,8 @@ where // LLIL_REG_PHI pub struct RegPhi; -impl Debug for Operation<'_, A, M, F, RegPhi> +impl Debug for Operation<'_, M, F, RegPhi> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1004,9 +861,8 @@ where // LLIL_FLAG_PHI pub struct FlagPhi; -impl Debug for Operation<'_, A, M, F, FlagPhi> +impl Debug for Operation<'_, M, F, FlagPhi> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1018,9 +874,8 @@ where // LLIL_MEM_PHI pub struct MemPhi; -impl Debug for Operation<'_, A, M, F, MemPhi> +impl Debug for Operation<'_, M, F, MemPhi> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1032,9 +887,8 @@ where // LLIL_CONST, LLIL_CONST_PTR pub struct Const; -impl Operation<'_, A, M, F, Const> +impl Operation<'_, M, F, Const> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1073,9 +927,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Const> +impl Debug for Operation<'_, M, F, Const> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1090,9 +943,8 @@ where // LLIL_EXTERN_PTR pub struct Extern; -impl Operation<'_, A, M, F, Extern> +impl Operation<'_, M, F, Extern> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1131,9 +983,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Extern> +impl Debug for Operation<'_, M, F, Extern> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1152,9 +1003,8 @@ where // LLIL_MODS pub struct BinaryOp; -impl<'func, A, M, F> Operation<'func, A, M, F, BinaryOp> +impl<'func, M, F> Operation<'func, M, F, BinaryOp> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1162,14 +1012,14 @@ where self.op.size } - pub fn left(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), ) } - pub fn right(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -1177,9 +1027,8 @@ where } } -impl Debug for Operation<'_, A, M, F, BinaryOp> +impl Debug for Operation<'_, M, F, BinaryOp> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1195,9 +1044,8 @@ where // LLIL_ADC, LLIL_SBB, LLIL_RLC, LLIL_RRC pub struct BinaryOpCarry; -impl<'func, A, M, F> Operation<'func, A, M, F, BinaryOpCarry> +impl<'func, M, F> Operation<'func, M, F, BinaryOpCarry> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1205,21 +1053,21 @@ where self.op.size } - pub fn left(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), ) } - pub fn right(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), ) } - pub fn carry(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn carry(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[2] as usize), @@ -1227,9 +1075,8 @@ where } } -impl Debug for Operation<'_, A, M, F, BinaryOpCarry> +impl Debug for Operation<'_, M, F, BinaryOpCarry> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1246,9 +1093,8 @@ where // LLIL_DIVS_DP, LLIL_DIVU_DP, LLIL_MODU_DP, LLIL_MODS_DP pub struct DoublePrecDivOp; -impl<'func, A, M, F> Operation<'func, A, M, F, DoublePrecDivOp> +impl<'func, M, F> Operation<'func, M, F, DoublePrecDivOp> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1256,14 +1102,14 @@ where self.op.size } - pub fn high(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn high(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), ) } - pub fn low(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn low(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -1271,7 +1117,7 @@ where } // TODO: I don't think this actually exists? - pub fn right(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[2] as usize), @@ -1279,9 +1125,8 @@ where } } -impl Debug for Operation<'_, A, M, F, DoublePrecDivOp> +impl Debug for Operation<'_, M, F, DoublePrecDivOp> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1300,9 +1145,8 @@ where // LLIL_ZX, LLIL_LOW_PART, LLIL_BOOL_TO_INT, LLIL_UNIMPL_MEM pub struct UnaryOp; -impl<'func, A, M, F> Operation<'func, A, M, F, UnaryOp> +impl<'func, M, F> Operation<'func, M, F, UnaryOp> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1310,7 +1154,7 @@ where self.op.size } - pub fn operand(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn operand(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -1318,9 +1162,8 @@ where } } -impl Debug for Operation<'_, A, M, F, UnaryOp> +impl Debug for Operation<'_, M, F, UnaryOp> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1335,9 +1178,8 @@ where // LLIL_CMP_X pub struct Condition; -impl<'func, A, M, F> Operation<'func, A, M, F, Condition> +impl<'func, M, F> Operation<'func, M, F, Condition> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1345,14 +1187,14 @@ where self.op.size } - pub fn left(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), ) } - pub fn right(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[1] as usize), @@ -1360,9 +1202,8 @@ where } } -impl Debug for Operation<'_, A, M, F, Condition> +impl Debug for Operation<'_, M, F, Condition> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1378,9 +1219,8 @@ where // LLIL_UNIMPL_MEM pub struct UnimplMem; -impl<'func, A, M, F> Operation<'func, A, M, F, UnimplMem> +impl<'func, M, F> Operation<'func, M, F, UnimplMem> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { @@ -1388,7 +1228,7 @@ where self.op.size } - pub fn mem_expr(&self) -> LowLevelILExpression<'func, A, M, F, ValueExpr> { + pub fn mem_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> { LowLevelILExpression::new( self.function, LowLevelExpressionIndex(self.op.operands[0] as usize), @@ -1396,9 +1236,8 @@ where } } -impl Debug for Operation<'_, A, M, F, UnimplMem> +impl Debug for Operation<'_, M, F, UnimplMem> where - A: Architecture, M: FunctionMutability, F: FunctionForm, { diff --git a/rust/src/relocation.rs b/rust/src/relocation.rs index 8fa9a86b..f10115c8 100644 --- a/rust/src/relocation.rs +++ b/rust/src/relocation.rs @@ -83,7 +83,7 @@ impl From for usize { } // TODO: How to handle related relocation linked lists? -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct RelocationInfo { pub type_: RelocationType, pub pc_relative: bool, @@ -265,7 +265,7 @@ pub trait RelocationHandler: 'static + Sized + AsRef { _data: &[u8], _addr: u64, // TODO: Are we sure this is not a liftedilfunction? - _il: &RegularLowLevelILFunction, + _il: &RegularLowLevelILFunction, _reloc: &Relocation, ) -> RelocationOperand { RelocationOperand::AutocoerceExternPtr @@ -363,7 +363,7 @@ impl RelocationHandler for CoreRelocationHandler { &self, data: &[u8], addr: u64, - il: &RegularLowLevelILFunction, + il: &RegularLowLevelILFunction, reloc: &Relocation, ) -> RelocationOperand { unsafe { @@ -496,7 +496,7 @@ where return RelocationOperand::Invalid.into(); } let arch = unsafe { CoreArchitecture::from_raw(arch) }; - let il = unsafe { RegularLowLevelILFunction::from_raw(arch, il) }; + let il = unsafe { RegularLowLevelILFunction::from_raw_with_arch(il, Some(arch)) }; custom_handler .get_operand_for_external_relocation(data, addr, &il, &reloc) diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs index b9c67a5d..ca42ff68 100644 --- a/rust/src/workflow.rs +++ b/rust/src/workflow.rs @@ -1,8 +1,5 @@ use binaryninjacore_sys::*; -use std::ffi::{c_char, c_void}; -use std::ptr::NonNull; -use crate::architecture::CoreArchitecture; use crate::basic_block::BasicBlock; use crate::binary_view::BinaryView; use crate::flowgraph::FlowGraph; @@ -13,6 +10,8 @@ use crate::low_level_il::MutableLiftedILFunction; use crate::medium_level_il::MediumLevelILFunction; use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable}; use crate::string::{BnStrCompatible, BnString}; +use std::ffi::{c_char, c_void}; +use std::ptr::NonNull; #[repr(transparent)] /// The AnalysisContext struct is used to represent the current state of @@ -47,21 +46,17 @@ impl AnalysisContext { } /// [`LowLevelILFunction`] used to represent Low Level IL - pub unsafe fn lifted_il_function( - &self, - ) -> Option>> { + pub unsafe fn lifted_il_function(&self) -> Option> { let func = self.function(); let result = unsafe { BNGetFunctionLiftedIL(func.handle) }; - let arch = self.function().arch(); unsafe { Some(LowLevelILFunction::ref_from_raw( - arch, NonNull::new(result)?.as_ptr(), )) } } - pub fn set_lifted_il_function(&self, value: &MutableLiftedILFunction) { + pub fn set_lifted_il_function(&self, value: &MutableLiftedILFunction) { unsafe { BNSetLiftedILFunction(self.handle.as_ptr(), value.handle) } } @@ -70,12 +65,10 @@ impl AnalysisContext { /// [`LowLevelILFunction`] used to represent Low Level IL pub unsafe fn llil_function( &self, - ) -> Option>>> { + ) -> Option>>> { let result = unsafe { BNAnalysisContextGetLowLevelILFunction(self.handle.as_ptr()) }; - let arch = self.function().arch(); unsafe { Some(LowLevelILFunction::ref_from_raw( - arch, NonNull::new(result)?.as_ptr(), )) } @@ -85,7 +78,7 @@ impl AnalysisContext { // TODO: At some point we need to take the lifting code and make it available to regular IL. pub fn set_llil_function( &self, - value: &LowLevelILFunction>, + value: &LowLevelILFunction>, ) { unsafe { BNSetLowLevelILFunction(self.handle.as_ptr(), value.handle) } } diff --git a/rust/tests/low_level_il.rs b/rust/tests/low_level_il.rs index b9d7d203..88d915dc 100644 --- a/rust/tests/low_level_il.rs +++ b/rust/tests/low_level_il.rs @@ -7,7 +7,7 @@ use binaryninja::low_level_il::expression::{ use binaryninja::low_level_il::instruction::{ InstructionHandler, LowLevelILInstructionKind, LowLevelInstructionIndex, }; -use binaryninja::low_level_il::{LowLevelILRegister, VisitorAction}; +use binaryninja::low_level_il::{LowLevelILRegisterKind, VisitorAction}; use std::path::PathBuf; #[test] @@ -34,7 +34,7 @@ fn test_llil_info() { LowLevelILInstructionKind::SetReg(op) => { assert_eq!(op.size(), 4); match op.dest_reg() { - LowLevelILRegister::ArchReg(reg) => assert_eq!(reg.name(), "edi"), + LowLevelILRegisterKind::Arch(reg) => assert_eq!(reg.name(), "edi"), _ => panic!("Expected Register::ArchReg"), } assert_eq!(op.source_expr().index, LowLevelExpressionIndex(0)); @@ -55,7 +55,7 @@ fn test_llil_info() { LowLevelILExpressionKind::Reg(op) => { assert_eq!(op.size(), 4); match op.source_reg() { - LowLevelILRegister::ArchReg(reg) => assert_eq!(reg.name(), "ebp"), + LowLevelILRegisterKind::Arch(reg) => assert_eq!(reg.name(), "ebp"), _ => panic!("Expected Register::ArchReg"), } } @@ -73,7 +73,7 @@ fn test_llil_info() { LowLevelILInstructionKind::SetReg(op) => { assert_eq!(op.size(), 4); match op.dest_reg() { - LowLevelILRegister::ArchReg(reg) => assert_eq!(reg.name(), "ebp"), + LowLevelILRegisterKind::Arch(reg) => assert_eq!(reg.name(), "ebp"), _ => panic!("Expected Register::ArchReg"), } assert_eq!(op.source_expr().index, LowLevelExpressionIndex(4)); @@ -89,7 +89,7 @@ fn test_llil_info() { LowLevelILInstructionKind::SetReg(op) => { assert_eq!(op.size(), 4); match op.dest_reg() { - LowLevelILRegister::ArchReg(reg) => assert_eq!(reg.name(), "eax"), + LowLevelILRegisterKind::Arch(reg) => assert_eq!(reg.name(), "eax"), _ => panic!("Expected Register::ArchReg"), } assert_eq!(op.source_expr().index, LowLevelExpressionIndex(9)); @@ -128,7 +128,7 @@ fn test_llil_info() { LowLevelILInstructionKind::SetReg(op) => { assert_eq!(op.size(), 4); match op.dest_reg() { - LowLevelILRegister::ArchReg(reg) => assert_eq!(reg.name(), "esp"), + LowLevelILRegisterKind::Arch(reg) => assert_eq!(reg.name(), "esp"), _ => panic!("Expected Register::ArchReg"), } assert_eq!(op.source_expr().index, LowLevelExpressionIndex(17)); @@ -144,7 +144,7 @@ fn test_llil_info() { LowLevelILInstructionKind::SetReg(op) => { assert_eq!(op.size(), 4); match op.dest_reg() { - LowLevelILRegister::ArchReg(reg) => assert_eq!(reg.name(), "ebp"), + LowLevelILRegisterKind::Arch(reg) => assert_eq!(reg.name(), "ebp"), _ => panic!("Expected Register::ArchReg"), } assert_eq!(op.source_expr().index, LowLevelExpressionIndex(19)); -- cgit v1.3.1