summaryrefslogtreecommitdiff
path: root/plugins/warp/api
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-01-31 12:59:42 -0500
committerMason Reed <mason@vector35.com>2025-07-02 01:58:31 -0400
commit110c06851bbbd09f78a3e87979d529d6e09df851 (patch)
tree7849015b26a14cd2b7be2d87fc1e0d5c101ef457 /plugins/warp/api
parent7b1e8bbdb971aed21b6d889aa4a46f9ef54829c1 (diff)
WARP 1.0
- Added FFI - Added a sidebar to the UI - Added project, directory and archive processing - Added generic `Container` interface for extensible stores of WARP data - Fixed type references being constructed and pulled incorrectly - Added HTML, Markdown and JSON report generation - Made the WARP information added as an analysis activity - Flattened the signatures directory, the target information is stored in the file now - Matched function information is stored as function metadata in the database to reliably persist, alongside the function GUID - Split the matching out from the application, allowing you to match on a given function without applying it - Added more/better tests - Added support for binaries with multiple architectures, the functions are now also queried based off the Target, see WARP spec for more details - Greatly improved support for RISC architectures, see WARP spec for more details - Greatly improved UX when loading files after the fact, will now sanely rerun the matcher - Omitted the function type if not a user type, this greatly reduces file size - Improved support for functions that reference a page aligned base pointer, see WARP spec for more details - Removed some extra cache structures that were causing erroneous behavior - Fixed edge-case in LLIL traversal missing some constant pointers, this was a bug in the Rust bindings - Added support for function comments - Made long running tasks, such as generating, matching and loading signatures, cancellable where possible - Made function constraints more versatile, allowing for easy extensions in the future, see WARP spec for details - Added options to signature generation, such as what data to store, and whether to compress the data or not - Made all long running tasks prompt the user for required information before the task starts, allowing users to "set it and forget it" and not have to baby sit the finalization of the task - Myriad of other changes to the actual WARP format that impact performance, file size and general feature set, see https://github.com/Vector35/warp for more details
Diffstat (limited to 'plugins/warp/api')
-rw-r--r--plugins/warp/api/CMakeLists.txt49
-rw-r--r--plugins/warp/api/python/CMakeLists.txt50
-rw-r--r--plugins/warp/api/python/__init__.py7
-rw-r--r--plugins/warp/api/python/_warpcore.py1081
-rw-r--r--plugins/warp/api/python/_warpcore_template.py58
-rw-r--r--plugins/warp/api/python/generator.cpp652
-rw-r--r--plugins/warp/api/python/warp.py384
-rw-r--r--plugins/warp/api/python/warp_enums.py1
-rw-r--r--plugins/warp/api/warp.cpp336
-rw-r--r--plugins/warp/api/warp.h378
-rw-r--r--plugins/warp/api/warpcore.h143
11 files changed, 3139 insertions, 0 deletions
diff --git a/plugins/warp/api/CMakeLists.txt b/plugins/warp/api/CMakeLists.txt
new file mode 100644
index 00000000..4aded248
--- /dev/null
+++ b/plugins/warp/api/CMakeLists.txt
@@ -0,0 +1,49 @@
+cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
+
+project(warp_api CXX C)
+
+add_library(warp_api STATIC warp.cpp warp.h warpcore.h)
+target_include_directories(warp_api PUBLIC ${PROJECT_SOURCE_DIR})
+
+if (NOT BN_API_BUILD_EXAMPLES AND NOT BN_INTERNAL_BUILD)
+ # Out-of-tree build
+ find_path(
+ BN_API_PATH
+ NAMES binaryninjaapi.h
+ HINTS ../.. binaryninjaapi $ENV{BN_API_PATH}
+ REQUIRED
+ )
+ add_subdirectory(${BN_API_PATH} api)
+endif()
+
+# Make sure the core rust dylib is built before warp_api.
+add_dependencies(warp_api warp_ninja)
+
+target_link_libraries(warp_api binaryninjaui)
+
+if (NOT DEMO)
+ add_subdirectory(python)
+endif()
+
+# Link to the warp plugin.
+# TODO: Need to make this less scuffed, but this will do for now.
+if (WIN32)
+ # By linking to warp_ninja_interface we insure that we get built _after_ the lib has been generated.
+ target_link_libraries(${PROJECT_NAME} warp_ninja_interface "${BN_CORE_PLUGIN_DIR}/warp_ninja.lib")
+else ()
+ target_link_libraries(${PROJECT_NAME} warp_ninja_interface ${BN_CORE_PLUGIN_DIR}/libwarp_ninja${CMAKE_SHARED_LIBRARY_SUFFIX})
+ # Set RPATH so the library can be found at runtime
+ if(APPLE)
+ set_target_properties(${PROJECT_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH "@loader_path")
+ else()
+ set_target_properties(${PROJECT_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH "$ORIGIN")
+ endif()
+endif()
+
+set_target_properties(warp_api PROPERTIES
+ CXX_STANDARD 17
+ CXX_VISIBILITY_PRESET hidden
+ CXX_STANDARD_REQUIRED ON
+ VISIBILITY_INLINES_HIDDEN ON
+ POSITION_INDEPENDENT_CODE ON
+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/out) \ No newline at end of file
diff --git a/plugins/warp/api/python/CMakeLists.txt b/plugins/warp/api/python/CMakeLists.txt
new file mode 100644
index 00000000..8e6003c0
--- /dev/null
+++ b/plugins/warp/api/python/CMakeLists.txt
@@ -0,0 +1,50 @@
+cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR)
+
+project(warp-python-api)
+
+file(GLOB PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/*.py)
+list(REMOVE_ITEM PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/_warpcore.py)
+list(REMOVE_ITEM PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/enums.py)
+
+add_executable(warp_generator
+ ${PROJECT_SOURCE_DIR}/generator.cpp)
+target_link_libraries(warp_generator binaryninjaapi)
+target_include_directories(warp_generator PUBLIC {PROJECT_SOURCE_DIR}/../../api)
+
+set_target_properties(warp_generator PROPERTIES
+ CXX_STANDARD 17
+ CXX_STANDARD_REQUIRED ON
+ BUILD_WITH_INSTALL_RPATH OFF
+ RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+
+if(BN_INTERNAL_BUILD)
+ set(PYTHON_OUTPUT_DIRECTORY ${BN_RESOURCE_DIR}/python/binaryninja/warp/)
+else()
+ set(PYTHON_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out/plugins/warp/)
+endif()
+
+if(WIN32)
+ if (BN_INTERNAL_BUILD)
+ add_custom_command(TARGET warp_generator PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BN_CORE_OUTPUT_DIR}/binaryninjacore.dll ${PROJECT_BINARY_DIR}/)
+ else()
+ add_custom_command(TARGET warp_generator PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BN_INSTALL_DIR}/binaryninjacore.dll ${PROJECT_BINARY_DIR}/)
+ endif()
+endif()
+
+add_custom_target(warp_generator_copy ALL
+ BYPRODUCTS ${PROJECT_SOURCE_DIR}/_warpcore.py ${PROJECT_SOURCE_DIR}/enums.py
+ DEPENDS ${PYTHON_SOURCES} ${PROJECT_SOURCE_DIR}/../warpcore.h $<TARGET_FILE:warp_generator>
+ COMMAND ${CMAKE_COMMAND} -E echo "Copying WARP Python Sources"
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS=detect_leaks=0 $<TARGET_FILE:warp_generator>
+ ${PROJECT_SOURCE_DIR}/../warpcore.h
+ ${PROJECT_SOURCE_DIR}/_warpcore.py
+ ${PROJECT_SOURCE_DIR}/_warpcore_template.py
+ ${PROJECT_SOURCE_DIR}/warp_enums.py
+
+ COMMAND ${CMAKE_COMMAND} -E copy ${PYTHON_SOURCES} ${PYTHON_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/_warpcore.py ${PYTHON_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/warp_enums.py ${PYTHON_OUTPUT_DIRECTORY})
+
diff --git a/plugins/warp/api/python/__init__.py b/plugins/warp/api/python/__init__.py
new file mode 100644
index 00000000..f4bc8e83
--- /dev/null
+++ b/plugins/warp/api/python/__init__.py
@@ -0,0 +1,7 @@
+import os
+
+from binaryninja._binaryninjacore import BNGetUserPluginDirectory
+user_plugin_dir = os.path.realpath(BNGetUserPluginDirectory())
+current_path = os.path.realpath(__file__)
+
+from .warp import * \ No newline at end of file
diff --git a/plugins/warp/api/python/_warpcore.py b/plugins/warp/api/python/_warpcore.py
new file mode 100644
index 00000000..c53feefa
--- /dev/null
+++ b/plugins/warp/api/python/_warpcore.py
@@ -0,0 +1,1081 @@
+import binaryninja
+import ctypes, os
+
+from typing import Optional
+from . import warp_enums
+# Load core module
+import platform
+core = None
+core_platform = platform.system()
+
+from binaryninja import Settings
+if Settings().get_bool("corePlugins.warp"):
+ from binaryninja._binaryninjacore import BNGetBundledPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+else:
+ from binaryninja._binaryninjacore import BNGetUserPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+
+def cstr(var) -> Optional[ctypes.c_char_p]:
+ if var is None:
+ return None
+ if isinstance(var, bytes):
+ return var
+ return var.encode("utf-8")
+
+def pyNativeStr(arg):
+ if isinstance(arg, str):
+ return arg
+ else:
+ return arg.decode('utf8')
+
+def free_string(value:ctypes.c_char_p) -> None:
+ BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte)))
+
+from binaryninja._binaryninjacore import BNFreeString
+# Type definitions
+from binaryninja._binaryninjacore import BNArchitecture, BNArchitectureHandle
+from binaryninja._binaryninjacore import BNBasicBlock, BNBasicBlockHandle
+from binaryninja._binaryninjacore import BNBinaryView, BNBinaryViewHandle
+from binaryninja._binaryninjacore import BNFunction, BNFunctionHandle
+from binaryninja._binaryninjacore import BNLowLevelILFunction, BNLowLevelILFunctionHandle
+from binaryninja._binaryninjacore import BNPlatform, BNPlatformHandle
+from binaryninja._binaryninjacore import BNSymbol, BNSymbolHandle
+from binaryninja._binaryninjacore import BNType, BNTypeHandle
+class BNWARPConstraint(ctypes.Structure):
+ pass
+BNWARPConstraintHandle = ctypes.POINTER(BNWARPConstraint)
+class BNWARPContainer(ctypes.Structure):
+ pass
+BNWARPContainerHandle = ctypes.POINTER(BNWARPContainer)
+class BNWARPFunction(ctypes.Structure):
+ pass
+BNWARPFunctionHandle = ctypes.POINTER(BNWARPFunction)
+class BNWARPFunctionComment(ctypes.Structure):
+ @property
+ def text(self):
+ return pyNativeStr(self._text)
+ @text.setter
+ def text(self, value):
+ self._text = cstr(value)
+BNWARPFunctionCommentHandle = ctypes.POINTER(BNWARPFunctionComment)
+class BNWARPTarget(ctypes.Structure):
+ pass
+BNWARPTargetHandle = ctypes.POINTER(BNWARPTarget)
+class BNWARPUUID(ctypes.Structure):
+ pass
+BNWARPUUIDHandle = ctypes.POINTER(BNWARPUUID)
+
+# Structure definitions
+BNWARPBasicBlockGUID = BNWARPUUID
+BNWARPBasicBlockGUIDHandle = BNWARPUUIDHandle
+BNWARPConstraintGUID = BNWARPUUID
+BNWARPConstraintGUIDHandle = BNWARPUUIDHandle
+BNWARPFunctionComment._fields_ = [
+ ("_text", ctypes.c_char_p),
+ ("offset", ctypes.c_longlong),
+ ]
+BNWARPFunctionGUID = BNWARPUUID
+BNWARPFunctionGUIDHandle = BNWARPUUIDHandle
+BNWARPSource = BNWARPUUID
+BNWARPSourceHandle = BNWARPUUIDHandle
+BNWARPTypeGUID = BNWARPUUID
+BNWARPTypeGUIDHandle = BNWARPUUIDHandle
+BNWARPUUID._fields_ = [
+ ("uuid", ctypes.c_ubyte * 16),
+ ]
+BNWARPConstraint._fields_ = [
+ ("guid", BNWARPConstraintGUID),
+ ("offset", ctypes.c_longlong),
+ ]
+
+# Function definitions
+# -------------------------------------------------------
+# _BNWARPContainerAddFunctions
+
+_BNWARPContainerAddFunctions = core.BNWARPContainerAddFunctions
+_BNWARPContainerAddFunctions.restype = ctypes.c_bool
+_BNWARPContainerAddFunctions.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerAddFunctions(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ source: ctypes.POINTER(BNWARPSource),
+ functions: ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerAddFunctions(container, target, source, functions, count)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerAddSource
+
+_BNWARPContainerAddSource = core.BNWARPContainerAddSource
+_BNWARPContainerAddSource.restype = ctypes.c_bool
+_BNWARPContainerAddSource.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.c_char_p,
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerAddSource(
+ container: ctypes.POINTER(BNWARPContainer),
+ sourcePath: Optional[str],
+ result: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerAddSource(container, cstr(sourcePath), result)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerAddTypes
+
+_BNWARPContainerAddTypes = core.BNWARPContainerAddTypes
+_BNWARPContainerAddTypes.restype = ctypes.c_bool
+_BNWARPContainerAddTypes.argtypes = [
+ ctypes.POINTER(BNBinaryView),
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(ctypes.POINTER(BNType)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerAddTypes(
+ view: ctypes.POINTER(BNBinaryView),
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ types: ctypes.POINTER(ctypes.POINTER(BNType)),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerAddTypes(view, container, source, types, count)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerCommitSource
+
+_BNWARPContainerCommitSource = core.BNWARPContainerCommitSource
+_BNWARPContainerCommitSource.restype = ctypes.c_bool
+_BNWARPContainerCommitSource.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerCommitSource(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerCommitSource(container, source)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetFunctionsWithGUID
+
+_BNWARPContainerGetFunctionsWithGUID = core.BNWARPContainerGetFunctionsWithGUID
+_BNWARPContainerGetFunctionsWithGUID.restype = ctypes.POINTER(ctypes.POINTER(BNWARPFunction))
+_BNWARPContainerGetFunctionsWithGUID.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(BNWARPFunctionGUID),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetFunctionsWithGUID(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ source: ctypes.POINTER(BNWARPSource),
+ guid: ctypes.POINTER(BNWARPFunctionGUID),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(ctypes.POINTER(BNWARPFunction))]:
+ result = _BNWARPContainerGetFunctionsWithGUID(container, target, source, guid, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetName
+
+_BNWARPContainerGetName = core.BNWARPContainerGetName
+_BNWARPContainerGetName.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPContainerGetName.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetName(
+ container: ctypes.POINTER(BNWARPContainer)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPContainerGetName(container)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSourcePath
+
+_BNWARPContainerGetSourcePath = core.BNWARPContainerGetSourcePath
+_BNWARPContainerGetSourcePath.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPContainerGetSourcePath.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSourcePath(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPContainerGetSourcePath(container, source)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSources
+
+_BNWARPContainerGetSources = core.BNWARPContainerGetSources
+_BNWARPContainerGetSources.restype = ctypes.POINTER(BNWARPSource)
+_BNWARPContainerGetSources.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSources(
+ container: ctypes.POINTER(BNWARPContainer),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPSource)]:
+ result = _BNWARPContainerGetSources(container, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSourcesWithFunctionGUID
+
+_BNWARPContainerGetSourcesWithFunctionGUID = core.BNWARPContainerGetSourcesWithFunctionGUID
+_BNWARPContainerGetSourcesWithFunctionGUID.restype = ctypes.POINTER(BNWARPSource)
+_BNWARPContainerGetSourcesWithFunctionGUID.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPFunctionGUID),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSourcesWithFunctionGUID(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ guid: ctypes.POINTER(BNWARPFunctionGUID),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPSource)]:
+ result = _BNWARPContainerGetSourcesWithFunctionGUID(container, target, guid, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSourcesWithTypeGUID
+
+_BNWARPContainerGetSourcesWithTypeGUID = core.BNWARPContainerGetSourcesWithTypeGUID
+_BNWARPContainerGetSourcesWithTypeGUID.restype = ctypes.POINTER(BNWARPSource)
+_BNWARPContainerGetSourcesWithTypeGUID.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTypeGUID),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSourcesWithTypeGUID(
+ container: ctypes.POINTER(BNWARPContainer),
+ guid: ctypes.POINTER(BNWARPTypeGUID),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPSource)]:
+ result = _BNWARPContainerGetSourcesWithTypeGUID(container, guid, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetTypeGUIDsWithName
+
+_BNWARPContainerGetTypeGUIDsWithName = core.BNWARPContainerGetTypeGUIDsWithName
+_BNWARPContainerGetTypeGUIDsWithName.restype = ctypes.POINTER(BNWARPTypeGUID)
+_BNWARPContainerGetTypeGUIDsWithName.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.c_char_p,
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetTypeGUIDsWithName(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ name: Optional[str],
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPTypeGUID)]:
+ result = _BNWARPContainerGetTypeGUIDsWithName(container, source, cstr(name), count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetTypeWithGUID
+
+_BNWARPContainerGetTypeWithGUID = core.BNWARPContainerGetTypeWithGUID
+_BNWARPContainerGetTypeWithGUID.restype = ctypes.POINTER(BNType)
+_BNWARPContainerGetTypeWithGUID.argtypes = [
+ ctypes.POINTER(BNArchitecture),
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(BNWARPTypeGUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetTypeWithGUID(
+ arch: ctypes.POINTER(BNArchitecture),
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ guid: ctypes.POINTER(BNWARPTypeGUID)
+ ) -> Optional[ctypes.POINTER(BNType)]:
+ result = _BNWARPContainerGetTypeWithGUID(arch, container, source, guid)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerIsSourceUncommitted
+
+_BNWARPContainerIsSourceUncommitted = core.BNWARPContainerIsSourceUncommitted
+_BNWARPContainerIsSourceUncommitted.restype = ctypes.c_bool
+_BNWARPContainerIsSourceUncommitted.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerIsSourceUncommitted(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerIsSourceUncommitted(container, source)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerIsSourceWritable
+
+_BNWARPContainerIsSourceWritable = core.BNWARPContainerIsSourceWritable
+_BNWARPContainerIsSourceWritable.restype = ctypes.c_bool
+_BNWARPContainerIsSourceWritable.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerIsSourceWritable(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerIsSourceWritable(container, source)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerRemoveFunctions
+
+_BNWARPContainerRemoveFunctions = core.BNWARPContainerRemoveFunctions
+_BNWARPContainerRemoveFunctions.restype = ctypes.c_bool
+_BNWARPContainerRemoveFunctions.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerRemoveFunctions(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ source: ctypes.POINTER(BNWARPSource),
+ functions: ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerRemoveFunctions(container, target, source, functions, count)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerRemoveTypes
+
+_BNWARPContainerRemoveTypes = core.BNWARPContainerRemoveTypes
+_BNWARPContainerRemoveTypes.restype = ctypes.c_bool
+_BNWARPContainerRemoveTypes.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(BNWARPTypeGUID),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerRemoveTypes(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ types: ctypes.POINTER(BNWARPTypeGUID),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerRemoveTypes(container, source, types, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeConstraintList
+
+_BNWARPFreeConstraintList = core.BNWARPFreeConstraintList
+_BNWARPFreeConstraintList.restype = None
+_BNWARPFreeConstraintList.argtypes = [
+ ctypes.POINTER(BNWARPConstraint),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeConstraintList(
+ constraints: ctypes.POINTER(BNWARPConstraint),
+ count: int
+ ) -> None:
+ return _BNWARPFreeConstraintList(constraints, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeContainerList
+
+_BNWARPFreeContainerList = core.BNWARPFreeContainerList
+_BNWARPFreeContainerList.restype = None
+_BNWARPFreeContainerList.argtypes = [
+ ctypes.POINTER(ctypes.POINTER(BNWARPContainer)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeContainerList(
+ containers: ctypes.POINTER(ctypes.POINTER(BNWARPContainer)),
+ count: int
+ ) -> None:
+ return _BNWARPFreeContainerList(containers, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeContainerReference
+
+_BNWARPFreeContainerReference = core.BNWARPFreeContainerReference
+_BNWARPFreeContainerReference.restype = None
+_BNWARPFreeContainerReference.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeContainerReference(
+ container: ctypes.POINTER(BNWARPContainer)
+ ) -> None:
+ return _BNWARPFreeContainerReference(container)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeFunctionCommentList
+
+_BNWARPFreeFunctionCommentList = core.BNWARPFreeFunctionCommentList
+_BNWARPFreeFunctionCommentList.restype = None
+_BNWARPFreeFunctionCommentList.argtypes = [
+ ctypes.POINTER(BNWARPFunctionComment),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeFunctionCommentList(
+ comments: ctypes.POINTER(BNWARPFunctionComment),
+ count: int
+ ) -> None:
+ return _BNWARPFreeFunctionCommentList(comments, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeFunctionList
+
+_BNWARPFreeFunctionList = core.BNWARPFreeFunctionList
+_BNWARPFreeFunctionList.restype = None
+_BNWARPFreeFunctionList.argtypes = [
+ ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeFunctionList(
+ functions: ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ count: int
+ ) -> None:
+ return _BNWARPFreeFunctionList(functions, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeFunctionReference
+
+_BNWARPFreeFunctionReference = core.BNWARPFreeFunctionReference
+_BNWARPFreeFunctionReference.restype = None
+_BNWARPFreeFunctionReference.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeFunctionReference(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> None:
+ return _BNWARPFreeFunctionReference(function)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeTargetReference
+
+_BNWARPFreeTargetReference = core.BNWARPFreeTargetReference
+_BNWARPFreeTargetReference.restype = None
+_BNWARPFreeTargetReference.argtypes = [
+ ctypes.POINTER(BNWARPTarget),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeTargetReference(
+ target: ctypes.POINTER(BNWARPTarget)
+ ) -> None:
+ return _BNWARPFreeTargetReference(target)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeUUIDList
+
+_BNWARPFreeUUIDList = core.BNWARPFreeUUIDList
+_BNWARPFreeUUIDList.restype = None
+_BNWARPFreeUUIDList.argtypes = [
+ ctypes.POINTER(BNWARPUUID),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeUUIDList(
+ uuids: ctypes.POINTER(BNWARPUUID),
+ count: int
+ ) -> None:
+ return _BNWARPFreeUUIDList(uuids, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionApply
+
+_BNWARPFunctionApply = core.BNWARPFunctionApply
+_BNWARPFunctionApply.restype = None
+_BNWARPFunctionApply.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionApply(
+ function: ctypes.POINTER(BNWARPFunction),
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> None:
+ return _BNWARPFunctionApply(function, analysisFunction)
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetComments
+
+_BNWARPFunctionGetComments = core.BNWARPFunctionGetComments
+_BNWARPFunctionGetComments.restype = ctypes.POINTER(BNWARPFunctionComment)
+_BNWARPFunctionGetComments.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetComments(
+ function: ctypes.POINTER(BNWARPFunction),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPFunctionComment)]:
+ result = _BNWARPFunctionGetComments(function, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetConstraints
+
+_BNWARPFunctionGetConstraints = core.BNWARPFunctionGetConstraints
+_BNWARPFunctionGetConstraints.restype = ctypes.POINTER(BNWARPConstraint)
+_BNWARPFunctionGetConstraints.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetConstraints(
+ function: ctypes.POINTER(BNWARPFunction),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPConstraint)]:
+ result = _BNWARPFunctionGetConstraints(function, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetGUID
+
+_BNWARPFunctionGetGUID = core.BNWARPFunctionGetGUID
+_BNWARPFunctionGetGUID.restype = BNWARPFunctionGUID
+_BNWARPFunctionGetGUID.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetGUID(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> BNWARPFunctionGUID:
+ return _BNWARPFunctionGetGUID(function)
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetSymbol
+
+_BNWARPFunctionGetSymbol = core.BNWARPFunctionGetSymbol
+_BNWARPFunctionGetSymbol.restype = ctypes.POINTER(BNSymbol)
+_BNWARPFunctionGetSymbol.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetSymbol(
+ function: ctypes.POINTER(BNWARPFunction),
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNSymbol)]:
+ result = _BNWARPFunctionGetSymbol(function, analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetSymbolName
+
+_BNWARPFunctionGetSymbolName = core.BNWARPFunctionGetSymbolName
+_BNWARPFunctionGetSymbolName.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPFunctionGetSymbolName.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetSymbolName(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPFunctionGetSymbolName(function)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetType
+
+_BNWARPFunctionGetType = core.BNWARPFunctionGetType
+_BNWARPFunctionGetType.restype = ctypes.POINTER(BNType)
+_BNWARPFunctionGetType.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetType(
+ function: ctypes.POINTER(BNWARPFunction),
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNType)]:
+ result = _BNWARPFunctionGetType(function, analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionsEqual
+
+_BNWARPFunctionsEqual = core.BNWARPFunctionsEqual
+_BNWARPFunctionsEqual.restype = ctypes.c_bool
+_BNWARPFunctionsEqual.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionsEqual(
+ functionA: ctypes.POINTER(BNWARPFunction),
+ functionB: ctypes.POINTER(BNWARPFunction)
+ ) -> bool:
+ return _BNWARPFunctionsEqual(functionA, functionB)
+
+
+# -------------------------------------------------------
+# _BNWARPGetAnalysisFunctionGUID
+
+_BNWARPGetAnalysisFunctionGUID = core.BNWARPGetAnalysisFunctionGUID
+_BNWARPGetAnalysisFunctionGUID.restype = ctypes.c_bool
+_BNWARPGetAnalysisFunctionGUID.argtypes = [
+ ctypes.POINTER(BNFunction),
+ ctypes.POINTER(BNWARPFunctionGUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetAnalysisFunctionGUID(
+ analysisFunction: ctypes.POINTER(BNFunction),
+ result: ctypes.POINTER(BNWARPFunctionGUID)
+ ) -> bool:
+ return _BNWARPGetAnalysisFunctionGUID(analysisFunction, result)
+
+
+# -------------------------------------------------------
+# _BNWARPGetBasicBlockGUID
+
+_BNWARPGetBasicBlockGUID = core.BNWARPGetBasicBlockGUID
+_BNWARPGetBasicBlockGUID.restype = ctypes.c_bool
+_BNWARPGetBasicBlockGUID.argtypes = [
+ ctypes.POINTER(BNBasicBlock),
+ ctypes.POINTER(BNWARPBasicBlockGUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetBasicBlockGUID(
+ basicBlock: ctypes.POINTER(BNBasicBlock),
+ result: ctypes.POINTER(BNWARPBasicBlockGUID)
+ ) -> bool:
+ return _BNWARPGetBasicBlockGUID(basicBlock, result)
+
+
+# -------------------------------------------------------
+# _BNWARPGetContainers
+
+_BNWARPGetContainers = core.BNWARPGetContainers
+_BNWARPGetContainers.restype = ctypes.POINTER(ctypes.POINTER(BNWARPContainer))
+_BNWARPGetContainers.argtypes = [
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetContainers(
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(ctypes.POINTER(BNWARPContainer))]:
+ result = _BNWARPGetContainers(count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPGetFunction
+
+_BNWARPGetFunction = core.BNWARPGetFunction
+_BNWARPGetFunction.restype = ctypes.POINTER(BNWARPFunction)
+_BNWARPGetFunction.argtypes = [
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetFunction(
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNWARPFunction)]:
+ result = _BNWARPGetFunction(analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPGetMatchedFunction
+
+_BNWARPGetMatchedFunction = core.BNWARPGetMatchedFunction
+_BNWARPGetMatchedFunction.restype = ctypes.POINTER(BNWARPFunction)
+_BNWARPGetMatchedFunction.argtypes = [
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetMatchedFunction(
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNWARPFunction)]:
+ result = _BNWARPGetMatchedFunction(analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPGetTarget
+
+_BNWARPGetTarget = core.BNWARPGetTarget
+_BNWARPGetTarget.restype = ctypes.POINTER(BNWARPTarget)
+_BNWARPGetTarget.argtypes = [
+ ctypes.POINTER(BNPlatform),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetTarget(
+ platform: ctypes.POINTER(BNPlatform)
+ ) -> Optional[ctypes.POINTER(BNWARPTarget)]:
+ result = _BNWARPGetTarget(platform)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPIsLiftedInstructionBlacklisted
+
+_BNWARPIsLiftedInstructionBlacklisted = core.BNWARPIsLiftedInstructionBlacklisted
+_BNWARPIsLiftedInstructionBlacklisted.restype = ctypes.c_bool
+_BNWARPIsLiftedInstructionBlacklisted.argtypes = [
+ ctypes.POINTER(BNLowLevelILFunction),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPIsLiftedInstructionBlacklisted(
+ liftedFunction: ctypes.POINTER(BNLowLevelILFunction),
+ idx: int
+ ) -> bool:
+ return _BNWARPIsLiftedInstructionBlacklisted(liftedFunction, idx)
+
+
+# -------------------------------------------------------
+# _BNWARPIsLiftedInstructionVariant
+
+_BNWARPIsLiftedInstructionVariant = core.BNWARPIsLiftedInstructionVariant
+_BNWARPIsLiftedInstructionVariant.restype = ctypes.c_bool
+_BNWARPIsLiftedInstructionVariant.argtypes = [
+ ctypes.POINTER(BNLowLevelILFunction),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPIsLiftedInstructionVariant(
+ liftedFunction: ctypes.POINTER(BNLowLevelILFunction),
+ idx: int
+ ) -> bool:
+ return _BNWARPIsLiftedInstructionVariant(liftedFunction, idx)
+
+
+# -------------------------------------------------------
+# _BNWARPNewContainerReference
+
+_BNWARPNewContainerReference = core.BNWARPNewContainerReference
+_BNWARPNewContainerReference.restype = ctypes.POINTER(BNWARPContainer)
+_BNWARPNewContainerReference.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPNewContainerReference(
+ container: ctypes.POINTER(BNWARPContainer)
+ ) -> Optional[ctypes.POINTER(BNWARPContainer)]:
+ result = _BNWARPNewContainerReference(container)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPNewFunctionReference
+
+_BNWARPNewFunctionReference = core.BNWARPNewFunctionReference
+_BNWARPNewFunctionReference.restype = ctypes.POINTER(BNWARPFunction)
+_BNWARPNewFunctionReference.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPNewFunctionReference(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> Optional[ctypes.POINTER(BNWARPFunction)]:
+ result = _BNWARPNewFunctionReference(function)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPNewTargetReference
+
+_BNWARPNewTargetReference = core.BNWARPNewTargetReference
+_BNWARPNewTargetReference.restype = ctypes.POINTER(BNWARPTarget)
+_BNWARPNewTargetReference.argtypes = [
+ ctypes.POINTER(BNWARPTarget),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPNewTargetReference(
+ target: ctypes.POINTER(BNWARPTarget)
+ ) -> Optional[ctypes.POINTER(BNWARPTarget)]:
+ result = _BNWARPNewTargetReference(target)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPRunMatcher
+
+_BNWARPRunMatcher = core.BNWARPRunMatcher
+_BNWARPRunMatcher.restype = None
+_BNWARPRunMatcher.argtypes = [
+ ctypes.POINTER(BNBinaryView),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPRunMatcher(
+ view: ctypes.POINTER(BNBinaryView)
+ ) -> None:
+ return _BNWARPRunMatcher(view)
+
+
+# -------------------------------------------------------
+# _BNWARPUUIDEqual
+
+_BNWARPUUIDEqual = core.BNWARPUUIDEqual
+_BNWARPUUIDEqual.restype = ctypes.c_bool
+_BNWARPUUIDEqual.argtypes = [
+ ctypes.POINTER(BNWARPUUID),
+ ctypes.POINTER(BNWARPUUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPUUIDEqual(
+ a: ctypes.POINTER(BNWARPUUID),
+ b: ctypes.POINTER(BNWARPUUID)
+ ) -> bool:
+ return _BNWARPUUIDEqual(a, b)
+
+
+# -------------------------------------------------------
+# _BNWARPUUIDGetString
+
+_BNWARPUUIDGetString = core.BNWARPUUIDGetString
+_BNWARPUUIDGetString.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPUUIDGetString.argtypes = [
+ ctypes.POINTER(BNWARPUUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPUUIDGetString(
+ uuid: ctypes.POINTER(BNWARPUUID)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPUUIDGetString(uuid)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+
+# Helper functions
+def handle_of_type(value, handle_type):
+ if isinstance(value, ctypes.POINTER(handle_type)) or isinstance(value, ctypes.c_void_p):
+ return ctypes.cast(value, ctypes.POINTER(handle_type))
+ raise ValueError('expected pointer to %s' % str(handle_type))
diff --git a/plugins/warp/api/python/_warpcore_template.py b/plugins/warp/api/python/_warpcore_template.py
new file mode 100644
index 00000000..fd923450
--- /dev/null
+++ b/plugins/warp/api/python/_warpcore_template.py
@@ -0,0 +1,58 @@
+import binaryninja
+import ctypes, os
+
+from typing import Optional
+from . import warp_enums
+# Load core module
+import platform
+core = None
+core_platform = platform.system()
+
+from binaryninja import Settings
+if Settings().get_bool("corePlugins.warp"):
+ from binaryninja._binaryninjacore import BNGetBundledPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+else:
+ from binaryninja._binaryninjacore import BNGetUserPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+
+def cstr(var) -> Optional[ctypes.c_char_p]:
+ if var is None:
+ return None
+ if isinstance(var, bytes):
+ return var
+ return var.encode("utf-8")
+
+def pyNativeStr(arg):
+ if isinstance(arg, str):
+ return arg
+ else:
+ return arg.decode('utf8')
+
+def free_string(value:ctypes.c_char_p) -> None:
+ BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte)))
+
diff --git a/plugins/warp/api/python/generator.cpp b/plugins/warp/api/python/generator.cpp
new file mode 100644
index 00000000..f40fc01a
--- /dev/null
+++ b/plugins/warp/api/python/generator.cpp
@@ -0,0 +1,652 @@
+/*
+Copyright 2020-2025 Vector 35 Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+
+#include <stdio.h>
+#include <inttypes.h>
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+map<string, string> g_pythonKeywordReplacements = {
+ {"False", "False_"},
+ {"True", "True_"},
+ {"None", "None_"},
+ {"and", "and_"},
+ {"as", "as_"},
+ {"assert", "assert_"},
+ {"async", "async_"},
+ {"await", "await_"},
+ {"break", "break_"},
+ {"class", "class_"},
+ {"continue", "continue_"},
+ {"def", "def_"},
+ {"del", "del_"},
+ {"elif", "elif_"},
+ {"else", "else_"},
+ {"except", "except_"},
+ {"finally", "finally_"},
+ {"for", "for_"},
+ {"from", "from_"},
+ {"global", "global_"},
+ {"if", "if_"},
+ {"import", "import_"},
+ {"in", "in_"},
+ {"is", "is_"},
+ {"lambda", "lambda_"},
+ {"nonlocal", "nonlocal_"},
+ {"not", "not_"},
+ {"or", "or_"},
+ {"pass", "pass_"},
+ {"raise", "raise_"},
+ {"return", "return_"},
+ {"try", "try_"},
+ {"while", "while_"},
+ {"with", "with_"},
+ {"yield", "yield_"},
+};
+
+
+void OutputType(FILE* out, Type* type, bool isReturnType = false, bool isCallback = false)
+{
+ switch (type->GetClass())
+ {
+ case BoolTypeClass:
+ fprintf(out, "ctypes.c_bool");
+ break;
+ case IntegerTypeClass:
+ switch (type->GetWidth())
+ {
+ case 1:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_byte");
+ else
+ fprintf(out, "ctypes.c_ubyte");
+ break;
+ case 2:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_short");
+ else
+ fprintf(out, "ctypes.c_ushort");
+ break;
+ case 4:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_int");
+ else
+ fprintf(out, "ctypes.c_uint");
+ break;
+ default:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_longlong");
+ else
+ fprintf(out, "ctypes.c_ulonglong");
+ break;
+ }
+ break;
+ case FloatTypeClass:
+ if (type->GetWidth() == 4)
+ fprintf(out, "ctypes.c_float");
+ else
+ fprintf(out, "ctypes.c_double");
+ break;
+ case NamedTypeReferenceClass:
+ if (type->GetNamedTypeReference()->GetTypeReferenceClass() == EnumNamedTypeClass)
+ {
+ string name = type->GetNamedTypeReference()->GetName().GetString();
+ if (name.size() > 16 && name.substr(0, 11) == "_BNDebugger")
+ name = name.substr(3);
+ else if (name.size() > 15 && name.substr(0, 10) == "BNDebugger")
+ name = name.substr(2);
+ else if (name.size() > 15 && name.substr(0, 7) == "BNDebug")
+ name = name.substr(2);
+ else if (name.size() > 2 && name.substr(0, 2) == "BN")
+ name = name.substr(2);
+ fprintf(out, "%sEnum", name.c_str());
+ }
+ else
+ {
+ fprintf(out, "%s", type->GetNamedTypeReference()->GetName().GetString().c_str());
+ }
+ break;
+ case PointerTypeClass:
+ if (isCallback || (type->GetChildType()->GetClass() == VoidTypeClass))
+ {
+ fprintf(out, "ctypes.c_void_p");
+ break;
+ }
+ else if ((type->GetChildType()->GetClass() == IntegerTypeClass) &&
+ (type->GetChildType()->GetWidth() == 1) && (type->GetChildType()->IsSigned()))
+ {
+ if (isReturnType)
+ fprintf(out, "ctypes.POINTER(ctypes.c_byte)");
+ else
+ fprintf(out, "ctypes.c_char_p");
+ break;
+ }
+ else if (type->GetChildType()->GetClass() == FunctionTypeClass)
+ {
+ fprintf(out, "ctypes.CFUNCTYPE(");
+ OutputType(out, type->GetChildType()->GetChildType().GetValue(), true, true);
+ for (auto& i : type->GetChildType()->GetParameters())
+ {
+ fprintf(out, ", ");
+ OutputType(out, i.type.GetValue());
+ }
+ fprintf(out, ")");
+ break;
+ }
+ fprintf(out, "ctypes.POINTER(");
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, ")");
+ break;
+ case ArrayTypeClass:
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, " * %" PRId64, type->GetElementCount());
+ break;
+ default:
+ fprintf(out, "None");
+ break;
+ }
+}
+
+
+void OutputSwizzledType(FILE* out, Type* type)
+{
+ switch (type->GetClass())
+ {
+ case BoolTypeClass:
+ fprintf(out, "bool");
+ break;
+ case IntegerTypeClass:
+ fprintf(out, "int");
+ break;
+ case FloatTypeClass:
+ fprintf(out, "float");
+ break;
+ case NamedTypeReferenceClass:
+ if (type->GetNamedTypeReference()->GetTypeReferenceClass() == EnumNamedTypeClass)
+ {
+ string name = type->GetNamedTypeReference()->GetName().GetString();
+ if (name.size() > 16 && name.substr(0, 11) == "_BNDebugger")
+ name = name.substr(3);
+ else if (name.size() > 15 && name.substr(0, 10) == "BNDebugger")
+ name = name.substr(2);
+ else if (name.size() > 15 && name.substr(0, 7) == "BNDebug")
+ name = name.substr(2);
+ else if (name.size() > 2 && name.substr(0, 2) == "BN")
+ name = name.substr(2);
+ fprintf(out, "%sEnum", name.c_str());
+ }
+ else
+ {
+ fprintf(out, "%s", type->GetNamedTypeReference()->GetName().GetString().c_str());
+ }
+ break;
+ case PointerTypeClass:
+ if (type->GetChildType()->GetClass() == VoidTypeClass)
+ {
+ fprintf(out, "Optional[ctypes.c_void_p]");
+ break;
+ }
+ else if ((type->GetChildType()->GetClass() == IntegerTypeClass) &&
+ (type->GetChildType()->GetWidth() == 1) && (type->GetChildType()->IsSigned()))
+ {
+ fprintf(out, "Optional[str]");
+ break;
+ }
+ else if (type->GetChildType()->GetClass() == FunctionTypeClass)
+ {
+ fprintf(out, "ctypes.CFUNCTYPE(");
+ OutputType(out, type->GetChildType()->GetChildType().GetValue(), true, true);
+ for (auto& i : type->GetChildType()->GetParameters())
+ {
+ fprintf(out, ", ");
+ OutputType(out, i.type.GetValue());
+ }
+ fprintf(out, ")");
+ break;
+ }
+ fprintf(out, "ctypes.POINTER(");
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, ")");
+ break;
+ case ArrayTypeClass:
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, " * %" PRId64, type->GetElementCount());
+ break;
+ default:
+ fprintf(out, "None");
+ break;
+ }
+}
+
+
+int main(int argc, char* argv[])
+{
+ if (argc < 5)
+ {
+ fprintf(stderr, "Usage: generator <header> <output> <output_template> <output_enum>\n");
+ return 1;
+ }
+
+ // Parse API header to get type and function information
+ map<QualifiedName, Ref<Type>> types, vars, funcs;
+ string errors;
+ auto arch = new CoreArchitecture(BNGetNativeTypeParserArchitecture());
+
+ // Enable ephemeral settings
+ Settings::Instance()->LoadSettingsFile("");
+ Settings::Instance()->Set("analysis.types.parserName", "ClangTypeParser");
+ bool ok = arch->GetStandalonePlatform()->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors);
+
+ if (!ok)
+ {
+ fprintf(stderr, "Errors: %s\n", errors.c_str());
+ return 1;
+ }
+
+ FILE* out = fopen(argv[2], "w");
+ FILE* out_template = fopen(argv[3], "r");
+ FILE* enums = fopen(argv[4], "w");
+
+ fprintf(enums, "import enum\n");
+
+ // Copy the content of the template to the output file
+ int c;
+ while((c = fgetc(out_template)) != EOF)
+ fputc(c, out);
+
+ // Create type objects
+ fprintf(out, "from binaryninja._binaryninjacore import BNFreeString\n");
+ fprintf(out, "# Type definitions\n");
+ for (auto& i : types)
+ {
+ string name;
+ if (i.first.size() != 1)
+ continue;
+ name = i.first[0];
+ if (name == "BNBinaryView")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNBinaryView, BNBinaryViewHandle\n");
+ continue;
+ }
+ if (name == "BNArchitecture")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNArchitecture, BNArchitectureHandle\n");
+ continue;
+ }
+ if (name == "BNBasicBlock")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNBasicBlock, BNBasicBlockHandle\n");
+ continue;
+ }
+ if (name == "BNFunction")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNFunction, BNFunctionHandle\n");
+ continue;
+ }
+ if (name == "BNLowLevelILFunction")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNLowLevelILFunction, BNLowLevelILFunctionHandle\n");
+ continue;
+ }
+ if (name == "BNPlatform")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNPlatform, BNPlatformHandle\n");
+ continue;
+ }
+ if (name == "BNSymbol")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNSymbol, BNSymbolHandle\n");
+ continue;
+ }
+ if (name == "BNType")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNType, BNTypeHandle\n");
+ continue;
+ }
+ if (i.second->GetClass() == StructureTypeClass)
+ {
+ fprintf(out, "class %s(ctypes.Structure):\n", name.c_str());
+
+ // python uses str's, C uses byte-arrays
+ bool stringField = false;
+ for (auto& arg : i.second->GetStructure()->GetMembers())
+ {
+ if ((arg.type->GetClass() == PointerTypeClass) &&
+ (arg.type->GetChildType()->GetWidth() == 1) &&
+ (arg.type->GetChildType()->IsSigned()))
+ {
+ fprintf(out, "\t@property\n\tdef %s(self):\n\t\treturn pyNativeStr(self._%s)\n", arg.name.c_str(), arg.name.c_str());
+ fprintf(out, "\t@%s.setter\n\tdef %s(self, value):\n\t\tself._%s = cstr(value)\n", arg.name.c_str(), arg.name.c_str(), arg.name.c_str());
+ stringField = true;
+ }
+ }
+
+ if (!stringField)
+ fprintf(out, "\tpass\n");
+
+ fprintf(out, "%sHandle = ctypes.POINTER(%s)\n", name.c_str(), name.c_str());
+ }
+ else if (i.second->GetClass() == EnumerationTypeClass)
+ {
+ bool isBNAPIEnum = false;
+ if (name.size() > 16 && name.substr(0, 11) == "_BNDebugger")
+ name = name.substr(3);
+ else if (name.size() > 15 && name.substr(0, 10) == "BNDebugger")
+ name = name.substr(2);
+ else if (name.size() > 15 && name.substr(0, 7) == "BNDebug")
+ name = name.substr(2);
+ else if (name.size() > 2 && name.substr(0, 2) == "BN")
+ {
+ name = name.substr(2);
+ isBNAPIEnum = false;
+ }
+ else
+ continue;
+
+ if (isBNAPIEnum)
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import %sEnum\n", name.c_str());
+ continue;
+ }
+
+ fprintf(out, "%sEnum = ctypes.c_int\n", name.c_str());
+
+ fprintf(enums, "\n\nclass %s(enum.IntEnum):\n", name.c_str());
+ for (auto& j : i.second->GetEnumeration()->GetMembers())
+ {
+ fprintf(enums, "\t%s = %" PRId64 "\n", j.name.c_str(), j.value);
+ }
+ }
+ else if ((i.second->GetClass() == BoolTypeClass) || (i.second->GetClass() == IntegerTypeClass) ||
+ (i.second->GetClass() == FloatTypeClass) || (i.second->GetClass() == ArrayTypeClass))
+ {
+ fprintf(out, "%s = ", name.c_str());
+ OutputType(out, i.second);
+ fprintf(out, "\n");
+ }
+ }
+
+
+ fprintf(out, "\n# Structure definitions\n");
+ set<QualifiedName> structsToProcess;
+ set<QualifiedName> finishedStructs;
+ for (auto& i : types)
+ structsToProcess.insert(i.first);
+ while (structsToProcess.size() != 0)
+ {
+ set<QualifiedName> currentStructList = structsToProcess;
+ structsToProcess.clear();
+ bool processedSome = false;
+ for (auto& i : currentStructList)
+ {
+ string name;
+ if (i.size() != 1)
+ continue;
+ Ref<Type> type = types[i];
+ name = i[0];
+ if ((type->GetClass() == StructureTypeClass) && (type->GetStructure()->GetMembers().size() != 0))
+ {
+ bool requiresDependency = false;
+ for (auto& j : type->GetStructure()->GetMembers())
+ {
+ if ((j.type->GetClass() == NamedTypeReferenceClass) &&
+ (finishedStructs.count(j.type->GetNamedTypeReference()->GetName()) == 0))
+ {
+ // This structure needs another structure that isn't fully defined yet, need to wait
+ // for the dependencies to be defined
+ structsToProcess.insert(i);
+ requiresDependency = true;
+ break;
+ }
+ }
+
+ if (requiresDependency)
+ continue;
+ fprintf(out, "%s._fields_ = [\n", name.c_str());
+ for (auto& j : type->GetStructure()->GetMembers())
+ {
+ // To help the python->C wrappers
+ if ((j.type->GetClass() == PointerTypeClass) &&
+ (j.type->GetChildType()->GetWidth() == 1) &&
+ (j.type->GetChildType()->IsSigned()))
+ {
+ fprintf(out, "\t\t(\"_%s\", ", j.name.c_str());
+ }
+ else
+ fprintf(out, "\t\t(\"%s\", ", j.name.c_str());
+ OutputType(out, j.type.GetValue());
+ fprintf(out, "),\n");
+ }
+ fprintf(out, "\t]\n");
+ finishedStructs.insert(i);
+ processedSome = true;
+ }
+ else if (type->GetClass() == NamedTypeReferenceClass)
+ {
+ if (type->GetNamedTypeReference()->GetTypeReferenceClass() == StructNamedTypeClass)
+ {
+ fprintf(out, "%s = %s\n", name.c_str(), type->GetNamedTypeReference()->GetName().GetString().c_str());
+ fprintf(out, "%sHandle = %sHandle\n", name.c_str(), type->GetNamedTypeReference()->GetName().GetString().c_str());
+ }
+ else if (type->GetNamedTypeReference()->GetTypeReferenceClass() == EnumNamedTypeClass)
+ {
+ fprintf(out, "%s = ctypes.c_int\n", name.c_str());
+ }
+ finishedStructs.insert(i);
+ processedSome = true;
+ }
+ }
+
+ if (!processedSome && structsToProcess.size() != 0)
+ {
+ fprintf(stderr, "Detected dependency cycle in structures\n");
+ for (auto& i : structsToProcess)
+ fprintf(stderr, "%s\n", i.GetString().c_str());
+ return 1;
+ }
+ }
+
+ fprintf(out, "\n# Function definitions\n");
+ for (auto& i : funcs)
+ {
+ string name;
+ if (i.first.size() != 1)
+ continue;
+ name = i.first[0];
+
+ // Check for a string result, these will be automatically wrapped to free the string
+ // memory and return a Python string
+ bool stringResult = (i.second->GetChildType()->GetClass() == PointerTypeClass) &&
+ (i.second->GetChildType()->GetChildType()->GetWidth() == 1) &&
+ (i.second->GetChildType()->GetChildType()->IsSigned());
+ // Pointer returns will be automatically wrapped to return None on null pointer
+ bool pointerResult = (i.second->GetChildType()->GetClass() == PointerTypeClass);
+
+ // From python -> C python3 requires str -> str.encode('charmap')
+ bool swizzleArgs = true;
+ if (name == "BNFreeString")
+ swizzleArgs = false;
+
+ bool callbackConvention = false;
+ if (name == "BNAllocString")
+ {
+ // Don't perform automatic wrapping of string allocation, and return a void
+ // pointer so that callback functions (which is the only valid use of BNDebuggerAllocString)
+ // can properly return the result
+ stringResult = false;
+ callbackConvention = true;
+ swizzleArgs = false;
+ }
+
+ string funcName = string("_") + name;
+
+ fprintf(out, "# -------------------------------------------------------\n");
+ fprintf(out, "# %s\n\n", funcName.c_str());
+ fprintf(out, "%s = core.%s\n", funcName.c_str(), name.c_str());
+ fprintf(out, "%s.restype = ", funcName.c_str());
+ OutputType(out, i.second->GetChildType().GetValue(), true, callbackConvention);
+ fprintf(out, "\n");
+ if (!i.second->HasVariableArguments())
+ {
+ fprintf(out, "%s.argtypes = [\n", funcName.c_str());
+ for (auto& j : i.second->GetParameters())
+ {
+ fprintf(out, "\t\t");
+ if (name == "BNFreeString")
+ {
+ // BNDebuggerFreeString expects a pointer to a string allocated by the core, so do not use
+ // a c_char_p here, as that would be allocated by the Python runtime. This can
+ // be enforced by outputting like a return value.
+ OutputType(out, j.type.GetValue(), true);
+ }
+ else
+ {
+ OutputType(out, j.type.GetValue());
+ }
+ fprintf(out, ",\n");
+ }
+ fprintf(out, "\t]");
+ }
+ else
+ {
+ // As of writing this, only BNLog's have variable instruction lengths, but in an attempt not to break in the future:
+ if (funcName.compare(0, 6, "_BNLog") == 0)
+ {
+ if (funcName != "_BNLog")
+ {
+ fprintf(out, "def %s(*args):\n", name.c_str());
+ fprintf(out, "\treturn %s(*[cstr(arg) for arg in args])\n\n", funcName.c_str());
+ continue;
+ }
+ else
+ {
+ fprintf(out, "def %s(level, *args):\n", name.c_str());
+ fprintf(out, "\treturn %s(level, *[cstr(arg) for arg in args])\n\n", funcName.c_str());
+ continue;
+ }
+ }
+ }
+ fprintf(out, "\n\n\n# noinspection PyPep8Naming\n");
+ fprintf(out, "def %s(", name.c_str());
+ if (!i.second->HasVariableArguments())
+ {
+ size_t argN = 0;
+ for (auto& arg: i.second->GetParameters())
+ {
+ string argName = arg.name;
+ if (g_pythonKeywordReplacements.find(argName) != g_pythonKeywordReplacements.end())
+ argName = g_pythonKeywordReplacements[argName];
+
+ if (argName.empty())
+ argName = "arg" + to_string(argN);
+
+ if (argN > 0)
+ fprintf(out, ", ");
+ fprintf(out, "\n\t\t");
+ fprintf(out, "%s: ", argName.c_str());
+ if (swizzleArgs)
+ OutputSwizzledType(out, arg.type.GetValue());
+ else
+ OutputType(out, arg.type.GetValue());
+ argN ++;
+ }
+ }
+ fprintf(out, "\n\t\t) -> ");
+ if (swizzleArgs)
+ {
+ if (stringResult || pointerResult)
+ fprintf(out, "Optional[");
+ OutputSwizzledType(out, i.second->GetChildType().GetValue());
+ if (stringResult || pointerResult)
+ fprintf(out, "]");
+ }
+ else
+ {
+ OutputType(out, i.second->GetChildType().GetValue());
+ }
+ fprintf(out, ":\n");
+
+ string stringArgFuncCall = funcName + "(";
+ size_t argN = 0;
+ for (auto& arg : i.second->GetParameters())
+ {
+ string argName = arg.name;
+ if (g_pythonKeywordReplacements.find(argName) != g_pythonKeywordReplacements.end())
+ argName = g_pythonKeywordReplacements[argName];
+
+ if (argName.empty())
+ argName = "arg" + to_string(argN);
+
+ if (swizzleArgs && (arg.type->GetClass() == PointerTypeClass) &&
+ (arg.type->GetChildType()->GetClass() == IntegerTypeClass) &&
+ (arg.type->GetChildType()->GetWidth() == 1) &&
+ (arg.type->GetChildType()->IsSigned()))
+ {
+ stringArgFuncCall += string("cstr(") + argName + "), ";
+ }
+ else
+ {
+ stringArgFuncCall += argName + ", ";
+ }
+ argN++;
+ }
+ if (argN > 0)
+ stringArgFuncCall = stringArgFuncCall.substr(0, stringArgFuncCall.size()-2);
+ stringArgFuncCall += ")";
+
+ if (stringResult)
+ {
+ // Emit wrapper to get Python string and free native memory
+ fprintf(out, "\tresult = ");
+ fprintf(out, "%s\n", stringArgFuncCall.c_str());
+ fprintf(out, "\tif not result:\n");
+ fprintf(out, "\t\treturn None\n");
+ fprintf(out, "\tstring = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))\n");
+ fprintf(out, "\tBNFreeString(result)\n");
+ fprintf(out, "\treturn string\n");
+ }
+ else if (pointerResult)
+ {
+ // Emit wrapper to return None on null pointer
+ fprintf(out, "\tresult = ");
+ fprintf(out, "%s\n", stringArgFuncCall.c_str());
+ fprintf(out, "\tif not result:\n");
+ fprintf(out, "\t\treturn None\n");
+ fprintf(out, "\treturn result\n");
+ }
+ else
+ {
+ fprintf(out, "\treturn ");
+ fprintf(out, "%s\n", stringArgFuncCall.c_str());
+ }
+ fprintf(out, "\n\n");
+ }
+
+ fprintf(out, "\n# Helper functions\n");
+ fprintf(out, "def handle_of_type(value, handle_type):\n");
+ fprintf(out, "\tif isinstance(value, ctypes.POINTER(handle_type)) or isinstance(value, ctypes.c_void_p):\n");
+ fprintf(out, "\t\treturn ctypes.cast(value, ctypes.POINTER(handle_type))\n");
+ fprintf(out, "\traise ValueError('expected pointer to %%s' %% str(handle_type))\n");
+
+ fclose(out);
+ fclose(enums);
+ return 0;
+}
diff --git a/plugins/warp/api/python/warp.py b/plugins/warp/api/python/warp.py
new file mode 100644
index 00000000..e0500215
--- /dev/null
+++ b/plugins/warp/api/python/warp.py
@@ -0,0 +1,384 @@
+import ctypes
+import dataclasses
+import uuid
+from typing import List, Optional, Union
+
+import binaryninja
+from binaryninja import BinaryView, Function, BasicBlock, Architecture, Platform, Type, Symbol, LowLevelILInstruction, LowLevelILFunction
+from binaryninja._binaryninjacore import BNFreeString, BNAllocString, BNType
+
+from . import _warpcore as warpcore
+
+
+class WarpUUID:
+ def __init__(self, _uuid: Union[warpcore.BNWARPUUID, str, uuid.UUID]):
+ if isinstance(_uuid, str):
+ _uuid = uuid.UUID(_uuid)
+ if isinstance(_uuid, uuid.UUID):
+ uuid_bytes = _uuid.bytes
+ _uuid = warpcore.BNWARPUUID()
+ _uuid.uuid = (ctypes.c_ubyte * 16).from_buffer_copy(uuid_bytes)
+ elif isinstance(_uuid, warpcore.BNWARPUUID):
+ # We must create a copy!
+ new_uuid = warpcore.BNWARPUUID()
+ new_uuid.uuid = (ctypes.c_ubyte * 16).from_buffer_copy(_uuid.uuid)
+ _uuid = new_uuid
+ self._uuid = _uuid
+
+ def to_string(self) -> str:
+ return warpcore.BNWARPUUIDGetString(self._uuid)
+
+ def __str__(self):
+ return self.to_string()
+
+ def __repr__(self):
+ return f"<WarpUUID '{str(self)}'>"
+
+ def __hash__(self):
+ # Hash based on the UUID bytes
+ return hash(bytes(self._uuid.uuid))
+
+ def __eq__(self, other):
+ if not isinstance(other, WarpUUID):
+ return False
+ return warpcore.BNWARPUUIDEqual(self._uuid, other._uuid)
+
+ @property
+ def uuid(self):
+ return self._uuid
+
+
+class Source(WarpUUID):
+ def __repr__(self):
+ return f"<Source '{str(self)}'>"
+
+
+class BasicBlockGUID(WarpUUID):
+ def __repr__(self):
+ return f"<BasicBlockGUID '{str(self)}'>"
+
+
+class FunctionGUID(WarpUUID):
+ def __repr__(self):
+ return f"<FunctionGUID '{str(self)}'>"
+
+
+class ConstraintGUID(WarpUUID):
+ def __repr__(self):
+ return f"<ConstraintGUID '{str(self)}'>"
+
+
+class TypeGUID(WarpUUID):
+ def __repr__(self):
+ return f"<TypeGUID '{str(self)}'>"
+
+
+@dataclasses.dataclass
+class WarpFunctionComment:
+ text: str
+ offset: int
+
+ def __str__(self):
+ return repr(self)
+
+ def __repr__(self):
+ return f"<WarpFunctionComment '{self.text}': {self.offset:#x}>"
+
+ @staticmethod
+ def from_api(comment: warpcore.BNWARPFunctionComment) -> 'WarpFunctionComment':
+ return WarpFunctionComment(
+ text=comment.text.decode('utf-8'),
+ offset=comment.offset
+ )
+
+@dataclasses.dataclass
+class WarpConstraint:
+ guid: ConstraintGUID
+ offset: Optional[int]
+
+ def __str__(self):
+ return repr(self)
+
+ def __repr__(self):
+ if self.offset is None:
+ return f"<WarpConstraint '{self.guid}'>"
+ return f"<WarpConstraint '{self.guid}': {self.offset:#x}>"
+
+ @staticmethod
+ def from_api(constraint: warpcore.BNWARPConstraint) -> 'WarpConstraint':
+ if constraint.offset == -1:
+ return WarpConstraint(guid=ConstraintGUID(constraint.guid), offset=None)
+ return WarpConstraint(guid=ConstraintGUID(constraint.guid), offset=constraint.offset)
+
+class WarpTarget:
+ def __init__(self, handle: Union[warpcore.BNWARPTarget, Platform]):
+ if isinstance(handle, Platform):
+ self.handle = warpcore.BNWARPGetTarget(handle.handle)
+ else:
+ self.handle = handle
+
+ def __del__(self):
+ if self.handle is not None:
+ warpcore.BNWARPFreeTargetReference(self.handle)
+
+ @staticmethod
+ def from_platform(platform: Platform) -> Optional['WarpTarget']:
+ handle = warpcore.BNWARPGetTarget(platform.handle)
+ if not handle:
+ return None
+ return WarpTarget(handle)
+
+
+class WarpFunction:
+ def __init__(self, handle: Union[warpcore.BNWARPFunction, Function]):
+ if isinstance(handle, Function):
+ self.handle = warpcore.BNWARPGetFunction(handle.handle)
+ else:
+ self.handle = handle
+ def __del__(self):
+ if self.handle is not None:
+ warpcore.BNWARPFreeFunctionReference(self.handle)
+
+ def __repr__(self):
+ return f"<WarpFunction '{self.name}': '{self.guid}'>"
+
+ @property
+ def guid(self) -> FunctionGUID:
+ return FunctionGUID(warpcore.BNWARPFunctionGetGUID(self.handle))
+
+ @property
+ def name(self) -> str:
+ return warpcore.BNWARPFunctionGetSymbolName(self.handle)
+
+ def get_symbol(self, function: Function) -> Symbol:
+ symbol_handle = warpcore.BNWARPFunctionGetSymbol(self.handle, function.handle)
+ return Symbol(symbol_handle)
+
+ def get_type(self, function: Function) -> Optional[Type]:
+ type_handle = warpcore.BNWARPFunctionGetType(self.handle, function.handle)
+ if not type_handle:
+ return None
+ return Type(type_handle)
+
+ @property
+ def constraints(self) -> List[WarpConstraint]:
+ count = ctypes.c_size_t()
+ constraints = warpcore.BNWARPFunctionGetConstraints(self.handle, count)
+ if not constraints:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpConstraint.from_api(constraints[i]))
+ warpcore.BNWARPFreeConstraintList(constraints, count.value)
+ return result
+
+ @property
+ def comments(self) -> List[WarpFunctionComment]:
+ count = ctypes.c_size_t()
+ comments = warpcore.BNWARPFunctionGetComments(self.handle, count)
+ if not comments:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpFunctionComment.from_api(comments[i]))
+ warpcore.BNWARPFreeFunctionCommentList(comments, count.value)
+ return result
+
+ @staticmethod
+ def get_matched(function: Function) -> Optional['WarpFunction']:
+ handle = warpcore.BNWARPGetMatchedFunction(function.handle)
+ if not handle:
+ return None
+ return WarpFunction(handle)
+
+ def apply(self, function: Function):
+ warpcore.BNWARPFunctionApply(self.handle, function.handle)
+
+
+class _WarpContainerMetaclass(type):
+ def __iter__(self):
+ binaryninja._init_plugins()
+ count = ctypes.c_ulonglong()
+ containers = warpcore.BNWARPGetContainers(count)
+ try:
+ for i in range(0, count.value):
+ yield WarpContainer(warpcore.BNWARPNewContainerReference(containers[i]))
+ finally:
+ warpcore.BNWARPFreeContainerList(containers, count.value)
+
+ def __getitem__(self, value):
+ binaryninja._init_plugins()
+ count = ctypes.c_ulonglong()
+ containers = warpcore.BNWARPGetContainers(count)
+ try:
+ for i in range(0, count.value):
+ container = WarpContainer(warpcore.BNWARPNewContainerReference(containers[i]))
+ if container.name == str(value):
+ return container
+ raise KeyError(f"'{value}' is not a valid container name")
+ finally:
+ warpcore.BNWARPFreeContainerList(containers, count.value)
+
+
+class WarpContainer(metaclass=_WarpContainerMetaclass):
+ def __init__(self, handle: warpcore.BNWARPContainer):
+ self.handle = handle
+
+ def __del__(self):
+ if self.handle is not None:
+ warpcore.BNWARPFreeContainerReference(self.handle)
+
+ def __repr__(self):
+ return f"<WarpContainer '{self.name}'>"
+
+ @staticmethod
+ def all() -> List['WarpContainer']:
+ count = ctypes.c_size_t()
+ containers = warpcore.BNWARPGetContainers(count)
+ if not containers:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpContainer(warpcore.BNWARPNewContainerReference(containers[i])))
+ warpcore.BNWARPFreeContainerList(containers, count.value)
+ return result
+
+ @property
+ def name(self) -> str:
+ return warpcore.BNWARPContainerGetName(self.handle)
+
+ @property
+ def sources(self) -> List[Source]:
+ count = ctypes.c_size_t()
+ sources = warpcore.BNWARPContainerGetSources(self.handle, count)
+ if not sources:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(Source(sources[i]))
+ warpcore.BNWARPFreeUUIDList(sources, count.value)
+ return result
+
+ def add_source(self, source_path: str) -> Optional[Source]:
+ source = warpcore.BNWARPUUID()
+ if not warpcore.BNWARPContainerAddSource(self.handle, source_path, source):
+ return None
+ return Source(source)
+
+ def commit_source(self, source: Source) -> bool:
+ return warpcore.BNWARPContainerCommitSource(self.handle, source.uuid)
+
+ def is_source_uncommitted(self, source: Source) -> bool:
+ return warpcore.BNWARPContainerIsSourceWritable(self.handle, source.uuid)
+
+ def is_source_writable(self, source: Source) -> bool:
+ return warpcore.BNWARPContainerIsSourceWritable(self.handle, source.uuid)
+
+ def get_source_path(self, source: Source) -> Optional[str]:
+ return warpcore.BNWARPContainerGetSourcePath(self.handle, source.uuid)
+
+ def add_functions(self, target: WarpTarget, source: Source, functions: List[Function]) -> bool:
+ count = len(functions)
+ core_funcs = (ctypes.POINTER(warpcore.BNWARPFunction) * count)()
+ for i in range(count):
+ core_funcs[i] = functions[i].handle
+ return warpcore.BNWARPContainerAddFunctions(self.handle, target.handle, source.uuid, core_funcs, count)
+
+ def add_types(self, view: BinaryView, source: Source, types: List[Type]) -> bool:
+ count = len(types)
+ core_types = (ctypes.POINTER(BNType) * count)()
+ for i in range(count):
+ core_types[i] = types[i].handle
+ return warpcore.BNWARPContainerAddTypes(view.handle, self.handle, source.uuid, core_types, count)
+
+ def remove_functions(self, target: WarpTarget, source: Source, functions: List[Function]) -> bool:
+ count = len(functions)
+ core_funcs = (ctypes.POINTER(warpcore.BNWARPFunction) * count)()
+ for i in range(count):
+ core_funcs[i] = functions[i].handle
+ return warpcore.BNWARPContainerRemoveFunctions(self.handle, target.handle, source.uuid, core_funcs, count)
+
+ def remove_types(self, source: Source, guids: List[TypeGUID]) -> bool:
+ count = len(guids)
+ core_guids = (ctypes.POINTER(warpcore.BNWARPTypeGUID) * count)()
+ for i in range(count):
+ core_guids[i] = guids[i].uuid
+ return warpcore.BNWARPContainerRemoveTypes(self.handle, source.uuid, core_guids, count)
+
+ def get_sources_with_function_guid(self, target: WarpTarget, guid: FunctionGUID) -> List[Source]:
+ count = ctypes.c_size_t()
+ sources = warpcore.BNWARPContainerGetSourcesWithFunctionGUID(self.handle, target.handle, guid.uuid, count)
+ if not sources:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(Source(sources[i]))
+ warpcore.BNWARPFreeUUIDList(sources, count.value)
+ return result
+
+ def get_sources_with_type_guid(self, guid: TypeGUID) -> List[Source]:
+ count = ctypes.c_size_t()
+ sources = warpcore.BNWARPContainerGetSourcesWithTypeGUID(self.handle, guid.uuid, count)
+ if not sources:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(Source(sources[i]))
+ warpcore.BNWARPFreeUUIDList(sources, count.value)
+ return result
+
+ def get_functions_with_guid(self, target: WarpTarget, source: Source, guid: FunctionGUID) -> List[Function]:
+ count = ctypes.c_size_t()
+ funcs = warpcore.BNWARPContainerGetFunctionsWithGUID(self.handle, target.handle, source.uuid, guid.uuid, count)
+ if not funcs:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpFunction(warpcore.BNWARPNewFunctionReference(funcs[i])))
+ warpcore.BNWARPFreeFunctionList(funcs, count.value)
+ return result
+
+ def get_type_with_guid(self, arch: Architecture, source: Source, guid: TypeGUID) -> Optional[Type]:
+ ty = warpcore.BNWARPContainerGetTypeWithGUID(self.handle, arch.handle, source.uuid, guid.uuid)
+ if not ty:
+ return None
+ return Type(ty)
+
+ def get_type_guids_with_name(self, source: Source, name: str) -> List[TypeGUID]:
+ count = ctypes.c_size_t()
+ guids = warpcore.BNWARPContainerGetTypeGUIDsWithName(self.handle, source.uuid, name, count)
+ if not guids:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(TypeGUID(guids[i]))
+ warpcore.BNWARPFreeUUIDList(guids, count.value)
+ return result
+
+
+def run_matcher(view: BinaryView):
+ warpcore.BNWARPRunMatcher(view.handle)
+
+def is_instruction_variant(function: LowLevelILFunction, variant: LowLevelILInstruction) -> bool:
+ return warpcore.BNWARPIsLiftedInstructionVariant(function.handle, variant.instr_index)
+
+def is_instruction_blacklisted(function: LowLevelILFunction, variant: LowLevelILInstruction) -> bool:
+ return warpcore.BNWARPIsLiftedInstructionBlacklisted(function.handle, variant.instr_index)
+
+def get_function_guid(function: Function) -> Optional[FunctionGUID]:
+ guid = warpcore.BNWARPUUID()
+ if not warpcore.BNWARPGetAnalysisFunctionGUID(function.handle, guid):
+ return None
+ return FunctionGUID(guid)
+
+
+def get_basic_block_guid(basic_block: BasicBlock) -> Optional[BasicBlockGUID]:
+ # TODO: I believe this won't work for HLIL: https://github.com/Vector35/binaryninja-api/issues/6998
+ if basic_block.is_il:
+ basic_block = basic_block.source_block
+ guid = warpcore.BNWARPUUID()
+ if not warpcore.BNWARPGetBasicBlockGUID(basic_block.handle, guid):
+ return None
+ return BasicBlockGUID(guid)
+
+# TODO: Magic matched_function, possible_functions \ No newline at end of file
diff --git a/plugins/warp/api/python/warp_enums.py b/plugins/warp/api/python/warp_enums.py
new file mode 100644
index 00000000..e47ff1c3
--- /dev/null
+++ b/plugins/warp/api/python/warp_enums.py
@@ -0,0 +1 @@
+import enum
diff --git a/plugins/warp/api/warp.cpp b/plugins/warp/api/warp.cpp
new file mode 100644
index 00000000..7d91c6e2
--- /dev/null
+++ b/plugins/warp/api/warp.cpp
@@ -0,0 +1,336 @@
+#include "warpcore.h"
+#include "warp.h"
+
+#include <utility>
+
+using namespace Warp;
+
+std::string WarpUUID::ToString() const
+{
+ char *str = BNWARPUUIDGetString(&uuid);
+ std::string result = str;
+ BNFreeString(str);
+ return result;
+}
+
+Target::Target(BNWARPTarget *target)
+{
+ m_object = target;
+}
+
+Ref<Target> Target::FromPlatform(const BinaryNinja::Platform &platform)
+{
+ BNWARPTarget *result = BNWARPGetTarget(platform.m_object);
+ if (!result)
+ return nullptr;
+ return new Target(result);
+}
+
+Constraint::Constraint(ConstraintGUID guid, std::optional<int64_t> offset)
+{
+ this->guid = guid;
+ this->offset = offset;
+}
+
+Constraint Constraint::FromAPIObject(BNWARPConstraint *constraint)
+{
+ auto offset = constraint->offset == INT64_MAX ? std::nullopt : std::optional(constraint->offset);
+ return {constraint->guid, offset};
+}
+
+FunctionComment::FunctionComment(std::string text, int64_t offset)
+{
+ this->text = std::move(text);
+ this->offset = offset;
+}
+
+FunctionComment FunctionComment::FromAPIObject(BNWARPFunctionComment *comment)
+{
+ return {comment->text, comment->offset};
+}
+
+Function::Function(BNWARPFunction *function)
+{
+ m_object = function;
+}
+
+FunctionGUID Function::GetGUID() const
+{
+ return BNWARPFunctionGetGUID(m_object);
+}
+
+std::string Function::GetSymbolName() const
+{
+ char *name = BNWARPFunctionGetSymbolName(m_object);
+ std::string result = name;
+ BNFreeString(name);
+ return result;
+}
+
+BinaryNinja::Ref<BinaryNinja::Symbol> Function::GetSymbol(const BinaryNinja::Function &function) const
+{
+ BNSymbol *symbol = BNWARPFunctionGetSymbol(m_object, function.m_object);
+ if (!symbol)
+ return nullptr;
+ return new BinaryNinja::Symbol(symbol);
+}
+
+BinaryNinja::Ref<BinaryNinja::Type> Function::GetType(const BinaryNinja::Function &function) const
+{
+ BNType *type = BNWARPFunctionGetType(m_object, function.m_object);
+ if (!type)
+ return nullptr;
+ return new BinaryNinja::Type(type);
+}
+
+std::vector<Constraint> Function::GetConstraints() const
+{
+ size_t count;
+ BNWARPConstraint *constraints = BNWARPFunctionGetConstraints(m_object, &count);
+ std::vector<Constraint> result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.push_back(Constraint::FromAPIObject(&constraints[i]));
+ BNWARPFreeConstraintList(constraints, count);
+ return result;
+}
+
+std::vector<FunctionComment> Function::GetComments() const
+{
+ size_t count;
+ BNWARPFunctionComment *comments = BNWARPFunctionGetComments(m_object, &count);
+ std::vector<FunctionComment> result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.push_back(FunctionComment::FromAPIObject(&comments[i]));
+ BNWARPFreeFunctionCommentList(comments, count);
+ return result;
+}
+
+Ref<Function> Function::Get(const BinaryNinja::Function &function)
+{
+ BNWARPFunction *result = BNWARPGetFunction(function.m_object);
+ if (!result)
+ return nullptr;
+ return new Function(result);
+}
+
+Ref<Function> Function::GetMatched(const BinaryNinja::Function &function)
+{
+ BNWARPFunction *result = BNWARPGetMatchedFunction(function.m_object);
+ if (!result)
+ return nullptr;
+ return new Function(result);
+}
+
+void Function::Apply(const BinaryNinja::Function &function) const
+{
+ BNWARPFunctionApply(m_object, function.m_object);
+}
+
+void Function::RemoveMatch(const BinaryNinja::Function &function)
+{
+ BNWARPFunctionApply(nullptr, function.m_object);
+}
+
+Container::Container(BNWARPContainer *container)
+{
+ m_object = container;
+}
+
+std::vector<Ref<Container> > Container::All()
+{
+ size_t count;
+ BNWARPContainer **containers = BNWARPGetContainers(&count);
+ std::vector<Ref<Container> > result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.push_back(new Container(BNWARPNewContainerReference(containers[i])));
+ BNWARPFreeContainerList(containers, count);
+ return result;
+}
+
+std::string Container::GetName() const
+{
+ char *rawName = BNWARPContainerGetName(m_object);
+ std::string name = rawName;
+ BNFreeString(rawName);
+ return name;
+}
+
+std::vector<Source> Container::GetSources() const
+{
+ size_t count;
+ BNWARPSource *sources = BNWARPContainerGetSources(m_object, &count);
+ std::vector<Source> result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.emplace_back(sources[i]);
+ BNWARPFreeUUIDList(sources, count);
+ return result;
+}
+
+std::optional<Source> Container::AddSource(const std::string &sourcePath) const
+{
+ Source source;
+ if (!BNWARPContainerAddSource(m_object, sourcePath.c_str(), source.RawMut()))
+ return std::nullopt;
+ return source;
+}
+
+bool Container::CommitSource(const Source &source) const
+{
+ return BNWARPContainerCommitSource(m_object, source.Raw());
+}
+
+bool Container::IsSourceUncommitted(const Source &source) const
+{
+ return BNWARPContainerIsSourceUncommitted(m_object, source.Raw());
+}
+
+bool Container::IsSourceWritable(const Source &source) const
+{
+ return BNWARPContainerIsSourceWritable(m_object, source.Raw());
+}
+
+std::optional<std::string> Container::SourcePath(const Source &source) const
+{
+ char *rawPath = BNWARPContainerGetSourcePath(m_object, source.Raw());
+ if (!rawPath)
+ return std::nullopt;
+ std::string path = rawPath;
+ BNFreeString(rawPath);
+ return path;
+}
+
+bool Container::AddFunctions(const Target &target, const Source &source, const std::vector<Ref<Function> > &functions) const
+{
+ size_t count = functions.size();
+ BNWARPFunction **apiFunctions = new BNWARPFunction *[count];
+ for (size_t i = 0; i < count; i++)
+ apiFunctions[i] = functions[i]->m_object;
+ const bool result = BNWARPContainerAddFunctions(m_object, target.m_object, source.Raw(), apiFunctions, count);
+ delete[] apiFunctions;
+ return result;
+}
+
+bool Container::AddTypes(const BinaryNinja::BinaryView &view, const Source &source,
+ const std::vector<BinaryNinja::Ref<BinaryNinja::Type> > &types) const
+{
+ size_t count = types.size();
+ BNType **apiTypes = new BNType *[count];
+ for (size_t i = 0; i < count; i++)
+ apiTypes[i] = types[i]->m_object;
+ const bool result = BNWARPContainerAddTypes(view.m_object, m_object, source.Raw(), apiTypes, count);
+ delete[] apiTypes;
+ return result;
+}
+
+bool Container::RemoveFunctions(const Target &target, const Source &source,
+ const std::vector<Ref<Function>> &functions) const
+{
+ size_t count = functions.size();
+ BNWARPFunction **apiFunctions = new BNWARPFunction *[count];
+ for (size_t i = 0; i < count; i++)
+ apiFunctions[i] = functions[i]->m_object;
+ const bool result = BNWARPContainerRemoveFunctions(m_object, target.m_object, source.Raw(), apiFunctions, count);
+ delete[] apiFunctions;
+ return result;
+}
+
+bool Container::RemoveTypes(const Source &source, const std::vector<TypeGUID> &guids) const
+{
+ size_t count = guids.size();
+ BNWARPTypeGUID* apiGuids = new BNWARPTypeGUID[count];
+ for (size_t i = 0; i < count; i++)
+ apiGuids[i] = *guids[i].Raw();
+ const bool result = BNWARPContainerRemoveTypes(m_object, source.Raw(), apiGuids, count);
+ delete[] apiGuids;
+ return result;
+}
+
+std::vector<Source> Container::GetSourcesWithFunctionGUID(const Target& target, const FunctionGUID &guid) const
+{
+ size_t count;
+ BNWARPSource *sources = BNWARPContainerGetSourcesWithFunctionGUID(m_object, target.m_object, guid.Raw(), &count);
+ std::vector<Source> result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.emplace_back(sources[i]);
+ BNWARPFreeUUIDList(sources, count);
+ return result;
+}
+
+std::vector<Source> Container::GetSourcesWithTypeGUID(const TypeGUID &guid) const
+{
+ size_t count;
+ BNWARPSource *sources = BNWARPContainerGetSourcesWithTypeGUID(m_object, guid.Raw(), &count);
+ std::vector<Source> result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.emplace_back(sources[i]);
+ BNWARPFreeUUIDList(sources, count);
+ return result;
+}
+
+std::vector<Ref<Function> > Container::GetFunctionsWithGUID(const Target& target, const Source &source, const FunctionGUID &guid) const
+{
+ size_t count;
+ BNWARPFunction **functions = BNWARPContainerGetFunctionsWithGUID(m_object, target.m_object, source.Raw(), guid.Raw(), &count);
+ std::vector<Ref<Function> > result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.push_back(new Function(BNWARPNewFunctionReference(functions[i])));
+ BNWARPFreeFunctionList(functions, count);
+ return result;
+}
+
+BinaryNinja::Ref<BinaryNinja::Type> Container::GetTypeWithGUID(const BinaryNinja::Architecture &arch,
+ const Source &source, const TypeGUID &guid) const
+{
+ BNType *type = BNWARPContainerGetTypeWithGUID(arch.m_object, m_object, source.Raw(), guid.Raw());
+ return new BinaryNinja::Type(type);
+}
+
+std::vector<TypeGUID> Container::GetTypeGUIDsWithName(const Source &source, const std::string &name) const
+{
+ size_t count;
+ BNWARPTypeGUID *guids = BNWARPContainerGetTypeGUIDsWithName(m_object, source.Raw(), name.c_str(), &count);
+ std::vector<TypeGUID> result;
+ result.reserve(count);
+ for (int i = 0; i < count; i++)
+ result.emplace_back(guids[i]);
+ BNWARPFreeUUIDList(guids, count);
+ return result;
+}
+
+void Warp::RunMatcher(const BinaryNinja::BinaryView &view)
+{
+ BNWARPRunMatcher(view.m_object);
+}
+
+bool IsInstructionVariant(const BinaryNinja::LowLevelILFunction &function, BinaryNinja::ExprId idx)
+{
+ return BNWARPIsLiftedInstructionVariant(function.m_object, idx);
+}
+
+bool IsInstructionBlacklisted(const BinaryNinja::LowLevelILFunction &function, BinaryNinja::ExprId idx)
+{
+ return BNWARPIsLiftedInstructionBlacklisted(function.m_object, idx);
+}
+
+std::optional<FunctionGUID> Warp::GetAnalysisFunctionGUID(const BinaryNinja::Function &function)
+{
+ FunctionGUID guid;
+ if (!BNWARPGetAnalysisFunctionGUID(function.m_object, guid.RawMut()))
+ return std::nullopt;
+ return guid;
+}
+
+std::optional<BasicBlockGUID> Warp::GetBasicBlockGUID(const BinaryNinja::BasicBlock &basicBlock)
+{
+ BasicBlockGUID guid;
+ if (!BNWARPGetBasicBlockGUID(basicBlock.m_object, guid.RawMut()))
+ return std::nullopt;
+ return guid;
+}
diff --git a/plugins/warp/api/warp.h b/plugins/warp/api/warp.h
new file mode 100644
index 00000000..b57a0c7b
--- /dev/null
+++ b/plugins/warp/api/warp.h
@@ -0,0 +1,378 @@
+#pragma once
+
+#include <binaryninjaapi.h>
+#include "warpcore.h"
+
+template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
+class WarpRefCountObject
+{
+ void AddRefInternal() { m_refs.fetch_add(1); }
+
+ void ReleaseInternal()
+ {
+ if (m_refs.fetch_sub(1) == 1)
+ {
+ if (!m_registeredRef)
+ delete this;
+ }
+ }
+
+public:
+ std::atomic<int> m_refs;
+ bool m_registeredRef = false;
+ T *m_object;
+
+ WarpRefCountObject() : m_refs(0), m_object(nullptr)
+ {
+ }
+
+ virtual ~WarpRefCountObject() = default;
+
+ T *GetObject() const { return m_object; }
+
+ static T *GetObject(WarpRefCountObject *obj)
+ {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
+
+ void AddRef()
+ {
+ if (m_object && (m_refs != 0))
+ AddObjectReference(m_object);
+ AddRefInternal();
+ }
+
+ void Release()
+ {
+ if (m_object)
+ FreeObjectReference(m_object);
+ ReleaseInternal();
+ }
+
+ void AddRefForRegistration() { m_registeredRef = true; }
+
+ void ReleaseForRegistration()
+ {
+ m_object = nullptr;
+ m_registeredRef = false;
+ if (m_refs == 0)
+ delete this;
+ }
+};
+
+namespace Warp {
+ template<class T>
+ class Ref
+ {
+ T *m_obj;
+#ifdef BN_REF_COUNT_DEBUG
+ void* m_assignmentTrace = nullptr;
+#endif
+
+ public:
+ Ref() : m_obj(NULL)
+ {
+ }
+
+ Ref(T *obj) : m_obj(obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ }
+ }
+
+ Ref(const Ref &obj) : m_obj(obj.m_obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ }
+ }
+
+ Ref(Ref &&other) : m_obj(other.m_obj)
+ {
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ }
+
+ ~Ref()
+ {
+ if (m_obj)
+ {
+ m_obj->Release();
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
+ }
+ }
+
+ Ref<T> &operator=(const Ref<T> &obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj.m_obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T *oldObj = m_obj;
+ m_obj = obj.m_obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
+
+ Ref<T> &operator=(Ref<T> &&other)
+ {
+ if (m_obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
+ m_obj->Release();
+ }
+ m_obj = other.m_obj;
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ return *this;
+ }
+
+ Ref<T> &operator=(T *obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T *oldObj = m_obj;
+ m_obj = obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
+
+ operator T *() const
+ {
+ return m_obj;
+ }
+
+ T *operator->() const
+ {
+ return m_obj;
+ }
+
+ T &operator*() const
+ {
+ return *m_obj;
+ }
+
+ bool operator!() const
+ {
+ return m_obj == NULL;
+ }
+
+ bool operator==(const T *obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj);
+ }
+
+ bool operator==(const Ref<T> &obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj.m_obj);
+ }
+
+ bool operator!=(const T *obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj);
+ }
+
+ bool operator!=(const Ref<T> &obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj.m_obj);
+ }
+
+ bool operator<(const T *obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj);
+ }
+
+ bool operator<(const Ref<T> &obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj.m_obj);
+ }
+
+ T *GetPtr() const
+ {
+ return m_obj;
+ }
+ };
+
+ class WarpUUID
+ {
+ BNWARPUUID uuid;
+
+ public:
+ WarpUUID() = default;
+
+ WarpUUID(BNWARPUUID uuid) : uuid(uuid) {}
+
+ std::string ToString() const;
+
+ bool operator==(const WarpUUID &other) const
+ {
+ return BNWARPUUIDEqual(&uuid, &other.uuid);
+ }
+
+ bool operator!=(const WarpUUID &other) const
+ {
+ return !(*this == other);
+ }
+
+ BNWARPUUID* RawMut()
+ {
+ return &uuid;
+ }
+
+ const BNWARPUUID* Raw() const
+ {
+ return &uuid;
+ }
+ };
+
+ typedef WarpUUID Source;
+ typedef WarpUUID BasicBlockGUID;
+ typedef WarpUUID FunctionGUID;
+ typedef WarpUUID ConstraintGUID;
+ typedef WarpUUID TypeGUID;
+
+ class Target : public WarpRefCountObject<BNWARPTarget, BNWARPNewTargetReference,
+ BNWARPFreeTargetReference>
+ {
+ public:
+ explicit Target(BNWARPTarget *target);
+
+ static Ref<Target> FromPlatform(const BinaryNinja::Platform& platform);
+ };
+
+ struct Constraint
+ {
+ ConstraintGUID guid;
+ std::optional<int64_t> offset;
+
+ Constraint(ConstraintGUID guid, std::optional<int64_t> offset);
+
+ static Constraint FromAPIObject(BNWARPConstraint* constraint);
+ };
+
+ struct FunctionComment
+ {
+ std::string text;
+ int64_t offset;
+
+ FunctionComment(std::string text, int64_t offset);
+
+ static FunctionComment FromAPIObject(BNWARPFunctionComment* comment);
+ };
+
+ class Function : public WarpRefCountObject<BNWARPFunction, BNWARPNewFunctionReference, BNWARPFreeFunctionReference>
+ {
+ public:
+ explicit Function(BNWARPFunction *function);
+
+ bool operator==(const Function &other) const
+ {
+ return BNWARPFunctionsEqual(m_object, other.m_object);
+ }
+
+ FunctionGUID GetGUID() const;
+
+ std::string GetSymbolName() const;
+
+ BinaryNinja::Ref<BinaryNinja::Symbol> GetSymbol(const BinaryNinja::Function &function) const;
+
+ BinaryNinja::Ref<BinaryNinja::Type> GetType(const BinaryNinja::Function &function) const;
+
+ std::vector<Constraint> GetConstraints() const;
+
+ std::vector<FunctionComment> GetComments() const;
+
+ static Ref<Function> Get(const BinaryNinja::Function &function);
+
+ static Ref<Function> GetMatched(const BinaryNinja::Function &function);
+
+ void Apply(const BinaryNinja::Function &function) const;
+
+ static void RemoveMatch(const BinaryNinja::Function &function);
+ };
+
+ class Container : public WarpRefCountObject<BNWARPContainer, BNWARPNewContainerReference,
+ BNWARPFreeContainerReference>
+ {
+ public:
+ explicit Container(BNWARPContainer *container);
+
+ /// Retrieve all available containers.
+ static std::vector<Ref<Container> > All();
+
+ std::string GetName() const;
+
+ std::vector<Source> GetSources() const;
+
+ std::optional<Source> AddSource(const std::string &sourcePath) const;
+
+ bool CommitSource(const Source &source) const;
+
+ bool IsSourceUncommitted(const Source &source) const;
+
+ bool IsSourceWritable(const Source &source) const;
+
+ std::optional<std::string> SourcePath(const Source &source) const;
+
+ bool AddFunctions(const Target &target, const Source &source, const std::vector<Ref<Function> > &functions) const;
+
+ bool AddTypes(const BinaryNinja::BinaryView &view, const Source &source,
+ const std::vector<BinaryNinja::Ref<BinaryNinja::Type> > &types) const;
+
+ bool RemoveFunctions(const Target &target, const Source &source, const std::vector<Ref<Function> > &functions) const;
+
+ bool RemoveTypes(const Source &source, const std::vector<TypeGUID> &guids) const;
+
+ std::vector<Source> GetSourcesWithFunctionGUID(const Target& target, const FunctionGUID &guid) const;
+
+ std::vector<Source> GetSourcesWithTypeGUID(const TypeGUID &guid) const;
+
+ std::vector<Ref<Function> > GetFunctionsWithGUID(const Target& target, const Source &source, const FunctionGUID &guid) const;
+
+ BinaryNinja::Ref<BinaryNinja::Type> GetTypeWithGUID(const BinaryNinja::Architecture &arch, const Source &source,
+ const TypeGUID &guid) const;
+
+ std::vector<TypeGUID> GetTypeGUIDsWithName(const Source &source, const std::string &name) const;
+ };
+
+ void RunMatcher(const BinaryNinja::BinaryView& view);
+
+ bool IsInstructionVariant(const BinaryNinja::LowLevelILFunction &function, BinaryNinja::ExprId idx);
+
+ bool IsInstructionBlacklisted(const BinaryNinja::LowLevelILFunction &function, BinaryNinja::ExprId idx);
+
+ std::optional<FunctionGUID> GetAnalysisFunctionGUID(const BinaryNinja::Function &function);
+
+ std::optional<BasicBlockGUID> GetBasicBlockGUID(const BinaryNinja::BasicBlock &basicBlock);
+}
diff --git a/plugins/warp/api/warpcore.h b/plugins/warp/api/warpcore.h
new file mode 100644
index 00000000..d12c6b98
--- /dev/null
+++ b/plugins/warp/api/warpcore.h
@@ -0,0 +1,143 @@
+#pragma once
+
+#ifndef BN_TYPE_PARSER
+#ifdef __cplusplus
+#include <cstdint>
+#include <cstddef>
+#include <cstdlib>
+#else
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#endif
+#endif
+
+#ifdef __GNUC__
+ #ifdef WARP_LIBRARY
+ #define WARP_FFI_API __attribute__((visibility("default")))
+ #else // WARP_LIBRARY
+ #define WARP_FFI_API
+ #endif // WARP_LIBRARY
+#else // __GNUC__
+ #ifdef _MSC_VER
+ #ifndef DEMO_VERSION
+ #ifdef WARP_LIBRARY
+ #define WARP_FFI_API __declspec(dllexport)
+ #else // WARP_LIBRARY
+ #define WARP_FFI_API __declspec(dllimport)
+ #endif // WARP_LIBRARY
+ #else
+ #define WARP_FFI_API
+ #endif
+ #else // _MSC_VER
+ #define WARP_FFI_API
+ #endif // _MSC_VER
+#endif // __GNUC__C
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct BNArchitecture BNArchitecture;
+ typedef struct BNBinaryView BNBinaryView;
+ typedef struct BNPlatform BNPlatform;
+ typedef struct BNBasicBlock BNBasicBlock;
+ typedef struct BNLowLevelILFunction BNLowLevelILFunction;
+ typedef struct BNFunction BNFunction;
+ typedef struct BNSymbol BNSymbol;
+ typedef struct BNType BNType;
+
+ struct BNWARPUUID
+ {
+ uint8_t uuid[16];
+ };
+
+ struct BNWARPFunctionComment
+ {
+ char* text;
+ int64_t offset;
+ };
+
+ char* BNWARPUUIDGetString(const BNWARPUUID* uuid);
+ bool BNWARPUUIDEqual(const BNWARPUUID* a, const BNWARPUUID* b);
+ void BNWARPFreeUUIDList(BNWARPUUID* uuids, size_t count);
+
+ typedef BNWARPUUID BNWARPSource;
+ typedef BNWARPUUID BNWARPBasicBlockGUID;
+ typedef BNWARPUUID BNWARPConstraintGUID;
+ typedef BNWARPUUID BNWARPFunctionGUID;
+ typedef BNWARPUUID BNWARPTypeGUID;
+
+ typedef struct BNWARPTarget BNWARPTarget;
+ typedef struct BNWARPContainer BNWARPContainer;
+ typedef struct BNWARPFunction BNWARPFunction;
+ typedef struct BNWARPConstraint BNWARPConstraint;
+
+ struct BNWARPConstraint
+ {
+ BNWARPConstraintGUID guid;
+ int64_t offset;
+ };
+
+ WARP_FFI_API void BNWARPRunMatcher(BNBinaryView* view);
+
+ WARP_FFI_API bool BNWARPGetBasicBlockGUID(BNBasicBlock* basicBlock, BNWARPBasicBlockGUID* result);
+ WARP_FFI_API bool BNWARPGetAnalysisFunctionGUID(BNFunction* analysisFunction, BNWARPFunctionGUID* result);
+ WARP_FFI_API bool BNWARPIsLiftedInstructionVariant(BNLowLevelILFunction* liftedFunction, size_t idx);
+ WARP_FFI_API bool BNWARPIsLiftedInstructionBlacklisted(BNLowLevelILFunction* liftedFunction, size_t idx);
+
+ WARP_FFI_API BNWARPFunction* BNWARPGetFunction(BNFunction* analysisFunction);
+ WARP_FFI_API BNWARPFunction* BNWARPGetMatchedFunction(BNFunction* analysisFunction);
+ WARP_FFI_API BNWARPContainer** BNWARPGetContainers(size_t* count);
+
+ WARP_FFI_API char* BNWARPContainerGetName(BNWARPContainer* container);
+
+ WARP_FFI_API BNWARPSource* BNWARPContainerGetSources(BNWARPContainer* container, size_t* count);
+ WARP_FFI_API bool BNWARPContainerAddSource(BNWARPContainer* container, const char* sourcePath, BNWARPSource* result);
+ WARP_FFI_API bool BNWARPContainerCommitSource(BNWARPContainer* container, const BNWARPSource* source);
+ WARP_FFI_API bool BNWARPContainerIsSourceUncommitted(BNWARPContainer* container, const BNWARPSource* source);
+ WARP_FFI_API bool BNWARPContainerIsSourceWritable(BNWARPContainer* container, const BNWARPSource* source);
+ WARP_FFI_API char* BNWARPContainerGetSourcePath(BNWARPContainer* container, const BNWARPSource* source);
+
+ WARP_FFI_API bool BNWARPContainerAddFunctions(BNWARPContainer* container, const BNWARPTarget* target, const BNWARPSource* source, BNWARPFunction** functions, size_t count);
+ WARP_FFI_API bool BNWARPContainerAddTypes(BNBinaryView* view, BNWARPContainer* container, const BNWARPSource* source, BNType** types, size_t count);
+
+ WARP_FFI_API bool BNWARPContainerRemoveFunctions(BNWARPContainer* container, const BNWARPTarget* target, const BNWARPSource* source, BNWARPFunction** functions, size_t count);
+ WARP_FFI_API bool BNWARPContainerRemoveTypes(BNWARPContainer* container, const BNWARPSource* source, BNWARPTypeGUID* types, size_t count);
+
+ WARP_FFI_API BNWARPSource* BNWARPContainerGetSourcesWithFunctionGUID(BNWARPContainer* container, const BNWARPTarget* target, const BNWARPFunctionGUID* guid, size_t* count);
+ WARP_FFI_API BNWARPSource* BNWARPContainerGetSourcesWithTypeGUID(BNWARPContainer* container, const BNWARPTypeGUID* guid, size_t* count);
+ WARP_FFI_API BNWARPFunction** BNWARPContainerGetFunctionsWithGUID(BNWARPContainer* container, const BNWARPTarget* target, const BNWARPSource* source, const BNWARPFunctionGUID* guid, size_t* count);
+ WARP_FFI_API BNType* BNWARPContainerGetTypeWithGUID(BNArchitecture* arch, BNWARPContainer* container, const BNWARPSource* source, const BNWARPTypeGUID* guid);
+ WARP_FFI_API BNWARPTypeGUID* BNWARPContainerGetTypeGUIDsWithName(BNWARPContainer* container, const BNWARPSource* source, const char* name, size_t* count);
+
+ WARP_FFI_API BNWARPContainer* BNWARPNewContainerReference(BNWARPContainer* container);
+ WARP_FFI_API void BNWARPFreeContainerReference(BNWARPContainer* container);
+ WARP_FFI_API void BNWARPFreeContainerList(BNWARPContainer** containers, size_t count);
+
+ WARP_FFI_API void BNWARPFunctionApply(BNWARPFunction* function, BNFunction* analysisFunction);
+ WARP_FFI_API BNWARPFunctionGUID BNWARPFunctionGetGUID(BNWARPFunction* function);
+ WARP_FFI_API BNSymbol* BNWARPFunctionGetSymbol(BNWARPFunction* function, BNFunction* analysisFunction);
+ WARP_FFI_API char* BNWARPFunctionGetSymbolName(BNWARPFunction* function);
+ WARP_FFI_API BNType* BNWARPFunctionGetType(BNWARPFunction* function, BNFunction* analysisFunction);
+ WARP_FFI_API BNWARPConstraint* BNWARPFunctionGetConstraints(BNWARPFunction* function, size_t* count);
+ WARP_FFI_API BNWARPFunctionComment* BNWARPFunctionGetComments(BNWARPFunction* function, size_t* count);
+ WARP_FFI_API bool BNWARPFunctionsEqual(BNWARPFunction* functionA, BNWARPFunction* functionB);
+
+ WARP_FFI_API void BNWARPFreeFunctionCommentList(BNWARPFunctionComment* comments, size_t count);
+ WARP_FFI_API void BNWARPFreeConstraintList(BNWARPConstraint* constraints, size_t count);
+
+ WARP_FFI_API BNWARPFunction* BNWARPNewFunctionReference(BNWARPFunction* function);
+ WARP_FFI_API void BNWARPFreeFunctionReference(BNWARPFunction* function);
+ WARP_FFI_API void BNWARPFreeFunctionList(BNWARPFunction** functions, size_t count);
+
+ WARP_FFI_API BNWARPTarget* BNWARPGetTarget(BNPlatform* platform);
+
+ WARP_FFI_API BNWARPTarget* BNWARPNewTargetReference(BNWARPTarget* target);
+ WARP_FFI_API void BNWARPFreeTargetReference(BNWARPTarget* target);
+
+#ifdef __cplusplus
+}
+#endif