@@ -23,14 +23,13 @@ use crate::{
2323 calling_convention:: CoreCallingConvention ,
2424 data_buffer:: DataBuffer ,
2525 disassembly:: InstructionTextToken ,
26- function:: Function ,
26+ function:: { ArchAndAddr , Function , NativeBlock } ,
2727 platform:: Platform ,
2828 rc:: * ,
2929 relocation:: CoreRelocationHandler ,
30- string:: IntoCStr ,
31- string:: * ,
30+ string:: { IntoCStr , * } ,
3231 types:: { NameAndType , Type } ,
33- Endianness ,
32+ BranchType , Endianness ,
3433} ;
3534use std:: ops:: Deref ;
3635use std:: {
@@ -42,8 +41,10 @@ use std::{
4241 mem:: MaybeUninit ,
4342} ;
4443
44+ use crate :: basic_block:: BasicBlock ;
4545use crate :: function_recognizer:: FunctionRecognizer ;
4646use crate :: relocation:: { CustomRelocationHandlerHandle , RelocationHandler } ;
47+ use crate :: variable:: IndirectBranchInfo ;
4748
4849use crate :: confidence:: Conf ;
4950use crate :: low_level_il:: expression:: ValueExpr ;
@@ -54,6 +55,7 @@ use crate::low_level_il::{LowLevelILMutableExpression, LowLevelILMutableFunction
5455pub use binaryninjacore_sys:: BNFlagRole as FlagRole ;
5556pub use binaryninjacore_sys:: BNImplicitRegisterExtend as ImplicitRegisterExtend ;
5657pub use binaryninjacore_sys:: BNLowLevelILFlagCondition as FlagCondition ;
58+ use std:: collections:: HashSet ;
5759
5860macro_rules! newtype {
5961 ( $name: ident, $inner_type: ty) => {
@@ -171,6 +173,23 @@ impl From<BranchKind> for BranchInfo {
171173 }
172174}
173175
176+ impl From < BranchKind > for BranchType {
177+ fn from ( value : BranchKind ) -> Self {
178+ match value {
179+ BranchKind :: Unresolved => BranchType :: UnresolvedBranch ,
180+ BranchKind :: Unconditional ( _) => BranchType :: UnconditionalBranch ,
181+ BranchKind :: True ( _) => BranchType :: TrueBranch ,
182+ BranchKind :: False ( _) => BranchType :: FalseBranch ,
183+ BranchKind :: Call ( _) => BranchType :: CallDestination ,
184+ BranchKind :: FunctionReturn => BranchType :: FunctionReturn ,
185+ BranchKind :: SystemCall => BranchType :: SystemCall ,
186+ BranchKind :: Indirect => BranchType :: IndirectBranch ,
187+ BranchKind :: Exception => BranchType :: ExceptionBranch ,
188+ BranchKind :: UserDefined => BranchType :: UserDefinedBranch ,
189+ }
190+ }
191+ }
192+
174193/// This is the number of branches that can be specified in an [`InstructionInfo`].
175194pub const NUM_BRANCH_INFO : usize = 3 ;
176195
@@ -471,13 +490,13 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
471490 il : & LowLevelILMutableFunction ,
472491 ) -> Option < ( usize , bool ) > ;
473492
474- unsafe fn analyze_basic_blocks (
493+ fn analyze_basic_blocks (
475494 & self ,
476495 function : & mut Function ,
477- context : * mut BNBasicBlockAnalysisContext ,
496+ context : & mut BasicBlockAnalysisContext ,
478497 ) {
479498 unsafe {
480- BNArchitectureDefaultAnalyzeBasicBlocks ( function. handle , context) ;
499+ BNArchitectureDefaultAnalyzeBasicBlocks ( function. handle , context. handle ) ;
481500 }
482501 }
483502
@@ -1544,13 +1563,13 @@ impl Architecture for CoreArchitecture {
15441563 }
15451564 }
15461565
1547- unsafe fn analyze_basic_blocks (
1566+ fn analyze_basic_blocks (
15481567 & self ,
15491568 function : & mut Function ,
1550- context : * mut BNBasicBlockAnalysisContext ,
1569+ context : & mut BasicBlockAnalysisContext ,
15511570 ) {
15521571 unsafe {
1553- BNArchitectureAnalyzeBasicBlocks ( self . handle , function. handle , context) ;
1572+ BNArchitectureAnalyzeBasicBlocks ( self . handle , function. handle , context. handle ) ;
15541573 }
15551574 }
15561575
@@ -1922,6 +1941,222 @@ impl Architecture for CoreArchitecture {
19221941 }
19231942}
19241943
1944+ pub struct BasicBlockAnalysisContext {
1945+ pub ( crate ) handle : * mut BNBasicBlockAnalysisContext ,
1946+ contextual_returns_dirty : bool ,
1947+
1948+ // In
1949+ pub indirect_branches : Vec < IndirectBranchInfo > ,
1950+ pub indirect_no_return_calls : HashSet < ArchAndAddr > ,
1951+ pub analysis_skip_override : BNFunctionAnalysisSkipOverride ,
1952+ pub translate_tail_calls : bool ,
1953+ pub disallow_branch_to_string : bool ,
1954+ pub max_function_size : u64 ,
1955+ pub halt_on_invalid_instruction : bool ,
1956+ pub max_size_reached : bool ,
1957+
1958+ // In/Out
1959+ contextual_returns : HashMap < ArchAndAddr , bool > ,
1960+
1961+ // Out
1962+ direct_code_references : HashMap < u64 , ArchAndAddr > ,
1963+ direct_no_return_calls : HashSet < ArchAndAddr > ,
1964+ halted_disassembly_addresses : HashSet < ArchAndAddr > ,
1965+ }
1966+
1967+ impl BasicBlockAnalysisContext {
1968+ pub unsafe fn from_raw ( handle : * mut BNBasicBlockAnalysisContext ) -> Self {
1969+ debug_assert ! ( !handle. is_null( ) ) ;
1970+
1971+ let ctx_ref = & * handle;
1972+
1973+ let indirect_branches = ( 0 ..ctx_ref. indirectBranchesCount )
1974+ . map ( |i| {
1975+ let raw: BNIndirectBranchInfo =
1976+ unsafe { std:: ptr:: read ( ctx_ref. indirectBranches . add ( i) ) } ;
1977+ IndirectBranchInfo :: from ( raw)
1978+ } )
1979+ . collect :: < Vec < _ > > ( ) ;
1980+
1981+ let indirect_no_return_calls = ( 0 ..ctx_ref. indirectNoReturnCallsCount )
1982+ . map ( |i| {
1983+ let raw = unsafe { std:: ptr:: read ( ctx_ref. indirectNoReturnCalls . add ( i) ) } ;
1984+ ArchAndAddr :: from ( raw)
1985+ } )
1986+ . collect :: < HashSet < _ > > ( ) ;
1987+
1988+ let contextual_returns = ( 0 ..ctx_ref. contextualFunctionReturnCount )
1989+ . map ( |i| {
1990+ let loc = unsafe {
1991+ let raw = std:: ptr:: read ( ctx_ref. contextualFunctionReturnLocations . add ( i) ) ;
1992+ ArchAndAddr :: from ( raw)
1993+ } ;
1994+ let val = unsafe { * ctx_ref. contextualFunctionReturnValues . add ( i) } ;
1995+ ( loc, val)
1996+ } )
1997+ . collect :: < HashMap < _ , _ > > ( ) ;
1998+
1999+ let direct_code_references = ( 0 ..ctx_ref. directRefCount )
2000+ . map ( |i| {
2001+ let src = unsafe {
2002+ let raw = std:: ptr:: read ( ctx_ref. directRefSources . add ( i) ) ;
2003+ ArchAndAddr :: from ( raw)
2004+ } ;
2005+ let tgt = unsafe { * ctx_ref. directRefTargets . add ( i) } ;
2006+ ( tgt, src)
2007+ } )
2008+ . collect :: < HashMap < _ , _ > > ( ) ;
2009+
2010+ let direct_no_return_calls = ( 0 ..ctx_ref. directNoReturnCallsCount )
2011+ . map ( |i| {
2012+ let raw = unsafe { std:: ptr:: read ( ctx_ref. directNoReturnCalls . add ( i) ) } ;
2013+ ArchAndAddr :: from ( raw)
2014+ } )
2015+ . collect :: < HashSet < _ > > ( ) ;
2016+
2017+ let halted_disassembly_addresses = ( 0 ..ctx_ref. haltedDisassemblyAddressesCount )
2018+ . map ( |i| {
2019+ let raw = unsafe { std:: ptr:: read ( ctx_ref. haltedDisassemblyAddresses . add ( i) ) } ;
2020+ ArchAndAddr :: from ( raw)
2021+ } )
2022+ . collect :: < HashSet < _ > > ( ) ;
2023+
2024+ BasicBlockAnalysisContext {
2025+ handle,
2026+ contextual_returns_dirty : false ,
2027+ indirect_branches,
2028+ indirect_no_return_calls,
2029+ analysis_skip_override : ctx_ref. analysisSkipOverride ,
2030+ translate_tail_calls : ctx_ref. translateTailCalls ,
2031+ disallow_branch_to_string : ctx_ref. disallowBranchToString ,
2032+ max_function_size : ctx_ref. maxFunctionSize ,
2033+ halt_on_invalid_instruction : ctx_ref. haltOnInvalidInstructions ,
2034+ max_size_reached : ctx_ref. maxSizeReached ,
2035+ contextual_returns,
2036+ direct_code_references,
2037+ direct_no_return_calls,
2038+ halted_disassembly_addresses,
2039+ }
2040+ }
2041+
2042+ pub fn add_contextual_return ( & mut self , loc : ArchAndAddr , value : bool ) {
2043+ if !self . contextual_returns . contains_key ( & loc) {
2044+ self . contextual_returns_dirty = true ;
2045+ }
2046+
2047+ self . contextual_returns . insert ( loc, value) ;
2048+ }
2049+
2050+ pub fn add_direct_code_reference ( & mut self , target : u64 , src : ArchAndAddr ) {
2051+ self . direct_code_references . entry ( target) . or_insert ( src) ;
2052+ }
2053+
2054+ pub fn add_direct_no_return_call ( & mut self , loc : ArchAndAddr ) {
2055+ self . direct_no_return_calls . insert ( loc) ;
2056+ }
2057+
2058+ pub fn add_halted_disassembly_address ( & mut self , loc : ArchAndAddr ) {
2059+ self . halted_disassembly_addresses . insert ( loc) ;
2060+ }
2061+
2062+ pub fn create_basic_block (
2063+ & self ,
2064+ arch : CoreArchitecture ,
2065+ start : u64 ,
2066+ ) -> Option < Ref < BasicBlock < NativeBlock > > > {
2067+ let raw_block =
2068+ unsafe { BNAnalyzeBasicBlocksContextCreateBasicBlock ( self . handle , arch. handle , start) } ;
2069+
2070+ if raw_block. is_null ( ) {
2071+ return None ;
2072+ }
2073+
2074+ unsafe { Some ( BasicBlock :: ref_from_raw ( raw_block, NativeBlock :: new ( ) ) ) }
2075+ }
2076+
2077+ pub fn add_basic_block ( & self , block : Ref < BasicBlock < NativeBlock > > ) {
2078+ unsafe {
2079+ BNAnalyzeBasicBlocksContextAddBasicBlockToFunction ( self . handle , block. handle ) ;
2080+ }
2081+ }
2082+
2083+ pub fn add_temp_outgoing_reference ( & self , target : & Function ) {
2084+ unsafe {
2085+ BNAnalyzeBasicBlocksContextAddTempReference ( self . handle , target. handle ) ;
2086+ }
2087+ }
2088+
2089+ pub fn finalize ( & mut self ) {
2090+ if !self . direct_code_references . is_empty ( ) {
2091+ let total = self . direct_code_references . len ( ) ;
2092+ let mut sources: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2093+ let mut targets: Vec < u64 > = Vec :: with_capacity ( total) ;
2094+ for ( target, src) in & self . direct_code_references {
2095+ sources. push ( src. into_raw ( ) ) ;
2096+ targets. push ( * target) ;
2097+ }
2098+ unsafe {
2099+ BNAnalyzeBasicBlocksContextSetDirectCodeReferences (
2100+ self . handle ,
2101+ sources. as_mut_ptr ( ) ,
2102+ targets. as_mut_ptr ( ) ,
2103+ total,
2104+ ) ;
2105+ }
2106+ }
2107+
2108+ if !self . direct_no_return_calls . is_empty ( ) {
2109+ let total = self . direct_no_return_calls . len ( ) ;
2110+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2111+ for loc in & self . direct_no_return_calls {
2112+ locations. push ( loc. into_raw ( ) ) ;
2113+ }
2114+ unsafe {
2115+ BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls (
2116+ self . handle ,
2117+ locations. as_mut_ptr ( ) ,
2118+ total,
2119+ ) ;
2120+ }
2121+ }
2122+
2123+ if !self . halted_disassembly_addresses . is_empty ( ) {
2124+ let total = self . halted_disassembly_addresses . len ( ) ;
2125+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2126+ for loc in & self . halted_disassembly_addresses {
2127+ locations. push ( loc. into_raw ( ) ) ;
2128+ }
2129+ unsafe {
2130+ BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses (
2131+ self . handle ,
2132+ locations. as_mut_ptr ( ) ,
2133+ total,
2134+ ) ;
2135+ }
2136+ }
2137+
2138+ if self . contextual_returns_dirty {
2139+ let total = self . contextual_returns . len ( ) ;
2140+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2141+ let mut values: Vec < bool > = Vec :: with_capacity ( total) ;
2142+ for ( loc, value) in & self . contextual_returns {
2143+ locations. push ( loc. into_raw ( ) ) ;
2144+ values. push ( * value) ;
2145+ }
2146+ unsafe {
2147+ BNAnalyzeBasicBlocksContextSetContextualFunctionReturns (
2148+ self . handle ,
2149+ locations. as_mut_ptr ( ) ,
2150+ values. as_mut_ptr ( ) ,
2151+ total,
2152+ ) ;
2153+ }
2154+ }
2155+
2156+ unsafe { BNAnalyzeBasicBlocksContextFinalize ( self . handle ) } ;
2157+ }
2158+ }
2159+
19252160impl Debug for CoreArchitecture {
19262161 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
19272162 f. debug_struct ( "CoreArchitecture" )
@@ -2264,9 +2499,9 @@ where
22642499 {
22652500 let custom_arch = unsafe { & * ( ctxt as * mut A ) } ;
22662501 let mut function = unsafe { Function :: from_raw ( function) } ;
2267- unsafe {
2268- custom_arch . analyze_basic_blocks ( & mut function , context) ;
2269- }
2502+ let mut context : BasicBlockAnalysisContext =
2503+ unsafe { BasicBlockAnalysisContext :: from_raw ( context) } ;
2504+ custom_arch . analyze_basic_blocks ( & mut function , & mut context ) ;
22702505 }
22712506
22722507 extern "C" fn cb_reg_name < A > ( ctxt : * mut c_void , reg : u32 ) -> * mut c_char
0 commit comments