8
8
from binaryninja ._binaryninjacore import BNFreeString , BNAllocString , BNType
9
9
10
10
from . import _warpcore as warpcore
11
+ from .warp_enums import WARPContainerSearchItemKind
11
12
12
13
13
14
class WarpUUID :
@@ -195,6 +196,108 @@ def apply(self, function: Function):
195
196
warpcore .BNWARPFunctionApply (self .handle , function .handle )
196
197
197
198
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
+
198
301
class _WarpContainerMetaclass (type ):
199
302
def __iter__ (self ):
200
303
binaryninja ._init_plugins ()
@@ -305,12 +408,19 @@ def remove_types(self, source: Source, guids: List[TypeGUID]) -> bool:
305
408
core_guids [i ] = guids [i ].uuid
306
409
return warpcore .BNWARPContainerRemoveTypes (self .handle , source .uuid , core_guids , count )
307
410
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 ):
309
412
count = len (guids )
310
413
core_guids = (warpcore .BNWARPFunctionGUID * count )()
311
414
for i in range (count ):
312
415
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 )
314
424
315
425
def get_sources_with_function_guid (self , target : WarpTarget , guid : FunctionGUID ) -> List [Source ]:
316
426
count = ctypes .c_size_t ()
@@ -346,7 +456,7 @@ def get_functions_with_guid(self, target: WarpTarget, source: Source, guid: Func
346
456
return result
347
457
348
458
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 )
350
460
if not ty :
351
461
return None
352
462
return Type (ty )
@@ -362,6 +472,12 @@ def get_type_guids_with_name(self, source: Source, name: str) -> List[TypeGUID]:
362
472
warpcore .BNWARPFreeUUIDList (guids , count .value )
363
473
return result
364
474
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
+
365
481
366
482
def run_matcher (view : BinaryView ):
367
483
warpcore .BNWARPRunMatcher (view .handle )
0 commit comments