diff --git a/fugue-core/src/arch/aarch64.rs b/fugue-core/src/arch/aarch64.rs index 7cd5423..770c52d 100644 --- a/fugue-core/src/arch/aarch64.rs +++ b/fugue-core/src/arch/aarch64.rs @@ -27,7 +27,7 @@ impl AArch64InsnLifter { Self { decoder } } - pub fn boxed<'a>(self) -> Box> { + pub fn boxed(self) -> Box { Box::new(self) } } @@ -39,14 +39,14 @@ fn should_lift(insn: &AArch64Instruction) -> bool { } } -impl<'a> InsnLifter<'a> for AArch64InsnLifter { - fn properties<'b>( +impl InsnLifter for AArch64InsnLifter { + fn properties<'input, 'lifter>( &mut self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, + irb: &'lifter IRBuilderArena, address: Address, - bytes: &'b [u8], - ) -> Result, LifterError> { + bytes: &'input [u8], + ) -> Result, LifterError> { let mut reader = yaxpeax_arch::U8Reader::new(bytes); let insn = self .decoder diff --git a/fugue-core/src/arch/arm.rs b/fugue-core/src/arch/arm.rs index 6f2b387..e4a5e24 100644 --- a/fugue-core/src/arch/arm.rs +++ b/fugue-core/src/arch/arm.rs @@ -26,7 +26,7 @@ impl ARMInsnLifter { Self { decoder } } - pub fn boxed<'a>(self) -> Box> { + pub fn boxed(self) -> Box { Box::new(self) } } @@ -47,14 +47,14 @@ fn should_lift(insn: &ARMInstruction) -> bool { } } -impl<'a> InsnLifter<'a> for ARMInsnLifter { - fn properties<'b>( +impl InsnLifter for ARMInsnLifter { + fn properties<'input, 'lifter>( &mut self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, + irb: &'lifter IRBuilderArena, address: Address, - bytes: &'b [u8], - ) -> Result, LifterError> { + bytes: &'input [u8], + ) -> Result, LifterError> { let mut reader = yaxpeax_arch::U8Reader::new(bytes); let insn = self .decoder diff --git a/fugue-core/src/arch/x86.rs b/fugue-core/src/arch/x86.rs index 972ae97..db24da0 100644 --- a/fugue-core/src/arch/x86.rs +++ b/fugue-core/src/arch/x86.rs @@ -103,17 +103,21 @@ where Self::new_with(D::Decoder::default()) } + pub fn new_with(decoder: D::Decoder) -> Self { + Self { decoder } + } +} + +impl X86InsnLifter { pub fn new_32() -> X86InsnLifter { X86InsnLifter::new_with(X86_32InstDecoder::default()) } +} +impl X86InsnLifter { pub fn new_64() -> X86InsnLifter { X86InsnLifter::new_with(X86_64InstDecoder::default()) } - - pub fn new_with(decoder: D::Decoder) -> Self { - Self { decoder } - } } impl X86InsnLifter @@ -124,26 +128,26 @@ where <::Diff as TryInto>::Error: std::error::Error + Send + Sync + 'static, { - pub fn boxed<'a>(self) -> Box> { + pub fn boxed(self) -> Box { Box::new(self) } } -impl<'a, D> InsnLifter<'a> for X86InsnLifter +impl InsnLifter for X86InsnLifter where D: X86Arch, - for<'b> U8Reader<'b>: Reader, + for<'input> U8Reader<'input>: Reader, ::Diff: TryInto, <::Diff as TryInto>::Error: std::error::Error + Send + Sync + 'static, { - fn properties<'b>( + fn properties<'input, 'lifter>( &mut self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, + irb: &'lifter IRBuilderArena, address: Address, - bytes: &'b [u8], - ) -> Result, LifterError> { + bytes: &'input [u8], + ) -> Result, LifterError> { let mut reader = yaxpeax_arch::U8Reader::new(bytes); let insn = self diff --git a/fugue-core/src/icfg/mod.rs b/fugue-core/src/icfg/mod.rs index d72dc44..0fb76a0 100644 --- a/fugue-core/src/icfg/mod.rs +++ b/fugue-core/src/icfg/mod.rs @@ -40,10 +40,7 @@ mod test { use fugue_ir::Address; use yaxpeax_arch::*; - - use yaxpeax_arm::armv7::DecodeError as ARMDecoderError; use yaxpeax_arm::armv7::InstDecoder as ARMInstDecoder; - use yaxpeax_arm::armv7::Instruction as ARMInstruction; use crate::language::LanguageBuilder; use crate::lifter::*; @@ -76,18 +73,16 @@ mod test { } } - impl<'a> InsnLifter<'a, ARMInstruction> for ARMInsnLifter { - type Error = ARMDecoderError; - - fn properties<'b>( + impl InsnLifter for ARMInsnLifter { + fn properties<'a, 'b>( &mut self, _lifter: &mut Lifter, - _irb: &'a IRBuilderArena, + _irb: &'b IRBuilderArena, address: Address, - bytes: &'b [u8], - ) -> Result, Self::Error> { + bytes: &'a [u8], + ) -> Result, LifterError> { let mut reader = yaxpeax_arch::U8Reader::new(bytes); - let insn = self.0.decode(&mut reader)?; + let insn = self.0.decode(&mut reader).map_err(LifterError::decode)?; let size = insn.len().to_const() as u8; Ok(LiftedInsn { @@ -97,7 +92,6 @@ mod test { operations: RefCell::new(None), delay_slots: 0, length: size, - data: insn, }) } } @@ -107,9 +101,6 @@ mod test { while off < memory.len() { let lifted = plifter.properties(&mut lifter, &irb, address + off, &memory[off..])?; - println!("--- insn @ {} ---", lifted.address()); - println!("{}", lifted.data()); - println!("--- pcode @ {} ---", lifted.address()); for (i, op) in lifted.pcode(&mut lifter, &irb)?.iter().enumerate() { println!("{i:02} {}", op.display(language.translator())); diff --git a/fugue-core/src/lifter.rs b/fugue-core/src/lifter.rs index 435ad5e..6201407 100644 --- a/fugue-core/src/lifter.rs +++ b/fugue-core/src/lifter.rs @@ -1,8 +1,7 @@ use std::cell::{Cell, Ref, RefCell}; use fugue_ir::disassembly::lift::ArenaVec; -use fugue_ir::disassembly::PCodeRaw; -use fugue_ir::disassembly::{ContextDatabase, IRBuilderArena, PCodeData}; +use fugue_ir::disassembly::{ContextDatabase, IRBuilderArena, PCodeData, PCodeRaw}; use fugue_ir::error::Error; use fugue_ir::il::instruction::Instruction; use fugue_ir::translator::TranslationContext; @@ -10,6 +9,9 @@ use fugue_ir::{Address, Translator}; use thiserror::Error; +use crate::arch::aarch64::AArch64InsnLifter; +use crate::arch::arm::ARMInsnLifter; +use crate::arch::x86::X86InsnLifter; use crate::ir::{Insn, PCode}; #[derive(Debug, Error)] @@ -117,6 +119,18 @@ impl<'a> Lifter<'a> { }) } + pub fn lifter_for_arch(&self) -> Box { + let arch = self.translator().architecture(); + + match (arch.processor(), arch.bits()) { + ("AARCH64", 64) => AArch64InsnLifter::new().boxed(), + ("ARM", 32) => ARMInsnLifter::new().boxed(), + ("x86", 64) => X86InsnLifter::new_64().boxed(), + ("x86", 32) => X86InsnLifter::new_32().boxed(), + _ => DefaultInsnLifter::new().boxed(), + } + } + pub fn translator(&self) -> &Translator { self.0.translator() } @@ -177,16 +191,16 @@ bitflags::bitflags! { } } -pub struct LiftedInsn<'a, 'b> { +pub struct LiftedInsn<'input, 'lifter> { pub address: Address, - pub bytes: &'b [u8], + pub bytes: &'input [u8], pub properties: Cell, - pub operations: RefCell>>>, + pub operations: RefCell>>>, pub delay_slots: u8, pub length: u8, } -impl<'a, 'b> LiftedInsn<'a, 'b> { +impl<'input, 'lifter> LiftedInsn<'input, 'lifter> { pub fn address(&self) -> Address { self.address } @@ -206,8 +220,8 @@ impl<'a, 'b> LiftedInsn<'a, 'b> { pub fn pcode( &self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, - ) -> Result>>, Error> { + irb: &'lifter IRBuilderArena, + ) -> Result>>, Error> { if let Some(operations) = self.try_pcode() { return Ok(operations); } @@ -218,15 +232,15 @@ impl<'a, 'b> LiftedInsn<'a, 'b> { self.pcode(lifter, irb) } - pub fn try_pcode(&self) -> Option>>> { + pub fn try_pcode(&self) -> Option>>> { Ref::filter_map(self.operations.borrow(), |v| v.as_ref()).ok() } pub fn into_pcode( self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, - ) -> Result, Error> { + irb: &'lifter IRBuilderArena, + ) -> Result, Error> { if let Some(operations) = self.operations.into_inner() { return Ok(PCode { address: self.address, @@ -240,14 +254,14 @@ impl<'a, 'b> LiftedInsn<'a, 'b> { } } -pub trait InsnLifter<'a> { - fn properties<'b>( +pub trait InsnLifter { + fn properties<'input, 'lifter>( &mut self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, + irb: &'lifter IRBuilderArena, address: Address, - bytes: &'b [u8], - ) -> Result, LifterError>; + bytes: &'input [u8], + ) -> Result, LifterError>; } #[derive(Debug, Clone, Copy, Default)] @@ -257,22 +271,28 @@ impl DefaultInsnLifter { pub fn new() -> Self { Self::default() } + + pub fn boxed(self) -> Box { + Box::new(self) + } } -impl<'a> InsnLifter<'a> for DefaultInsnLifter { - fn properties<'b>( +impl InsnLifter for DefaultInsnLifter { + fn properties<'input, 'lifter>( &mut self, lifter: &mut Lifter, - irb: &'a IRBuilderArena, + irb: &'lifter IRBuilderArena, address: Address, - bytes: &'b [u8], - ) -> Result, LifterError> { + bytes: &'input [u8], + ) -> Result, LifterError> { let PCode { address, operations, delay_slots, length, - } = lifter.lift(irb, address, bytes).map_err(LifterError::lift)?; + } = lifter + .lift(irb, address, bytes) + .map_err(LifterError::lift)?; Ok(LiftedInsn { address,