@@ -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
@@ -1925,6 +1944,222 @@ impl Architecture for CoreArchitecture {
19251944 }
19261945}
19271946
1947+ pub struct BasicBlockAnalysisContext {
1948+ pub ( crate ) handle : * mut BNBasicBlockAnalysisContext ,
1949+ contextual_returns_dirty : bool ,
1950+
1951+ // In
1952+ pub indirect_branches : Vec < IndirectBranchInfo > ,
1953+ pub indirect_no_return_calls : HashSet < ArchAndAddr > ,
1954+ pub analysis_skip_override : BNFunctionAnalysisSkipOverride ,
1955+ pub translate_tail_calls : bool ,
1956+ pub disallow_branch_to_string : bool ,
1957+ pub max_function_size : u64 ,
1958+ pub halt_on_invalid_instruction : bool ,
1959+ pub max_size_reached : bool ,
1960+
1961+ // In/Out
1962+ contextual_returns : HashMap < ArchAndAddr , bool > ,
1963+
1964+ // Out
1965+ direct_code_references : HashMap < u64 , ArchAndAddr > ,
1966+ direct_no_return_calls : HashSet < ArchAndAddr > ,
1967+ halted_disassembly_addresses : HashSet < ArchAndAddr > ,
1968+ }
1969+
1970+ impl BasicBlockAnalysisContext {
1971+ pub unsafe fn from_raw ( handle : * mut BNBasicBlockAnalysisContext ) -> Self {
1972+ debug_assert ! ( !handle. is_null( ) ) ;
1973+
1974+ let ctx_ref = & * handle;
1975+
1976+ let indirect_branches = ( 0 ..ctx_ref. indirectBranchesCount )
1977+ . map ( |i| {
1978+ let raw: BNIndirectBranchInfo =
1979+ unsafe { std:: ptr:: read ( ctx_ref. indirectBranches . add ( i) ) } ;
1980+ IndirectBranchInfo :: from ( raw)
1981+ } )
1982+ . collect :: < Vec < _ > > ( ) ;
1983+
1984+ let indirect_no_return_calls = ( 0 ..ctx_ref. indirectNoReturnCallsCount )
1985+ . map ( |i| {
1986+ let raw = unsafe { std:: ptr:: read ( ctx_ref. indirectNoReturnCalls . add ( i) ) } ;
1987+ ArchAndAddr :: from ( raw)
1988+ } )
1989+ . collect :: < HashSet < _ > > ( ) ;
1990+
1991+ let contextual_returns = ( 0 ..ctx_ref. contextualFunctionReturnCount )
1992+ . map ( |i| {
1993+ let loc = unsafe {
1994+ let raw = std:: ptr:: read ( ctx_ref. contextualFunctionReturnLocations . add ( i) ) ;
1995+ ArchAndAddr :: from ( raw)
1996+ } ;
1997+ let val = unsafe { * ctx_ref. contextualFunctionReturnValues . add ( i) } ;
1998+ ( loc, val)
1999+ } )
2000+ . collect :: < HashMap < _ , _ > > ( ) ;
2001+
2002+ let direct_code_references = ( 0 ..ctx_ref. directRefCount )
2003+ . map ( |i| {
2004+ let src = unsafe {
2005+ let raw = std:: ptr:: read ( ctx_ref. directRefSources . add ( i) ) ;
2006+ ArchAndAddr :: from ( raw)
2007+ } ;
2008+ let tgt = unsafe { * ctx_ref. directRefTargets . add ( i) } ;
2009+ ( tgt, src)
2010+ } )
2011+ . collect :: < HashMap < _ , _ > > ( ) ;
2012+
2013+ let direct_no_return_calls = ( 0 ..ctx_ref. directNoReturnCallsCount )
2014+ . map ( |i| {
2015+ let raw = unsafe { std:: ptr:: read ( ctx_ref. directNoReturnCalls . add ( i) ) } ;
2016+ ArchAndAddr :: from ( raw)
2017+ } )
2018+ . collect :: < HashSet < _ > > ( ) ;
2019+
2020+ let halted_disassembly_addresses = ( 0 ..ctx_ref. haltedDisassemblyAddressesCount )
2021+ . map ( |i| {
2022+ let raw = unsafe { std:: ptr:: read ( ctx_ref. haltedDisassemblyAddresses . add ( i) ) } ;
2023+ ArchAndAddr :: from ( raw)
2024+ } )
2025+ . collect :: < HashSet < _ > > ( ) ;
2026+
2027+ BasicBlockAnalysisContext {
2028+ handle,
2029+ contextual_returns_dirty : false ,
2030+ indirect_branches,
2031+ indirect_no_return_calls,
2032+ analysis_skip_override : ctx_ref. analysisSkipOverride ,
2033+ translate_tail_calls : ctx_ref. translateTailCalls ,
2034+ disallow_branch_to_string : ctx_ref. disallowBranchToString ,
2035+ max_function_size : ctx_ref. maxFunctionSize ,
2036+ halt_on_invalid_instruction : ctx_ref. haltOnInvalidInstructions ,
2037+ max_size_reached : ctx_ref. maxSizeReached ,
2038+ contextual_returns,
2039+ direct_code_references,
2040+ direct_no_return_calls,
2041+ halted_disassembly_addresses,
2042+ }
2043+ }
2044+
2045+ pub fn add_contextual_return ( & mut self , loc : ArchAndAddr , value : bool ) {
2046+ if !self . contextual_returns . contains_key ( & loc) {
2047+ self . contextual_returns_dirty = true ;
2048+ }
2049+
2050+ self . contextual_returns . insert ( loc, value) ;
2051+ }
2052+
2053+ pub fn add_direct_code_reference ( & mut self , target : u64 , src : ArchAndAddr ) {
2054+ self . direct_code_references . entry ( target) . or_insert ( src) ;
2055+ }
2056+
2057+ pub fn add_direct_no_return_call ( & mut self , loc : ArchAndAddr ) {
2058+ self . direct_no_return_calls . insert ( loc) ;
2059+ }
2060+
2061+ pub fn add_halted_disassembly_address ( & mut self , loc : ArchAndAddr ) {
2062+ self . halted_disassembly_addresses . insert ( loc) ;
2063+ }
2064+
2065+ pub fn create_basic_block (
2066+ & self ,
2067+ arch : CoreArchitecture ,
2068+ start : u64 ,
2069+ ) -> Option < Ref < BasicBlock < NativeBlock > > > {
2070+ let raw_block =
2071+ unsafe { BNAnalyzeBasicBlocksContextCreateBasicBlock ( self . handle , arch. handle , start) } ;
2072+
2073+ if raw_block. is_null ( ) {
2074+ return None ;
2075+ }
2076+
2077+ unsafe { Some ( BasicBlock :: ref_from_raw ( raw_block, NativeBlock :: new ( ) ) ) }
2078+ }
2079+
2080+ pub fn add_basic_block ( & self , block : Ref < BasicBlock < NativeBlock > > ) {
2081+ unsafe {
2082+ BNAnalyzeBasicBlocksContextAddBasicBlockToFunction ( self . handle , block. handle ) ;
2083+ }
2084+ }
2085+
2086+ pub fn add_temp_outgoing_reference ( & self , target : & Function ) {
2087+ unsafe {
2088+ BNAnalyzeBasicBlocksContextAddTempReference ( self . handle , target. handle ) ;
2089+ }
2090+ }
2091+
2092+ pub fn finalize ( & mut self ) {
2093+ if !self . direct_code_references . is_empty ( ) {
2094+ let total = self . direct_code_references . len ( ) ;
2095+ let mut sources: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2096+ let mut targets: Vec < u64 > = Vec :: with_capacity ( total) ;
2097+ for ( target, src) in & self . direct_code_references {
2098+ sources. push ( src. into_raw ( ) ) ;
2099+ targets. push ( * target) ;
2100+ }
2101+ unsafe {
2102+ BNAnalyzeBasicBlocksContextSetDirectCodeReferences (
2103+ self . handle ,
2104+ sources. as_mut_ptr ( ) ,
2105+ targets. as_mut_ptr ( ) ,
2106+ total,
2107+ ) ;
2108+ }
2109+ }
2110+
2111+ if !self . direct_no_return_calls . is_empty ( ) {
2112+ let total = self . direct_no_return_calls . len ( ) ;
2113+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2114+ for loc in & self . direct_no_return_calls {
2115+ locations. push ( loc. into_raw ( ) ) ;
2116+ }
2117+ unsafe {
2118+ BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls (
2119+ self . handle ,
2120+ locations. as_mut_ptr ( ) ,
2121+ total,
2122+ ) ;
2123+ }
2124+ }
2125+
2126+ if !self . halted_disassembly_addresses . is_empty ( ) {
2127+ let total = self . halted_disassembly_addresses . len ( ) ;
2128+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2129+ for loc in & self . halted_disassembly_addresses {
2130+ locations. push ( loc. into_raw ( ) ) ;
2131+ }
2132+ unsafe {
2133+ BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses (
2134+ self . handle ,
2135+ locations. as_mut_ptr ( ) ,
2136+ total,
2137+ ) ;
2138+ }
2139+ }
2140+
2141+ if self . contextual_returns_dirty {
2142+ let total = self . contextual_returns . len ( ) ;
2143+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
2144+ let mut values: Vec < bool > = Vec :: with_capacity ( total) ;
2145+ for ( loc, value) in & self . contextual_returns {
2146+ locations. push ( loc. into_raw ( ) ) ;
2147+ values. push ( * value) ;
2148+ }
2149+ unsafe {
2150+ BNAnalyzeBasicBlocksContextSetContextualFunctionReturns (
2151+ self . handle ,
2152+ locations. as_mut_ptr ( ) ,
2153+ values. as_mut_ptr ( ) ,
2154+ total,
2155+ ) ;
2156+ }
2157+ }
2158+
2159+ unsafe { BNAnalyzeBasicBlocksContextFinalize ( self . handle ) } ;
2160+ }
2161+ }
2162+
19282163impl Debug for CoreArchitecture {
19292164 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
19302165 f. debug_struct ( "CoreArchitecture" )
@@ -2267,9 +2502,9 @@ where
22672502 {
22682503 let custom_arch = unsafe { & * ( ctxt as * mut A ) } ;
22692504 let mut function = unsafe { Function :: from_raw ( function) } ;
2270- unsafe {
2271- custom_arch . analyze_basic_blocks ( & mut function , context) ;
2272- }
2505+ let mut context : BasicBlockAnalysisContext =
2506+ unsafe { BasicBlockAnalysisContext :: from_raw ( context) } ;
2507+ custom_arch . analyze_basic_blocks ( & mut function , & mut context ) ;
22732508 }
22742509
22752510 extern "C" fn cb_reg_name < A > ( ctxt : * mut c_void , reg : u32 ) -> * mut c_char
0 commit comments