diff options
| author | Brian Potchik <brian@vector35.com> | 2024-08-20 14:27:35 -0400 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2024-08-20 14:27:35 -0400 |
| commit | 46b26cf9f4a8eee8e94f86532220e61120c2a54d (patch) | |
| tree | f308e0ce6a3cb4cab0172bbf2decef4d101c102c | |
| parent | 53164c16a6aff903c0eb4ed278cd2168c107f298 (diff) | |
Initial support for per-function settings.
| -rw-r--r-- | binaryninjaapi.h | 35 | ||||
| -rw-r--r-- | binaryninjacore.h | 40 | ||||
| -rw-r--r-- | python/settings.py | 357 | ||||
| -rw-r--r-- | rust/src/settings.rs | 14 | ||||
| -rw-r--r-- | settings.cpp | 198 | ||||
| -rw-r--r-- | view/macho/machoview.cpp | 2 |
6 files changed, 505 insertions, 141 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index eed15ac4..3f0ec438 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -16191,6 +16191,28 @@ namespace BinaryNinja { BNSettingsScope scope = SettingsAutoScope); bool SetJson(const std::string& key, const std::string& value, Ref<BinaryView> view = nullptr, BNSettingsScope scope = SettingsAutoScope); + + // Function Settings + bool DeserializeSettings(const std::string& contents, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + std::string SerializeSettings(Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + + bool Reset(const std::string& key, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool ResetAll(Ref<Function> func, BNSettingsScope scope = SettingsAutoScope, bool schemaOnly = true); + + template <typename T> + T Get(const std::string& key, Ref<Function> func, BNSettingsScope* scope = nullptr); + + std::string GetJson(const std::string& key, Ref<Function> func, BNSettingsScope* scope = nullptr); + + bool Set(const std::string& key, bool value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, double value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, int value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, int64_t value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, uint64_t value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, const char* value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, const std::string& value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool Set(const std::string& key, const std::vector<std::string>& value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); + bool SetJson(const std::string& key, const std::string& value, Ref<Function> func, BNSettingsScope scope = SettingsAutoScope); }; // explicit specializations @@ -16215,6 +16237,19 @@ namespace BinaryNinja { const std::string& key, Ref<BinaryView> view, BNSettingsScope* scope); /*! \endcond*/ + template <> + bool Settings::Get<bool>(const std::string& key, Ref<Function> func, BNSettingsScope* scope); + template <> + double Settings::Get<double>(const std::string& key, Ref<Function> func, BNSettingsScope* scope); + template <> + int64_t Settings::Get<int64_t>(const std::string& key, Ref<Function> func, BNSettingsScope* scope); + template <> + uint64_t Settings::Get<uint64_t>(const std::string& key, Ref<Function> func, BNSettingsScope* scope); + template <> + std::string Settings::Get<std::string>(const std::string& key, Ref<Function> func, BNSettingsScope* scope); + template <> + std::vector<std::string> Settings::Get<std::vector<std::string>>(const std::string& key, Ref<Function> func, BNSettingsScope* scope); + typedef BNMetadataType MetadataType; /*! DataRenderer objects tell the Linear View how to render specific types. diff --git a/binaryninjacore.h b/binaryninjacore.h index f06ca4e2..44165b2d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,14 +37,14 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 73 +#define BN_CURRENT_CORE_ABI_VERSION 74 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and // will require rebuilding. The minimum version is increased when there are // incompatible changes that break binary compatibility, such as changes to // existing types or functions. -#define BN_MINIMUM_CORE_ABI_VERSION 72 +#define BN_MINIMUM_CORE_ABI_VERSION 74 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -6887,44 +6887,44 @@ extern "C" BNSettings* settings, const char* schema, BNSettingsScope scope, bool merge); BINARYNINJACOREAPI char* BNSettingsSerializeSchema(BNSettings* settings); BINARYNINJACOREAPI bool BNDeserializeSettings( - BNSettings* settings, const char* contents, BNBinaryView* view, BNSettingsScope scope); - BINARYNINJACOREAPI char* BNSerializeSettings(BNSettings* settings, BNBinaryView* view, BNSettingsScope scope); + BNSettings* settings, const char* contents, BNBinaryView* view, BNFunction* func, BNSettingsScope scope); + BINARYNINJACOREAPI char* BNSerializeSettings(BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope); BINARYNINJACOREAPI bool BNSettingsReset( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope scope); BINARYNINJACOREAPI bool BNSettingsResetAll( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, bool schemaOnly); + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, bool schemaOnly); BINARYNINJACOREAPI bool BNSettingsGetBool( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope); BINARYNINJACOREAPI double BNSettingsGetDouble( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope); BINARYNINJACOREAPI int64_t BNSettingsGetInt64( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope); BINARYNINJACOREAPI uint64_t BNSettingsGetUInt64( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope); BINARYNINJACOREAPI char* BNSettingsGetString( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope); BINARYNINJACOREAPI const char** BNSettingsGetStringList( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope, size_t* inoutSize); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope, size_t* inoutSize); BINARYNINJACOREAPI char* BNSettingsGetJson( - BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope); + BNSettings* settings, const char* key, BNBinaryView* view, BNFunction* func, BNSettingsScope* scope); BINARYNINJACOREAPI bool BNSettingsSetBool( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, bool value); + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, bool value); BINARYNINJACOREAPI bool BNSettingsSetDouble( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, double value); + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, double value); BINARYNINJACOREAPI bool BNSettingsSetInt64( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, int64_t value); + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, int64_t value); BINARYNINJACOREAPI bool BNSettingsSetUInt64( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, uint64_t value); + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, uint64_t value); BINARYNINJACOREAPI bool BNSettingsSetString( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, const char* value); - BINARYNINJACOREAPI bool BNSettingsSetStringList(BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, const char* value); + BINARYNINJACOREAPI bool BNSettingsSetStringList(BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, const char** value, size_t size); BINARYNINJACOREAPI bool BNSettingsSetJson( - BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, const char* value); + BNSettings* settings, BNBinaryView* view, BNFunction* func, BNSettingsScope scope, const char* key, const char* value); // Metadata APIs diff --git a/python/settings.py b/python/settings.py index af9e4972..6a2227ae 100644 --- a/python/settings.py +++ b/python/settings.py @@ -23,7 +23,10 @@ import ctypes # Binary Ninja components from . import _binaryninjacore as core from .enums import SettingsScope +from . import binaryview +from . import function +from typing import List, Optional, Union class Settings: """ @@ -157,7 +160,7 @@ class Settings: return hash((self.instance_id, ctypes.addressof(self.handle.contents))) @property - def instance_id(self): + def instance_id(self) -> str: """Returns the ``instance_id`` for this :class:`Settings` repository (read-only)""" return self._instance_id @@ -173,14 +176,14 @@ class Settings: :param BinaryView view: a BinaryView object :rtype: bool """ - def load_settings_file(self, filename=None, scope=SettingsScope.SettingsAutoScope, view=None): + def load_settings_file(self, filename: str=None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope, view: Optional['binaryview.BinaryView'] = None) -> bool: if filename is None: filename = "" if view is not None: view = view.handle return core.BNLoadSettingsFile(self.handle, filename, scope, view) - def set_resource_id(self, resource_id=None): + def set_resource_id(self, resource_id: str = None): """ ``set_resource_id`` Sets the resource identifier for this class:`Settings` instance. When accessing setting values at the \ ``SettingsResourceScope`` level, the resource identifier is passed along through the backing store interface. @@ -197,7 +200,7 @@ class Settings: resource_id = "" core.BNSettingsSetResourceId(self.handle, resource_id) - def register_group(self, group, title): + def register_group(self, group: str, title: str) -> bool: """ ``register_group`` registers a group in the schema for this :class:`Settings` instance @@ -213,7 +216,7 @@ class Settings: """ return core.BNSettingsRegisterGroup(self.handle, group, title) - def register_setting(self, key, properties): + def register_setting(self, key: str, properties: str) -> bool: """ ``register_setting`` registers a new setting with this :class:`Settings` instance @@ -230,7 +233,7 @@ class Settings: """ return core.BNSettingsRegisterSetting(self.handle, key, properties) - def contains(self, key): + def contains(self, key: str) -> bool: """ ``contains`` determine if a setting identifier exists in the active settings schema @@ -240,7 +243,7 @@ class Settings: """ return core.BNSettingsContains(self.handle, key) - def is_empty(self): + def is_empty(self) -> bool: """ ``is_empty`` determine if the active settings schema is empty @@ -249,7 +252,7 @@ class Settings: """ return core.BNSettingsIsEmpty(self.handle) - def keys(self): + def keys(self) -> List[str]: """ ``keys`` retrieve the list of setting identifiers in the active settings schema @@ -265,7 +268,7 @@ class Settings: core.BNFreeStringList(result, length) return out_list - def query_property_string_list(self, key, property_name): + def query_property_string_list(self, key: str, property_name: str) -> List[str]: length = ctypes.c_ulonglong() result = core.BNSettingsQueryPropertyStringList(self.handle, key, property_name, ctypes.byref(length)) assert result is not None, "core.BNSettingsQueryPropertyStringList returned None" @@ -275,60 +278,123 @@ class Settings: core.BNFreeStringList(result, length) return out_list - def update_property(self, key, setting_property): + def update_property(self, key: str, setting_property: str) -> bool: return core.BNSettingsUpdateProperty(self.handle, key, setting_property) - def deserialize_schema(self, schema, scope=SettingsScope.SettingsAutoScope, merge=True): + def deserialize_schema(self, schema: str, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope, merge: bool = True) -> bool: return core.BNSettingsDeserializeSchema(self.handle, schema, scope, merge) - def serialize_schema(self): + def serialize_schema(self) -> str: return core.BNSettingsSerializeSchema(self.handle) - def deserialize_settings(self, contents, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNDeserializeSettings(self.handle, contents, view, scope) + def deserialize_settings(self, contents: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNDeserializeSettings(self.handle, contents, view_handle, func_handle, scope) - def serialize_settings(self, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSerializeSettings(self.handle, view, scope) + def serialize_settings(self, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> str: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSerializeSettings(self.handle, view_handle, func_handle, scope) - def reset(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSettingsReset(self.handle, key, view, scope) + def reset(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsReset(self.handle, key, view_handle, func_handle, scope) - def reset_all(self, view=None, scope=SettingsScope.SettingsAutoScope, schema_only=True): - if view is not None: - view = view.handle - return core.BNSettingsResetAll(self.handle, view, scope, schema_only) + def reset_all(self, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope, schema_only=True) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsResetAll(self.handle, view_handle, func_handle, scope, schema_only) - def get_bool(self, key, view=None): - if view is not None: - view = view.handle - return core.BNSettingsGetBool(self.handle, key, view, None) + def get_bool(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsGetBool(self.handle, key, view_handle, func_handle, None) - def get_double(self, key, view=None): - if view is not None: - view = view.handle - return core.BNSettingsGetDouble(self.handle, key, view, None) + def get_double(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None) -> float: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsGetDouble(self.handle, key, view_handle, func_handle, None) - def get_integer(self, key, view=None): - if view is not None: - view = view.handle - return core.BNSettingsGetUInt64(self.handle, key, view, None) + def get_integer(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None) -> int: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsGetUInt64(self.handle, key, view_handle, func_handle, None) - def get_string(self, key, view=None): - if view is not None: - view = view.handle - return core.BNSettingsGetString(self.handle, key, view, None) + def get_string(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None) -> str: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsGetString(self.handle, key, view_handle, func_handle, None) - def get_string_list(self, key, view=None): - if view is not None: - view = view.handle + def get_string_list(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None) -> List[str]: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") length = ctypes.c_ulonglong() - result = core.BNSettingsGetStringList(self.handle, key, view, None, ctypes.byref(length)) + result = core.BNSettingsGetStringList(self.handle, key, view_handle, func_handle, None, ctypes.byref(length)) assert result is not None, "core.BNSettingsGetStringList returned None" out_list = [] for i in range(length.value): @@ -336,45 +402,87 @@ class Settings: core.BNFreeStringList(result, length) return out_list - def get_json(self, key, view=None): - if view is not None: - view = view.handle - return core.BNSettingsGetJson(self.handle, key, view, None) + def get_json(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None) -> str: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsGetJson(self.handle, key, view_handle, func_handle, None) - def get_bool_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def get_bool_with_scope(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> (bool, SettingsScope): + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") c_scope = core.SettingsScopeEnum(scope) - result = core.BNSettingsGetBool(self.handle, key, view, ctypes.byref(c_scope)) + result = core.BNSettingsGetBool(self.handle, key, view_handle, func_handle, ctypes.byref(c_scope)) return (result, SettingsScope(c_scope.value)) - def get_double_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def get_double_with_scope(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> (float, SettingsScope): + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") c_scope = core.SettingsScopeEnum(scope) - result = core.BNSettingsGetDouble(self.handle, key, view, ctypes.byref(c_scope)) + result = core.BNSettingsGetDouble(self.handle, key, view_handle, func_handle, ctypes.byref(c_scope)) return (result, SettingsScope(c_scope.value)) - def get_integer_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def get_integer_with_scope(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> (int, SettingsScope): + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") c_scope = core.SettingsScopeEnum(scope) - result = core.BNSettingsGetUInt64(self.handle, key, view, ctypes.byref(c_scope)) + result = core.BNSettingsGetUInt64(self.handle, key, view_handle, func_handle, ctypes.byref(c_scope)) return (result, SettingsScope(c_scope.value)) - def get_string_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def get_string_with_scope(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> (str, SettingsScope): + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") c_scope = core.SettingsScopeEnum(scope) - result = core.BNSettingsGetString(self.handle, key, view, ctypes.byref(c_scope)) + result = core.BNSettingsGetString(self.handle, key, view_handle, func_handle, ctypes.byref(c_scope)) return (result, SettingsScope(c_scope.value)) - def get_string_list_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def get_string_list_with_scope(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> (List[str], SettingsScope): + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") c_scope = core.SettingsScopeEnum(scope) length = ctypes.c_ulonglong() - result = core.BNSettingsGetStringList(self.handle, key, view, ctypes.byref(c_scope), ctypes.byref(length)) + result = core.BNSettingsGetStringList(self.handle, key, view_handle, func_handle, ctypes.byref(c_scope), ctypes.byref(length)) assert result is not None, "core.BNSettingsGetStringList returned None" out_list = [] for i in range(length.value): @@ -382,44 +490,93 @@ class Settings: core.BNFreeStringList(result, length) return (out_list, SettingsScope(c_scope.value)) - def get_json_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def get_json_with_scope(self, key: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> (str, SettingsScope): + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") c_scope = core.SettingsScopeEnum(scope) - result = core.BNSettingsGetJson(self.handle, key, view, ctypes.byref(c_scope)) + result = core.BNSettingsGetJson(self.handle, key, view_handle, func_handle, ctypes.byref(c_scope)) return (result, SettingsScope(c_scope.value)) - def set_bool(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSettingsSetBool(self.handle, view, scope, key, value) + def set_bool(self, key: str, value: bool, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsSetBool(self.handle, view_handle, func_handle, scope, key, value) - def set_double(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSettingsSetDouble(self.handle, view, scope, key, value) + def set_double(self, key: str, value: float, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsSetDouble(self.handle, view_handle, func_handle, scope, key, value) - def set_integer(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSettingsSetUInt64(self.handle, view, scope, key, value) + def set_integer(self, key: str, value: int, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsSetUInt64(self.handle, view_handle, func_handle, scope, key, value) - def set_string(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSettingsSetString(self.handle, view, scope, key, value) + def set_string(self, key: str, value: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsSetString(self.handle, view_handle, func_handle, scope, key, value) - def set_string_list(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle + def set_string_list(self, key: str, value: List[str], resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") length = ctypes.c_ulonglong() length.value = len(value) string_list = (ctypes.c_char_p * len(value))() for i in range(len(value)): string_list[i] = value[i].encode('charmap') - return core.BNSettingsSetStringList(self.handle, view, scope, key, string_list, length) + return core.BNSettingsSetStringList(self.handle, view_handle, func_handle, scope, key, string_list, length) - def set_json(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope): - if view is not None: - view = view.handle - return core.BNSettingsSetJson(self.handle, view, scope, key, value) + def set_json(self, key: str, value: str, resource: Optional[Union['binaryview.BinaryView', 'function.Function']] = None, scope: 'SettingsScope' = SettingsScope.SettingsAutoScope) -> bool: + view_handle = None + func_handle = None + if resource is not None: + if isinstance(resource, binaryview.BinaryView): + view_handle = resource.handle + elif isinstance(resource, function.Function): + func_handle = resource.handle + else: + raise TypeError("Expected resource to be either a BinaryView or a Function.") + return core.BNSettingsSetJson(self.handle, view_handle, func_handle, scope, key, value) diff --git a/rust/src/settings.rs b/rust/src/settings.rs index 3ec3e406..ff959cfc 100644 --- a/rust/src/settings.rs +++ b/rust/src/settings.rs @@ -78,6 +78,8 @@ impl Settings { unsafe { BNSettingsContains(self.handle, key.as_ref().as_ptr() as *mut _) } } + // TODO Update the settings API to take an optional BinaryView or Function. Separate functions or...? + pub fn get_bool<S: BnStrCompatible>( &self, key: S, @@ -98,6 +100,7 @@ impl Settings { self.handle, key.as_ref().as_ptr() as *mut _, view_handle, + std::ptr::null_mut(), scope_ptr, ) } @@ -123,6 +126,7 @@ impl Settings { self.handle, key.as_ref().as_ptr() as *mut _, view_handle, + std::ptr::null_mut(), scope_ptr, ) } @@ -148,6 +152,7 @@ impl Settings { self.handle, key.as_ref().as_ptr() as *mut _, view_handle, + std::ptr::null_mut(), scope_ptr, ) } @@ -173,6 +178,7 @@ impl Settings { self.handle, key.as_ref().as_ptr() as *mut _, view_handle, + std::ptr::null_mut(), scope_ptr, )) } @@ -200,6 +206,7 @@ impl Settings { self.handle, key.as_ref().as_ptr() as *mut _, view_handle, + std::ptr::null_mut(), scope_ptr, &mut size, ) as *mut *mut c_char, @@ -229,6 +236,7 @@ impl Settings { self.handle, key.as_ref().as_ptr() as *mut _, view_handle, + std::ptr::null_mut(), scope_ptr, )) } @@ -254,6 +262,7 @@ impl Settings { BNSettingsSetBool( self.handle, view_handle, + std::ptr::null_mut(), scope, key.as_ref().as_ptr() as *mut _, value, @@ -281,6 +290,7 @@ impl Settings { BNSettingsSetDouble( self.handle, view_handle, + std::ptr::null_mut(), scope, key.as_ref().as_ptr() as *mut _, value, @@ -308,6 +318,7 @@ impl Settings { BNSettingsSetUInt64( self.handle, view_handle, + std::ptr::null_mut(), scope, key.as_ref().as_ptr() as *mut _, value, @@ -336,6 +347,7 @@ impl Settings { BNSettingsSetString( self.handle, view_handle, + std::ptr::null_mut(), scope, key.as_ref().as_ptr() as *mut _, value.as_ref().as_ptr() as *mut _, @@ -372,6 +384,7 @@ impl Settings { BNSettingsSetStringList( self.handle, view_handle, + std::ptr::null_mut(), scope, key.as_ref().as_ptr() as *mut _, value.as_mut_ptr(), @@ -404,6 +417,7 @@ impl Settings { BNSettingsSetJson( self.handle, view_handle, + std::ptr::null_mut(), scope, key.as_ref().as_ptr() as *mut _, value.as_ref().as_ptr() as *mut _, diff --git a/settings.cpp b/settings.cpp index 59394c42..549c7b6a 100644 --- a/settings.cpp +++ b/settings.cpp @@ -179,13 +179,13 @@ string Settings::SerializeSchema() bool Settings::DeserializeSettings(const string& contents, Ref<BinaryView> view, BNSettingsScope scope) { - return BNDeserializeSettings(m_object, contents.c_str(), view ? view->GetObject() : nullptr, scope); + return BNDeserializeSettings(m_object, contents.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); } string Settings::SerializeSettings(Ref<BinaryView> view, BNSettingsScope scope) { - char* settingsStr = BNSerializeSettings(m_object, view ? view->GetObject() : nullptr, scope); + char* settingsStr = BNSerializeSettings(m_object, view ? view->GetObject() : nullptr, nullptr, scope); string settings(settingsStr); BNFreeString(settingsStr); return settings; @@ -194,48 +194,48 @@ string Settings::SerializeSettings(Ref<BinaryView> view, BNSettingsScope scope) bool Settings::Reset(const string& key, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsReset(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + return BNSettingsReset(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); } bool Settings::ResetAll(Ref<BinaryView> view, BNSettingsScope scope, bool schemaOnly) { - return BNSettingsResetAll(m_object, view ? view->GetObject() : nullptr, scope, schemaOnly); + return BNSettingsResetAll(m_object, view ? view->GetObject() : nullptr, nullptr, scope, schemaOnly); } template <> bool Settings::Get<bool>(const string& key, Ref<BinaryView> view, BNSettingsScope* scope) { - return BNSettingsGetBool(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + return BNSettingsGetBool(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); } template <> double Settings::Get<double>(const string& key, Ref<BinaryView> view, BNSettingsScope* scope) { - return BNSettingsGetDouble(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + return BNSettingsGetDouble(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); } template <> int64_t Settings::Get<int64_t>(const string& key, Ref<BinaryView> view, BNSettingsScope* scope) { - return BNSettingsGetInt64(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + return BNSettingsGetInt64(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); } template <> uint64_t Settings::Get<uint64_t>(const string& key, Ref<BinaryView> view, BNSettingsScope* scope) { - return BNSettingsGetUInt64(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + return BNSettingsGetUInt64(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); } template <> string Settings::Get<string>(const string& key, Ref<BinaryView> view, BNSettingsScope* scope) { - char* tmpStr = BNSettingsGetString(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + char* tmpStr = BNSettingsGetString(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); string result(tmpStr); BNFreeString(tmpStr); return result; @@ -247,7 +247,7 @@ vector<string> Settings::Get<vector<string>>(const string& key, Ref<BinaryView> { size_t size = 0; char** outBuffer = - (char**)BNSettingsGetStringList(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope, &size); + (char**)BNSettingsGetStringList(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope, &size); vector<string> result; result.reserve(size); @@ -261,7 +261,7 @@ vector<string> Settings::Get<vector<string>>(const string& key, Ref<BinaryView> string Settings::GetJson(const string& key, Ref<BinaryView> view, BNSettingsScope* scope) { - char* tmpStr = BNSettingsGetJson(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope); + char* tmpStr = BNSettingsGetJson(m_object, key.c_str(), view ? view->GetObject() : nullptr, nullptr, scope); string result(tmpStr); BNFreeString(tmpStr); return result; @@ -270,43 +270,43 @@ string Settings::GetJson(const string& key, Ref<BinaryView> view, BNSettingsScop bool Settings::Set(const string& key, bool value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetBool(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value); + return BNSettingsSetBool(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value); } bool Settings::Set(const string& key, double value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetDouble(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value); + return BNSettingsSetDouble(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value); } bool Settings::Set(const string& key, int value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetInt64(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value); + return BNSettingsSetInt64(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value); } bool Settings::Set(const string& key, int64_t value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetInt64(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value); + return BNSettingsSetInt64(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value); } bool Settings::Set(const string& key, uint64_t value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetUInt64(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value); + return BNSettingsSetUInt64(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value); } bool Settings::Set(const string& key, const char* value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetString(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value); + return BNSettingsSetString(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value); } bool Settings::Set(const string& key, const string& value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetString(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value.c_str()); + return BNSettingsSetString(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value.c_str()); } @@ -320,7 +320,7 @@ bool Settings::Set(const string& key, const vector<string>& value, Ref<BinaryVie buffer[i] = BNAllocString(value[i].c_str()); bool result = BNSettingsSetStringList( - m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), (const char**)buffer, value.size()); + m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), (const char**)buffer, value.size()); for (size_t i = 0; i < value.size(); i++) BNFreeString(buffer[i]); @@ -331,5 +331,163 @@ bool Settings::Set(const string& key, const vector<string>& value, Ref<BinaryVie bool Settings::SetJson(const string& key, const string& value, Ref<BinaryView> view, BNSettingsScope scope) { - return BNSettingsSetJson(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value.c_str()); + return BNSettingsSetJson(m_object, view ? view->GetObject() : nullptr, nullptr, scope, key.c_str(), value.c_str()); +} + + +bool Settings::DeserializeSettings(const string& contents, Ref<Function> func, BNSettingsScope scope) +{ + return BNDeserializeSettings(m_object, contents.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); +} + + +string Settings::SerializeSettings(Ref<Function> func, BNSettingsScope scope) +{ + char* settingsStr = BNSerializeSettings(m_object, nullptr, func ? func->GetObject() : nullptr, scope); + string settings(settingsStr); + BNFreeString(settingsStr); + return settings; +} + + +bool Settings::Reset(const string& key, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsReset(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); +} + + +bool Settings::ResetAll(Ref<Function> func, BNSettingsScope scope, bool schemaOnly) +{ + return BNSettingsResetAll(m_object, nullptr, func ? func->GetObject() : nullptr, scope, schemaOnly); +} + + +template <> +bool Settings::Get<bool>(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + return BNSettingsGetBool(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); +} + + +template <> +double Settings::Get<double>(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + return BNSettingsGetDouble(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); +} + + +template <> +int64_t Settings::Get<int64_t>(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + return BNSettingsGetInt64(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); +} + + +template <> +uint64_t Settings::Get<uint64_t>(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + return BNSettingsGetUInt64(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); +} + + +template <> +string Settings::Get<string>(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + char* tmpStr = BNSettingsGetString(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); + string result(tmpStr); + BNFreeString(tmpStr); + return result; +} + + +template <> +vector<string> Settings::Get<vector<string>>(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + size_t size = 0; + char** outBuffer = + (char**)BNSettingsGetStringList(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope, &size); + + vector<string> result; + result.reserve(size); + for (size_t i = 0; i < size; i++) + result.emplace_back(outBuffer[i]); + + BNFreeStringList(outBuffer, size); + return result; +} + + +string Settings::GetJson(const string& key, Ref<Function> func, BNSettingsScope* scope) +{ + char* tmpStr = BNSettingsGetJson(m_object, key.c_str(), nullptr, func ? func->GetObject() : nullptr, scope); + string result(tmpStr); + BNFreeString(tmpStr); + return result; +} + + +bool Settings::Set(const string& key, bool value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetBool(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value); +} + + +bool Settings::Set(const string& key, double value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetDouble(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value); +} + + +bool Settings::Set(const string& key, int value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetInt64(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value); +} + + +bool Settings::Set(const string& key, int64_t value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetInt64(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value); +} + + +bool Settings::Set(const string& key, uint64_t value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetUInt64(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value); +} + + +bool Settings::Set(const string& key, const char* value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetString(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value); +} + + +bool Settings::Set(const string& key, const string& value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetString(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value.c_str()); +} + + +bool Settings::Set(const string& key, const vector<string>& value, Ref<Function> func, BNSettingsScope scope) +{ + char** buffer = new char*[value.size()]; + if (!buffer) + return false; + + for (size_t i = 0; i < value.size(); i++) + buffer[i] = BNAllocString(value[i].c_str()); + + bool result = BNSettingsSetStringList( + m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), (const char**)buffer, value.size()); + + for (size_t i = 0; i < value.size(); i++) + BNFreeString(buffer[i]); + delete[] buffer; + return result; +} + + +bool Settings::SetJson(const string& key, const string& value, Ref<Function> func, BNSettingsScope scope) +{ + return BNSettingsSetJson(m_object, nullptr, func ? func->GetObject() : nullptr, scope, key.c_str(), value.c_str()); } diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp index ad20ebaf..9d854f7b 100644 --- a/view/macho/machoview.cpp +++ b/view/macho/machoview.cpp @@ -250,7 +250,7 @@ MachoView::MachoView(const string& typeName, BinaryView* data, bool parseOnly): data->SetLoadSettings(typeName, loadSettings); if (!m_file->IsBackedByDatabase(typeName)) { - auto defaultSettings = loadSettings->SerializeSettings(nullptr, SettingsDefaultScope); + auto defaultSettings = loadSettings->SerializeSettings(Ref<BinaryView>(), SettingsDefaultScope); loadSettings->DeserializeSettings(defaultSettings, data, SettingsResourceScope); } |
