@@ -23,12 +23,11 @@ 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 } ,
3332 Endianness ,
3433} ;
@@ -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) => {
@@ -471,13 +473,13 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
471473 il : & LowLevelILMutableFunction ,
472474 ) -> Option < ( usize , bool ) > ;
473475
474- unsafe fn analyze_basic_blocks (
476+ fn analyze_basic_blocks (
475477 & self ,
476478 function : & mut Function ,
477- context : * mut BNBasicBlockAnalysisContext ,
479+ context : & mut BasicBlockAnalysisContext ,
478480 ) {
479481 unsafe {
480- BNArchitectureDefaultAnalyzeBasicBlocks ( function. handle , context) ;
482+ BNArchitectureDefaultAnalyzeBasicBlocks ( function. handle , context. handle ) ;
481483 }
482484 }
483485
@@ -1544,13 +1546,13 @@ impl Architecture for CoreArchitecture {
15441546 }
15451547 }
15461548
1547- unsafe fn analyze_basic_blocks (
1549+ fn analyze_basic_blocks (
15481550 & self ,
15491551 function : & mut Function ,
1550- context : * mut BNBasicBlockAnalysisContext ,
1552+ context : & mut BasicBlockAnalysisContext ,
15511553 ) {
15521554 unsafe {
1553- BNArchitectureAnalyzeBasicBlocks ( self . handle , function. handle , context) ;
1555+ BNArchitectureAnalyzeBasicBlocks ( self . handle , function. handle , context. handle ) ;
15541556 }
15551557 }
15561558
@@ -1925,6 +1927,222 @@ impl Architecture for CoreArchitecture {
19251927 }
19261928}
19271929
1930+ pub struct BasicBlockAnalysisContext {
1931+ pub ( crate ) handle : * mut BNBasicBlockAnalysisContext ,
1932+ contextual_returns_dirty : bool ,
1933+
1934+ // In
1935+ pub indirect_branches : Vec < IndirectBranchInfo > ,
1936+ pub indirect_no_return_calls : HashSet < ArchAndAddr > ,
1937+ pub analysis_skip_override : BNFunctionAnalysisSkipOverride ,
1938+ pub translate_tail_calls : bool ,
1939+ pub disallow_branch_to_string : bool ,
1940+ pub max_function_size : u64 ,
1941+ pub halt_on_invalid_instruction : bool ,
1942+ pub max_size_reached : bool ,
1943+
1944+ // In/Out
1945+ contextual_returns : HashMap < ArchAndAddr , bool > ,
1946+
1947+ // Out
1948+ direct_code_references : HashMap < u64 , ArchAndAddr > ,
1949+ direct_no_return_calls : HashSet < ArchAndAddr > ,
1950+ halted_disassembly_addresses : HashSet < ArchAndAddr > ,
1951+ }
1952+
1953+ impl BasicBlockAnalysisContext {
1954+ pub unsafe fn from_raw ( handle : * mut BNBasicBlockAnalysisContext ) -> Self {
1955+ debug_assert ! ( !handle. is_null( ) ) ;
1956+
1957+ let ctx_ref = & * handle;
1958+
1959+ let indirect_branches = ( 0 ..ctx_ref. indirectBranchesCount )
1960+ . map ( |i| {
1961+ let raw: BNIndirectBranchInfo =
1962+ unsafe { std:: ptr:: read ( ctx_ref. indirectBranches . add ( i) ) } ;
1963+ IndirectBranchInfo :: from ( raw)
1964+ } )
1965+ . collect :: < Vec < _ > > ( ) ;
1966+
1967+ let indirect_no_return_calls = ( 0 ..ctx_ref. indirectNoReturnCallsCount )
1968+ . map ( |i| {
1969+ let raw = unsafe { std:: ptr:: read ( ctx_ref. indirectNoReturnCalls . add ( i) ) } ;
1970+ ArchAndAddr :: from ( raw)
1971+ } )
1972+ . collect :: < HashSet < _ > > ( ) ;
1973+
1974+ let contextual_returns = ( 0 ..ctx_ref. contextualFunctionReturnCount )
1975+ . map ( |i| {
1976+ let loc = unsafe {
1977+ let raw = std:: ptr:: read ( ctx_ref. contextualFunctionReturnLocations . add ( i) ) ;
1978+ ArchAndAddr :: from ( raw)
1979+ } ;
1980+ let val = unsafe { * ctx_ref. contextualFunctionReturnValues . add ( i) } ;
1981+ ( loc, val)
1982+ } )
1983+ . collect :: < HashMap < _ , _ > > ( ) ;
1984+
1985+ let direct_code_references = ( 0 ..ctx_ref. directRefCount )
1986+ . map ( |i| {
1987+ let src = unsafe {
1988+ let raw = std:: ptr:: read ( ctx_ref. directRefSources . add ( i) ) ;
1989+ ArchAndAddr :: from ( raw)
1990+ } ;
1991+ let tgt = unsafe { * ctx_ref. directRefTargets . add ( i) } ;
1992+ ( tgt, src)
1993+ } )
1994+ . collect :: < HashMap < _ , _ > > ( ) ;
1995+
1996+ let direct_no_return_calls = ( 0 ..ctx_ref. directNoReturnCallsCount )
1997+ . map ( |i| {
1998+ let raw = unsafe { std:: ptr:: read ( ctx_ref. directNoReturnCalls . add ( i) ) } ;
1999+ ArchAndAddr :: from ( raw)
2000+ } )
2001+ . collect :: < HashSet < _ > > ( ) ;
2002+
2003+ let halted_disassembly_addresses = ( 0 ..ctx_ref. haltedDisassemblyAddressesCount )
2004+ . map ( |i| {
2005+ let raw = unsafe { std:: ptr:: read ( ctx_ref. haltedDisassemblyAddresses . add ( i) ) } ;
2006+ ArchAndAddr :: from ( raw)
2007+ } )
2008+ . collect :: < HashSet < _ > > ( ) ;
2009+
2010+ BasicBlockAnalysisContext {
2011+ handle,
2012+ contextual_returns_dirty : false ,
2013+ indirect_branches,
2014+ indirect_no_return_calls,
2015+ analysis_skip_override : ctx_ref. analysisSkipOverride ,
2016+ translate_tail_calls : ctx_ref. translateTailCalls ,
2017+ disallow_branch_to_string : ctx_ref. disallowBranchToString ,
2018+ max_function_size : ctx_ref. maxFunctionSize ,
2019+ halt_on_invalid_instruction : ctx_ref. haltOnInvalidInstructions ,
2020+ max_size_reached : ctx_ref. maxSizeReached ,
2021+ contextual_returns,
2022+ direct_code_references,
2023+ direct_no_return_calls,
2024+ halted_disassembly_addresses,
2025+ }
2026+ }
2027+
2028+ pub fn add_contextual_return ( & mut self , loc : ArchAndAddr , value : bool ) {
2029+ if !self . contextual_returns . contains_key ( & loc) {
2030+ self . contextual_returns_dirty = true ;
2031+ }
2032+
2033+ self . contextual_returns . insert ( loc, value) ;
2034+ }
2035+
2036+ pub fn add_direct_code_reference ( & mut self , target : u64 , src : ArchAndAddr ) {
2037+ self . direct_code_references . entry ( target) . or_insert ( src) ;
2038+ }
2039+
2040+ pub fn add_direct_no_return_call ( & mut self , loc : ArchAndAddr ) {
2041+ self . direct_no_return_calls . insert ( loc) ;
2042+ }
2043+
2044+ pub fn add_halted_disassembly_address ( & mut self , loc : ArchAndAddr ) {
2045+ self . halted_disassembly_addresses . insert ( loc) ;
2046+ }
2047+
2048+ pub fn create_basic_block (
2049+ & self ,
2050+ arch : CoreArchitecture ,
2051+ start : u64 ,
2052+ ) -> Option < BasicBlock < NativeBlock > > {
2053+ let raw_block =
2054+ unsafe { BNAnalyzeBasicBlocksContextCreateBasicBlock ( self . handle , arch. handle , start) } ;
2055+
2056+ if raw_block. is_null ( ) {
2057+ return None ;
2058+ }
2059+
2060+ unsafe { Some ( BasicBlock :: from_raw ( raw_block, NativeBlock :: new ( ) ) ) }
2061+ }
2062+
2063+ pub fn add_basic_block ( & self , block : & BasicBlock < NativeBlock > ) {
2064+ unsafe {
2065+ BNAnalyzeBasicBlocksContextAddBasicBlockToFunction ( self . handle , block. handle ) ;
2066+ }
2067+ }
2068+
2069+ pub fn add_temp_outgoing_reference ( & self , target : & Function ) {
2070+ unsafe {
2071+ BNAnalyzeBasicBlocksContextAddTempReference ( self . handle , target. handle ) ;
2072+ }
2073+ }
2074+
2075+ pub fn finalize ( & mut self ) {
2076+ if !self . direct_code_references . is_empty ( ) {
2077+ let total = self . direct_code_references . len ( ) ;
2078+ let mut sources: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2079+ let mut targets: Vec < u64 > = Vec :: with_capacity ( total) ;
2080+ for ( target, src) in & self . direct_code_references {
2081+ sources. push ( src. into_raw ( ) ) ;
2082+ targets. push ( * target) ;
2083+ }
2084+ unsafe {
2085+ BNAnalyzeBasicBlocksContextSetDirectCodeReferences (
2086+ self . handle ,
2087+ sources. as_mut_ptr ( ) ,
2088+ targets. as_mut_ptr ( ) ,
2089+ total,
2090+ ) ;
2091+ }
2092+ }
2093+
2094+ if !self . direct_no_return_calls . is_empty ( ) {
2095+ let total = self . direct_no_return_calls . len ( ) ;
2096+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2097+ for loc in & self . direct_no_return_calls {
2098+ locations. push ( loc. into_raw ( ) ) ;
2099+ }
2100+ unsafe {
2101+ BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls (
2102+ self . handle ,
2103+ locations. as_mut_ptr ( ) ,
2104+ total,
2105+ ) ;
2106+ }
2107+ }
2108+
2109+ if !self . halted_disassembly_addresses . is_empty ( ) {
2110+ let total = self . halted_disassembly_addresses . len ( ) ;
2111+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2112+ for loc in & self . halted_disassembly_addresses {
2113+ locations. push ( loc. into_raw ( ) ) ;
2114+ }
2115+ unsafe {
2116+ BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses (
2117+ self . handle ,
2118+ locations. as_mut_ptr ( ) ,
2119+ total,
2120+ ) ;
2121+ }
2122+ }
2123+
2124+ if self . contextual_returns_dirty {
2125+ let total = self . contextual_returns . len ( ) ;
2126+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2127+ let mut values: Vec < bool > = Vec :: with_capacity ( total) ;
2128+ for ( loc, value) in & self . contextual_returns {
2129+ locations. push ( loc. into_raw ( ) ) ;
2130+ values. push ( * value) ;
2131+ }
2132+ unsafe {
2133+ BNAnalyzeBasicBlocksContextSetContextualFunctionReturns (
2134+ self . handle ,
2135+ locations. as_mut_ptr ( ) ,
2136+ values. as_mut_ptr ( ) ,
2137+ total,
2138+ ) ;
2139+ }
2140+ }
2141+
2142+ unsafe { BNAnalyzeBasicBlocksContextFinalize ( self . handle ) } ;
2143+ }
2144+ }
2145+
19282146impl Debug for CoreArchitecture {
19292147 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
19302148 f. debug_struct ( "CoreArchitecture" )
@@ -2267,9 +2485,9 @@ where
22672485 {
22682486 let custom_arch = unsafe { & * ( ctxt as * mut A ) } ;
22692487 let mut function = unsafe { Function :: from_raw ( function) } ;
2270- unsafe {
2271- custom_arch . analyze_basic_blocks ( & mut function , context) ;
2272- }
2488+ let mut context : BasicBlockAnalysisContext =
2489+ unsafe { BasicBlockAnalysisContext :: from_raw ( context) } ;
2490+ custom_arch . analyze_basic_blocks ( & mut function , & mut context ) ;
22732491 }
22742492
22752493 extern "C" fn cb_reg_name < A > ( ctxt : * mut c_void , reg : u32 ) -> * mut c_char
0 commit comments