@@ -38,14 +38,13 @@ use crate::{
3838 calling_convention:: CoreCallingConvention ,
3939 data_buffer:: DataBuffer ,
4040 disassembly:: InstructionTextToken ,
41- function:: Function ,
41+ function:: { ArchAndAddr , Function , NativeBlock } ,
4242 platform:: Platform ,
4343 rc:: * ,
4444 relocation:: CoreRelocationHandler ,
45- string:: IntoCStr ,
46- string:: * ,
45+ string:: { IntoCStr , * } ,
4746 types:: { NameAndType , Type } ,
48- Endianness ,
47+ BranchType , Endianness ,
4948} ;
5049
5150pub mod basic_block;
@@ -135,13 +134,13 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
135134 il : & LowLevelILMutableFunction ,
136135 ) -> Option < ( usize , bool ) > ;
137136
138- unsafe fn analyze_basic_blocks (
137+ fn analyze_basic_blocks (
139138 & self ,
140139 function : & mut Function ,
141- context : * mut BNBasicBlockAnalysisContext ,
140+ context : & mut BasicBlockAnalysisContext ,
142141 ) {
143142 unsafe {
144- BNArchitectureDefaultAnalyzeBasicBlocks ( function. handle , context) ;
143+ BNArchitectureDefaultAnalyzeBasicBlocks ( function. handle , context. handle ) ;
145144 }
146145 }
147146
@@ -484,13 +483,13 @@ impl Architecture for CoreArchitecture {
484483 }
485484 }
486485
487- unsafe fn analyze_basic_blocks (
486+ fn analyze_basic_blocks (
488487 & self ,
489488 function : & mut Function ,
490- context : * mut BNBasicBlockAnalysisContext ,
489+ context : & mut BasicBlockAnalysisContext ,
491490 ) {
492491 unsafe {
493- BNArchitectureAnalyzeBasicBlocks ( self . handle , function. handle , context) ;
492+ BNArchitectureAnalyzeBasicBlocks ( self . handle , function. handle , context. handle ) ;
494493 }
495494 }
496495
@@ -862,6 +861,222 @@ impl Architecture for CoreArchitecture {
862861 }
863862}
864863
864+ pub struct BasicBlockAnalysisContext {
865+ pub ( crate ) handle : * mut BNBasicBlockAnalysisContext ,
866+ contextual_returns_dirty : bool ,
867+
868+ // In
869+ pub indirect_branches : Vec < IndirectBranchInfo > ,
870+ pub indirect_no_return_calls : HashSet < ArchAndAddr > ,
871+ pub analysis_skip_override : BNFunctionAnalysisSkipOverride ,
872+ pub translate_tail_calls : bool ,
873+ pub disallow_branch_to_string : bool ,
874+ pub max_function_size : u64 ,
875+ pub halt_on_invalid_instruction : bool ,
876+ pub max_size_reached : bool ,
877+
878+ // In/Out
879+ contextual_returns : HashMap < ArchAndAddr , bool > ,
880+
881+ // Out
882+ direct_code_references : HashMap < u64 , ArchAndAddr > ,
883+ direct_no_return_calls : HashSet < ArchAndAddr > ,
884+ halted_disassembly_addresses : HashSet < ArchAndAddr > ,
885+ }
886+
887+ impl BasicBlockAnalysisContext {
888+ pub unsafe fn from_raw ( handle : * mut BNBasicBlockAnalysisContext ) -> Self {
889+ debug_assert ! ( !handle. is_null( ) ) ;
890+
891+ let ctx_ref = & * handle;
892+
893+ let indirect_branches = ( 0 ..ctx_ref. indirectBranchesCount )
894+ . map ( |i| {
895+ let raw: BNIndirectBranchInfo =
896+ unsafe { std:: ptr:: read ( ctx_ref. indirectBranches . add ( i) ) } ;
897+ IndirectBranchInfo :: from ( raw)
898+ } )
899+ . collect :: < Vec < _ > > ( ) ;
900+
901+ let indirect_no_return_calls = ( 0 ..ctx_ref. indirectNoReturnCallsCount )
902+ . map ( |i| {
903+ let raw = unsafe { std:: ptr:: read ( ctx_ref. indirectNoReturnCalls . add ( i) ) } ;
904+ ArchAndAddr :: from ( raw)
905+ } )
906+ . collect :: < HashSet < _ > > ( ) ;
907+
908+ let contextual_returns = ( 0 ..ctx_ref. contextualFunctionReturnCount )
909+ . map ( |i| {
910+ let loc = unsafe {
911+ let raw = std:: ptr:: read ( ctx_ref. contextualFunctionReturnLocations . add ( i) ) ;
912+ ArchAndAddr :: from ( raw)
913+ } ;
914+ let val = unsafe { * ctx_ref. contextualFunctionReturnValues . add ( i) } ;
915+ ( loc, val)
916+ } )
917+ . collect :: < HashMap < _ , _ > > ( ) ;
918+
919+ let direct_code_references = ( 0 ..ctx_ref. directRefCount )
920+ . map ( |i| {
921+ let src = unsafe {
922+ let raw = std:: ptr:: read ( ctx_ref. directRefSources . add ( i) ) ;
923+ ArchAndAddr :: from ( raw)
924+ } ;
925+ let tgt = unsafe { * ctx_ref. directRefTargets . add ( i) } ;
926+ ( tgt, src)
927+ } )
928+ . collect :: < HashMap < _ , _ > > ( ) ;
929+
930+ let direct_no_return_calls = ( 0 ..ctx_ref. directNoReturnCallsCount )
931+ . map ( |i| {
932+ let raw = unsafe { std:: ptr:: read ( ctx_ref. directNoReturnCalls . add ( i) ) } ;
933+ ArchAndAddr :: from ( raw)
934+ } )
935+ . collect :: < HashSet < _ > > ( ) ;
936+
937+ let halted_disassembly_addresses = ( 0 ..ctx_ref. haltedDisassemblyAddressesCount )
938+ . map ( |i| {
939+ let raw = unsafe { std:: ptr:: read ( ctx_ref. haltedDisassemblyAddresses . add ( i) ) } ;
940+ ArchAndAddr :: from ( raw)
941+ } )
942+ . collect :: < HashSet < _ > > ( ) ;
943+
944+ BasicBlockAnalysisContext {
945+ handle,
946+ contextual_returns_dirty : false ,
947+ indirect_branches,
948+ indirect_no_return_calls,
949+ analysis_skip_override : ctx_ref. analysisSkipOverride ,
950+ translate_tail_calls : ctx_ref. translateTailCalls ,
951+ disallow_branch_to_string : ctx_ref. disallowBranchToString ,
952+ max_function_size : ctx_ref. maxFunctionSize ,
953+ halt_on_invalid_instruction : ctx_ref. haltOnInvalidInstructions ,
954+ max_size_reached : ctx_ref. maxSizeReached ,
955+ contextual_returns,
956+ direct_code_references,
957+ direct_no_return_calls,
958+ halted_disassembly_addresses,
959+ }
960+ }
961+
962+ pub fn add_contextual_return ( & mut self , loc : ArchAndAddr , value : bool ) {
963+ if !self . contextual_returns . contains_key ( & loc) {
964+ self . contextual_returns_dirty = true ;
965+ }
966+
967+ self . contextual_returns . insert ( loc, value) ;
968+ }
969+
970+ pub fn add_direct_code_reference ( & mut self , target : u64 , src : ArchAndAddr ) {
971+ self . direct_code_references . entry ( target) . or_insert ( src) ;
972+ }
973+
974+ pub fn add_direct_no_return_call ( & mut self , loc : ArchAndAddr ) {
975+ self . direct_no_return_calls . insert ( loc) ;
976+ }
977+
978+ pub fn add_halted_disassembly_address ( & mut self , loc : ArchAndAddr ) {
979+ self . halted_disassembly_addresses . insert ( loc) ;
980+ }
981+
982+ pub fn create_basic_block (
983+ & self ,
984+ arch : CoreArchitecture ,
985+ start : u64 ,
986+ ) -> Option < Ref < BasicBlock < NativeBlock > > > {
987+ let raw_block =
988+ unsafe { BNAnalyzeBasicBlocksContextCreateBasicBlock ( self . handle , arch. handle , start) } ;
989+
990+ if raw_block. is_null ( ) {
991+ return None ;
992+ }
993+
994+ unsafe { Some ( BasicBlock :: ref_from_raw ( raw_block, NativeBlock :: new ( ) ) ) }
995+ }
996+
997+ pub fn add_basic_block ( & self , block : Ref < BasicBlock < NativeBlock > > ) {
998+ unsafe {
999+ BNAnalyzeBasicBlocksContextAddBasicBlockToFunction ( self . handle , block. handle ) ;
1000+ }
1001+ }
1002+
1003+ pub fn add_temp_outgoing_reference ( & self , target : & Function ) {
1004+ unsafe {
1005+ BNAnalyzeBasicBlocksContextAddTempReference ( self . handle , target. handle ) ;
1006+ }
1007+ }
1008+
1009+ pub fn finalize ( & mut self ) {
1010+ if !self . direct_code_references . is_empty ( ) {
1011+ let total = self . direct_code_references . len ( ) ;
1012+ let mut sources: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
1013+ let mut targets: Vec < u64 > = Vec :: with_capacity ( total) ;
1014+ for ( target, src) in & self . direct_code_references {
1015+ sources. push ( src. into_raw ( ) ) ;
1016+ targets. push ( * target) ;
1017+ }
1018+ unsafe {
1019+ BNAnalyzeBasicBlocksContextSetDirectCodeReferences (
1020+ self . handle ,
1021+ sources. as_mut_ptr ( ) ,
1022+ targets. as_mut_ptr ( ) ,
1023+ total,
1024+ ) ;
1025+ }
1026+ }
1027+
1028+ if !self . direct_no_return_calls . is_empty ( ) {
1029+ let total = self . direct_no_return_calls . len ( ) ;
1030+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
1031+ for loc in & self . direct_no_return_calls {
1032+ locations. push ( loc. into_raw ( ) ) ;
1033+ }
1034+ unsafe {
1035+ BNAnalyzeBasicBlocksContextSetDirectNoReturnCalls (
1036+ self . handle ,
1037+ locations. as_mut_ptr ( ) ,
1038+ total,
1039+ ) ;
1040+ }
1041+ }
1042+
1043+ if !self . halted_disassembly_addresses . is_empty ( ) {
1044+ let total = self . halted_disassembly_addresses . len ( ) ;
1045+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
1046+ for loc in & self . halted_disassembly_addresses {
1047+ locations. push ( loc. into_raw ( ) ) ;
1048+ }
1049+ unsafe {
1050+ BNAnalyzeBasicBlocksContextSetHaltedDisassemblyAddresses (
1051+ self . handle ,
1052+ locations. as_mut_ptr ( ) ,
1053+ total,
1054+ ) ;
1055+ }
1056+ }
1057+
1058+ if self . contextual_returns_dirty {
1059+ let total = self . contextual_returns . len ( ) ;
1060+ let mut locations: Vec < BNArchitectureAndAddress > = Vec :: with_capacity ( total) ;
1061+ let mut values: Vec < bool > = Vec :: with_capacity ( total) ;
1062+ for ( loc, value) in & self . contextual_returns {
1063+ locations. push ( loc. into_raw ( ) ) ;
1064+ values. push ( * value) ;
1065+ }
1066+ unsafe {
1067+ BNAnalyzeBasicBlocksContextSetContextualFunctionReturns (
1068+ self . handle ,
1069+ locations. as_mut_ptr ( ) ,
1070+ values. as_mut_ptr ( ) ,
1071+ total,
1072+ ) ;
1073+ }
1074+ }
1075+
1076+ unsafe { BNAnalyzeBasicBlocksContextFinalize ( self . handle ) } ;
1077+ }
1078+ }
1079+
8651080impl Debug for CoreArchitecture {
8661081 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
8671082 f. debug_struct ( "CoreArchitecture" )
@@ -1204,9 +1419,9 @@ where
12041419 {
12051420 let custom_arch = unsafe { & * ( ctxt as * mut A ) } ;
12061421 let mut function = unsafe { Function :: from_raw ( function) } ;
1207- unsafe {
1208- custom_arch . analyze_basic_blocks ( & mut function , context) ;
1209- }
1422+ let mut context : BasicBlockAnalysisContext =
1423+ unsafe { BasicBlockAnalysisContext :: from_raw ( context) } ;
1424+ custom_arch . analyze_basic_blocks ( & mut function , & mut context ) ;
12101425 }
12111426
12121427 extern "C" fn cb_reg_name < A > ( ctxt : * mut c_void , reg : u32 ) -> * mut c_char
0 commit comments