#pragma once #include #include "MetadataSerializable.hpp" #include "view/macho/machoview.h" #include "sharedcachecore.h" using namespace BinaryNinja; namespace SharedCacheAPI { template class SCRefCountObject { void AddRefInternal() { m_refs.fetch_add(1); } void ReleaseInternal() { if (m_refs.fetch_sub(1) == 1) delete this; } public: std::atomic m_refs; T *m_object; SCRefCountObject() : m_refs(0), m_object(nullptr) {} virtual ~SCRefCountObject() {} T *GetObject() const { return m_object; } static T *GetObject(SCRefCountObject *obj) { if (!obj) return nullptr; return obj->GetObject(); } void AddRef() { AddRefInternal(); } void Release() { ReleaseInternal(); } void AddRefForRegistration() { AddRefInternal(); } }; template class SCCoreRefCountObject { void AddRefInternal() { m_refs.fetch_add(1); } void ReleaseInternal() { if (m_refs.fetch_sub(1) == 1) { if (!m_registeredRef) delete this; } } public: std::atomic m_refs; bool m_registeredRef = false; T *m_object; SCCoreRefCountObject() : m_refs(0), m_object(nullptr) {} virtual ~SCCoreRefCountObject() {} T *GetObject() const { return m_object; } static T *GetObject(SCCoreRefCountObject *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(); } void AddRefForRegistration() { m_registeredRef = true; } void ReleaseForRegistration() { m_object = nullptr; m_registeredRef = false; if (m_refs == 0) delete this; } }; template class SCRef { T *m_obj; #ifdef BN_REF_COUNT_DEBUG void* m_assignmentTrace = nullptr; #endif public: SCRef() : m_obj(NULL) {} SCRef(T *obj) : m_obj(obj) { if (m_obj) { m_obj->AddRef(); #ifdef BN_REF_COUNT_DEBUG m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name()); #endif } } SCRef(const SCRef &obj) : m_obj(obj.m_obj) { if (m_obj) { m_obj->AddRef(); #ifdef BN_REF_COUNT_DEBUG m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name()); #endif } } SCRef(SCRef &&other) : m_obj(other.m_obj) { other.m_obj = 0; #ifdef BN_REF_COUNT_DEBUG m_assignmentTrace = other.m_assignmentTrace; #endif } ~SCRef() { if (m_obj) { m_obj->Release(); #ifdef BN_REF_COUNT_DEBUG BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace); #endif } } SCRef &operator=(const Ref &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; } SCRef &operator=(SCRef &&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; } SCRef &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; } operator T *() const { return m_obj; } T *operator->() const { return m_obj; } T &operator*() const { return *m_obj; } bool operator!() const { return m_obj == NULL; } bool operator==(const T *obj) const { return T::GetObject(m_obj) == T::GetObject(obj); } bool operator==(const SCRef &obj) const { return T::GetObject(m_obj) == T::GetObject(obj.m_obj); } bool operator!=(const T *obj) const { return T::GetObject(m_obj) != T::GetObject(obj); } bool operator!=(const SCRef &obj) const { return T::GetObject(m_obj) != T::GetObject(obj.m_obj); } bool operator<(const T *obj) const { return T::GetObject(m_obj) < T::GetObject(obj); } bool operator<(const SCRef &obj) const { return T::GetObject(m_obj) < T::GetObject(obj.m_obj); } T *GetPtr() const { return m_obj; } }; struct DSCMemoryRegion { uint64_t vmAddress; uint64_t size; std::string prettyName; }; struct BackingCacheMapping { uint64_t vmAddress; uint64_t size; uint64_t fileOffset; }; struct BackingCache { std::string path; bool isPrimary; std::vector mappings; }; struct DSCImageMemoryMapping { std::string filePath; std::string name; uint64_t vmAddress; uint64_t size; bool loaded; uint64_t rawViewOffset; }; struct DSCImage { std::string name; uint64_t headerAddress; std::vector mappings; }; struct DSCSymbol { uint64_t address; std::string name; std::string image; }; using namespace BinaryNinja; struct SharedCacheMachOHeader : public MetadataSerializable { uint64_t textBase = 0; uint64_t loadCommandOffset = 0; mach_header_64 ident; std::string identifierPrefix; std::string installName; std::vector> entryPoints; std::vector m_entryPoints; //list of entrypoints symtab_command symtab; dysymtab_command dysymtab; dyld_info_command dyldInfo; routines_command_64 routines64; function_starts_command functionStarts; std::vector moduleInitSections; linkedit_data_command exportTrie; linkedit_data_command chainedFixups {}; uint64_t relocationBase; // Section and program headers, internally use 64-bit form as it is a superset of 32-bit std::vector segments; //only three types of sections __TEXT, __DATA, __IMPORT segment_command_64 linkeditSegment; std::vector sections; std::vector sectionNames; std::vector symbolStubSections; std::vector symbolPointerSections; std::vector dylibs; build_version_command buildVersion; std::vector buildToolVersions; std::string exportTriePath; bool dysymPresent = false; bool dyldInfoPresent = false; bool exportTriePresent = false; bool chainedFixupsPresent = false; bool routinesPresent = false; bool functionStartsPresent = false; bool relocatable = false; void Serialize(const std::string& name, mach_header_64 b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.magic, m_activeContext.allocator); bArr.PushBack(b.cputype, m_activeContext.allocator); bArr.PushBack(b.cpusubtype, m_activeContext.allocator); bArr.PushBack(b.filetype, m_activeContext.allocator); bArr.PushBack(b.ncmds, m_activeContext.allocator); bArr.PushBack(b.sizeofcmds, m_activeContext.allocator); bArr.PushBack(b.flags, m_activeContext.allocator); bArr.PushBack(b.reserved, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, mach_header_64& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.magic = bArr[0].GetInt64(); b.cputype = bArr[1].GetInt64(); b.cpusubtype = bArr[2].GetInt64(); b.filetype = bArr[3].GetInt64(); b.ncmds = bArr[4].GetInt64(); b.sizeofcmds = bArr[5].GetInt64(); b.flags = bArr[6].GetInt64(); b.reserved = bArr[7].GetInt64(); } void Serialize(const std::string& name, symtab_command b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.symoff, m_activeContext.allocator); bArr.PushBack(b.nsyms, m_activeContext.allocator); bArr.PushBack(b.stroff, m_activeContext.allocator); bArr.PushBack(b.strsize, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, symtab_command& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.symoff = bArr[2].GetUint(); b.nsyms = bArr[3].GetUint(); b.stroff = bArr[4].GetUint(); b.strsize = bArr[5].GetUint(); } void Serialize(const std::string& name, dysymtab_command b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.ilocalsym, m_activeContext.allocator); bArr.PushBack(b.nlocalsym, m_activeContext.allocator); bArr.PushBack(b.iextdefsym, m_activeContext.allocator); bArr.PushBack(b.nextdefsym, m_activeContext.allocator); bArr.PushBack(b.iundefsym, m_activeContext.allocator); bArr.PushBack(b.nundefsym, m_activeContext.allocator); bArr.PushBack(b.tocoff, m_activeContext.allocator); bArr.PushBack(b.ntoc, m_activeContext.allocator); bArr.PushBack(b.modtaboff, m_activeContext.allocator); bArr.PushBack(b.nmodtab, m_activeContext.allocator); bArr.PushBack(b.extrefsymoff, m_activeContext.allocator); bArr.PushBack(b.nextrefsyms, m_activeContext.allocator); bArr.PushBack(b.indirectsymoff, m_activeContext.allocator); bArr.PushBack(b.nindirectsyms, m_activeContext.allocator); bArr.PushBack(b.extreloff, m_activeContext.allocator); bArr.PushBack(b.nextrel, m_activeContext.allocator); bArr.PushBack(b.locreloff, m_activeContext.allocator); bArr.PushBack(b.nlocrel, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, dysymtab_command& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.ilocalsym = bArr[2].GetUint(); b.nlocalsym = bArr[3].GetUint(); b.iextdefsym = bArr[4].GetUint(); b.nextdefsym = bArr[5].GetUint(); b.iundefsym = bArr[6].GetUint(); b.nundefsym = bArr[7].GetUint(); b.tocoff = bArr[8].GetUint(); b.ntoc = bArr[9].GetUint(); b.modtaboff = bArr[10].GetUint(); b.nmodtab = bArr[11].GetUint(); b.extrefsymoff = bArr[12].GetUint(); b.nextrefsyms = bArr[13].GetUint(); b.indirectsymoff = bArr[14].GetUint(); b.nindirectsyms = bArr[15].GetUint(); b.extreloff = bArr[16].GetUint(); b.nextrel = bArr[17].GetUint(); b.locreloff = bArr[18].GetUint(); b.nlocrel = bArr[19].GetUint(); } void Serialize(const std::string& name, dyld_info_command b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.rebase_off, m_activeContext.allocator); bArr.PushBack(b.rebase_size, m_activeContext.allocator); bArr.PushBack(b.bind_off, m_activeContext.allocator); bArr.PushBack(b.bind_size, m_activeContext.allocator); bArr.PushBack(b.weak_bind_off, m_activeContext.allocator); bArr.PushBack(b.weak_bind_size, m_activeContext.allocator); bArr.PushBack(b.lazy_bind_off, m_activeContext.allocator); bArr.PushBack(b.lazy_bind_size, m_activeContext.allocator); bArr.PushBack(b.export_off, m_activeContext.allocator); bArr.PushBack(b.export_size, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, dyld_info_command& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.rebase_off = bArr[2].GetUint(); b.rebase_size = bArr[3].GetUint(); b.bind_off = bArr[4].GetUint(); b.bind_size = bArr[5].GetUint(); b.weak_bind_off = bArr[6].GetUint(); b.weak_bind_size = bArr[7].GetUint(); b.lazy_bind_off = bArr[8].GetUint(); b.lazy_bind_size = bArr[9].GetUint(); b.export_off = bArr[10].GetUint(); b.export_size = bArr[11].GetUint(); } void Serialize(const std::string& name, routines_command_64 b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.init_address, m_activeContext.allocator); bArr.PushBack(b.init_module, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, routines_command_64& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.init_address = bArr[2].GetUint(); b.init_module = bArr[3].GetUint(); } void Serialize(const std::string& name, function_starts_command b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.funcoff, m_activeContext.allocator); bArr.PushBack(b.funcsize, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, function_starts_command& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.funcoff = bArr[2].GetUint(); b.funcsize = bArr[3].GetUint(); } void Serialize(const std::string& name, std::vector b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); for (auto& s : b) { rapidjson::Value sArr(rapidjson::kArrayType); std::string sectNameStr; char sectName[16]; memcpy(sectName, s.sectname, 16); sectName[15] = 0; sectNameStr = std::string(sectName); sArr.PushBack(rapidjson::Value(sectNameStr.c_str(), m_activeContext.allocator), m_activeContext.allocator); std::string segNameStr; char segName[16]; memcpy(segName, s.segname, 16); segName[15] = 0; segNameStr = std::string(segName); sArr.PushBack(rapidjson::Value(segNameStr.c_str(), m_activeContext.allocator), m_activeContext.allocator); sArr.PushBack(s.addr, m_activeContext.allocator); sArr.PushBack(s.size, m_activeContext.allocator); sArr.PushBack(s.offset, m_activeContext.allocator); sArr.PushBack(s.align, m_activeContext.allocator); sArr.PushBack(s.reloff, m_activeContext.allocator); sArr.PushBack(s.nreloc, m_activeContext.allocator); sArr.PushBack(s.flags, m_activeContext.allocator); sArr.PushBack(s.reserved1, m_activeContext.allocator); sArr.PushBack(s.reserved2, m_activeContext.allocator); sArr.PushBack(s.reserved3, m_activeContext.allocator); bArr.PushBack(sArr, m_activeContext.allocator); } m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, std::vector& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); for (auto& s : bArr) { section_64 sec; auto s2 = s.GetArray(); std::string sectNameStr = s2[0].GetString(); memcpy(sec.sectname, sectNameStr.c_str(), sectNameStr.size()); std::string segNameStr = s2[1].GetString(); memcpy(sec.segname, segNameStr.c_str(), segNameStr.size()); sec.addr = s2[2].GetUint64(); sec.size = s2[3].GetUint64(); sec.offset = s2[4].GetUint(); sec.align = s2[5].GetUint(); sec.reloff = s2[6].GetUint(); sec.nreloc = s2[7].GetUint(); sec.flags = s2[8].GetUint(); sec.reserved1 = s2[9].GetUint(); sec.reserved2 = s2[10].GetUint(); sec.reserved3 = s2[11].GetUint(); b.push_back(sec); } } void Serialize(const std::string& name, linkedit_data_command b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.dataoff, m_activeContext.allocator); bArr.PushBack(b.datasize, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, linkedit_data_command& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.dataoff = bArr[2].GetUint(); b.datasize = bArr[3].GetUint(); } void Serialize(const std::string& name, segment_command_64 b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); std::string segNameStr; char segName[16]; memcpy(segName, b.segname, 16); segName[15] = 0; segNameStr = std::string(segName); bArr.PushBack(rapidjson::Value(segNameStr.c_str(), m_activeContext.allocator), m_activeContext.allocator); bArr.PushBack(b.vmaddr, m_activeContext.allocator); bArr.PushBack(b.vmsize, m_activeContext.allocator); bArr.PushBack(b.fileoff, m_activeContext.allocator); bArr.PushBack(b.filesize, m_activeContext.allocator); bArr.PushBack(b.maxprot, m_activeContext.allocator); bArr.PushBack(b.initprot, m_activeContext.allocator); bArr.PushBack(b.nsects, m_activeContext.allocator); bArr.PushBack(b.flags, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, segment_command_64& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); std::string segNameStr = bArr[0].GetString(); memcpy(b.segname, segNameStr.c_str(), segNameStr.size()); b.vmaddr = bArr[1].GetUint64(); b.vmsize = bArr[2].GetUint64(); b.fileoff = bArr[3].GetUint64(); b.filesize = bArr[4].GetUint64(); b.maxprot = bArr[5].GetUint(); b.initprot = bArr[6].GetUint(); b.nsects = bArr[7].GetUint(); b.flags = bArr[8].GetUint(); } void Serialize(const std::string& name, std::vector b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); for (auto& s : b) { rapidjson::Value sArr(rapidjson::kArrayType); std::string segNameStr; char segName[16]; memcpy(segName, s.segname, 16); segName[15] = 0; segNameStr = std::string(segName); sArr.PushBack(rapidjson::Value(segNameStr.c_str(), m_activeContext.allocator), m_activeContext.allocator); sArr.PushBack(s.vmaddr, m_activeContext.allocator); sArr.PushBack(s.vmsize, m_activeContext.allocator); sArr.PushBack(s.fileoff, m_activeContext.allocator); sArr.PushBack(s.filesize, m_activeContext.allocator); sArr.PushBack(s.maxprot, m_activeContext.allocator); sArr.PushBack(s.initprot, m_activeContext.allocator); sArr.PushBack(s.nsects, m_activeContext.allocator); sArr.PushBack(s.flags, m_activeContext.allocator); bArr.PushBack(sArr, m_activeContext.allocator); } m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, std::vector& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); for (auto& s : bArr) { segment_command_64 sec; auto s2 = s.GetArray(); std::string segNameStr = s2[0].GetString(); memcpy(sec.segname, segNameStr.c_str(), segNameStr.size()); sec.vmaddr = s2[1].GetUint64(); sec.vmsize = s2[2].GetUint64(); sec.fileoff = s2[3].GetUint64(); sec.filesize = s2[4].GetUint64(); sec.maxprot = s2[5].GetUint(); sec.initprot = s2[6].GetUint(); sec.nsects = s2[7].GetUint(); sec.flags = s2[8].GetUint(); b.push_back(sec); } } void Serialize(const std::string& name, build_version_command b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); bArr.PushBack(b.cmd, m_activeContext.allocator); bArr.PushBack(b.cmdsize, m_activeContext.allocator); bArr.PushBack(b.platform, m_activeContext.allocator); bArr.PushBack(b.minos, m_activeContext.allocator); bArr.PushBack(b.sdk, m_activeContext.allocator); bArr.PushBack(b.ntools, m_activeContext.allocator); m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, build_version_command& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); b.cmd = bArr[0].GetUint(); b.cmdsize = bArr[1].GetUint(); b.platform = bArr[2].GetUint(); b.minos = bArr[3].GetUint(); b.sdk = bArr[4].GetUint(); b.ntools = bArr[5].GetUint(); } void Serialize(const std::string& name, std::vector b) { S(); rapidjson::Value key(name.c_str(), m_activeContext.allocator); rapidjson::Value bArr(rapidjson::kArrayType); for (auto& s : b) { rapidjson::Value sArr(rapidjson::kArrayType); sArr.PushBack(s.tool, m_activeContext.allocator); sArr.PushBack(s.version, m_activeContext.allocator); bArr.PushBack(sArr, m_activeContext.allocator); } m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); } void Deserialize(const std::string& name, std::vector& b) { auto bArr = m_activeDeserContext.doc[name.c_str()].GetArray(); for (auto& s : bArr) { build_tool_version sec; auto s2 = s.GetArray(); sec.tool = s2[0].GetUint(); sec.version = s2[1].GetUint(); b.push_back(sec); } } void Store() override { 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(dysymPresent); MSS(dyldInfoPresent); MSS(exportTriePresent); MSS(chainedFixupsPresent); MSS(routinesPresent); MSS(functionStartsPresent); MSS(relocatable); } void Load() override { MSL(textBase); MSL(loadCommandOffset); MSL_SUBCLASS(ident); MSL(identifierPrefix); MSL(installName); MSL(entryPoints); MSL(m_entryPoints); MSL_SUBCLASS(symtab); MSL_SUBCLASS(dysymtab); MSL_SUBCLASS(dyldInfo); // MSL_SUBCLASS(routines64); // FIXME CRASH but also do we even use this? MSL_SUBCLASS(functionStarts); MSL_SUBCLASS(moduleInitSections); MSL_SUBCLASS(exportTrie); MSL_SUBCLASS(chainedFixups); MSL(relocationBase); MSL_SUBCLASS(segments); MSL_SUBCLASS(linkeditSegment); MSL_SUBCLASS(sections); MSL(sectionNames); MSL_SUBCLASS(symbolStubSections); MSL_SUBCLASS(symbolPointerSections); MSL(dylibs); MSL_SUBCLASS(buildVersion); MSL_SUBCLASS(buildToolVersions); MSL(exportTriePath); MSL(dysymPresent); MSL(dyldInfoPresent); MSL(exportTriePresent); MSL(chainedFixupsPresent); // MSL(routinesPresent); MSL(functionStartsPresent); MSL(relocatable); } }; class SharedCache : public SCCoreRefCountObject { public: SharedCache(Ref view); BNDSCViewState GetState(); static BNDSCViewLoadProgress GetLoadProgress(Ref view); static uint64_t FastGetBackingCacheCount(Ref view); bool LoadImageWithInstallName(std::string installName); bool LoadSectionAtAddress(uint64_t addr); bool LoadImageContainingAddress(uint64_t addr); std::vector GetAvailableImages(); std::vector LoadAllSymbolsAndWait(); std::string GetNameForAddress(uint64_t address); std::string GetImageNameForAddress(uint64_t address); std::vector GetBackingCaches(); std::vector GetImages(); std::optional GetMachOHeaderForImage(std::string name); std::optional GetMachOHeaderForAddress(uint64_t address); std::vector GetLoadedMemoryRegions(); void FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis = true) const; }; }