summaryrefslogtreecommitdiff
path: root/view/sharedcache/api/sharedcacheapi.h
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-03-10 11:05:40 -0400
committerMason Reed <mason@vector35.com>2025-04-02 05:36:54 -0400
commit25cc02431b61097b2adfc2fbc493b648b0300c3b (patch)
treea79d9c4f4f67234d3bf9bda413e8608f479a4cc8 /view/sharedcache/api/sharedcacheapi.h
parentfa85bf28502286c4821427c5d0ed91a7ed46f8f6 (diff)
[SharedCache] Refactor Shared Cache
In absence of a better name, this commit refactors the shared cache code.
Diffstat (limited to 'view/sharedcache/api/sharedcacheapi.h')
-rw-r--r--view/sharedcache/api/sharedcacheapi.h490
1 files changed, 266 insertions, 224 deletions
diff --git a/view/sharedcache/api/sharedcacheapi.h b/view/sharedcache/api/sharedcacheapi.h
index 5c50e283..e12582f2 100644
--- a/view/sharedcache/api/sharedcacheapi.h
+++ b/view/sharedcache/api/sharedcacheapi.h
@@ -1,285 +1,327 @@
#pragma once
#include <binaryninjaapi.h>
-#include "../core/MetadataSerializable.hpp"
-#include "view/macho/machoview.h"
#include "sharedcachecore.h"
-namespace SharedCacheAPI {
- template<class T>
- class SCRefCountObject {
- void AddRefInternal() { m_refs.fetch_add(1); }
+template<class T>
+class DSCRefCountObject {
+ void AddRefInternal() { m_refs.fetch_add(1); }
- void ReleaseInternal() {
- if (m_refs.fetch_sub(1) == 1)
- delete this;
- }
+ void ReleaseInternal() {
+ if (m_refs.fetch_sub(1) == 1)
+ delete this;
+ }
- public:
- std::atomic<int> m_refs;
- T *m_object;
+public:
+ std::atomic<int> m_refs;
+ T *m_object;
- SCRefCountObject() : m_refs(0), m_object(nullptr) {}
+ DSCRefCountObject() : m_refs(0), m_object(nullptr) {}
- virtual ~SCRefCountObject() {}
+ virtual ~DSCRefCountObject() = default;
- T *GetObject() const { return m_object; }
+ T *GetObject() const { return m_object; }
- static T *GetObject(SCRefCountObject *obj) {
- if (!obj)
- return nullptr;
- return obj->GetObject();
- }
+ static T *GetObject(DSCRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
- void AddRef() { AddRefInternal(); }
+ void AddRef() { AddRefInternal(); }
- void Release() { ReleaseInternal(); }
+ void Release() { ReleaseInternal(); }
- void AddRefForRegistration() { AddRefInternal(); }
- };
+ void AddRefForRegistration() { AddRefInternal(); }
+};
- template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
- class SCCoreRefCountObject {
- void AddRefInternal() { m_refs.fetch_add(1); }
+template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
+class DSCCoreRefCountObject {
+ void AddRefInternal() { m_refs.fetch_add(1); }
- void ReleaseInternal() {
- if (m_refs.fetch_sub(1) == 1) {
- if (!m_registeredRef)
- delete this;
- }
+ void ReleaseInternal() {
+ if (m_refs.fetch_sub(1) == 1) {
+ if (!m_registeredRef)
+ delete this;
}
+ }
- public:
- std::atomic<int> m_refs;
- bool m_registeredRef = false;
- T *m_object;
+public:
+ std::atomic<int> m_refs;
+ bool m_registeredRef = false;
+ T *m_object;
+
+ DSCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
+
+ virtual ~DSCCoreRefCountObject() = default;
+
+ T *GetObject() const { return m_object; }
+
+ static T *GetObject(DSCCoreRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
+
+ void AddRef() {
+ if (m_object && (m_refs != 0))
+ AddObjectReference(m_object);
+ AddRefInternal();
+ }
+
+ void Release() {
+ if (m_object)
+ FreeObjectReference(m_object);
+ ReleaseInternal();
+ }
- SCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
+ void AddRefForRegistration() { m_registeredRef = true; }
- virtual ~SCCoreRefCountObject() {}
+ void ReleaseForRegistration() {
+ m_object = nullptr;
+ m_registeredRef = false;
+ if (m_refs == 0)
+ delete this;
+ }
+};
- T *GetObject() const { return m_object; }
+template <class T>
+class DSCRef
+{
+ T* m_obj;
+#ifdef BN_REF_COUNT_DEBUG
+ void* m_assignmentTrace = nullptr;
+#endif
- static T *GetObject(SCCoreRefCountObject *obj) {
- if (!obj)
- return nullptr;
- return obj->GetObject();
+public:
+ DSCRef() : m_obj(NULL) {}
+
+ DSCRef(T* obj) : m_obj(obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
}
+ }
- void AddRef() {
- if (m_object && (m_refs != 0))
- AddObjectReference(m_object);
- AddRefInternal();
+ DSCRef(const DSCRef<T>& obj) : m_obj(obj.m_obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
}
+ }
+
+ DSCRef(DSCRef<T>&& other) : m_obj(other.m_obj)
+ {
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ }
- void Release() {
- if (m_object)
- FreeObjectReference(m_object);
- ReleaseInternal();
+ ~DSCRef()
+ {
+ if (m_obj)
+ {
+ m_obj->Release();
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
}
+ }
- void AddRefForRegistration() { m_registeredRef = true; }
+ DSCRef<T>& operator=(const BinaryNinja::Ref<T>& obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj.m_obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T* oldObj = m_obj;
+ m_obj = obj.m_obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
- void ReleaseForRegistration() {
- m_object = nullptr;
- m_registeredRef = false;
- if (m_refs == 0)
- delete this;
+ DSCRef<T>& operator=(DSCRef<T>&& other)
+ {
+ if (m_obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
+ m_obj->Release();
}
- };
+ m_obj = other.m_obj;
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ return *this;
+ }
- struct DSCMemoryRegion {
- uint64_t vmAddress;
- uint64_t size;
- std::string prettyName;
- };
+ DSCRef<T>& operator=(T* obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T* oldObj = m_obj;
+ m_obj = obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
- struct BackingCacheMapping {
- uint64_t vmAddress;
- uint64_t size;
- uint64_t fileOffset;
- };
+ operator T*() const
+ {
+ return m_obj;
+ }
- struct BackingCache {
- std::string path;
- BNBackingCacheType cacheType;
- std::vector<BackingCacheMapping> mappings;
- };
+ T* operator->() const
+ {
+ return m_obj;
+ }
- struct DSCImageMemoryMapping {
- std::string filePath;
- std::string name;
- uint64_t vmAddress;
- uint64_t size;
- bool loaded;
- uint64_t rawViewOffset;
- };
+ T& operator*() const
+ {
+ return *m_obj;
+ }
- struct DSCImage {
- std::string name;
- uint64_t headerAddress;
- std::vector<DSCImageMemoryMapping> mappings;
- };
+ bool operator!() const
+ {
+ return m_obj == NULL;
+ }
- struct DSCSymbol {
- uint64_t address;
- BinaryNinja::StringRef name;
- std::string image;
- };
+ bool operator==(const T* obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj);
+ }
- struct SharedCacheMachOHeader : public SharedCacheCore::MetadataSerializable<SharedCacheMachOHeader> {
- uint64_t textBase = 0;
- uint64_t loadCommandOffset = 0;
- mach_header_64 ident;
- std::string identifierPrefix;
- std::string installName;
+ bool operator==(const DSCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj.m_obj);
+ }
- std::vector<std::pair<uint64_t, bool>> entryPoints;
- std::vector<uint64_t> m_entryPoints; // list of entrypoints
+ bool operator!=(const T* obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj);
+ }
- symtab_command symtab;
- dysymtab_command dysymtab;
- dyld_info_command dyldInfo;
- routines_command_64 routines64;
- function_starts_command functionStarts;
- std::vector<section_64> moduleInitSections;
- linkedit_data_command exportTrie;
- linkedit_data_command chainedFixups {};
+ bool operator!=(const DSCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj.m_obj);
+ }
- uint64_t relocationBase;
- // Section and program headers, internally use 64-bit form as it is a superset of 32-bit
- std::vector<segment_command_64> segments; // only three types of sections __TEXT, __DATA, __IMPORT
- segment_command_64 linkeditSegment;
- std::vector<section_64> sections;
- std::vector<std::string> sectionNames;
+ bool operator<(const T* obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj);
+ }
- std::vector<section_64> symbolStubSections;
- std::vector<section_64> symbolPointerSections;
+ bool operator<(const DSCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj.m_obj);
+ }
- std::vector<std::string> dylibs;
+ T* GetPtr() const
+ {
+ return m_obj;
+ }
+};
- build_version_command buildVersion;
- std::vector<build_tool_version> buildToolVersions;
- std::string exportTriePath;
- bool linkeditPresent = false;
- bool dysymPresent = false;
- bool dyldInfoPresent = false;
- bool exportTriePresent = false;
- bool chainedFixupsPresent = false;
- bool routinesPresent = false;
- bool functionStartsPresent = false;
- bool relocatable = false;
+// TODO: replace namespace?
+namespace SharedCacheAPI {
+ struct CacheRegion
+ {
+ BNSharedCacheRegionType type;
+ std::string name;
+ uint64_t start;
+ uint64_t size;
+ std::optional<uint64_t> imageStart;
+ BNSegmentFlag flags;
+ };
- void Store(SharedCacheCore::SerializationContext& context) const {
- MSS(textBase);
- MSS(loadCommandOffset);
- MSS_SUBCLASS(ident);
- MSS(identifierPrefix);
- MSS(installName);
- MSS(entryPoints);
- MSS(m_entryPoints);
- MSS_SUBCLASS(symtab);
- MSS_SUBCLASS(dysymtab);
- MSS_SUBCLASS(dyldInfo);
- MSS_SUBCLASS(routines64);
- MSS_SUBCLASS(functionStarts);
- MSS_SUBCLASS(moduleInitSections);
- MSS_SUBCLASS(exportTrie);
- MSS_SUBCLASS(chainedFixups);
- MSS(relocationBase);
- MSS_SUBCLASS(segments);
- MSS_SUBCLASS(linkeditSegment);
- MSS_SUBCLASS(sections);
- MSS(sectionNames);
- MSS_SUBCLASS(symbolStubSections);
- MSS_SUBCLASS(symbolPointerSections);
- MSS(dylibs);
- MSS_SUBCLASS(buildVersion);
- MSS_SUBCLASS(buildToolVersions);
- MSS(exportTriePath);
- MSS(linkeditPresent);
- MSS(dysymPresent);
- MSS(dyldInfoPresent);
- MSS(exportTriePresent);
- MSS(chainedFixupsPresent);
- MSS(routinesPresent);
- MSS(functionStartsPresent);
- MSS(relocatable);
- }
+ std::string GetRegionTypeAsString(const BNSharedCacheRegionType& type);
- static SharedCacheMachOHeader Load(SharedCacheCore::DeserializationContext& context) {
- SharedCacheMachOHeader header;
- header.MSL(textBase);
- header.MSL(loadCommandOffset);
- header.MSL(ident);
- header.MSL(identifierPrefix);
- header.MSL(installName);
- header.MSL(entryPoints);
- header.MSL(m_entryPoints);
- header.MSL(symtab);
- header.MSL(dysymtab);
- header.MSL(dyldInfo);
- header.MSL(routines64);
- header.MSL(functionStarts);
- header.MSL(moduleInitSections);
- header.MSL(exportTrie);
- header.MSL(chainedFixups);
- header.MSL(relocationBase);
- header.MSL(segments);
- header.MSL(linkeditSegment);
- header.MSL(sections);
- header.MSL(sectionNames);
- header.MSL(symbolStubSections);
- header.MSL(symbolPointerSections);
- header.MSL(dylibs);
- header.MSL(buildVersion);
- header.MSL(buildToolVersions);
- header.MSL(exportTriePath);
- header.MSL(linkeditPresent);
- header.MSL(dysymPresent);
- header.MSL(dyldInfoPresent);
- header.MSL(exportTriePresent);
- header.MSL(chainedFixupsPresent);
- header.MSL(routinesPresent);
- header.MSL(functionStartsPresent);
- header.MSL(relocatable);
- return header;
- }
+ struct CacheMappingInfo
+ {
+ uint64_t vmAddress;
+ uint64_t size;
+ uint64_t fileOffset;
+ };
+
+ struct CacheImage
+ {
+ uint64_t headerAddress;
+ std::string name;
+ std::vector<uint64_t> regionStarts;
};
+ struct CacheEntry
+ {
+ std::string path;
+ BNSharedCacheEntryType entryType;
+ std::vector<CacheMappingInfo> mappings;
+ };
+
+ struct CacheSymbol
+ {
+ BNSymbolType type;
+ uint64_t address;
+ std::string name;
+ };
- class SharedCache : public SCCoreRefCountObject<BNSharedCache, BNNewSharedCacheReference, BNFreeSharedCacheReference> {
+ class SharedCacheController : public DSCCoreRefCountObject<BNSharedCacheController, BNNewSharedCacheControllerReference, BNFreeSharedCacheControllerReference> {
public:
- SharedCache(Ref<BinaryView> view);
+ explicit SharedCacheController(BNSharedCacheController* controller);
+ static DSCRef<SharedCacheController> GetController(BinaryNinja::BinaryView& view);
- BNDSCViewState GetState();
- static BNDSCViewLoadProgress GetLoadProgress(Ref<BinaryView> view);
- static uint64_t FastGetBackingCacheCount(Ref<BinaryView> view);
+ bool ApplyRegion(BinaryNinja::BinaryView& view, const CacheRegion& region);
- bool LoadImageWithInstallName(std::string installName, bool skipObjC = false);
- bool LoadSectionAtAddress(uint64_t addr);
- bool LoadImageContainingAddress(uint64_t addr, bool skipObjC = false);
- std::vector<std::string> GetAvailableImages();
-
- void ProcessObjCSectionsForImageWithInstallName(std::string installName);
- void ProcessAllObjCSections();
+ // Attempt to load the given image into the view.
+ //
+ // It is the callers responsibility to run linear sweep and update analysis, as you might want to add
+ // multiple images at a time.
+ bool ApplyImage(BinaryNinja::BinaryView& view, const CacheImage& image);
- std::vector<DSCSymbol> LoadAllSymbolsAndWait();
+ bool IsRegionLoaded(const CacheRegion& region) const;
+ bool IsImageLoaded(const CacheImage& image) const;
- std::string GetNameForAddress(uint64_t address);
- std::string GetImageNameForAddress(uint64_t address);
+ std::optional<CacheRegion> GetRegionAt(uint64_t address) const;
+ std::optional<CacheRegion> GetRegionContaining(uint64_t address) const;
- std::vector<BackingCache> GetBackingCaches();
- std::vector<DSCImage> GetImages();
+ std::optional<CacheImage> GetImageAt(uint64_t address) const;
+ std::optional<CacheImage> GetImageContaining(uint64_t address) const;
+ std::optional<CacheImage> GetImageWithName(const std::string& name) const;
- std::optional<SharedCacheMachOHeader> GetMachOHeaderForImage(std::string name);
- std::optional<SharedCacheMachOHeader> GetMachOHeaderForAddress(uint64_t address);
+ std::vector<std::string> GetImageDependencies(const CacheImage& image) const;
- std::vector<DSCMemoryRegion> GetLoadedMemoryRegions();
+ std::optional<CacheSymbol> GetSymbolAt(uint64_t address) const;
+ std::optional<CacheSymbol> GetSymbolWithName(const std::string& name) const;
- void FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis = true) const;
+ std::vector<CacheEntry> GetEntries() const;
+ std::vector<CacheRegion> GetRegions() const;
+ std::vector<CacheRegion> GetLoadedRegions() const;
+ std::vector<CacheImage> GetImages() const;
+ std::vector<CacheImage> GetLoadedImages() const;
+ std::vector<CacheSymbol> GetSymbols() const;
};
-} \ No newline at end of file
+}