summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkat <katherine@vector35.com>2022-09-22 09:25:01 -0400
committerkat <katherine@vector35.com>2022-09-22 09:25:01 -0400
commite95b220ef18c9dd9e1aecab32b735ff47237f9c7 (patch)
treee302ace94bc5c8707edbc037c1fea55cfabc73cd
parent07be3689f173e7a55af5e795c10377e0afdd594f (diff)
Add the Components API
-rw-r--r--binaryninjaapi.h311
-rw-r--r--binaryninjacore.h52
-rw-r--r--binaryview.cpp163
-rw-r--r--component.cpp163
-rw-r--r--function.cpp18
-rw-r--r--python/__init__.py1
-rw-r--r--python/binaryview.py203
-rw-r--r--python/component.py266
-rw-r--r--python/function.py10
9 files changed, 1186 insertions, 1 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 6f0ca20a..752b9c52 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1586,6 +1586,7 @@ namespace BinaryNinja {
struct TagReference;
class Section;
class Segment;
+ class Component;
class BinaryDataNotification
{
@@ -1624,6 +1625,14 @@ namespace BinaryNinja {
static void SectionAddedCallback(void* ctx, BNBinaryView* data, BNSection* section);
static void SectionUpdatedCallback(void* ctx, BNBinaryView* data, BNSection* section);
static void SectionRemovedCallback(void* ctx, BNBinaryView* data, BNSection* section);
+ static void ComponentNameUpdatedCallback(void* ctxt, BNBinaryView* data, char* previousName, BNComponent* component);
+ static void ComponentAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* component);
+ static void ComponentRemovedCallback(
+ void* ctxt, BNBinaryView* data, BNComponent* formerParent, BNComponent* component);
+ static void ComponentMovedCallback(
+ void* ctxt, BNBinaryView* data, BNComponent* formerParent, BNComponent* newParent, BNComponent* component);
+ static void ComponentFunctionAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNFunction* function);
+ static void ComponentFunctionRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNFunction* function);
public:
@@ -1793,6 +1802,91 @@ namespace BinaryNinja {
(void)data;
(void)section;
}
+
+ /*! This notification is posted after the display name for a component is updated.
+
+ \param data BinaryView the Component is contained in
+ \param previousName Previous name of the component
+ \param component The component which was modified.
+ */
+ virtual void OnComponentNameUpdated(BinaryView* data, std::string& previousName, Component* component)
+ {
+ (void)data;
+ (void)previousName;
+ (void)component;
+ }
+
+ /*! This notification is posted after a Component is added to the tree.
+
+ \param data BinaryView the Component was added to
+ \param component Component which was added.
+ */
+ virtual void OnComponentAdded(BinaryView* data, Component* component)
+ {
+ (void)data;
+ (void)component;
+ }
+
+ /*! This notification is posted after a Component is removed from the tree.
+
+ \param data BinaryView the Component was removed from
+ \param formerParent Former parent of the Component
+ \param component
+ \parblock
+ The removed and now "dead" Component object.
+
+ This "dead" Component can no longer be moved to other components or have components added to it. It
+ should not be used after this point for storing any objects, and will be destroyed once no more references
+ are held to it.
+ \endparblock
+ */
+ virtual void OnComponentRemoved(BinaryView* data, Component* formerParent, Component* component)
+ {
+ (void)data;
+ (void)formerParent;
+ (void)component;
+ }
+
+ /*! This notification is posted whenever a component is moved from one component to another.
+
+ \param data BinaryView the Component was removed from
+ \param formerParent Former parent of the Component
+ \param newParent New parent which the Component was moved to
+ \param component The component that was moved.
+ */
+ virtual void OnComponentMoved(BinaryView* data, Component* formerParent, Component* newParent, Component* component)
+ {
+ (void)data;
+ (void)formerParent;
+ (void)newParent;
+ (void)component;
+ }
+
+ /*! This notification is posted whenever a Function is added to a Component
+
+ \param data BinaryView containing the Component and Function
+ \param component Component the Function was added to
+ \param function The Function which was added
+ */
+ virtual void OnComponentFunctionAdded(BinaryView* data, Component* component, Function* function)
+ {
+ (void)data;
+ (void)component;
+ (void)function;
+ }
+
+ /*! This notification is posted whenever a Function is removed from a Component
+
+ \param data BinaryView containing the Component and Function
+ \param component Component the Function was removed from
+ \param function The Function which was removed
+ */
+ virtual void OnComponentFunctionRemoved(BinaryView* data, Component* component, Function* function)
+ {
+ (void)data;
+ (void)component;
+ (void)function;
+ }
};
class FileAccessor
@@ -2367,6 +2461,7 @@ namespace BinaryNinja {
class Structure;
class NamedTypeReference;
struct TypeParserResult;
+ class Component;
class QueryMetadataException : public std::exception
{
@@ -3643,6 +3738,96 @@ namespace BinaryNinja {
Ref<Tag> CreateAutoDataTag(uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique = false);
Ref<Tag> CreateUserDataTag(uint64_t addr, Ref<TagType> tagType, const std::string& data, bool unique = false);
+ /*! Lookup a component by its GUID
+
+ \param guid GUID of the component to look up
+ \return The component with that GUID
+ */
+ std::optional<Ref<Component>> GetComponentByGuid(std::string guid);
+
+ /*! Lookup a component by its pathname
+
+ \note This is a convenience method, and for performance-sensitive lookups, GetComponentByGuid is very
+ highly recommended.
+
+ \see GetComponentByGuid, Component::GetGuid
+
+ All lookups are absolute from the root component, and are case-sensitive. Pathnames are delimited with "/"
+
+ Lookups are done using the display name of the component, which is liable to change when it or its siblings
+ are moved around.
+
+ \see Component::GetDisplayName
+
+ \param path Path of the desired component
+ \return The component at that path
+ */
+ std::optional<Ref<Component>> GetComponentByPath(std::string path);
+
+ /*! Get the root component for the BinaryView (read-only)
+
+ This Component cannot be removed, and houses all unparented Components.
+
+ \return The Root Component
+ */
+ Ref<Component> GetRootComponent();
+
+ /*! Create a component
+
+ This component will be added to the root component and initialized with the name "Component"
+
+ \return The created Component
+ */
+ Ref<Component> CreateComponent();
+
+ /*! Create a component as a subcomponent of the component with a given Guid
+
+ This component will be initialized with the name "Component"
+
+ \param parentGUID Guid of the component this component will be added to
+ \return The created Component
+ */
+ Ref<Component> CreateComponent(std::string parentGUID);
+
+ /*! Create a component as a subcomponent of a given Component
+
+ This component will be initialized with the name "Component"
+
+ \param parent Parent Component
+ \return The created Component
+ */
+ Ref<Component> CreateComponent(Ref<Component> parent);
+
+ /*! Create a component with a given name and optional parent
+
+ \param name Name to initialize the component with
+ \param parentGUID Optional Guid of the component this component will be added to
+ \return The created Component
+ */
+ Ref<Component> CreateComponentWithName(std::string name, std::string parentGUID = {});
+
+ /*! Create a component with a given name and parent
+
+ \param name Name to initialize the component with
+ \param parentGUID Guid of the component this component will be added to
+ \return The created Component
+ */
+ Ref<Component> CreateComponentWithName(std::string name, Ref<Component> parent);
+
+ /*! Remove a component from the tree entirely. This will also by nature remove all subcomponents.
+
+ \param component Component to remove
+ \return Whether removal was successful
+ */
+ bool RemoveComponent(Ref<Component> component);
+
+ /*! Remove a component from the tree entirely. This will also by nature remove all subcomponents.
+
+ \param guid Guid of the Component to remove
+ \return Whether removal was successful
+ */
+ bool RemoveComponent(std::string guid);
+
/*! Check whether the given architecture supports assembling instructions
\param arch Architecture to check
@@ -7340,6 +7525,7 @@ namespace BinaryNinja {
};
class FlowGraph;
+ class Component;
struct SSAVariable;
class Function : public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction>
@@ -7409,6 +7595,7 @@ namespace BinaryNinja {
\return Whether this function needs update
*/
bool NeedsUpdate() const;
+ std::vector<Ref<Component>> GetParentComponents() const;
/*! Get a list of Basic Blocks for this function
@@ -11857,4 +12044,128 @@ namespace BinaryNinja {
virtual bool StoreData(const std::string& key, const std::string& data) override;
virtual bool DeleteData(const std::string& key) override;
};
+
+ /*! Components are objects that can contain Functions and other Components.
+
+ \note Components should not be instantiated directly. Instead use BinaryView::CreateComponent()
+
+ They can be queried for information about the functions contained within them.
+
+ Components have a Guid, which persistent across saves and loads of the database, and should be
+ used for retrieving components when such is required and a reference to the Component cannot be held.
+
+ */
+ class Component : public CoreRefCountObject<BNComponent, BNNewComponentReference, BNFreeComponent>
+ {
+ public:
+ Component(BNComponent* type);
+
+ /*! Get the unique identifier for this component.
+
+ \return Component GUID
+ */
+ std::string GetGuid();
+
+ bool operator==(const Component& other) const;
+ bool operator!=(const Component& other) const;
+
+ Ref<BinaryView> GetView();
+
+ /*! The displayed name for the component
+
+ This can differ from the GetOriginalName() value if the parent
+ component also contains other components with the same name.
+
+ Subsequent duplicates will return the original name with " (1)", " (2)" and so on appended.
+
+ This name can change whenever a different duplicate is removed.
+
+ \note For looking up Components, utilizing Guid is highly recommended, as it will *always* map to this component,
+ and as Guid lookups are faster by nature.
+
+ \return Component name
+ */
+ std::string GetDisplayName();
+
+ /*! The original name for the component
+
+ This may differ from Component::GetName() whenever the parent contains Components with the same original name.
+
+ This function will always return the value originally set for this Component.
+
+ \return Component name
+ */
+ std::string GetName();
+
+ /*! Set the name for the component
+
+ \see GetName(), GetOriginalName()
+
+ \param name New component name.
+ */
+ void SetName(const std::string &name);
+
+ /*! Get the parent component. If it's a top level component, it will return the "root" Component.
+
+ \return Parent Component
+ */
+ Ref<Component> GetParent();
+
+ /*! Add a function to this component
+
+ \param func Function to add.
+ \return True if the function was successfully added.
+ */
+ bool AddFunction(Ref<Function> func);
+
+ /*! Move a component to this component.
+
+ \param component Component to add.
+ \return True if the component was successfully added.
+ */
+ bool AddComponent(Ref<Component> component);
+
+ /*! Remove a Component from this Component, moving it to the root component.
+
+ This will not remove a component from the tree entirely.
+
+ \see BinaryView::GetRootComponent(), BinaryView::RemoveComponent()
+
+ \param component Component to remove
+ \return True if the component was successfully removed
+ */
+ bool RemoveComponent(Ref<Component> component);
+
+ /*! Remove a function
+
+ \param func Function to remove
+ \return True if the function was successfully removed.
+ */
+ bool RemoveFunction(Ref<Function> func);
+
+ /*! Get a list of types referenced by the functions in this Component.
+
+ \return vector of Type objects
+ */
+ std::vector<Ref<Type>> GetReferencedTypes();
+
+ /*! Get a list of components contained by this component.
+
+ \return vector of Component objects
+ */
+ std::vector<Ref<Component>> GetContainedComponents();
+
+ /*! Get a list of functions contained within this Component.
+
+ \return vector of Function objects
+ */
+ std::vector<Ref<Function>> GetContainedFunctions();
+
+ /*! Get a list of DataVariables referenced by the functions in this Component.
+
+ \return vector of DataVariable objects
+ */
+ std::vector<DataVariable> GetReferencedDataVariables();
+ };
+
} // namespace BinaryNinja
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 212c8b62..12c1b277 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -220,6 +220,7 @@ extern "C"
struct BNRepository;
struct BNRepoPlugin;
struct BNRepositoryManager;
+ struct BNComponent;
struct BNSettings;
struct BNMetadata;
struct BNReportCollection;
@@ -1379,6 +1380,12 @@ extern "C"
void (*sectionAdded)(void* ctxt, BNBinaryView* view, BNSection* section);
void (*sectionUpdated)(void* ctxt, BNBinaryView* view, BNSection* section);
void (*sectionRemoved)(void* ctxt, BNBinaryView* view, BNSection* section);
+ void (*componentNameUpdated)(void* ctxt, BNBinaryView* view, char* previousName, BNComponent* component);
+ void (*componentAdded)(void*ctxt, BNBinaryView* view, BNComponent* component);
+ void (*componentMoved)(void*ctxt, BNBinaryView* view, BNComponent* formerParent, BNComponent* newParent, BNComponent* component);
+ void (*componentRemoved)(void*ctxt, BNBinaryView* view, BNComponent* formerParent, BNComponent* component);
+ void (*componentFunctionAdded)(void*ctxt, BNBinaryView* view, BNComponent* component, BNFunction* function);
+ void (*componentFunctionRemoved)(void*ctxt, BNBinaryView* view, BNComponent* component, BNFunction* function);
};
struct BNFileAccessor
@@ -3324,6 +3331,16 @@ extern "C"
BINARYNINJACOREAPI BNSegment* BNGetSegmentAt(BNBinaryView* view, uint64_t addr);
BINARYNINJACOREAPI bool BNGetAddressForDataOffset(BNBinaryView* view, uint64_t offset, uint64_t* addr);
+ BINARYNINJACOREAPI BNComponent* BNGetComponentByGuid(BNBinaryView* view, const char *guid);
+ BINARYNINJACOREAPI BNComponent* BNGetRootComponent(BNBinaryView* view);
+ BINARYNINJACOREAPI BNComponent* BNCreateComponent(BNBinaryView* view);
+ BINARYNINJACOREAPI BNComponent* BNCreateComponentWithParent(BNBinaryView* view, const char* parentGUID);
+ BINARYNINJACOREAPI BNComponent* BNCreateComponentWithName(BNBinaryView* view, const char *name);
+ BINARYNINJACOREAPI BNComponent* BNCreateComponentWithParentAndName(BNBinaryView* view, const char* parentGUID, const char *name);
+ BINARYNINJACOREAPI BNComponent* BNGetComponentByPath(BNBinaryView* view, const char* path);
+ BINARYNINJACOREAPI bool BNRemoveComponent(BNBinaryView* view, BNComponent* component);
+ BINARYNINJACOREAPI bool BNRemoveComponentByGuid(BNBinaryView* view, const char *guid);
+
BINARYNINJACOREAPI void BNAddAutoSection(BNBinaryView* view, const char* name, uint64_t start, uint64_t length,
BNSectionSemantics semantics, const char* type, uint64_t align, uint64_t entrySize, const char* linkedSection,
const char* infoSection, uint64_t infoData);
@@ -3703,6 +3720,7 @@ extern "C"
BINARYNINJACOREAPI uint64_t BNGetFunctionHighestAddress(BNFunction* func);
BINARYNINJACOREAPI uint64_t BNGetFunctionLowestAddress(BNFunction* func);
BINARYNINJACOREAPI BNAddressRange* BNGetFunctionAddressRanges(BNFunction* func, size_t* count);
+ BINARYNINJACOREAPI BNComponent** BNGetFunctionParentComponents(BNFunction *func, size_t* count);
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelIL(BNFunction* func);
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelILIfAvailable(BNFunction* func);
@@ -5933,6 +5951,40 @@ extern "C"
BINARYNINJACOREAPI BNRepository* BNRepositoryManagerGetDefaultRepository(BNRepositoryManager* r);
+ // Components
+
+ BINARYNINJACOREAPI BNComponent* BNNewComponentReference(BNComponent *component);
+ BINARYNINJACOREAPI void BNFreeComponent(BNComponent *component);
+
+ BINARYNINJACOREAPI BNFunction** BNComponentGetContainedFunctions(BNComponent *component, size_t *count);
+ BINARYNINJACOREAPI BNComponent** BNComponentGetContainedComponents(BNComponent *component, size_t *count);
+
+ BINARYNINJACOREAPI BNDataVariable* BNComponentGetReferencedDataVariables(BNComponent *component, size_t *count);
+ BINARYNINJACOREAPI BNDataVariable* BNComponentGetReferencedDataVariablesRecursive(BNComponent *component, size_t *count);
+ BINARYNINJACOREAPI BNType** BNComponentGetReferencedTypes(BNComponent *component, size_t *count);
+ BINARYNINJACOREAPI BNType** BNComponentGetReferencedTypesRecursive(BNComponent *component, size_t *count);
+
+ BINARYNINJACOREAPI void BNFreeComponents(BNComponent** components, size_t count);
+ BINARYNINJACOREAPI void BNComponentFreeReferencedTypes(BNType** types, size_t count);
+
+ BINARYNINJACOREAPI BNComponent* BNComponentGetParent(BNComponent* component);
+
+ BINARYNINJACOREAPI bool BNComponentContainsFunction(BNComponent* component, BNFunction *function);
+ BINARYNINJACOREAPI bool BNComponentContainsComponent(BNComponent *parent, BNComponent *component);
+ BINARYNINJACOREAPI bool BNComponentAddFunctionReference(BNComponent* component, BNFunction* function);
+ BINARYNINJACOREAPI bool BNComponentAddComponent(BNComponent* parent, BNComponent* component);
+ BINARYNINJACOREAPI bool BNComponentRemoveComponent(BNComponent* component);
+ BINARYNINJACOREAPI void BNComponentAddAllMembersFromComponent(BNComponent *component, BNComponent *fromComponent);
+ BINARYNINJACOREAPI bool BNComponentRemoveFunctionReference(BNComponent *component, BNFunction *function);
+ BINARYNINJACOREAPI void BNComponentRemoveAllFunctions(BNComponent *component);
+ BINARYNINJACOREAPI char *BNComponentGetGuid(BNComponent *component);
+ BINARYNINJACOREAPI bool BNComponentsEqual(BNComponent* a, BNComponent* b);
+ BINARYNINJACOREAPI bool BNComponentsNotEqual(BNComponent* a, BNComponent* b);
+ BINARYNINJACOREAPI char *BNComponentGetDisplayName(BNComponent* component);
+ BINARYNINJACOREAPI char *BNComponentGetOriginalName(BNComponent* component);
+ BINARYNINJACOREAPI void BNComponentSetName(BNComponent* component, const char* name);
+ BINARYNINJACOREAPI BNBinaryView* BNComponentGetView(BNComponent* component);
+
// LLVM Services APIs
BINARYNINJACOREAPI void BNLlvmServicesInit(void);
diff --git a/binaryview.cpp b/binaryview.cpp
index db45cc88..fa00b4e9 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -299,6 +299,71 @@ void BinaryDataNotification::SectionRemovedCallback(void* ctxt, BNBinaryView* da
notify->OnSectionRemoved(view, sectionObj);
}
+void BinaryDataNotification::ComponentNameUpdatedCallback(void* ctxt, BNBinaryView* data, char *previousName, BNComponent* bnComponent)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Component> component = new Component(BNNewComponentReference(bnComponent));
+ std::string prevName = previousName;
+ BNFreeString(previousName);
+ notify->OnComponentNameUpdated(view, prevName, component);
+}
+
+
+void BinaryDataNotification::ComponentAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* bnComponent)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Component> component = new Component(BNNewComponentReference(bnComponent));
+ notify->OnComponentAdded(view, component);
+}
+
+
+void BinaryDataNotification::ComponentRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* bnFormerParent,
+ BNComponent* bnComponent)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Component> formerParent = new Component(BNNewComponentReference(bnFormerParent));
+ Ref<Component> component = new Component(BNNewComponentReference(bnComponent));
+ notify->OnComponentRemoved(view, formerParent, component);
+}
+
+
+void BinaryDataNotification::ComponentMovedCallback(void* ctxt, BNBinaryView* data, BNComponent* bnFormerParent,
+ BNComponent* bnNewParent, BNComponent* bnComponent)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Component> formerParent = new Component(BNNewComponentReference(bnFormerParent));
+ Ref<Component> newParent = new Component(BNNewComponentReference(bnNewParent));
+ Ref<Component> component = new Component(BNNewComponentReference(bnComponent));
+ notify->OnComponentMoved(view, formerParent, newParent, component);
+}
+
+
+void BinaryDataNotification::ComponentFunctionAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* bnComponent,
+ BNFunction* func)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Component> component = new Component(BNNewComponentReference(bnComponent));
+ Ref<Function> function = new Function(BNNewFunctionReference(func));
+ notify->OnComponentFunctionAdded(view, component, function);
+}
+
+
+void BinaryDataNotification::ComponentFunctionRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* bnComponent,
+ BNFunction* func)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Component> component = new Component(BNNewComponentReference(bnComponent));
+ Ref<Function> function = new Function(BNNewFunctionReference(func));
+ notify->OnComponentFunctionRemoved(view, component, function);
+}
+
+
BinaryDataNotification::BinaryDataNotification()
{
@@ -333,6 +398,12 @@ BinaryDataNotification::BinaryDataNotification()
m_callbacks.sectionAdded = SectionAddedCallback;
m_callbacks.sectionUpdated = SectionUpdatedCallback;
m_callbacks.sectionRemoved = SectionRemovedCallback;
+ m_callbacks.componentNameUpdated = ComponentNameUpdatedCallback;
+ m_callbacks.componentAdded = ComponentAddedCallback;
+ m_callbacks.componentRemoved = ComponentRemovedCallback;
+ m_callbacks.componentMoved = ComponentMovedCallback;
+ m_callbacks.componentFunctionAdded = ComponentFunctionAddedCallback;
+ m_callbacks.componentFunctionRemoved = ComponentFunctionRemovedCallback;
}
@@ -2873,11 +2944,103 @@ Ref<Tag> BinaryView::CreateUserDataTag(uint64_t addr, Ref<TagType> tagType, cons
return tag;
}
+
+std::optional<Ref<Component>> BinaryView::GetComponentByGuid(std::string guid)
+{
+ BNComponent* bncomponent = BNGetComponentByGuid(m_object, guid.c_str());
+
+ if (bncomponent)
+ {
+ auto component = new Component(bncomponent);
+ return std::optional<Ref<Component>>{component};
+ }
+
+ return std::nullopt;
+}
+
+Ref<Component> BinaryView::GetRootComponent()
+{
+ BNComponent* bncomponent = BNGetRootComponent(m_object);
+
+ return new Component(bncomponent);
+}
+
+
+std::optional<Ref<Component>> BinaryView::GetComponentByPath(std::string path)
+{
+ BNComponent* component = BNGetComponentByPath(this->m_object, path.c_str());
+ if (component)
+ return {new Component(component)};
+ return std::nullopt;
+}
+
+
+Ref<Component> BinaryView::CreateComponent()
+{
+ auto bnComponent = BNCreateComponent(m_object);
+
+ return new Component(bnComponent);
+}
+
+
+Ref<Component> BinaryView::CreateComponent(std::string parentGUID)
+{
+ BNComponent* bnComponent;
+ if (!parentGUID.empty())
+ bnComponent = BNCreateComponentWithParent(m_object, parentGUID.c_str());
+ else
+ bnComponent = BNCreateComponent(m_object);
+
+ return new Component(bnComponent);
+}
+
+
+Ref<Component> BinaryView::CreateComponent(Ref<Component> parent)
+{
+ auto bnComponent = BNCreateComponentWithParent(m_object, parent->GetGuid().c_str());
+
+ return new Component(bnComponent);
+}
+
+
+Ref<Component> BinaryView::CreateComponentWithName(std::string name, std::string parentGUID)
+{
+ BNComponent* bnComponent;
+ if (!parentGUID.empty())
+ bnComponent = BNCreateComponentWithParentAndName(m_object, parentGUID.c_str(), name.c_str());
+ else
+ bnComponent = BNCreateComponentWithName(m_object, name.c_str());
+
+ return new Component(bnComponent);
+}
+
+
+Ref<Component> BinaryView::CreateComponentWithName(std::string name, Ref<Component> parent)
+{
+ auto bnComponent = BNCreateComponentWithParentAndName(m_object, parent->GetGuid().c_str(), name.c_str());
+
+ return new Component(bnComponent);
+}
+
+
+bool BinaryView::RemoveComponent(Ref<Component> component)
+{
+ return BNRemoveComponent(m_object, component->m_object);
+}
+
+
+bool BinaryView::RemoveComponent(std::string guid)
+{
+ return BNRemoveComponentByGuid(m_object, guid.c_str());
+}
+
+
bool BinaryView::CanAssemble(Architecture* arch)
{
return BNCanAssemble(m_object, arch->GetObject());
}
+
bool BinaryView::IsNeverBranchPatchAvailable(Architecture* arch, uint64_t addr)
{
return BNIsNeverBranchPatchAvailable(m_object, arch->GetObject(), addr);
diff --git a/component.cpp b/component.cpp
new file mode 100644
index 00000000..88e7a20a
--- /dev/null
+++ b/component.cpp
@@ -0,0 +1,163 @@
+
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+bool Component::operator==(const Component& other) const
+{
+ return BNComponentsEqual(m_object, other.m_object);
+}
+
+
+bool Component::operator!=(const Component& other) const
+{
+ return BNComponentsNotEqual(m_object, other.m_object);
+}
+
+
+
+Component::Component(BNComponent* component)
+{
+ m_object = component;
+}
+
+
+std::string Component::GetDisplayName()
+{
+ return BNComponentGetDisplayName(m_object);
+}
+
+
+std::string Component::GetName()
+{
+ return BNComponentGetOriginalName(m_object);
+}
+
+
+Ref<BinaryView> Component::GetView()
+{
+ return new BinaryView(BNComponentGetView(m_object));
+}
+
+
+void Component::SetName(const std::string &name)
+{
+ BNComponentSetName(m_object, name.c_str());
+}
+
+
+Ref<Component> Component::GetParent()
+{
+ return new Component(BNComponentGetParent(m_object));
+}
+
+
+std::string Component::GetGuid()
+{
+ return string(BNComponentGetGuid(m_object));
+}
+
+
+bool Component::AddFunction(Ref<Function> func)
+{
+ return BNComponentAddFunctionReference(m_object, func->GetObject());
+}
+
+
+bool Component::AddComponent(Ref<Component> component)
+{
+ return BNComponentAddComponent(m_object, component->m_object);
+}
+
+
+bool Component::RemoveComponent(Ref<Component> component)
+{
+ return BNComponentRemoveComponent(component->m_object);
+}
+
+
+bool Component::RemoveFunction(Ref<Function> func)
+{
+ return BNComponentRemoveFunctionReference(m_object, func->GetObject());
+}
+
+
+std::vector<Ref<Component>> Component::GetContainedComponents()
+{
+ std::vector<Ref<Component>> components;
+
+ size_t count;
+ BNComponent** list = BNComponentGetContainedComponents(m_object, &count);
+
+ components.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ Ref<Component> component = new Component(BNNewComponentReference(list[i]));
+ components.push_back(component);
+ }
+
+ BNFreeComponents(list, count);
+
+ return components;
+}
+
+
+std::vector<Ref<Function>> Component::GetContainedFunctions()
+{
+ std::vector<Ref<Function>> functions;
+
+ size_t count;
+ BNFunction** list = BNComponentGetContainedFunctions(m_object, &count);
+
+ functions.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ Ref<Function> function = new Function(BNNewFunctionReference(list[i]));
+ functions.push_back(function);
+ }
+
+ BNFreeFunctionList(list, count);
+
+ return functions;
+}
+
+
+std::vector<Ref<Type>> Component::GetReferencedTypes()
+{
+ std::vector<Ref<Type>> types;
+
+ size_t count;
+ BNType** list = BNComponentGetReferencedTypes(m_object, &count);
+
+ types.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ Ref<Type> type = new Type(BNNewTypeReference(list[i]));
+ types.push_back(type);
+ }
+
+ BNComponentFreeReferencedTypes(list, count);
+
+ return types;
+}
+
+
+std::vector<DataVariable> Component::GetReferencedDataVariables()
+{
+ vector<DataVariable> result;
+
+ size_t count;
+ BNDataVariable* variables = BNComponentGetReferencedDataVariables(m_object, &count);
+
+ result.reserve(count);
+ for (size_t i = 0; i < count; ++i)
+ {
+ result.emplace_back(variables[i].address,
+ Confidence(new Type(BNNewTypeReference(variables[i].type)), variables[i].typeConfidence),
+ variables[i].autoDiscovered);
+ }
+
+ BNFreeDataVariables(variables, count);
+ return result;
+}
diff --git a/function.cpp b/function.cpp
index 96795ef0..12c9d241 100644
--- a/function.cpp
+++ b/function.cpp
@@ -1446,6 +1446,24 @@ set<SSAVariable> Function::GetHighLevelILSSAVariablesIfAvailable()
}
+std::vector<Ref<Component>> Function::GetParentComponents() const
+{
+ std::vector<Ref<Component>> components;
+
+ size_t count;
+ BNComponent** list = BNGetFunctionParentComponents(m_object, &count);
+
+ components.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ Ref<Component> component = new Component(list[i]);
+ components.push_back(component);
+ }
+
+ return components;
+}
+
+
void Function::CreateAutoVariable(
const Variable& var, const Confidence<Ref<Type>>& type, const string& name, bool ignoreDisjointUses)
{
diff --git a/python/__init__.py b/python/__init__.py
index ef316c36..1e73f2cc 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -67,6 +67,7 @@ from .database import *
from .secretsprovider import *
from .typeparser import *
from .typeprinter import *
+from .component import *
# We import each of these by name to prevent conflicts between
# log.py and the function 'log' which we don't import below
from .log import (
diff --git a/python/binaryview.py b/python/binaryview.py
index 278cbecd..e68bf69d 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -48,6 +48,7 @@ from . import typelibrary
from . import fileaccessor
from . import databuffer
from . import basicblock
+from . import component
from . import lineardisassembly
from . import metadata
from . import highlight
@@ -228,6 +229,30 @@ class BinaryDataNotification:
def section_removed(self, view: 'BinaryView', section: 'Section') -> None:
pass
+ def component_added(self, view: 'BinaryView', _component: component.Component) -> None:
+ pass
+
+ def component_removed(self, view: 'BinaryView', formerParent: component.Component,
+ _component: component.Component) -> None:
+ pass
+
+ def component_name_updated(self, view: 'BinaryView', previous_name: str, _component: component.Component) -> None:
+ pass
+
+ def component_moved(self, view: 'BinaryView', formerParent: component.Component, newParent: component.Component,
+ _component: component.Component) -> None:
+ pass
+
+ def component_function_added(self, view: 'BinaryView', _component: component.Component, func: '_function.Function'):
+ pass
+
+ def component_function_removed(self, view: 'BinaryView', _component: component.Component,
+ func: '_function.Function'):
+ pass
+
+
+
+
class StringReference:
_decodings = {
StringType.AsciiString: "ascii", StringType.Utf8String: "utf-8", StringType.Utf16String: "utf-16",
@@ -462,7 +487,12 @@ class BinaryDataNotificationCallbacks:
self._cb.sectionAdded = self._cb.sectionAdded.__class__(self._section_added)
self._cb.sectionUpdated = self._cb.sectionUpdated.__class__(self._section_updated)
self._cb.sectionRemoved = self._cb.sectionRemoved.__class__(self._section_removed)
-
+ self._cb.componentNameUpdated = self._cb.componentNameUpdated.__class__(self._component_name_updated)
+ self._cb.componentAdded = self._cb.componentAdded.__class__(self._component_added)
+ self._cb.componentRemoved = self._cb.componentRemoved.__class__(self._component_removed)
+ self._cb.componentMoved = self._cb.componentMoved.__class__(self._component_moved)
+ self._cb.componentFunctionAdded = self._cb.componentFunctionAdded.__class__(self._component_function_added)
+ self._cb.componentFunctionRemoved = self._cb.componentFunctionRemoved.__class__(self._component_function_removed)
def _register(self) -> None:
core.BNRegisterDataNotification(self._view.handle, self._cb)
@@ -736,6 +766,78 @@ class BinaryDataNotificationCallbacks:
except:
log_error(traceback.format_exc())
+ def _component_added(self, ctxt, view: core.BNBinaryView, _component: core.BNComponent):
+ try:
+ component_handle = core.BNNewComponentReference(_component)
+ assert component_handle is not None, "core.BNNewComponentReference returned None"
+ result = component.Component(component_handle)
+ self._notify.component_added(self._view, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _component_removed(self, ctxt, view: core.BNBinaryView, formerParent: core.BNComponent, _component: core.BNComponent):
+ try:
+ formerParent_handle = core.BNNewComponentReference(formerParent)
+ assert formerParent_handle is not None, "core.BNNewComponentReference returned None"
+ formerParentResult = component.Component(formerParent_handle)
+ component_handle = core.BNNewComponentReference(_component)
+ assert component_handle is not None, "core.BNNewComponentReference returned None"
+ result = component.Component(component_handle)
+ self._notify.component_removed(self._view, formerParentResult, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _component_name_updated(self, ctxt, view: core.BNBinaryView, previous_name: str, _component: core.BNComponent):
+ try:
+ component_handle = core.BNNewComponentReference(_component)
+ assert component_handle is not None, "core.BNNewComponentReference returned None"
+ result = component.Component(component_handle)
+ self._notify.component_name_updated(self._view, previous_name, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _component_moved(self, ctxt, view: core.BNBinaryView, formerParent: core.BNComponent,
+ newParent: core.BNComponent, _component: core.BNComponent):
+ try:
+ formerParent_handle = core.BNNewComponentReference(formerParent)
+ assert formerParent_handle is not None, "core.BNNewComponentReference returned None"
+ formerParentResult = component.Component(formerParent_handle)
+ newParent_handle = core.BNNewComponentReference(newParent)
+ assert newParent_handle is not None, "core.BNNewComponentReference returned None"
+ newParentResult = component.Component(newParent_handle)
+ component_handle = core.BNNewComponentReference(_component)
+ assert component_handle is not None, "core.BNNewComponentReference returned None"
+ result = component.Component(component_handle)
+ self._notify.component_moved(self._view, formerParentResult, newParentResult, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _component_function_added(self, ctxt, view: core.BNBinaryView, _component: core.BNComponent,
+ func: '_function.Function'):
+ try:
+ component_handle = core.BNNewComponentReference(_component)
+ assert component_handle is not None, "core.BNNewComponentReference returned None"
+ result = component.Component(component_handle)
+ function_handle = core.BNNewFunctionReference(func)
+ assert function_handle is not None, "core.BNNewFunctionReference returned None"
+ function = _function.Function(self._view, function_handle)
+ self._notify.component_function_added(self._view, result, function)
+ except:
+ log_error(traceback.format_exc())
+
+ def _component_function_removed(self, ctxt, view: core.BNBinaryView, _component: core.BNComponent,
+ func: '_function.Function'):
+ try:
+ component_handle = core.BNNewComponentReference(_component)
+ assert component_handle is not None, "core.BNNewComponentReference returned None"
+ result = component.Component(component_handle)
+ function_handle = core.BNNewFunctionReference(func)
+ assert function_handle is not None, "core.BNNewFunctionReference returned None"
+ function = _function.Function(self._view, function_handle)
+ self._notify.component_function_removed(self._view, result, function)
+ except:
+ log_error(traceback.format_exc())
+
@property
def view(self) -> 'BinaryView':
return self._view
@@ -5827,6 +5929,105 @@ class BinaryView:
def notify_data_removed(self, offset: int, length: int) -> None:
core.BNNotifyDataRemoved(self.handle, offset, length)
+ def get_component(self, guid: str) -> Optional[component.Component]:
+ """
+ Lookup a Component by its Guid
+
+ :param guid: Guid of the component to look up
+ :return: The Component with that Guid
+ """
+ bn_component = core.BNGetComponentByGuid(self.handle, guid)
+ if bn_component is None:
+ return None
+ return component.Component(bn_component)
+
+ def get_component_by_path(self, path: str) -> Optional[component.Component]:
+ """
+ Lookup a Component by its pathname
+
+ :note: This is a convenience method, and for performance-sensitive lookups, GetComponentByGuid is very highly recommended.
+
+ Lookups are done based on the .display_name of the Component.
+
+ All lookups are absolute from the root component, and are case-sensitive. Pathnames are delimited with "/"
+
+ :param path: Pathname of the desired Component
+ :return: The Component at that pathname
+ :Example:
+
+ >>> c = bv.create_component(name="MyComponent")
+ >>> c2 = bv.create_component(name="MySubComponent", parent=c)
+ >>> bv.get_component_by_path("/MyComponent/MySubComponent") == c2
+ True
+ >>> c3 = bv.create_component(name="MySubComponent", parent=c)
+ >>> c3
+ <Component "MySubComponent (1)" "(20712aff...")>
+ >>> bv.get_component_by_path("/MyComponent/MySubComponent (1)") == c3
+ True
+ """
+ if not isinstance(path, str):
+ raise TypeError("Pathname must be a string")
+ bn_component = core.BNGetComponentByPath(self.handle, path)
+ if bn_component is None:
+ return None
+ return component.Component(bn_component)
+
+ @property
+ def root_component(self) -> component.Component:
+ """
+ The root component for the BinaryView (read-only)
+
+ This Component cannot be removed, and houses all unparented Components.
+
+ :return: The root component
+ """
+ return component.Component(core.BNGetRootComponent(self.handle))
+
+ def create_component(self, name: Optional[str] = None, parent: Union[component.Component, str, None] = None) -> component.Component:
+ """
+ Create a new component with an optional name and parent.
+
+ The `parent` argument can be either a Component or the Guid of a component that the created component will be
+ added as a child of
+
+ :param name: Optional name to create the component with
+ :param parent: Optional parent to which the component will be added
+ :return: The created component
+ """
+
+ if parent:
+ if isinstance(parent, component.Component):
+ if name:
+ return component.Component(core.BNCreateComponentWithParentAndName(self.handle, parent.guid, name))
+ else:
+ return component.Component(core.BNCreateComponentWithParent(self.handle, parent.guid))
+ elif isinstance(parent, str):
+ if name:
+ return component.Component(core.BNCreateComponentWithParentAndName(self.handle, parent, name))
+ else:
+ return component.Component(core.BNCreateComponentWithParent(self.handle, parent))
+ else:
+ raise TypeError("parent can only be a Component object or string GUID representing one")
+ else:
+ if name:
+ return component.Component(core.BNCreateComponentWithName(self.handle, name))
+ else:
+ return component.Component(core.BNCreateComponent(self.handle))
+
+ def remove_component(self, _component: Union[component.Component, str]) -> bool:
+ """
+ Remove a component from the tree entirely.
+
+ :param _component: Component to remove
+ :return: Whether the removal was successful
+ """
+ if isinstance(_component, component.Component):
+ return core.BNRemoveComponent(self.handle, _component.handle)
+ elif isinstance(_component, str):
+ return core.BNRemoveComponentByGuid(self.handle, _component)
+
+ raise TypeError("Removal is only supported with a Component or string representing its Guid")
+
def get_strings(self, start: Optional[int] = None, length: Optional[int] = None) -> List['StringReference']:
"""
``get_strings`` returns a list of strings defined in the binary in the optional virtual address range:
diff --git a/python/component.py b/python/component.py
new file mode 100644
index 00000000..21942297
--- /dev/null
+++ b/python/component.py
@@ -0,0 +1,266 @@
+
+import ctypes
+import inspect
+from typing import Generator, Optional, List, Tuple, Union, Mapping, Any, Dict, Iterator
+from dataclasses import dataclass
+
+from . import binaryview
+
+from . import function
+from . import _binaryninjacore as core
+from . import types
+
+
+class Component:
+ """
+ Components are objects that can contain Functions and other Components.
+
+ They can be queried for information about the functions contained within them.
+
+ Components have a Guid, which persistent across saves and loads of the database, and should be
+ used for retrieving components when such is required and a reference to the Component cannot be held.
+
+ """
+ def __init__(self, handle=None):
+
+ assert handle is not None, "Cannot create component directly, run `bv.create_component?`"
+
+ self.handle = handle
+
+ self.guid = core.BNComponentGetGuid(self.handle)
+
+ def __eq__(self, other):
+ if not isinstance(other, Component):
+ return NotImplemented
+ return core.BNComponentsEqual(self.handle, other.handle)
+
+ def __ne__(self, other):
+ if not isinstance(other, Component):
+ return NotImplemented
+ return core.BNComponentsNotEqual(self.handle, other.handle)
+
+ def __repr__(self):
+ return f'<Component "{self.display_name}" "({self.guid[:8]}...")>'
+
+ def __del__(self):
+ core.BNFreeComponent(self.handle)
+
+ def __str__(self):
+ return self._sprawl_component(self)
+
+ def _sprawl_component(self, c, depth=1, out=None):
+ """
+ Recursive quick function to print out the component's tree of items
+
+ :param c: Current cycle's component. On initial call, pass `self`
+ :param depth: Current tree depth.
+ :param out: Current text
+ :return:
+ """
+ _out = ([repr(c)] if not out else out.split('\n')) + [(' ' * depth + repr(f)) for f in c.functions]
+ _out += [' ' * (depth+1) + repr(i) for i in (c.get_referenced_data_variables() + c.get_referenced_types())]
+ for i in c.components:
+ _out.append(' ' * depth + repr(i))
+ _out = self._sprawl_component(i, depth+1, '\n'.join(_out)).split('\n')
+ return '\n'.join(_out)
+
+ def add_function(self, func: 'function.Function') -> bool:
+ """
+ Add function to this component.
+
+ :param func: Function to add
+ :return: True if function was successfully added.
+ """
+ return core.BNComponentAddFunctionReference(self.handle, func.handle)
+
+ def contains_function(self, func: 'function.Function') -> bool:
+ """
+ Check whether this component contains a function.
+
+ :param func: Function to check
+ :return: True if this component contains the function.
+ """
+ return core.BNComponentContainsFunction(self.handle, func.handle)
+
+ def add_component(self, component: 'Component') -> bool:
+ """
+ Move component to this component. This will remove it from the old parent.
+
+ :param component: Component to add to this component.
+ :return: True if the component was successfully moved to this component
+ """
+ return core.BNComponentAddComponent(self.handle, component.handle)
+
+ def remove_function(self, func: 'function.Function') -> bool:
+ """
+ Remove function from this component.
+
+ :param func: Function to remove
+ :return: True if function was successfully removed.
+ """
+ return core.BNComponentRemoveFunctionReference(self.handle, func.handle)
+
+ def remove_component(self, component: 'Component') -> bool:
+ """
+ Remove a component from the current component, moving it to the root.
+
+ This function has no effect when used from the root component.
+ Use `BinaryView.remove_component` to Remove a component from the tree entirely.
+
+ :param component: Component to remove
+ :return:
+ """
+
+ return self.view.root_component.add_component(component)
+
+ def contains_component(self, component: 'Component') -> bool:
+ """
+ Check whether this component contains a component.
+
+ :param component: Component to check
+ :return: True if this component contains the component.
+ """
+ return core.BNComponentContainsComponent(self.handle, component.handle)
+
+ @property
+ def display_name(self) -> str:
+ """Original Name of the component (read-only)"""
+ return core.BNComponentGetDisplayName(self.handle)
+
+ @property
+ def name(self) -> str:
+ """Original name set for this component
+
+ :note: The `.display_name` property should be used for `bv.get_component_by_path()` lookups.
+
+ This can differ from the .display_name property if one of its sibling components has the same .original_name; In that
+ case, .name will be an automatically generated unique name (e.g. "MyComponentName (1)") while .original_name will
+ remain what was originally set (e.g. "MyComponentName")
+
+ If this component has a duplicate name and is moved to a component where none of its siblings share its name,
+ the .name property will return the original "MyComponentName"
+ """
+ return core.BNComponentGetOriginalName(self.handle)
+
+ @name.setter
+ def name(self, _name):
+ core.BNComponentSetName(self.handle, _name)
+
+ @property
+ def parent(self) -> Optional['Component']:
+ """
+ The component that contains this component, if it exists.
+ """
+ bn_component = core.BNComponentGetParent(self.handle)
+ if bn_component is not None:
+ return Component(bn_component)
+ return None
+
+ @property
+ def view(self):
+ bn_binaryview = core.BNComponentGetView(self.handle)
+ if bn_binaryview is not None:
+ return binaryview.BinaryView(handle=bn_binaryview)
+ return None
+
+ @property
+ def components(self) -> Iterator['Component']:
+ """
+ ``components`` is an iterator for all Components contained within this Component
+
+ :return: An iterator containing Components
+ :rtype: SubComponentIterator
+ :Example:
+
+ >>> for subcomp in component.components:
+ ... print(repr(component))
+ """
+
+ @dataclass
+ class SubComponentIterator:
+ comp: Component
+
+ def __iter__(self):
+ count = ctypes.c_ulonglong(0)
+ bn_components = core.BNComponentGetContainedComponents(self.comp.handle, count)
+ try:
+ for i in range(count.value):
+ yield Component(core.BNNewComponentReference(bn_components[i]))
+ finally:
+ core.BNFreeComponents(bn_components, count.value)
+
+ return iter(SubComponentIterator(self))
+
+ @property
+ def functions(self) -> Iterator['function.Function']:
+ """
+ ``functions`` is an iterator for all Functions contained within this Component
+
+ :return: An iterator containing Components
+ :rtype: ComponentIterator
+ :Example:
+
+ >>> for func in component.functions:
+ ... print(func.name)
+ """
+ @dataclass
+ class FunctionIterator:
+ view: 'binaryview.BinaryView'
+ comp: Component
+
+ def __iter__(self):
+ count = ctypes.c_ulonglong(0)
+ bn_functions = core.BNComponentGetContainedFunctions(self.comp.handle, count)
+ try:
+ for i in range(count.value):
+ bn_function = core.BNNewFunctionReference(bn_functions[i])
+ yield function.Function(self.view, bn_function)
+ finally:
+ core.BNFreeFunctionList(bn_functions, count.value)
+
+ return iter(FunctionIterator(self.view, self))
+
+ def get_referenced_data_variables(self, recursive=False):
+ """
+ Get data variables referenced by this component
+
+ :param recursive: Optional; Get all DataVariables referenced by this component and subcomponents.
+ :return: List of DataVariables
+ """
+ data_vars = []
+ count = ctypes.c_ulonglong(0)
+ if recursive:
+ bn_data_vars = core.BNComponentGetReferencedDataVariablesRecursive(self.handle, count)
+ else:
+ bn_data_vars = core.BNComponentGetReferencedDataVariables(self.handle, count)
+ try:
+ for i in range(count.value):
+ bn_data_var = bn_data_vars[i]
+ data_var = binaryview.DataVariable.from_core_struct(bn_data_var, self.view)
+ data_vars.append(data_var)
+ finally:
+ core.BNFreeDataVariables(bn_data_vars, count.value)
+ return data_vars
+
+ def get_referenced_types(self, recursive=False):
+ """
+ Get Types referenced by this component
+
+ :param recursive: Optional; Get all Types referenced by this component and subcomponents.
+ :return: List of Types
+ """
+ _types = []
+ count = ctypes.c_ulonglong(0)
+
+ if recursive:
+ bn_types = core.BNComponentGetReferencedTypesRecursive(self.handle, count)
+ else:
+ bn_types = core.BNComponentGetReferencedTypes(self.handle, count)
+
+ try:
+ for i in range(count.value):
+ _types.append(types.Type(core.BNNewTypeReference(bn_types[i])))
+ finally:
+ core.BNComponentFreeReferencedTypes(bn_types, count.value)
+
+ return _types
diff --git a/python/function.py b/python/function.py
index 93ed8b49..d093c076 100644
--- a/python/function.py
+++ b/python/function.py
@@ -61,6 +61,7 @@ from .variable import (
)
from . import decorators
from .enums import RegisterValueType
+from . import component
ExpressionIndex = int
InstructionIndex = int
@@ -2196,6 +2197,15 @@ class Function:
core.BNFreeTagList(tags, count.value)
return result
+ @property
+ def parent_components(self):
+ _components = []
+ count = ctypes.c_ulonglong(0)
+ bn_components = core.BNGetFunctionParentComponents(self.handle, count)
+ for i in range(count.value):
+ _components.append(component.Component(self.view, bn_components[i]))
+ return _components
+
def get_lifted_il_at(
self, addr: int, arch: Optional['architecture.Architecture'] = None
) -> Optional['lowlevelil.LowLevelILInstruction']: