diff options
Diffstat (limited to 'rust/src/architecture.rs')
| -rw-r--r-- | rust/src/architecture.rs | 146 |
1 files changed, 138 insertions, 8 deletions
diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 76e9ab91..3d081b9f 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -27,7 +27,7 @@ use crate::{ data_buffer::DataBuffer, disassembly::InstructionTextToken, ffi::INVALID_REGISTER, - function::Function, + function::{Function, Location, NativeBlock}, platform::Platform, rc::*, relocation::CoreRelocationHandler, @@ -35,6 +35,7 @@ use crate::{ types::{NameAndType, Type}, Endianness, }; +use std::collections::{HashMap, HashSet}; use std::ops::Deref; use std::{ borrow::Borrow, @@ -48,7 +49,9 @@ use std::ptr::NonNull; use crate::function_recognizer::FunctionRecognizer; use crate::relocation::{CustomRelocationHandlerHandle, RelocationHandler}; +use crate::basic_block::BasicBlock; use crate::confidence::Conf; +use crate::logger::Logger; use crate::low_level_il::expression::ValueExpr; use crate::low_level_il::lifting::{ get_default_flag_cond_llil, get_default_flag_write_llil, LowLevelILFlagWriteOp, @@ -592,13 +595,133 @@ pub trait ArchitectureWithFunctionContext: Architecture { pub struct FunctionLifterContext { pub(crate) handle: *mut BNFunctionLifterContext, + pub function: *mut BNLowLevelILFunction, + pub platform: Ref<Platform>, + pub logger: Ref<Logger>, + pub blocks: Vec<Ref<BasicBlock<NativeBlock>>>, + pub no_return_calls: HashSet<Location>, + pub contextual_returns: HashMap<Location, bool>, + pub inlined_remapping: HashMap<Location, Location>, + pub user_indirect_branches: HashMap<Location, HashSet<Location>>, + pub auto_indirect_branches: HashMap<Location, HashSet<Location>>, + //pub inlined_calls: HashSet<u64>, +} + +unsafe fn lifter_context_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] { + if len == 0 { + &[] + } else { + debug_assert!(!ptr.is_null()); + unsafe { std::slice::from_raw_parts(ptr, len) } + } } impl FunctionLifterContext { - pub unsafe fn from_raw(handle: *mut BNFunctionLifterContext) -> Self { + pub unsafe fn from_raw( + function: *mut BNLowLevelILFunction, + handle: *mut BNFunctionLifterContext, + ) -> Self { + debug_assert!(!function.is_null()); debug_assert!(!handle.is_null()); + let flc_ref = &*handle; + let platform = unsafe { Platform::ref_from_raw(BNNewPlatformReference(flc_ref.platform)) }; + let logger = unsafe { Logger::ref_from_raw(BNNewLoggerReference(flc_ref.logger)) }; + + let mut blocks = Vec::new(); + for i in 0..flc_ref.basicBlockCount { + let block = unsafe { + Some(BasicBlock::ref_from_raw( + BNNewBasicBlockReference(*flc_ref.basicBlocks.add(i)), + NativeBlock::new(), + )) + }; + + blocks.push(block.unwrap()); + } + + let raw_no_return_calls: &[BNArchitectureAndAddress] = + lifter_context_slice(flc_ref.noReturnCalls, flc_ref.noReturnCallsCount); + let no_return_calls: HashSet<Location> = + raw_no_return_calls.iter().map(Location::from).collect(); + + let raw_contextual_return_locs: &[BNArchitectureAndAddress] = unsafe { + lifter_context_slice( + flc_ref.contextualFunctionReturnLocations, + flc_ref.contextualFunctionReturnCount, + ) + }; + let raw_contextual_return_vals: &[bool] = unsafe { + lifter_context_slice( + flc_ref.contextualFunctionReturnValues, + flc_ref.contextualFunctionReturnCount, + ) + }; + let contextual_returns: HashMap<Location, bool> = raw_contextual_return_locs + .iter() + .map(Location::from) + .zip(raw_contextual_return_vals.iter().copied()) + .collect(); - FunctionLifterContext { handle } + let inlined_remapping: HashMap<Location, Location> = { + let raw_inline_remap_locs: &[BNArchitectureAndAddress] = lifter_context_slice( + flc_ref.inlinedRemappingKeys, + flc_ref.inlinedRemappingEntryCount, + ); + + let raw_inline_remap_dests: &[BNArchitectureAndAddress] = lifter_context_slice( + flc_ref.inlinedRemappingValues, + flc_ref.inlinedRemappingEntryCount, + ); + + raw_inline_remap_locs + .iter() + .map(Location::from) + .zip(raw_inline_remap_dests.iter().map(Location::from)) + .collect() + }; + + let mut user_indirect_branches: HashMap<Location, HashSet<Location>> = HashMap::new(); + let mut auto_indirect_branches: HashMap<Location, HashSet<Location>> = HashMap::new(); + for i in 0..flc_ref.indirectBranchesCount { + let entry = unsafe { *flc_ref.indirectBranches.add(i) }; + let src = Location::new( + Some(CoreArchitecture::from_raw(entry.sourceArch)), + entry.sourceAddr, + ); + let dest = Location::new( + Some(CoreArchitecture::from_raw(entry.destArch)), + entry.destAddr, + ); + if entry.autoDefined { + auto_indirect_branches.entry(src).or_default().insert(dest); + } else { + user_indirect_branches.entry(src).or_default().insert(dest); + } + } + + FunctionLifterContext { + handle, + function: BNNewLowLevelILFunctionReference(function), + platform, + logger, + blocks, + no_return_calls, + contextual_returns, + inlined_remapping, + user_indirect_branches, + auto_indirect_branches, + } + } + + pub fn prepare_block_translation( + &self, + func: &LowLevelILMutableFunction, + arch: &CoreArchitecture, + address: u64, + ) { + unsafe { + BNPrepareBlockTranslation(func.handle, arch.handle, address); + } } pub fn get_function_arch_context<A: ArchitectureWithFunctionContext>( @@ -616,6 +739,14 @@ impl FunctionLifterContext { } } +impl Drop for FunctionLifterContext { + fn drop(&mut self) { + if !self.function.is_null() { + unsafe { BNFreeLowLevelILFunction(self.function) }; + } + } +} + // TODO: WTF?!?!?!? pub struct CoreArchitectureList(*mut *mut BNArchitecture, usize); @@ -1630,12 +1761,12 @@ where A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync, { let custom_arch = unsafe { &*(ctxt as *mut A) }; - let function = unsafe { + let llil = unsafe { LowLevelILMutableFunction::from_raw_with_arch(function, Some(*custom_arch.as_ref())) }; - let mut context: FunctionLifterContext = - unsafe { FunctionLifterContext::from_raw(context) }; - custom_arch.lift_function(function, &mut context) + + let mut ctx = unsafe { FunctionLifterContext::from_raw(function, context) }; + custom_arch.lift_function(llil, &mut ctx) } extern "C" fn cb_reg_name<A>(ctxt: *mut c_void, reg: u32) -> *mut c_char @@ -2630,7 +2761,6 @@ where unsafe { let res = BNRegisterArchitecture(name.as_ptr(), &mut custom_arch as *mut _); - assert!(!res.is_null()); (*raw).arch.assume_init_mut() |
