44from typing import List , Optional , Union
55
66import binaryninja
7- from binaryninja import BinaryView , Function , BasicBlock , Architecture , Platform , Type , Symbol , LowLevelILInstruction , LowLevelILFunction
7+ from binaryninja import BinaryView , Function , BasicBlock , Architecture , Platform , Type , Symbol , LowLevelILInstruction , LowLevelILFunction , DataBuffer , Project , ProjectFile
88from binaryninja ._binaryninjacore import BNFreeString , BNAllocString , BNType
99
1010from . import _warpcore as warpcore
11- from .warp_enums import WARPContainerSearchItemKind
11+ from .warp_enums import WARPContainerSearchItemKind , WARPProcessorIncludedData , WARPProcessorIncludedFunctions
1212
1313
1414class WarpUUID :
@@ -74,6 +74,30 @@ def __repr__(self):
7474 return f"<TypeGUID '{ str (self )} '>"
7575
7676
77+ class WarpType :
78+ def __init__ (self , handle : warpcore .BNWARPType ):
79+ self .handle = handle
80+
81+ def __del__ (self ):
82+ if self .handle is not None :
83+ warpcore .BNWARPFreeTypeReference (self .handle )
84+
85+ def __repr__ (self ):
86+ return f"<WarpType name: '{ self .name } ' confidence: '{ self .confidence } '>"
87+
88+ @property
89+ def name (self ) -> str :
90+ return warpcore .BNWARPTypeGetName (self .handle )
91+
92+ @property
93+ def confidence (self ) -> int :
94+ return warpcore .BNWARPTypeGetConfidence (self .handle )
95+
96+ def analysis_type (self , arch : Optional [Architecture ] = None ) -> Type :
97+ if arch is None :
98+ return Type .create (handle = warpcore .BNWARPTypeGetAnalysisType (None , self .handle ))
99+ return Type .create (handle = warpcore .BNWARPTypeGetAnalysisType (arch .handle , self .handle ))
100+
77101@dataclasses .dataclass
78102class WarpFunctionComment :
79103 text : str
@@ -155,11 +179,12 @@ def get_symbol(self, function: Function) -> Symbol:
155179 symbol_handle = warpcore .BNWARPFunctionGetSymbol (self .handle , function .handle )
156180 return Symbol (symbol_handle )
157181
158- def get_type (self , function : Function ) -> Optional [Type ]:
159- type_handle = warpcore .BNWARPFunctionGetType (self .handle , function .handle )
182+ @property
183+ def type (self ) -> Optional [WarpType ]:
184+ type_handle = warpcore .BNWARPFunctionGetType (self .handle )
160185 if not type_handle :
161186 return None
162- return Type (type_handle )
187+ return WarpType (type_handle )
163188
164189 @property
165190 def constraints (self ) -> List [WarpConstraint ]:
@@ -259,11 +284,12 @@ def source(self) -> Source:
259284 def name (self ) -> str :
260285 return warpcore .BNWARPContainerSearchItemGetName (self .handle )
261286
262- def get_type (self , arch : Architecture ) -> Optional [Type ]:
263- ty = warpcore .BNWARPContainerSearchItemGetType (arch .handle , self .handle )
287+ @property
288+ def type (self ) -> Optional [WarpType ]:
289+ ty = warpcore .BNWARPContainerSearchItemGetType (self .handle )
264290 if not ty :
265291 return None
266- return Type (ty )
292+ return WarpType (ty )
267293
268294 @property
269295 def function (self ) -> Optional [WarpFunction ]:
@@ -405,12 +431,12 @@ def add_functions(self, target: WarpTarget, source: Source, functions: List[Func
405431 core_funcs [i ] = functions [i ].handle
406432 return warpcore .BNWARPContainerAddFunctions (self .handle , target .handle , source .uuid , core_funcs , count )
407433
408- def add_types (self , view : BinaryView , source : Source , types : List [Type ]) -> bool :
434+ def add_types (self , source : Source , types : List [WarpType ]) -> bool :
409435 count = len (types )
410- core_types = (ctypes .POINTER (BNType ) * count )()
436+ core_types = (ctypes .POINTER (warpcore . BNWARPType ) * count )()
411437 for i in range (count ):
412438 core_types [i ] = types [i ].handle
413- return warpcore .BNWARPContainerAddTypes (view . handle , self .handle , source .uuid , core_types , count )
439+ return warpcore .BNWARPContainerAddTypes (self .handle , source .uuid , core_types , count )
414440
415441 def remove_functions (self , target : WarpTarget , source : Source , functions : List [Function ]) -> bool :
416442 count = len (functions )
@@ -479,11 +505,11 @@ def get_functions_with_guid(self, target: WarpTarget, source: Source, guid: Func
479505 warpcore .BNWARPFreeFunctionList (funcs , count .value )
480506 return result
481507
482- def get_type_with_guid (self , arch : Architecture , source : Source , guid : TypeGUID ) -> Optional [Type ]:
483- ty = warpcore .BNWARPContainerGetTypeWithGUID (arch . handle , self .handle , source .uuid , guid .uuid )
508+ def get_type_with_guid (self , source : Source , guid : TypeGUID ) -> Optional [WarpType ]:
509+ ty = warpcore .BNWARPContainerGetTypeWithGUID (self .handle , source .uuid , guid .uuid )
484510 if not ty :
485511 return None
486- return Type (ty )
512+ return WarpType (ty )
487513
488514 def get_type_guids_with_name (self , source : Source , name : str ) -> List [TypeGUID ]:
489515 count = ctypes .c_size_t ()
@@ -503,6 +529,128 @@ def search(self, query: WarpContainerSearchQuery) -> Optional[WarpContainerRespo
503529 return WarpContainerResponse .from_api (response .contents )
504530
505531
532+ class WarpChunk :
533+ def __init__ (self , handle : warpcore .BNWARPChunk ):
534+ self .handle = handle
535+
536+ def __del__ (self ):
537+ if self .handle is not None :
538+ warpcore .BNWARPFreeChunkReference (self .handle )
539+
540+ def __repr__ (self ):
541+ return f"<WarpChunk functions: '{ len (self .functions )} ' types: '{ len (self .types )} '>"
542+
543+ @property
544+ def functions (self ) -> List [WarpFunction ]:
545+ count = ctypes .c_size_t ()
546+ funcs = warpcore .BNWARPChunkGetFunctions (self .handle , count )
547+ if not funcs :
548+ return []
549+ result = []
550+ for i in range (count .value ):
551+ result .append (WarpFunction (warpcore .BNWARPNewFunctionReference (funcs [i ])))
552+ warpcore .BNWARPFreeFunctionList (funcs , count .value )
553+ return result
554+
555+ @property
556+ def types (self ) -> List [WarpType ]:
557+ count = ctypes .c_size_t ()
558+ types = warpcore .BNWARPChunkGetTypes (self .handle , count )
559+ if not types :
560+ return []
561+ result = []
562+ for i in range (count .value ):
563+ result .append (WarpType (warpcore .BNWARPNewTypeReference (types [i ])))
564+ warpcore .BNWARPFreeTypeList (types , count .value )
565+ return result
566+
567+ class WarpFile :
568+ def __init__ (self , handle : Union [warpcore .BNWARPFileHandle , str ]):
569+ if isinstance (handle , str ):
570+ self .handle = warpcore .BNWARPNewFileFromPath (handle )
571+ else :
572+ self .handle = handle
573+
574+ def __del__ (self ):
575+ if self .handle is not None :
576+ warpcore .BNWARPFreeFileReference (self .handle )
577+
578+ def __repr__ (self ):
579+ return f"<WarpFile chunks: '{ len (self .chunks )} '>"
580+
581+ @property
582+ def chunks (self ) -> List [WarpChunk ]:
583+ count = ctypes .c_size_t ()
584+ chunks = warpcore .BNWARPFileGetChunks (self .handle , count )
585+ if not chunks :
586+ return []
587+ result = []
588+ for i in range (count .value ):
589+ result .append (WarpChunk (warpcore .BNWARPNewChunkReference (chunks [i ])))
590+ warpcore .BNWARPFreeChunkList (chunks , count .value )
591+ return result
592+
593+ def to_data_buffer (self ) -> DataBuffer :
594+ return DataBuffer (handle = warpcore .BNWARPFileToDataBuffer (self .handle ))
595+
596+
597+ @dataclasses .dataclass
598+ class WarpProcessorState :
599+ cancelled : bool = False
600+ unprocessed_file_count : int = 0
601+ processed_file_count : int = 0
602+ analyzing_files : List [str ] = dataclasses .field (default_factory = list )
603+ processing_files : List [str ] = dataclasses .field (default_factory = list )
604+
605+ @staticmethod
606+ def from_api (state : warpcore .BNWARPProcessorState ) -> 'WarpProcessorState' :
607+ analyzing_files = []
608+ processing_files = []
609+ for i in range (state .analyzing_files_count ):
610+ analyzing_files .append (state .analyzing_files [i ])
611+ for i in range (state .processing_files_count ):
612+ processing_files .append (state .processing_files [i ])
613+ return WarpProcessorState (
614+ cancelled = state .cancelled ,
615+ unprocessed_file_count = state .unprocessed_file_count ,
616+ processed_file_count = state .processed_file_count ,
617+ analyzing_files = analyzing_files ,
618+ processing_files = processing_files
619+ )
620+
621+ class WarpProcessor :
622+ def __init__ (self , included_data : WARPProcessorIncludedData = WARPProcessorIncludedData .WARPProcessorIncludedDataAll ,
623+ included_functions : WARPProcessorIncludedFunctions = WARPProcessorIncludedFunctions .WARPProcessorIncludedFunctionsAnnotated ,
624+ worker_count : int = 1 ):
625+ self .handle = warpcore .BNWARPNewProcessor (ctypes .c_int (included_data ), ctypes .c_int (included_functions ), worker_count )
626+
627+ def __del__ (self ):
628+ if self .handle is not None :
629+ warpcore .BNWARPFreeProcessor (self .handle )
630+
631+ def add_path (self , path : str ):
632+ warpcore .BNWARPProcessorAddPath (self .handle , path )
633+
634+ def add_project (self , project : Project ):
635+ warpcore .BNWARPProcessorAddProject (self .handle , project .handle )
636+
637+ def add_project_file (self , project_file : ProjectFile ):
638+ warpcore .BNWARPProcessorAddProjectFile (self .handle , project_file .handle )
639+
640+ def add_binary_view (self , view : BinaryView ):
641+ warpcore .BNWARPProcessorAddBinaryView (self .handle , view .handle )
642+
643+ def start (self ) -> Optional [WarpFile ]:
644+ file = warpcore .BNWARPProcessorStart (self .handle )
645+ if not file :
646+ return None
647+ return WarpFile (file )
648+
649+ def state (self ) -> WarpProcessorState :
650+ state_raw = warpcore .BNWARPProcessorGetState (self .handle )
651+ warpcore .BNWARPFreeProcessorState (state_raw )
652+ return WarpProcessorState .from_api (state_raw )
653+
506654def run_matcher (view : BinaryView ):
507655 warpcore .BNWARPRunMatcher (view .handle )
508656
0 commit comments