diff options
| -rw-r--r-- | api-docs/cppdocs/Doxyfile | 2 | ||||
| -rw-r--r-- | binaryninjaapi.h | 156 | ||||
| -rw-r--r-- | python/settings.py | 2 |
3 files changed, 158 insertions, 2 deletions
diff --git a/api-docs/cppdocs/Doxyfile b/api-docs/cppdocs/Doxyfile index c2cd6428..72a82539 100644 --- a/api-docs/cppdocs/Doxyfile +++ b/api-docs/cppdocs/Doxyfile @@ -613,7 +613,7 @@ INLINE_INFO = YES # name. If set to NO, the members will appear in declaration order. # The default value is: YES. -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member diff --git a/binaryninjaapi.h b/binaryninjaapi.h index ca28377a..522024e7 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -9490,6 +9490,94 @@ namespace BinaryNinja { Ref<Repository> GetDefaultRepository(); }; + /*! \c Settings provides a way to define and access settings in a hierarchical fashion. The value of a setting can + be defined for each hierarchical level, where each level overrides the preceding level. The backing-store for setting + values at each level is also configurable. This allows for ephemeral or platform-independent persistent settings storage + for components within Binary Ninja or consumers of the Binary Ninja API. + + Each \c Settings instance has an \c instanceId which identifies a schema. The schema defines the settings contents + and the way in which settings are retrieved and manipulated. A new \c Settings instance defaults to using a value of <em><tt>default</tt></em> + for the \c instanceId . The <em><tt>default</tt></em> settings schema defines all of the settings available for the active Binary Ninja components + which include at a minimum, the settings defined by the Binary Ninja core. The <em><tt>default</tt></em> schema may additionally define settings + for the UI and/or installed plugins. Extending existing schemas, or defining new ones is accomplished by calling \c RegisterGroup() + and \c RegisterSetting() methods, or by deserializing an existing schema with \c DeserializeSchema() . + + \note All settings in the <em><tt>default</tt></em> settings schema are rendered with UI elements in the Settings View of Binary Ninja UI. + + Allowing setting overrides is an important feature and Binary Ninja accomplishes this by allowing one to override a setting at various + levels. The levels and their associated storage are shown in the following table. Default setting values are optional, and if specified, + saved in the schema itself. + + ================= ========================== ============== ============================================== + Setting Level Settings Scope Preference Storage + ================= ========================== ============== ============================================== + Default SettingsDefaultScope Lowest Settings Schema + User SettingsUserScope - <User Directory>/settings.json + Project SettingsProjectScope - <Project Directory>/.binaryninja/settings.json + Resource SettingsResourceScope Highest Raw BinaryView (Storage in BNDB) + ================= ========================== ============== ============================================== + + Settings are identified by a key, which is a string in the form of <b><tt><group>.<name></tt></b> or <b><tt><group>.<subGroup>.<name></tt></b> . Groups provide + a simple way to categorize settings. Sub-groups are optional and multiple sub-groups are allowed. When defining a settings group, the + \c RegisterGroup method allows for specifying a UI friendly title for use in the Binary Ninja UI. Defining a new setting requires a + unique setting key and a JSON string of property, value pairs. The following table describes the available properties and values. + + ================== ====================================== ================== ======== ======================================================================= + Property JSON Data Type Prerequisite Optional {Allowed Values} and Notes + ================== ====================================== ================== ======== ======================================================================= + "title" string None No Concise Setting Title + "type" string None No {"array", "boolean", "number", "string"} + "elementType" string "type" is "array" No {"string"} + "enum" array : {string} "type" is "array" Yes Enumeration definitions + "enumDescriptions" array : {string} "type" is "array" Yes Enumeration descriptions that match "enum" array + "minValue" number "type" is "number" Yes Specify 0 to infer unsigned (default is signed) + "maxValue" number "type" is "number" Yes Values less than or equal to INT_MAX result in a QSpinBox UI element + "precision" number "type" is "number" Yes Specify precision for a QDoubleSpinBox + "default" {array, boolean, number, string, null} None Yes Specify optimal default value + "aliases" array : {string} None Yes Array of deprecated setting key(s) + "description" string None No Detailed setting description + "ignore" array : {string} None Yes {"SettingsUserScope", "SettingsProjectScope", "SettingsResourceScope"} + "message" string None Yes An optional message with additional emphasis + "readOnly" bool None Yes Only enforced by UI elements + "optional" bool None Yes Indicates setting can be null + "requiresRestart bool None Yes Enable restart notification in the UI upon change + ================== ====================================== ================== ======== ======================================================================= + + \note In order to facilitate deterministic analysis results, settings from the <em><tt>default</tt></em> schema that impact analysis are serialized + from Default, User, and Project scope into Resource scope during initial BinaryView analysis. This allows an analysis database to be opened + at a later time with the same settings, regardless if Default, User, or Project settings have been modified. + + \note Settings that do not impact analysis (e.g. many UI settings) should use the \e "ignore" property to exclude + \e "SettingsProjectScope" and \e "SettingsResourceScope" from the applicable scopes for the setting. + + <b>Example analysis plugin setting:</b> + \code{.cpp} + auto settings = Settings::Instance() + + settings->RegisterGroup("myPlugin", "My Plugin") + + settings->RegisterSetting("myPlugin.enablePreAnalysis", + R"~({ + "title": "My Pre-Analysis Plugin", + "type": "boolean", + "default": false, + "description": "Enable extra analysis before core analysis.", + "ignore": ["SettingsProjectScope", "SettingsResourceScope"] + })~"); + + Json::Value options(Json::objectValue); + options["myPlugin.enablePreAnalysis"] = Json::Value(true); + Ref<BinaryView> bv = OpenView("/bin/ls", true, {}, options); + + Settings::Instance()->Get<bool>("myPlugin.enablePreAnalysis"); // false + Settings::Instance()->Get<bool>("myPlugin.enablePreAnalysis", bv); // true + \endcode + + <b>Getting a settings value:</b> + \code{.cpp} + bool excludeUnreferencedStrings = Settings::Instance()->Get<bool>("ui.stringView.excludeUnreferencedStrings", bv); + \endcode + */ class Settings : public CoreRefCountObject<BNSettings, BNNewSettingsReference, BNFreeSettings> { std::string m_instanceId; @@ -9502,12 +9590,51 @@ namespace BinaryNinja { static Ref<Settings> Instance(const std::string& schemaId = ""); virtual ~Settings() {} + /*! Sets the resource identifier for this \c Settings instance. When accessing setting values at the + \c SettingsResourceScope level, the resource identifier is passed along through the backing store interface. + + \note Currently the only available backing store for \c SettingsResourceScope is a \c BinaryView object. In the context + of a \c BinaryView the resource identifier is the \c BinaryViewType name. All settings for this type of backing store + are saved in the \e 'Raw' \c BinaryViewType . This enables the configuration of setting values such that they are available + during \c BinaryView creation and initialization. + + \param resourceId a unique identifier + */ void SetResourceId(const std::string& resourceId = ""); + /*! Registers a group in the schema for this \c Settings instance + + \param group a unique identifier + \param title a user friendly name appropriate for UI presentation + \return True on success, False on failure + */ bool RegisterGroup(const std::string& group, const std::string& title); + + /*! Registers a new setting with this \c Settings instance + + \param key a unique setting identifier in the form <b>'<group>.<name>'</b> + \param properties a JSON string describes the setting schema + \return True on success, False on failure. + */ bool RegisterSetting(const std::string& key, const std::string& properties); + + /*! Determine if a setting identifier exists in the active settings schema + + \param key the setting identifier + \return True if the identifier exists in this active settings schema, False otherwise + */ bool Contains(const std::string& key); + + /*! Determine if the active settings schema is empty + + \return True if the active settings schema is empty, False otherwise + */ bool IsEmpty(); + + /*! Retrieve the list of setting identifiers in the active settings schema + + \return List of setting identifiers + */ std::vector<std::string> Keys(); template <typename T> @@ -9533,8 +9660,33 @@ namespace BinaryNinja { bool ResetAll( Ref<BinaryView> view = nullptr, BNSettingsScope scope = SettingsAutoScope, bool schemaOnly = true); + /*! Get the current setting value for a particular key + + \code{.cpp} + bool excludeUnreferencedStrings = Settings::Instance()->Get<bool>("ui.stringView.excludeUnreferencedStrings", data); + \endcode + + \tparam T type for the value you are retrieving + \param key Key for the setting + \param view BinaryView, for factoring in resource-scoped settings + \param scope Scope for the settings + \return Value for the setting, with type T + */ template <typename T> T Get(const std::string& key, Ref<BinaryView> view = nullptr, BNSettingsScope* scope = nullptr); + + /*! Get the current settings value for a particular key, as a JSON representation of its value. + + \code{.cpp} + string value = Settings::Instance()->GetJson("analysis.mode"); + // '"full"' + \endcode + + \param key Key for the setting + \param view BinaryView, for factoring in resource-scoped settings + \param scope Scope for the settings + \return JSON value for the setting, as a string + */ std::string GetJson(const std::string& key, Ref<BinaryView> view = nullptr, BNSettingsScope* scope = nullptr); bool Set(const std::string& key, bool value, Ref<BinaryView> view = nullptr, @@ -9558,6 +9710,9 @@ namespace BinaryNinja { }; // explicit specializations + /*! \cond DOXYGEN_HIDE + Prevent these from having docs autogenerated twice, due to an odd quirk with doxygen + */ template <> std::vector<std::string> Settings::QueryProperty<std::vector<std::string>>( const std::string& key, const std::string& property); @@ -9574,6 +9729,7 @@ namespace BinaryNinja { template <> std::vector<std::string> Settings::Get<std::vector<std::string>>( const std::string& key, Ref<BinaryView> view, BNSettingsScope* scope); + /*! \endcond */ typedef BNMetadataType MetadataType; diff --git a/python/settings.py b/python/settings.py index 172c7392..55f0538f 100644 --- a/python/settings.py +++ b/python/settings.py @@ -113,7 +113,7 @@ class Settings: True >>> my_settings.register_setting("myPlugin.enableTableView", properties) True - >>> my_bv = open_view("/bin/ls", options={'myPlugin.enablePreAnalysis' : True}) + >>> my_bv = open_view("/bin/ls", options={'myPlugin.enableTableView' : True}) >>> Settings().get_bool("myPlugin.enableTableView") True |
