summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2024-01-25 22:31:15 -0500
committerBrian Potchik <brian@vector35.com>2024-01-25 22:31:15 -0500
commitd339fb169fa0ad2defceefa04974c2ddcef3943e (patch)
treebc141c09725a49867a893a057cd76a3a171e18b3
parent31bd9f2ca5922b9bd9e87669d7c0ece734d7bca8 (diff)
Move NotificationsDispather header to API submodule.
-rw-r--r--ui/notificationsdispatcher.h215
1 files changed, 215 insertions, 0 deletions
diff --git a/ui/notificationsdispatcher.h b/ui/notificationsdispatcher.h
new file mode 100644
index 00000000..60e0bb15
--- /dev/null
+++ b/ui/notificationsdispatcher.h
@@ -0,0 +1,215 @@
+#pragma once
+
+#include <QThread>
+
+#include <condition_variable>
+#include <deque>
+#include <functional>
+#include <mutex>
+#include <variant>
+#include <vector>
+#include "binaryninjaapi.h"
+#include "uitypes.h"
+
+
+class NotificationEvent
+{
+public:
+ class SymbolInfo
+ {
+ BNSymbolType m_symbolType;
+ BNSymbolBinding m_symbolBinding;
+ std::string m_rawName;
+ std::string m_shortName;
+ std::string m_fullName;
+ uint64_t m_address;
+ bool m_gratuitous;
+ bool m_autoDefined;
+
+ public:
+ SymbolInfo(BNSymbolType type, const std::string& name, uint64_t address) {
+ m_symbolType = type;
+ m_symbolBinding = NoBinding;
+ m_rawName = name;
+ m_address = address;
+ m_gratuitous = true;
+ m_autoDefined = true;
+ }
+
+ SymbolInfo(const SymbolRef& symbol) {
+ m_symbolType = symbol->GetType();
+ m_symbolBinding = symbol->GetBinding();
+ setNames(symbol->GetRawName(), symbol->GetShortName(), symbol->GetFullName());
+ m_address = symbol->GetAddress();
+ m_gratuitous = false;
+ m_autoDefined = symbol->IsAutoDefined();
+ }
+
+ BNSymbolType getType() const { return m_symbolType; }
+ uint64_t getAddress() const { return m_address; }
+ BNSymbolBinding getBinding() const { return m_symbolBinding; }
+ bool isGratuitous() const { return m_gratuitous; }
+ bool isAutoDefined() const { return m_autoDefined; }
+
+ const std::string& getRawName() const { return m_rawName; }
+ const std::string& getShortName() const { return m_shortName.empty() ? m_rawName : m_shortName; }
+ const std::string& getFullName() const { return m_fullName.empty() ? m_rawName : m_fullName; }
+
+ void setNames(const std::string& rawName, const std::string& shortName, const std::string& fullName) {
+ m_rawName = rawName;
+ if (!shortName.empty() && shortName != rawName)
+ m_shortName = shortName;
+ if (!fullName.empty() && fullName != rawName)
+ m_fullName = fullName;
+ }
+ };
+
+ struct ComponentInfo
+ {
+ ComponentRef component;
+ ComponentRef parent;
+ FunctionRef function;
+ BinaryNinja::DataVariable dataVar;
+
+ ComponentInfo() {};
+ ComponentInfo(BinaryNinja::Component* component) : component(component) {};
+ ComponentInfo(BinaryNinja::Component* component, BinaryNinja::Component* parent) : component(component), parent(parent) {};
+ ComponentInfo(BinaryNinja::Component* component, FunctionRef function) : component(component), function(function) {};
+ ComponentInfo(BinaryNinja::Component* component, const BinaryNinja::DataVariable& dataVar) : component(component), dataVar(dataVar) {};
+ };
+
+private:
+ using NotificationType = BinaryNinja::BinaryDataNotification::NotificationType;
+
+ NotificationType m_source;
+ SymbolRef m_symbol;
+ std::unique_ptr<SymbolInfo> m_symbolInfo;
+ std::variant<std::monostate, FunctionRef, BinaryNinja::DataVariable, SegmentRef, SectionRef, ComponentInfo> m_object;
+
+public:
+ NotificationEvent(NotificationType source, BinaryNinja::Symbol* symbol): m_source(source), m_symbol(symbol) { }
+ NotificationEvent(NotificationType source, BinaryNinja::Function* function): m_source(source), m_object(function) { }
+ NotificationEvent(NotificationType source, const BinaryNinja::DataVariable& dataVariable): m_source(source), m_object(dataVariable) { }
+ NotificationEvent(NotificationType source, BinaryNinja::Segment* segment): m_source(source), m_object(segment) { }
+ NotificationEvent(NotificationType source, BinaryNinja::Section* section): m_source(source), m_object(section) { }
+ NotificationEvent(NotificationType source, const ComponentInfo& componentInfo): m_source(source), m_object(componentInfo) { }
+
+ void cacheSymbolInfo();
+ SymbolInfo* getSymbolInfo() const { return m_symbolInfo.get(); }
+ std::unique_ptr<SymbolInfo> takeSymbolInfo() { return std::move(m_symbolInfo); }
+
+ bool hasDataVariableObject() const { return std::holds_alternative<BinaryNinja::DataVariable>(m_object); }
+ bool hasFunctionObject() const { return std::holds_alternative<FunctionRef>(m_object); }
+ bool hasObject() const { return !std::holds_alternative<std::monostate>(m_object); }
+
+ template <typename Visitor>
+ constexpr decltype(auto) getObject(Visitor&& visitor) { return std::visit(std::forward<Visitor>(visitor), m_object); }
+
+ template <typename T>
+ void setObject(const T& obj) { m_object = obj; }
+
+ NotificationType getSource() const { return m_source; }
+ bool isObjectRemoval() const { return (m_source & (NotificationType::DataVariableRemoved | NotificationType::FunctionRemoved)); }
+ bool isRemoval() const { return (m_source & (NotificationType::DataVariableRemoved | NotificationType::FunctionRemoved | NotificationType::SymbolRemoved)); }
+};
+
+
+class NotificationsDispatcher: public QThread, public BinaryNinja::BinaryDataNotification
+{
+ Q_OBJECT
+
+ class AnalysisCache: public BinaryNinja::RefCountObject
+ {
+ BinaryViewRef m_view;
+ std::vector<SymbolRef> m_symbols;
+ std::vector<FunctionRef> m_functions;
+ std::map<uint64_t, BinaryNinja::DataVariable> m_dataVariables;
+ std::unordered_map<uint64_t, NotificationEvent> m_coalesced;
+
+ public:
+ AnalysisCache(BinaryViewRef view): m_view(view) { }
+
+ void fetch();
+ void coalesce();
+ std::deque<std::vector<NotificationEvent>> generate();
+ };
+
+ BinaryViewRef m_view = nullptr;
+ BinaryNinja::Ref<BinaryNinja::Logger> m_logger;
+ bool m_registered = false;
+ bool m_request = false;
+ BinaryNinja::Ref<AnalysisCache> m_analysisCache = nullptr;
+ std::function<void(bool refresh, std::vector<NotificationEvent>&&)> m_updateHandler;
+
+ std::mutex m_mutex;
+ std::condition_variable m_condition;
+ std::condition_variable m_requestCondition;
+ std::atomic<bool> m_done = false;
+
+ std::vector<NotificationEvent> m_ingressQueue;
+ std::deque<std::vector<NotificationEvent>> m_egressQueue;
+
+ void run() override;
+
+public:
+ NotificationsDispatcher() = delete;
+ NotificationsDispatcher(BinaryViewRef view, NotificationTypes notifications): BinaryDataNotification(notifications), m_view(view) { m_logger = BinaryNinja::LogRegistry::CreateLogger("NotificationsDispatcher"); }
+
+ void setUpdateHandler(std::function<void(bool refresh, std::vector<NotificationEvent>&&)>&& updateHandler) { m_updateHandler = std::move(updateHandler); }
+
+ void asyncRefresh();
+ void cancel();
+
+ template <typename... Args>
+ void enqueue(NotificationType notification, Args&&... args) { m_ingressQueue.emplace_back(notification, std::forward<Args>(args)...); }
+
+ uint64_t OnNotificationBarrier(BinaryNinja::BinaryView* view) override;
+
+ void OnBinaryDataWritten(BinaryNinja::BinaryView* view, uint64_t offset, size_t len) override;
+ void OnBinaryDataInserted(BinaryNinja::BinaryView* view, uint64_t offset, size_t len) override;
+ void OnBinaryDataRemoved(BinaryNinja::BinaryView* view, uint64_t offset, uint64_t len) override;
+
+ void OnAnalysisFunctionAdded(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
+ void OnAnalysisFunctionRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
+ void OnAnalysisFunctionUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
+ void OnAnalysisFunctionUpdateRequested(BinaryNinja::BinaryView* view, BinaryNinja::Function* func) override;
+
+ void OnDataVariableAdded(BinaryNinja::BinaryView* view, const BinaryNinja::DataVariable& var) override;
+ void OnDataVariableRemoved(BinaryNinja::BinaryView* view, const BinaryNinja::DataVariable& var) override;
+ void OnDataVariableUpdated(BinaryNinja::BinaryView* view, const BinaryNinja::DataVariable& var) override;
+ void OnDataMetadataUpdated(BinaryNinja::BinaryView* view, uint64_t offset) override;
+
+ void OnTagTypeUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Ref<BinaryNinja::TagType> tagTypeRef) override;
+ void OnTagAdded(BinaryNinja::BinaryView* view, const BinaryNinja::TagReference& tagRef) override;
+ void OnTagRemoved(BinaryNinja::BinaryView* view, const BinaryNinja::TagReference& tagRef) override;
+ void OnTagUpdated(BinaryNinja::BinaryView* view, const BinaryNinja::TagReference& tagRef) override;
+
+ void OnSymbolAdded(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym) override;
+ void OnSymbolRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym) override;
+ void OnSymbolUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Symbol* sym) override;
+
+ void OnStringFound(BinaryNinja::BinaryView* view, BNStringType type, uint64_t offset, size_t len) override;
+ void OnStringRemoved(BinaryNinja::BinaryView* view, BNStringType type, uint64_t offset, size_t len) override;
+
+ void OnTypeDefined(BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override;
+ void OnTypeUndefined(BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override;
+ void OnTypeReferenceChanged(BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override;
+ void OnTypeFieldReferenceChanged(BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, uint64_t offset) override;
+
+ void OnSegmentAdded(BinaryNinja::BinaryView* view, BinaryNinja::Segment* segment) override;
+ void OnSegmentRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Segment* segment) override;
+ void OnSegmentUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Segment* segment) override;
+
+ void OnSectionAdded(BinaryNinja::BinaryView* view, BinaryNinja::Section* section) override;
+ void OnSectionRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Section* section) override;
+ void OnSectionUpdated(BinaryNinja::BinaryView* view, BinaryNinja::Section* section) override;
+
+ void OnComponentAdded(BinaryNinja::BinaryView* view, BinaryNinja::Component* component) override;
+ void OnComponentRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Component* component, BinaryNinja::Component*) override;
+ void OnComponentNameUpdated(BinaryNinja::BinaryView* view, std::string& previousName, BinaryNinja::Component* component) override;
+ void OnComponentMoved(BinaryNinja::BinaryView* view, BinaryNinja::Component* parent, BinaryNinja::Component*, BinaryNinja::Component* component) override;
+ void OnComponentFunctionAdded(BinaryNinja::BinaryView* view, BinaryNinja::Component* component, BinaryNinja::Function* func) override;
+ void OnComponentFunctionRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Component* component, BinaryNinja::Function* func) override;
+ void OnComponentDataVariableAdded(BinaryNinja::BinaryView* view, BinaryNinja::Component* component, const BinaryNinja::DataVariable& var) override;
+ void OnComponentDataVariableRemoved(BinaryNinja::BinaryView* view, BinaryNinja::Component* component, const BinaryNinja::DataVariable& var) override;
+};