summaryrefslogtreecommitdiff
path: root/view/sharedcache
diff options
context:
space:
mode:
authorMark Rowe <mrowe@bdash.net.nz>2025-02-08 10:40:44 -0800
committerMason Reed <mason@vector35.com>2025-02-12 18:43:02 -0500
commitc20bf355152d9a715dae3c19777c3d4a1046174b (patch)
treeca54b22241c36bcfd8259c16b2583b9d19487ed3 /view/sharedcache
parent714d7628097c5b02e23bcad1dba9880c7afc034b (diff)
[SharedCache] Make MetadataSerializable::Load static
`MetadataSerializable` is updated to allow a subclass to optionally specify the return type of `Load`. If not specified it defaults to the subclass itself. `SharedCache` specifies `std::optional` to represent the case where the serialized metadata is in a format or version it does not recognize. By making `Load` a static member function and having it return a new object it becomes easier to reason about the state of objects when a deserialization failure occurs. It can return `std::optional` to indicate failure and there is no object left in an unknown state. Prior to this, `Load` worked on an existing instance of an object. It was unclear what state the object would be in if a deserialization failure occurred (its original state prior to `Load`? some partially-loaded state? a null state?). The failure itself also had to be communicated out of band.
Diffstat (limited to 'view/sharedcache')
-rw-r--r--view/sharedcache/api/sharedcache.cpp9
-rw-r--r--view/sharedcache/api/sharedcacheapi.h70
-rw-r--r--view/sharedcache/core/MetadataSerializable.hpp40
-rw-r--r--view/sharedcache/core/SharedCache.cpp168
-rw-r--r--view/sharedcache/core/SharedCache.h159
5 files changed, 204 insertions, 242 deletions
diff --git a/view/sharedcache/api/sharedcache.cpp b/view/sharedcache/api/sharedcache.cpp
index e764531c..472bb024 100644
--- a/view/sharedcache/api/sharedcache.cpp
+++ b/view/sharedcache/api/sharedcache.cpp
@@ -204,9 +204,8 @@ namespace SharedCacheAPI {
BNFreeString(outputStr);
if (output.empty())
return {};
- SharedCacheMachOHeader header;
- header.LoadFromString(output);
- return header;
+
+ return SharedCacheMachOHeader::LoadFromString(output);
}
std::optional<SharedCacheMachOHeader> SharedCache::GetMachOHeaderForAddress(uint64_t address)
@@ -218,9 +217,7 @@ namespace SharedCacheAPI {
BNFreeString(outputStr);
if (output.empty())
return {};
- SharedCacheMachOHeader header;
- header.LoadFromString(output);
- return header;
+ return SharedCacheMachOHeader::LoadFromString(output);
}
BNDSCViewState SharedCache::GetState()
diff --git a/view/sharedcache/api/sharedcacheapi.h b/view/sharedcache/api/sharedcacheapi.h
index cfe78351..ec64ef10 100644
--- a/view/sharedcache/api/sharedcacheapi.h
+++ b/view/sharedcache/api/sharedcacheapi.h
@@ -211,40 +211,42 @@ namespace SharedCacheAPI {
MSS(relocatable);
}
- void Load(SharedCacheCore::DeserializationContext& context) {
- 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);
+ static SharedCacheMachOHeader Load(SharedCacheCore::DeserializationContext& context) {
+ return SharedCacheMachOHeader {
+ .MSL(textBase),
+ .MSL(loadCommandOffset),
+ .MSL(ident),
+ .MSL(identifierPrefix),
+ .MSL(installName),
+ .MSL(entryPoints),
+ .MSL(m_entryPoints),
+ .MSL(symtab),
+ .MSL(dysymtab),
+ .MSL(dyldInfo),
+ // .MSL(routines64), // FIXME CRASH but also do we even use this?
+ .MSL(functionStarts),
+ .MSL(moduleInitSections),
+ .MSL(exportTrie),
+ .MSL(chainedFixups),
+ .MSL(relocationBase),
+ .MSL(segments),
+ .MSL(linkeditSegment),
+ .MSL(sections),
+ .MSL(sectionNames),
+ .MSL(symbolStubSections),
+ .MSL(symbolPointerSections),
+ .MSL(dylibs),
+ .MSL(buildVersion),
+ .MSL(buildToolVersions),
+ .MSL(exportTriePath),
+ .MSL(dysymPresent),
+ .MSL(dyldInfoPresent),
+ .MSL(exportTriePresent),
+ .MSL(chainedFixupsPresent),
+ // .MSL(routinesPresent),
+ .MSL(functionStartsPresent),
+ .MSL(relocatable),
+ };
}
};
diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp
index 7b44ccbd..91ab2ed2 100644
--- a/view/sharedcache/core/MetadataSerializable.hpp
+++ b/view/sharedcache/core/MetadataSerializable.hpp
@@ -34,6 +34,10 @@
avoid that.
* */
+#ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP
+#define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP
+
+#include <cassert>
#include "binaryninjaapi.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
@@ -41,9 +45,6 @@
#include "../api/sharedcachecore.h"
#include "view/macho/machoview.h"
-#ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP
-#define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP
-
namespace SharedCacheCore {
#define MSS(name) context.store(#name, name)
@@ -51,7 +52,6 @@ namespace SharedCacheCore {
#define MSS_SUBCLASS(name) Serialize(context, #name, name)
#define MSL(name) name = context.load<decltype(name)>(#name)
#define MSL_CAST(name, storedType, type) name = (type)context.load<storedType>(#name)
-#define MSL_SUBCLASS(name) Deserialize(context, #name, name)
using namespace BinaryNinja;
@@ -83,44 +83,34 @@ struct DeserializationContext {
}
};
-template <typename Derived>
-class MetadataSerializable
-{
+template <typename Derived, typename LoadResult = Derived>
+class MetadataSerializable {
public:
- std::string AsString() const
- {
+ std::string AsString() const {
SerializationContext context;
Store(context);
return context.buffer.GetString();
}
- void LoadFromString(const std::string& s)
- {
+ static LoadResult LoadFromString(const std::string& s) {
DeserializationContext context;
- context.doc.Parse(s.c_str());
- AsDerived().Load(context);
+ [[maybe_unused]] rapidjson::ParseResult result = context.doc.Parse(s.c_str());
+ assert(result);
+ return Derived::Load(context);
}
- void LoadFromValue(rapidjson::Value& s)
- {
+ static LoadResult LoadFromValue(rapidjson::Value& s) {
DeserializationContext context;
context.doc.CopyFrom(s, context.doc.GetAllocator());
- AsDerived().Load(context);
+ return Derived::Load(context);
}
- Ref<Metadata> AsMetadata() {
+ Ref<Metadata> AsMetadata() const {
return new Metadata(AsString());
}
- bool LoadFromMetadata(const Ref<Metadata>& meta)
- {
- if (!meta->IsString())
- return false;
- LoadFromString(meta->GetString());
- return true;
- }
-
+ template <typename... Args>
void Store(SerializationContext& context) const {
context.writer.StartObject();
AsDerived().Store(context);
diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp
index 062031c6..bfc06db9 100644
--- a/view/sharedcache/core/SharedCache.cpp
+++ b/view/sharedcache/core/SharedCache.cpp
@@ -25,15 +25,16 @@
* */
#include "SharedCache.h"
+
+#include "DSCView.h"
#include "ObjC.h"
#include <filesystem>
#include <mutex>
+#include <optional>
#include <unordered_map>
#include <utility>
#include <fcntl.h>
#include <memory>
-#include <chrono>
-#include <thread>
using namespace BinaryNinja;
@@ -55,8 +56,9 @@ int count_trailing_zeros(uint64_t value) {
}
#endif
-struct SharedCache::State
-{
+namespace SharedCacheCore {
+
+struct SharedCacheState {
std::unordered_map<uint64_t, std::shared_ptr<std::unordered_map<uint64_t, Ref<Symbol>>>>
exportInfos;
std::unordered_map<uint64_t, std::vector<std::pair<uint64_t, std::pair<BNSymbolType, std::string>>>>
@@ -78,10 +80,12 @@ struct SharedCache::State
std::optional<std::pair<size_t, size_t>> objcOptimizationDataRange;
std::string baseFilePath;
- SharedCacheFormat cacheFormat;
+ SharedCache::SharedCacheFormat cacheFormat;
DSCViewState viewState = DSCViewStateUnloaded;
};
+} // namespace SharedCacheCore
+
struct SharedCache::ViewSpecificState {
std::mutex typeLibraryMutex;
std::unordered_map<std::string, Ref<TypeLibrary>> typeLibraries;
@@ -91,7 +95,7 @@ struct SharedCache::ViewSpecificState {
std::atomic<BNDSCViewLoadProgress> progress;
std::mutex stateMutex;
- std::shared_ptr<struct SharedCache::State> cachedState;
+ std::shared_ptr<SharedCacheState> cachedState;
};
@@ -993,33 +997,34 @@ std::shared_ptr<VM> SharedCache::GetVMMap(bool mapPages)
void SharedCache::DeserializeFromRawView()
{
- if (m_dscView->QueryMetadata(SharedCacheMetadataTag))
- {
+ if (m_dscView->QueryMetadata(SharedCacheMetadataTag)) {
std::lock_guard lock(m_viewSpecificState->stateMutex);
- if (m_viewSpecificState->cachedState)
- {
+ if (m_viewSpecificState->cachedState) {
m_state = m_viewSpecificState->cachedState;
m_stateIsShared = true;
m_metadataValid = true;
+ return;
}
- else
- {
- LoadFromString(m_dscView->GetStringMetadata(SharedCacheMetadataTag));
- }
- if (!m_metadataValid)
- {
- m_logger->LogError("Failed to deserialize Shared Cache metadata");
- WillMutateState();
- MutableState().viewState = DSCViewStateUnloaded;
+
+ if (auto state = LoadFromString(m_dscView->GetStringMetadata(SharedCacheMetadataTag))) {
+ m_state = std::make_shared<SharedCacheState>(std::move(*state));
+ m_stateIsShared = false;
+ m_metadataValid = true;
+ return;
}
- }
- else
- {
- m_metadataValid = true;
+
+ m_state = nullptr;
+ m_metadataValid = false;
+ m_logger->LogError("Failed to deserialize Shared Cache metadata");
WillMutateState();
MutableState().viewState = DSCViewStateUnloaded;
- MutableState().images.clear(); // fixme ??
+ return;
}
+
+ m_metadataValid = true;
+ WillMutateState();
+ MutableState().viewState = DSCViewStateUnloaded;
+ MutableState().images.clear(); // fixme ??
}
@@ -3026,7 +3031,7 @@ bool SharedCache::SaveToDSCView()
// By moving our state the to cache we can avoid creating a copy in the case
// that no further mutations are made to `this`. If we're not done being mutated,
// the data will be copied on the first mutation.
- auto cachedState = std::make_shared<struct State>(std::move(*m_state));
+ auto cachedState = std::make_shared<SharedCacheState>(std::move(*m_state));
m_state = cachedState;
m_stateIsShared = true;
@@ -3513,40 +3518,31 @@ void SharedCache::Store(SerializationContext& context) const
Serialize(context, "nonImageRegions", State().nonImageRegions);
}
-void SharedCache::Load(DeserializationContext& context)
-{
- if (context.doc.HasMember("metadataVersion"))
- {
- if (context.doc["metadataVersion"].GetUint() != METADATA_VERSION)
- {
- m_logger->LogError("Shared Cache metadata version mismatch");
- return;
- }
+std::optional<SharedCacheState> SharedCache::Load(DeserializationContext& context) {
+ if (!context.doc.HasMember("metadataVersion")) {
+ LogError("Shared Cache metadata version missing");
+ return std::nullopt;
}
- else
- {
- m_logger->LogError("Shared Cache metadata version missing");
- return;
+
+ if (context.doc["metadataVersion"].GetUint() != METADATA_VERSION) {
+ LogError("Shared Cache metadata version mismatch");
+ return std::nullopt;
}
- m_stateIsShared = false;
- m_state = std::make_shared<struct SharedCache::State>();
+ SharedCacheState state;
- MutableState().viewState = static_cast<DSCViewState>(context.load<uint8_t>("m_viewState"));
- MutableState().cacheFormat = static_cast<SharedCacheFormat>(context.load<uint8_t>("m_cacheFormat"));
+ state.viewState = static_cast<DSCViewState>(context.load<uint8_t>("m_viewState"));
+ state.cacheFormat = static_cast<SharedCacheFormat>(context.load<uint8_t>("m_cacheFormat"));
- for (auto& startAndHeader : context.doc["headers"].GetArray())
- {
- SharedCacheMachOHeader header;
- header.LoadFromValue(startAndHeader);
- MutableState().headers[header.textBase] = std::move(header);
+ for (auto& startAndHeader : context.doc["headers"].GetArray()) {
+ SharedCacheMachOHeader header = SharedCacheMachOHeader::LoadFromValue(startAndHeader);
+ state.headers[header.textBase] = std::move(header);
}
- Deserialize(context, "m_imageStarts", MutableState().imageStarts);
- Deserialize(context, "m_baseFilePath", MutableState().baseFilePath);
+ Deserialize(context, "m_imageStarts", state.imageStarts);
+ Deserialize(context, "m_baseFilePath", state.baseFilePath);
- for (const auto& obj1 : context.doc["exportInfos"].GetArray())
- {
+ for (const auto& obj1 : context.doc["exportInfos"].GetArray()) {
std::unordered_map<uint64_t, Ref<Symbol>> innerVec;
for (const auto& obj2 : obj1["value"].GetArray())
{
@@ -3556,11 +3552,10 @@ void SharedCache::Load(DeserializationContext& context)
raw.c_str(), raw.c_str(), addr, NoBinding, nullptr, 0));
}
- MutableState().exportInfos[obj1["key"].GetUint64()] = std::make_shared<std::unordered_map<uint64_t, Ref<Symbol>>>(innerVec);
+ state.exportInfos[obj1["key"].GetUint64()] = std::make_shared<std::unordered_map<uint64_t, Ref<Symbol>>>(innerVec);
}
- for (auto& symbolInfo : context.doc["symbolInfos"].GetArray())
- {
+ for (auto& symbolInfo : context.doc["symbolInfos"].GetArray()) {
std::vector<std::pair<uint64_t, std::pair<BNSymbolType, std::string>>>
symbolInfos;
auto symbolInfoArray = symbolInfo["value"].GetArray();
@@ -3570,65 +3565,48 @@ void SharedCache::Load(DeserializationContext& context)
symbolInfos.push_back({si["key"].GetUint64(),
{static_cast<BNSymbolType>(si["val1"].GetUint64()), si["val2"].GetString()}});
}
- MutableState().symbolInfos[symbolInfo["key"].GetUint64()] = std::move(symbolInfos);
+ state.symbolInfos[symbolInfo["key"].GetUint64()] = std::move(symbolInfos);
}
- for (auto& bcV : context.doc["backingCaches"].GetArray())
- {
- BackingCache bc;
- bc.LoadFromValue(bcV);
- MutableState().backingCaches.push_back(std::move(bc));
+ for (auto& bcV : context.doc["backingCaches"].GetArray()) {
+ state.backingCaches.push_back(BackingCache::LoadFromValue(bcV));
}
- for (auto& imgV : context.doc["images"].GetArray())
- {
- CacheImage img;
- img.LoadFromValue(imgV);
- MutableState().images.push_back(std::move(img));
+ for (auto& imgV : context.doc["images"].GetArray()) {
+ state.images.push_back(CacheImage::LoadFromValue(imgV));
}
- for (auto& rV : context.doc["regionsMappedIntoMemory"].GetArray())
- {
- MemoryRegion r;
- r.LoadFromValue(rV);
- MutableState().regionsMappedIntoMemory.push_back(std::move(r));
+ for (auto& rV : context.doc["regionsMappedIntoMemory"].GetArray()) {
+ state.regionsMappedIntoMemory.push_back(MemoryRegion::LoadFromValue(rV));
}
- for (auto& siV : context.doc["stubIslands"].GetArray())
- {
- MemoryRegion si;
- si.LoadFromValue(siV);
- MutableState().stubIslandRegions.push_back(std::move(si));
+ for (auto& siV : context.doc["stubIslands"].GetArray()) {
+ state.stubIslandRegions.push_back(MemoryRegion::LoadFromValue(siV));
}
- for (auto& siV : context.doc["dyldDataSections"].GetArray())
- {
- MemoryRegion si;
- si.LoadFromValue(siV);
- MutableState().dyldDataRegions.push_back(std::move(si));
+ for (auto& siV : context.doc["dyldDataSections"].GetArray()) {
+ state.dyldDataRegions.push_back(MemoryRegion::LoadFromValue(siV));
}
- for (auto& siV : context.doc["nonImageRegions"].GetArray())
- {
- MemoryRegion si;
- si.LoadFromValue(siV);
- MutableState().nonImageRegions.push_back(std::move(si));
+ for (auto& siV : context.doc["nonImageRegions"].GetArray()) {
+ state.nonImageRegions.push_back(MemoryRegion::LoadFromValue(siV));
}
- m_metadataValid = true;
+ return state;
}
-void BackingCache::Store(SerializationContext& context) const
-{
+void BackingCache::Store(SerializationContext& context) const {
MSS(path);
MSS(isPrimary);
MSS(mappings);
}
-void BackingCache::Load(DeserializationContext& context)
-{
- MSL(path);
- MSL(isPrimary);
- MSL(mappings);
+
+BackingCache BackingCache::Load(DeserializationContext& context) {
+ return BackingCache {
+ .MSL(path),
+ .MSL(isPrimary),
+ .MSL(mappings),
+ };
}
#if defined(__GNUC__) || defined(__clang__)
@@ -3650,11 +3628,11 @@ void SharedCache::WillMutateState()
{
if (!m_state)
{
- m_state = std::make_shared<struct State>();
+ m_state = std::make_shared<SharedCacheState>();
}
else if (m_stateIsShared)
{
- m_state = std::make_shared<struct State>(*m_state);
+ m_state = std::make_shared<SharedCacheState>(*m_state);
}
m_stateIsShared = false;
}
diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h
index 2f6f2ae4..1b3f8261 100644
--- a/view/sharedcache/core/SharedCache.h
+++ b/view/sharedcache/core/SharedCache.h
@@ -2,15 +2,16 @@
// Created by kat on 5/19/23.
//
+#ifndef SHAREDCACHE_SHAREDCACHE_H
+#define SHAREDCACHE_SHAREDCACHE_H
+
#include <binaryninjaapi.h>
-#include "DSCView.h"
#include "VM.h"
#include "view/macho/machoview.h"
#include "MetadataSerializable.hpp"
#include "../api/sharedcachecore.h"
-#ifndef SHAREDCACHE_SHAREDCACHE_H
-#define SHAREDCACHE_SHAREDCACHE_H
+#include <optional>
DECLARE_SHAREDCACHE_API_OBJECT(BNSharedCache, SharedCache);
@@ -25,8 +26,7 @@ namespace SharedCacheCore {
const std::string SharedCacheMetadataTag = "SHAREDCACHE-SharedCacheData";
- struct MemoryRegion : public MetadataSerializable<MemoryRegion>
- {
+ struct MemoryRegion : public MetadataSerializable<MemoryRegion> {
std::string prettyName;
uint64_t start;
uint64_t size;
@@ -35,8 +35,7 @@ namespace SharedCacheCore {
bool headerInitialized = false;
BNSegmentFlag flags;
- void Store(SerializationContext& context) const
- {
+ void Store(SerializationContext& context) const {
MSS(prettyName);
MSS(start);
MSS(size);
@@ -45,48 +44,46 @@ namespace SharedCacheCore {
MSS_CAST(flags, uint64_t);
}
- void Load(DeserializationContext& context)
- {
- MSL(prettyName);
- MSL(start);
- MSL(size);
- MSL(loaded);
- MSL(rawViewOffsetIfLoaded);
- MSL_CAST(flags, uint64_t, BNSegmentFlag);
+ static MemoryRegion Load(DeserializationContext& context) {
+ return MemoryRegion {
+ .MSL(prettyName),
+ .MSL(start),
+ .MSL(size),
+ .MSL(loaded),
+ .MSL(rawViewOffsetIfLoaded),
+ .MSL_CAST(flags, uint64_t, BNSegmentFlag),
+ };
}
};
- struct CacheImage : public MetadataSerializable<CacheImage>
- {
+ struct CacheImage : public MetadataSerializable<CacheImage> {
std::string installName;
uint64_t headerLocation;
std::vector<MemoryRegion> regions;
- void Store(SerializationContext& context) const
- {
+ void Store(SerializationContext& context) const {
MSS(installName);
MSS(headerLocation);
Serialize(context, "regions");
context.writer.StartArray();
- for (auto& region : regions)
- {
+ for (auto& region : regions) {
Serialize(context, region.AsString());
}
context.writer.EndArray();
}
- void Load(DeserializationContext& context)
- {
- MSL(installName);
- MSL(headerLocation);
- auto bArr = context.doc["regions"].GetArray();
- regions.clear();
- for (auto& region : bArr)
- {
- MemoryRegion r;
- r.LoadFromString(region.GetString());
- regions.push_back(r);
+ static CacheImage Load(DeserializationContext& context) {
+ auto regionsArray = context.doc["regions"].GetArray();
+ std::vector<MemoryRegion> regions;
+ for (auto& region : regionsArray) {
+ regions.push_back(MemoryRegion::LoadFromString(region.GetString()));
}
+
+ return CacheImage {
+ .MSL(installName),
+ .MSL(headerLocation),
+ .regions = std::move(regions),
+ };
}
};
@@ -111,14 +108,13 @@ namespace SharedCacheCore {
uint32_t initProt;
};
- struct BackingCache : public MetadataSerializable<BackingCache>
- {
+ struct BackingCache : public MetadataSerializable<BackingCache> {
std::string path;
bool isPrimary = false;
std::vector<dyld_cache_mapping_info> mappings;
void Store(SerializationContext& context) const;
- void Load(DeserializationContext& context);
+ static BackingCache Load(DeserializationContext& context);
};
struct LoadedMapping
@@ -436,8 +432,7 @@ namespace SharedCacheCore {
bool functionStartsPresent = false;
bool relocatable = false;
- void Store(SerializationContext& context) const
- {
+ void Store(SerializationContext& context) const {
MSS(textBase);
MSS(loadCommandOffset);
MSS_SUBCLASS(ident);
@@ -473,46 +468,47 @@ namespace SharedCacheCore {
MSS(functionStartsPresent);
MSS(relocatable);
}
- void Load(DeserializationContext& context)
- {
- 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(linkeditPresent);
- MSL(exportTriePath);
- MSL(dysymPresent);
- MSL(dyldInfoPresent);
- MSL(exportTriePresent);
- MSL(chainedFixupsPresent);
- // MSL(routinesPresent);
- MSL(functionStartsPresent);
- MSL(relocatable);
+
+ static SharedCacheMachOHeader Load(DeserializationContext& context) {
+ return SharedCacheMachOHeader {
+ .MSL(textBase),
+ .MSL(loadCommandOffset),
+ .MSL(ident),
+ .MSL(identifierPrefix),
+ .MSL(installName),
+ .MSL(entryPoints),
+ .MSL(m_entryPoints),
+ .MSL(symtab),
+ .MSL(dysymtab),
+ .MSL(dyldInfo),
+ // .MSL(routines64), // FIXME CRASH but also do we even use this?
+ .MSL(functionStarts),
+ .MSL(moduleInitSections),
+ .MSL(exportTrie),
+ .MSL(chainedFixups),
+ .MSL(relocationBase),
+ .MSL(segments),
+ .MSL(linkeditSegment),
+ .MSL(sections),
+ .MSL(sectionNames),
+ .MSL(symbolStubSections),
+ .MSL(symbolPointerSections),
+ .MSL(dylibs),
+ .MSL(buildVersion),
+ .MSL(buildToolVersions),
+ .MSL(linkeditPresent),
+ .MSL(exportTriePath),
+ .MSL(dysymPresent),
+ .MSL(dyldInfoPresent),
+ .MSL(exportTriePresent),
+ .MSL(chainedFixupsPresent),
+ // .MSL(routinesPresent),
+ .MSL(functionStartsPresent),
+ .MSL(relocatable),
+ };
}
};
-
struct MappingInfo
{
std::shared_ptr<MMappedFileAccessor> file;
@@ -528,8 +524,9 @@ namespace SharedCacheCore {
static std::atomic<uint64_t> sharedCacheReferences = 0;
- class SharedCache : public MetadataSerializable<SharedCache>
- {
+ struct SharedCacheState;
+
+ class SharedCache : public MetadataSerializable<SharedCache, std::optional<SharedCacheState>> {
IMPLEMENT_SHAREDCACHE_API_OBJECT(BNSharedCache);
std::atomic<int> m_refs = 0;
@@ -561,9 +558,7 @@ namespace SharedCacheCore {
};
void Store(SerializationContext& context) const;
- void Load(DeserializationContext& context);
-
- struct State;
+ static std::optional<SharedCacheState> Load(DeserializationContext& context);
struct ViewSpecificState;
@@ -575,7 +570,7 @@ namespace SharedCacheCore {
// Updated as the view is loaded further, more images are added, etc
// NOTE: Access via `State()` or `MutableState()` below.
// `WillMutateState()` must be called before the first access to `MutableState()`.
- std::shared_ptr<State> m_state;
+ std::shared_ptr<SharedCacheState> m_state;
bool m_stateIsShared = false;
// Serialized once by PerformInitialLoad and available after m_viewState == Loaded
@@ -651,8 +646,8 @@ private:
size_t GetBaseAddress() const;
std::optional<ObjCOptimizationHeader> GetObjCOptimizationHeader(VMReader reader) const;
- const State& State() const { return *m_state; }
- struct State& MutableState() { AssertMutable(); return *m_state; }
+ const SharedCacheState& State() const { return *m_state; }
+ struct SharedCacheState& MutableState() { AssertMutable(); return *m_state; }
void AssertMutable() const;