88from binaryninja ._binaryninjacore import BNFreeString , BNAllocString , BNType
99
1010from . import _warpcore as warpcore
11+ from .warp_enums import WARPContainerSearchItemKind
1112
1213
1314class WarpUUID :
@@ -195,6 +196,108 @@ def apply(self, function: Function):
195196 warpcore .BNWARPFunctionApply (self .handle , function .handle )
196197
197198
199+ class WarpContainerSearchQuery :
200+ def __init__ (self , query : str , offset : Optional [int ] = None , limit : Optional [int ] = None , source : Optional [Source ] = None , source_tags : Optional [List [str ]] = None ):
201+ self .query = query
202+ self .source = source
203+ self .offset = offset
204+ self .limit = limit
205+ offset_ptr = None
206+ if offset is not None :
207+ self ._c_offset = ctypes .c_size_t (offset )
208+ offset_ptr = ctypes .byref (self ._c_offset )
209+ limit_ptr = None
210+ if limit is not None :
211+ self ._c_limit = ctypes .c_size_t (limit )
212+ limit_ptr = ctypes .byref (self ._c_limit )
213+ source_ptr = None
214+ if source is not None :
215+ self ._c_source = source .uuid
216+ source_ptr = ctypes .byref (self ._c_source )
217+ source_tags_len = 0
218+ source_tags_array_ptr = None
219+ if source_tags is not None :
220+ source_tags_ptr = (ctypes .c_char_p * len (source_tags ))()
221+ source_tags_len = len (source_tags )
222+ for i in range (len (source_tags )):
223+ source_tags_ptr [i ] = source_tags [i ].encode ('utf-8' )
224+ source_tags_array_ptr = ctypes .cast (source_tags_ptr , ctypes .POINTER (ctypes .c_char_p ))
225+ self .handle = warpcore .BNWARPNewContainerSearchQuery (query , offset_ptr , limit_ptr , source_ptr , source_tags_array_ptr , source_tags_len )
226+
227+ def __del__ (self ):
228+ if self .handle is not None :
229+ warpcore .BNWARPFreeContainerSearchQueryReference (self .handle )
230+
231+ def __repr__ (self ):
232+ # TODO: Display offset and limit in a pythonic way.
233+ if self .source is None :
234+ return f"<WarpContainerSearchQuery '{ self .query } '>"
235+ return f"<WarpContainerSearchQuery '{ self .query } ': '{ self .source } '>"
236+
237+
238+ class WarpContainerSearchItem :
239+ def __init__ (self , handle : warpcore .BNWARPContainerSearchItem ):
240+ self .handle = handle
241+
242+ def __del__ (self ):
243+ if self .handle is not None :
244+ warpcore .BNWARPFreeContainerSearchItemReference (self .handle )
245+
246+ @property
247+ def kind (self ) -> WARPContainerSearchItemKind :
248+ return WARPContainerSearchItemKind (warpcore .BNWARPContainerSearchItemGetKind (self .handle ))
249+
250+ @property
251+ def source (self ) -> Source :
252+ return Source (warpcore .BNWARPContainerSearchItemGetSource (self .handle ))
253+
254+ @property
255+ def name (self ) -> str :
256+ return warpcore .BNWARPContainerSearchItemGetName (self .handle )
257+
258+ def get_type (self , arch : Architecture ) -> Optional [Type ]:
259+ ty = warpcore .BNWARPContainerSearchItemGetType (arch .handle , self .handle )
260+ if not ty :
261+ return None
262+ return Type (ty )
263+
264+ @property
265+ def function (self ) -> Optional [WarpFunction ]:
266+ func = warpcore .BNWARPContainerSearchItemGetFunction (self .handle )
267+ if not func :
268+ return None
269+ return WarpFunction (func )
270+
271+ def __repr__ (self ):
272+ return f"<WarpContainerSearchItem '{ self .name } ': '{ self .source } '>"
273+
274+
275+ class WarpContainerResponse :
276+ def __init__ (self , items : List [WarpContainerSearchItem ], offset : int , total : int ):
277+ self .items = items
278+ self .offset = offset
279+ self .total = total
280+
281+ def __iter__ (self ):
282+ return iter (self .items )
283+
284+ def __len__ (self ):
285+ return len (self .items )
286+
287+ def __repr__ (self ):
288+ return f"<WarpContainerResponse items={ len (self .items )} offset={ self .offset } total={ self .total } >"
289+
290+ @staticmethod
291+ def from_api (response : warpcore .BNWARPContainerSearchResponse ) -> 'WarpContainerResponse' :
292+ try :
293+ items = []
294+ for i in range (response .count ):
295+ items .append (WarpContainerSearchItem (warpcore .BNWARPNewContainerSearchItemReference (response .items [i ])))
296+ return WarpContainerResponse (items = items , offset = response .offset , total = response .total )
297+ finally :
298+ warpcore .BNWARPFreeContainerSearchResponse (response )
299+
300+
198301class _WarpContainerMetaclass (type ):
199302 def __iter__ (self ):
200303 binaryninja ._init_plugins ()
@@ -305,12 +408,19 @@ def remove_types(self, source: Source, guids: List[TypeGUID]) -> bool:
305408 core_guids [i ] = guids [i ].uuid
306409 return warpcore .BNWARPContainerRemoveTypes (self .handle , source .uuid , core_guids , count )
307410
308- def fetch_functions (self , target : WarpTarget , guids : List [FunctionGUID ]):
411+ def fetch_functions (self , target : WarpTarget , guids : List [FunctionGUID ], source_tags : Optional [ List [ str ]] = None ):
309412 count = len (guids )
310413 core_guids = (warpcore .BNWARPFunctionGUID * count )()
311414 for i in range (count ):
312415 core_guids [i ] = guids [i ].uuid
313- warpcore .BNWARPContainerFetchFunctions (self .handle , target .handle , core_guids , count )
416+ if source_tags is None :
417+ source_tags = []
418+ source_tags_ptr = (ctypes .c_char_p * len (source_tags ))()
419+ source_tags_len = len (source_tags )
420+ for i in range (len (source_tags )):
421+ source_tags_ptr [i ] = source_tags [i ].encode ('utf-8' )
422+ source_tags_array_ptr = ctypes .cast (source_tags_ptr , ctypes .POINTER (ctypes .c_char_p ))
423+ warpcore .BNWARPContainerFetchFunctions (self .handle , target .handle , source_tags_array_ptr , source_tags_len , core_guids , count )
314424
315425 def get_sources_with_function_guid (self , target : WarpTarget , guid : FunctionGUID ) -> List [Source ]:
316426 count = ctypes .c_size_t ()
@@ -346,7 +456,7 @@ def get_functions_with_guid(self, target: WarpTarget, source: Source, guid: Func
346456 return result
347457
348458 def get_type_with_guid (self , arch : Architecture , source : Source , guid : TypeGUID ) -> Optional [Type ]:
349- ty = warpcore .BNWARPContainerGetTypeWithGUID (self .handle , arch .handle , source .uuid , guid .uuid )
459+ ty = warpcore .BNWARPContainerGetTypeWithGUID (arch .handle , self .handle , source .uuid , guid .uuid )
350460 if not ty :
351461 return None
352462 return Type (ty )
@@ -362,6 +472,12 @@ def get_type_guids_with_name(self, source: Source, name: str) -> List[TypeGUID]:
362472 warpcore .BNWARPFreeUUIDList (guids , count .value )
363473 return result
364474
475+ def search (self , query : WarpContainerSearchQuery ) -> Optional [WarpContainerResponse ]:
476+ response = warpcore .BNWARPContainerSearch (self .handle , query .handle )
477+ if not response :
478+ return None
479+ return WarpContainerResponse .from_api (response .contents )
480+
365481
366482def run_matcher (view : BinaryView ):
367483 warpcore .BNWARPRunMatcher (view .handle )
0 commit comments