@@ -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,250 @@ 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 max_size_reached : bool ,
1956+
1957+ // In/Out
1958+ contextual_returns : HashMap < ArchAndAddr , bool > ,
1959+
1960+ // Out
1961+ direct_code_references : HashMap < u64 , ArchAndAddr > ,
1962+ direct_no_return_calls : HashSet < ArchAndAddr > ,
1963+ halted_disassembly_addresses : HashSet < ArchAndAddr > ,
1964+ inlined_unresolved_indirect_branches : 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+ let inlined_unresolved_indirect_branches = ( 0 ..ctx_ref
2025+ . inlinedUnresolvedIndirectBranchCount )
2026+ . map ( |i| {
2027+ let raw =
2028+ unsafe { std:: ptr:: read ( ctx_ref. inlinedUnresolvedIndirectBranches . add ( i) ) } ;
2029+ ArchAndAddr :: from ( raw)
2030+ } )
2031+ . collect :: < HashSet < _ > > ( ) ;
2032+
2033+ BasicBlockAnalysisContext {
2034+ handle,
2035+ contextual_returns_dirty : false ,
2036+ indirect_branches,
2037+ indirect_no_return_calls,
2038+ analysis_skip_override : ctx_ref. analysisSkipOverride ,
2039+ translate_tail_calls : ctx_ref. translateTailCalls ,
2040+ disallow_branch_to_string : ctx_ref. disallowBranchToString ,
2041+ max_function_size : ctx_ref. maxFunctionSize ,
2042+ max_size_reached : ctx_ref. maxSizeReached ,
2043+ contextual_returns,
2044+ direct_code_references,
2045+ direct_no_return_calls,
2046+ halted_disassembly_addresses,
2047+ inlined_unresolved_indirect_branches,
2048+ }
2049+ }
2050+
2051+ pub fn add_contextual_return ( & mut self , loc : ArchAndAddr , value : bool ) {
2052+ if !self . contextual_returns . contains_key ( & loc) {
2053+ self . contextual_returns_dirty = true ;
2054+ }
2055+
2056+ self . contextual_returns . insert ( loc, value) ;
2057+ }
2058+
2059+ pub fn add_direct_code_reference ( & mut self , target : u64 , src : ArchAndAddr ) {
2060+ self . direct_code_references . entry ( target) . or_insert ( src) ;
2061+ }
2062+
2063+ pub fn add_direct_no_return_call ( & mut self , loc : ArchAndAddr ) {
2064+ self . direct_no_return_calls . insert ( loc) ;
2065+ }
2066+
2067+ pub fn add_halted_disassembly_address ( & mut self , loc : ArchAndAddr ) {
2068+ self . halted_disassembly_addresses . insert ( loc) ;
2069+ }
2070+
2071+ pub fn add_inlined_unresolved_indirect_branch ( & mut self , loc : ArchAndAddr ) {
2072+ self . inlined_unresolved_indirect_branches . insert ( loc) ;
2073+ }
2074+
2075+ pub fn create_basic_block (
2076+ & self ,
2077+ arch : CoreArchitecture ,
2078+ start : u64 ,
2079+ ) -> Option < Ref < BasicBlock < NativeBlock > > > {
2080+ let raw_block =
2081+ unsafe { BNAnalyzeBasicBlocksContextCreateBasicBlock ( self . handle , arch. handle , start) } ;
2082+
2083+ if raw_block. is_null ( ) {
2084+ return None ;
2085+ }
2086+
2087+ unsafe { Some ( BasicBlock :: ref_from_raw ( raw_block, NativeBlock :: new ( ) ) ) }
2088+ }
2089+
2090+ pub fn add_basic_block ( & self , block : Ref < BasicBlock < NativeBlock > > ) {
2091+ unsafe {
2092+ BNAnalyzeBasicBlocksContextAddBasicBlockToFunction ( self . handle , block. handle ) ;
2093+ }
2094+ }
2095+
2096+ pub fn add_temp_outgoing_reference ( & self , target : & Function ) {
2097+ unsafe {
2098+ BNAnalyzeBasicBlocksContextAddTempReference ( self . handle , target. handle ) ;
2099+ }
2100+ }
2101+
2102+ pub fn finalize ( & mut self ) {
2103+ if !self . direct_code_references . is_empty ( ) {
2104+ let total = self . direct_code_references . len ( ) ;
2105+ let mut sources: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2106+ let mut targets: Vec < u64 > = Vec :: with_capacity ( total) ;
2107+ for ( target, src) in & self . direct_code_references {
2108+ sources. push ( src. into_raw ( ) ) ;
2109+ targets. push ( * target) ;
2110+ }
2111+ unsafe {
2112+ BNAnalyzeBasicBlocksContextSetDirectCodeReferences (
2113+ self . handle ,
2114+ sources. as_mut_ptr ( ) ,
2115+ targets. as_mut_ptr ( ) ,
2116+ total,
2117+ ) ;
2118+ }
2119+ }
2120+
2121+ if !self . direct_no_return_calls . is_empty ( ) {
2122+ let total = self . direct_no_return_calls . len ( ) ;
2123+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2124+ for loc in & self . direct_no_return_calls {
2125+ locations. push ( loc. into_raw ( ) ) ;
2126+ }
2127+ unsafe {
2128+ BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls (
2129+ self . handle ,
2130+ locations. as_mut_ptr ( ) ,
2131+ total,
2132+ ) ;
2133+ }
2134+ }
2135+
2136+ if !self . halted_disassembly_addresses . is_empty ( ) {
2137+ let total = self . halted_disassembly_addresses . len ( ) ;
2138+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2139+ for loc in & self . halted_disassembly_addresses {
2140+ locations. push ( loc. into_raw ( ) ) ;
2141+ }
2142+ unsafe {
2143+ BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses (
2144+ self . handle ,
2145+ locations. as_mut_ptr ( ) ,
2146+ total,
2147+ ) ;
2148+ }
2149+ }
2150+
2151+ if !self . inlined_unresolved_indirect_branches . is_empty ( ) {
2152+ let total = self . inlined_unresolved_indirect_branches . len ( ) ;
2153+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2154+ for loc in & self . inlined_unresolved_indirect_branches {
2155+ locations. push ( loc. into_raw ( ) ) ;
2156+ }
2157+ unsafe {
2158+ BNAnalyzeBasicBlocksContextSetInlinedUnresolvedIndirectBranches (
2159+ self . handle ,
2160+ locations. as_mut_ptr ( ) ,
2161+ total,
2162+ ) ;
2163+ }
2164+ }
2165+
2166+ if self . contextual_returns_dirty {
2167+ let total = self . contextual_returns . len ( ) ;
2168+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2169+ let mut values: Vec < bool > = Vec :: with_capacity ( total) ;
2170+ for ( loc, value) in & self . contextual_returns {
2171+ locations. push ( loc. into_raw ( ) ) ;
2172+ values. push ( * value) ;
2173+ }
2174+ unsafe {
2175+ BNAnalyzeBasicBlocksContextSetContextualFunctionReturns (
2176+ self . handle ,
2177+ locations. as_mut_ptr ( ) ,
2178+ values. as_mut_ptr ( ) ,
2179+ total,
2180+ ) ;
2181+ }
2182+ }
2183+
2184+ unsafe { BNAnalyzeBasicBlocksContextFinalize ( self . handle ) } ;
2185+ }
2186+ }
2187+
19252188impl Debug for CoreArchitecture {
19262189 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
19272190 f. debug_struct ( "CoreArchitecture" )
@@ -2264,9 +2527,9 @@ where
22642527 {
22652528 let custom_arch = unsafe { & * ( ctxt as * mut A ) } ;
22662529 let mut function = unsafe { Function :: from_raw ( function) } ;
2267- unsafe {
2268- custom_arch . analyze_basic_blocks ( & mut function , context) ;
2269- }
2530+ let mut context : BasicBlockAnalysisContext =
2531+ unsafe { BasicBlockAnalysisContext :: from_raw ( context) } ;
2532+ custom_arch . analyze_basic_blocks ( & mut function , & mut context ) ;
22702533 }
22712534
22722535 extern "C" fn cb_reg_name < A > ( ctxt : * mut c_void , reg : u32 ) -> * mut c_char
0 commit comments