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 --- rust/src/low_level_il.rs | 129 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 29 deletions(-) (limited to 'rust/src/low_level_il.rs') 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 { -- cgit v1.3.1