From 453ed0d431ceec371e15d64eecf47a0fcab6c3a9 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Wed, 13 Nov 2024 15:48:14 -0800 Subject: [PATCH 1/7] [SharedCache] Rework metadata serialization to reduce memory overhead api/MetadataSerializable.hpp is removed in favor of including core/MetadataSerializable.hpp. Both headers defined types with the same name leading to One Definition Rule violations and surprising behavior. The serialization and deserialization context are now created on-demand during serialization rather than being a member of `MetadataSerializable`. This reduces the size of every serializable object by ~220 bytes. The context is passed explicitly as an argument to `Serialize` / `Deserialize`. As a result, `Serialize` / `Deserialize` can now be free functions rather than member functions. Since `MetadataSerializable` is not used for dynamic dispatch, the virtual methods are removed and the class is updated to be a class template using CRTP. This allows delegating to the derived class's `Load` and `Store` methods without the additional size overhead of the vtable pointer in every serializable object. These changes reduce the memory footprint of Binary Ninja after loading the macOS shared cache and loading a single dylib from it from 8.3GB to 4.6GB. --- view/sharedcache/api/MetadataSerializable.hpp | 500 ----------- view/sharedcache/api/sharedcache.cpp | 395 +++++++++ view/sharedcache/api/sharedcacheapi.h | 439 +--------- .../sharedcache/core/MetadataSerializable.hpp | 820 +++++++++--------- view/sharedcache/core/SharedCache.cpp | 404 +++++++++ view/sharedcache/core/SharedCache.h | 573 ++---------- 6 files changed, 1325 insertions(+), 1806 deletions(-) delete mode 100644 view/sharedcache/api/MetadataSerializable.hpp diff --git a/view/sharedcache/api/MetadataSerializable.hpp b/view/sharedcache/api/MetadataSerializable.hpp deleted file mode 100644 index dd3951ea7f..0000000000 --- a/view/sharedcache/api/MetadataSerializable.hpp +++ /dev/null @@ -1,500 +0,0 @@ -// -// Created by kat on 5/31/23. -// - -/* - * Welcome to, this file. - * - * This is a metadata serialization helper. - * - * Have you ever wished turning a complex datastructure into a Metadata object was as easy in C++ as it is in python? - * Do you like macros and templates? - * - * Great news. - * - * Implement these on your `public MetadataSerializable` subclass: - * ``` - void Store() override { - MSS(m_someVariable); - MSS(m_someOtherVariable); - } - void Load() override { - MSL(m_someVariable); - MSL(m_someOtherVariable); - } - ``` - * Then, you can turn your object into a Metadata object with `AsMetadata()`, and load it back with - `LoadFromMetadata()`. - * - * Serialized fields will be automatically repopulated. - * - * Other ser/deser formats (rapidjson objects, strings) also exist. You can use these to achieve nesting, but probably - avoid that. - * */ - -#include "binaryninjaapi.h" -#include "rapidjson/document.h" -#include "rapidjson/stringbuffer.h" -#include "rapidjson/prettywriter.h" - -#ifndef SHAREDCACHE_METADATASERIALIZABLE_HPP -#define SHAREDCACHE_METADATASERIALIZABLE_HPP - -#define MSS(name) store(#name, name) -#define MSS_CAST(name, type) store(#name, (type) name) -#define MSS_SUBCLASS(name) Serialize(#name, name) -#define MSL(name) name = load(#name, name) -#define MSL_CAST(name, storedType, type) name = (type)load(#name, (storedType) name) -#define MSL_SUBCLASS(name) Deserialize(#name, name) - -using namespace BinaryNinja; - -class MetadataSerializable -{ -protected: - struct SerialContext - { - rapidjson::Document doc; - rapidjson::Document::AllocatorType allocator; - }; - struct DeserContext - { - rapidjson::Document doc; - }; - - DeserContext m_activeDeserContext; - SerialContext m_activeContext; - -public: - MetadataSerializable() - { - m_activeContext.doc.SetObject(); - m_activeContext.allocator = m_activeContext.doc.GetAllocator(); - } - - // copy constructor - MetadataSerializable(const MetadataSerializable& other) - { - m_activeContext.doc.CopyFrom(other.m_activeContext.doc, m_activeContext.doc.GetAllocator()); - } - - // copy assignment - MetadataSerializable& operator=(const MetadataSerializable& other) - { - m_activeContext.doc.CopyFrom(other.m_activeContext.doc, m_activeContext.doc.GetAllocator()); - return *this; - } - - virtual ~MetadataSerializable() - { - } - - void SetupSerContext(rapidjson::Document::AllocatorType* alloc = nullptr) - { - m_activeContext.doc.SetObject(); - m_activeContext.allocator = m_activeContext.doc.GetAllocator(); - } - void S() - { - // fixme factor out - } - void Serialize(std::string& name, bool b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, bool& b) { b = m_activeDeserContext.doc[name.c_str()].GetBool(); } - - void Serialize(std::string& name, uint8_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint8_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); - } - - void Serialize(std::string& name, uint16_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint16_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); - } - - void Serialize(std::string& name, uint32_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint32_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); - } - - void Serialize(std::string& name, uint64_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint64_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetUint64(); - } - - void Serialize(std::string& name, int8_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int8_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } - - void Serialize(std::string& name, int16_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int16_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } - - void Serialize(std::string& name, int32_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int32_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt(); - } - - void Serialize(std::string& name, int64_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int64_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } - - void Serialize(std::string& name, std::string b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value value(b.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, value, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::string& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetString(); - } - - void Serialize(std::string& name, std::map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); - } - - void Serialize(std::string& name, std::unordered_map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - - void Serialize(std::string& name, std::unordered_map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value key(i.first.c_str(), m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(key, m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::unordered_map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); - } - - void Serialize(std::string& name, std::unordered_map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - p.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::unordered_map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); - } - - // std::unordered_map> - void Serialize(std::string& name, std::unordered_map> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value classes(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value classArr(rapidjson::kArrayType); - rapidjson::Value classKey(i.first.c_str(), m_activeContext.allocator); - classArr.PushBack(classKey, m_activeContext.allocator); - rapidjson::Value membersArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value member(rapidjson::kArrayType); - member.PushBack(j.first, m_activeContext.allocator); - member.PushBack(j.second, m_activeContext.allocator); - membersArr.PushBack(member, m_activeContext.allocator); - } - classArr.PushBack(membersArr, m_activeContext.allocator); - classes.PushBack(classArr, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, classes, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::unordered_map>& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::string key = i.GetArray()[0].GetString(); - std::unordered_map memArray; - for (auto& member : i.GetArray()[1].GetArray()) - { - memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); - } - b[key] = memArray; - } - } - - void Deserialize(std::string& name, std::unordered_map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); - } - - void Serialize(std::string& name, std::vector b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (const auto& s : b) - { - rapidjson::Value value(s.c_str(), m_activeContext.allocator); - bArr.PushBack(value, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::vector& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b.emplace_back(i.GetString()); - } - - void Serialize(std::string& name, std::vector>> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - segV.PushBack(i.second.first, m_activeContext.allocator); - segV.PushBack(i.second.second, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::vector>>& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::pair> j; - j.first = i.GetArray()[0].GetUint64(); - j.second.first = i.GetArray()[1].GetUint64(); - j.second.second = i.GetArray()[2].GetUint64(); - b.push_back(j); - } - } - - void Serialize(std::string& name, std::vector> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - segV.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::vector>& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::pair j; - j.first = i.GetArray()[0].GetUint64(); - j.second = i.GetArray()[1].GetBool(); - b.push_back(j); - } - } - - void Serialize(std::string& name, std::vector b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - bArr.PushBack(i, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::vector& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - b.push_back(i.GetUint64()); - } - } - - // std::unordered_map - void Serialize(std::string& name, std::unordered_map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value key(i.first.c_str(), m_activeContext.allocator); - p.PushBack(key, m_activeContext.allocator); - p.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::unordered_map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); - } - } - - template - void store(std::string x, T y) - { - Serialize(x, y); - } - - template - T load(std::string x, T y) - { - T val; - Deserialize(x, val); - return val; - } - - rapidjson::Document& GetDoc() - { - S(); - Store(); - return m_activeContext.doc; - } - -public: - virtual void Store() = 0; - virtual void Load() = 0; - - std::string AsString() - { - rapidjson::StringBuffer strbuf; - rapidjson::PrettyWriter writer(strbuf); - GetDoc().Accept(writer); - - std::string s = strbuf.GetString(); - return s; - } - rapidjson::Document& AsDocument() { return GetDoc(); } - void LoadFromString(const std::string& s) - { - m_activeDeserContext.doc.Parse(s.c_str()); - Load(); - } - void LoadFromValue(rapidjson::Value& s) - { - m_activeDeserContext.doc.CopyFrom(s, m_activeDeserContext.doc.GetAllocator()); - Load(); - } - Ref AsMetadata() { return new Metadata(AsString()); } - bool LoadFromMetadata(const Ref& meta) - { - if (!meta->IsString()) - return false; - LoadFromString(meta->GetString()); - return true; - } -}; - -#endif // SHAREDCACHE_METADATASERIALIZABLE_HPP diff --git a/view/sharedcache/api/sharedcache.cpp b/view/sharedcache/api/sharedcache.cpp index 5ca7c480eb..45ca6377f6 100644 --- a/view/sharedcache/api/sharedcache.cpp +++ b/view/sharedcache/api/sharedcache.cpp @@ -221,4 +221,399 @@ namespace SharedCacheAPI { { BNDSCFindSymbolAtAddressAndApplyToAddress(m_object, symbolLocation, targetLocation, triggerReanalysis); } + + +void Serialize(SharedCacheCore::SerializationContext& context, std::string_view name, const mach_header_64& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.magic, context.allocator); + bArr.PushBack(b.cputype, context.allocator); + bArr.PushBack(b.cpusubtype, context.allocator); + bArr.PushBack(b.filetype, context.allocator); + bArr.PushBack(b.ncmds, context.allocator); + bArr.PushBack(b.sizeofcmds, context.allocator); + bArr.PushBack(b.flags, context.allocator); + bArr.PushBack(b.reserved, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, mach_header_64& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const symtab_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.symoff, context.allocator); + bArr.PushBack(b.nsyms, context.allocator); + bArr.PushBack(b.stroff, context.allocator); + bArr.PushBack(b.strsize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, symtab_command& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const dysymtab_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.ilocalsym, context.allocator); + bArr.PushBack(b.nlocalsym, context.allocator); + bArr.PushBack(b.iextdefsym, context.allocator); + bArr.PushBack(b.nextdefsym, context.allocator); + bArr.PushBack(b.iundefsym, context.allocator); + bArr.PushBack(b.nundefsym, context.allocator); + bArr.PushBack(b.tocoff, context.allocator); + bArr.PushBack(b.ntoc, context.allocator); + bArr.PushBack(b.modtaboff, context.allocator); + bArr.PushBack(b.nmodtab, context.allocator); + bArr.PushBack(b.extrefsymoff, context.allocator); + bArr.PushBack(b.nextrefsyms, context.allocator); + bArr.PushBack(b.indirectsymoff, context.allocator); + bArr.PushBack(b.nindirectsyms, context.allocator); + bArr.PushBack(b.extreloff, context.allocator); + bArr.PushBack(b.nextrel, context.allocator); + bArr.PushBack(b.locreloff, context.allocator); + bArr.PushBack(b.nlocrel, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, dysymtab_command& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const dyld_info_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.rebase_off, context.allocator); + bArr.PushBack(b.rebase_size, context.allocator); + bArr.PushBack(b.bind_off, context.allocator); + bArr.PushBack(b.bind_size, context.allocator); + bArr.PushBack(b.weak_bind_off, context.allocator); + bArr.PushBack(b.weak_bind_size, context.allocator); + bArr.PushBack(b.lazy_bind_off, context.allocator); + bArr.PushBack(b.lazy_bind_size, context.allocator); + bArr.PushBack(b.export_off, context.allocator); + bArr.PushBack(b.export_size, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, dyld_info_command& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const routines_command_64& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.init_address, context.allocator); + bArr.PushBack(b.init_module, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, routines_command_64& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const function_starts_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.funcoff, context.allocator); + bArr.PushBack(b.funcsize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, function_starts_command& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.cmd = bArr[0].GetUint(); + b.cmdsize = bArr[1].GetUint(); + b.funcoff = bArr[2].GetUint(); + b.funcsize = bArr[3].GetUint(); +} + +void Serialize(SharedCacheCore::SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.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(), context.allocator), context.allocator); + sArr.PushBack(s.addr, context.allocator); + sArr.PushBack(s.size, context.allocator); + sArr.PushBack(s.offset, context.allocator); + sArr.PushBack(s.align, context.allocator); + sArr.PushBack(s.reloff, context.allocator); + sArr.PushBack(s.nreloc, context.allocator); + sArr.PushBack(s.flags, context.allocator); + sArr.PushBack(s.reserved1, context.allocator); + sArr.PushBack(s.reserved2, context.allocator); + sArr.PushBack(s.reserved3, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const linkedit_data_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.dataoff, context.allocator); + bArr.PushBack(b.datasize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, linkedit_data_command& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.cmd = bArr[0].GetUint(); + b.cmdsize = bArr[1].GetUint(); + b.dataoff = bArr[2].GetUint(); + b.datasize = bArr[3].GetUint(); +} + +void Serialize(SharedCacheCore::SerializationContext& context, std::string_view name, const segment_command_64& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); + bArr.PushBack(b.vmaddr, context.allocator); + bArr.PushBack(b.vmsize, context.allocator); + bArr.PushBack(b.fileoff, context.allocator); + bArr.PushBack(b.filesize, context.allocator); + bArr.PushBack(b.maxprot, context.allocator); + bArr.PushBack(b.initprot, context.allocator); + bArr.PushBack(b.nsects, context.allocator); + bArr.PushBack(b.flags, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, segment_command_64& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); + sArr.PushBack(s.vmaddr, context.allocator); + sArr.PushBack(s.vmsize, context.allocator); + sArr.PushBack(s.fileoff, context.allocator); + sArr.PushBack(s.filesize, context.allocator); + sArr.PushBack(s.maxprot, context.allocator); + sArr.PushBack(s.initprot, context.allocator); + sArr.PushBack(s.nsects, context.allocator); + sArr.PushBack(s.flags, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const build_version_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.platform, context.allocator); + bArr.PushBack(b.minos, context.allocator); + bArr.PushBack(b.sdk, context.allocator); + bArr.PushBack(b.ntools, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, build_version_command& b) +{ + auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& s : b) + { + rapidjson::Value sArr(rapidjson::kArrayType); + sArr.PushBack(s.tool, context.allocator); + sArr.PushBack(s.version, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].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); + } +} + } // namespace SharedCacheAPI diff --git a/view/sharedcache/api/sharedcacheapi.h b/view/sharedcache/api/sharedcacheapi.h index 19f021e7c4..a9a67a29f4 100644 --- a/view/sharedcache/api/sharedcacheapi.h +++ b/view/sharedcache/api/sharedcacheapi.h @@ -1,13 +1,39 @@ #pragma once #include -#include "MetadataSerializable.hpp" +#include "../core/MetadataSerializable.hpp" #include "view/macho/machoview.h" #include "sharedcachecore.h" using namespace BinaryNinja; namespace SharedCacheAPI { + + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const mach_header_64& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, mach_header_64& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const symtab_command& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, symtab_command& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const dysymtab_command& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, dysymtab_command& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const dyld_info_command& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, dyld_info_command& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const routines_command_64& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, routines_command_64& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const function_starts_command& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, function_starts_command& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const std::vector& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, std::vector& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const linkedit_data_command& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, linkedit_data_command& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const segment_command_64& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, segment_command_64& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const std::vector& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, std::vector& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const build_version_command& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, build_version_command& b); + void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const std::vector& b); + void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, std::vector& b); + template class SCRefCountObject { void AddRefInternal() { m_refs.fetch_add(1); } @@ -131,7 +157,7 @@ namespace SharedCacheAPI { }; using namespace BinaryNinja; - struct SharedCacheMachOHeader : public MetadataSerializable { + struct SharedCacheMachOHeader : public SharedCacheCore::MetadataSerializable { uint64_t textBase = 0; uint64_t loadCommandOffset = 0; mach_header_64 ident; @@ -174,412 +200,8 @@ namespace SharedCacheAPI { 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 { + void Store(SharedCacheCore::SerializationContext& context) const { MSS(textBase); MSS(loadCommandOffset); MSS_SUBCLASS(ident); @@ -614,7 +236,8 @@ namespace SharedCacheAPI { MSS(functionStartsPresent); MSS(relocatable); } - void Load() override { + + void Load(SharedCacheCore::DeserializationContext& context) { MSL(textBase); MSL(loadCommandOffset); MSL_SUBCLASS(ident); diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp index c49a9e8c47..1b7a03d0df 100644 --- a/view/sharedcache/core/MetadataSerializable.hpp +++ b/view/sharedcache/core/MetadataSerializable.hpp @@ -12,15 +12,17 @@ * * Great news. * - * Implement these on your `public MetadataSerializable` subclass: + * Implement these on your `public MetadataSerializable` subclass: * ``` - void Store() override { - MSS(m_someVariable); - MSS(m_someOtherVariable); - } - void Load() override { - MSL(m_someVariable); - MSL(m_someOtherVariable); + class MyClass : public MetadataSerializable { + void Store(SerializationContext& context) const { + MSS(m_someVariable); + MSS(m_someOtherVariable); + } + void Load(DeserializationContext& context) { + MSL(m_someVariable); + MSL(m_someOtherVariable); + } } ``` * Then, you can turn your object into a Metadata object with `AsMetadata()`, and load it back with @@ -37,501 +39,481 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" -#ifndef SHAREDCACHE_METADATASERIALIZABLE_HPP -#define SHAREDCACHE_METADATASERIALIZABLE_HPP +#ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP +#define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP + +namespace SharedCacheCore { -#define MSS(name) store(#name, name) -#define MSS_CAST(name, type) store(#name, (type) name) -#define MSS_SUBCLASS(name) Serialize(#name, name) -#define MSL(name) name = load(#name, name) -#define MSL_CAST(name, storedType, type) name = (type)load(#name, (storedType) name) -#define MSL_SUBCLASS(name) Deserialize(#name, name) +#define MSS(name) context.store(#name, name) +#define MSS_CAST(name, type) context.store(#name, (type) name) +#define MSS_SUBCLASS(name) Serialize(context, #name, name) +#define MSL(name) name = context.load(#name) +#define MSL_CAST(name, storedType, type) name = (type)context.load(#name) +#define MSL_SUBCLASS(name) Deserialize(context, #name, name) using namespace BinaryNinja; -class MetadataSerializable -{ -protected: - struct SerialContext - { - rapidjson::Document doc; - rapidjson::Document::AllocatorType allocator; - }; - struct DeserContext - { - rapidjson::Document doc; - }; +struct DeserializationContext; - DeserContext m_activeDeserContext; - SerialContext m_activeContext; +struct SerializationContext { + rapidjson::Document doc; + rapidjson::Document::AllocatorType allocator; -public: - MetadataSerializable() - { - m_activeContext.doc.SetObject(); - m_activeContext.allocator = m_activeContext.doc.GetAllocator(); + SerializationContext() { + doc.SetObject(); + allocator = doc.GetAllocator(); } - // copy constructor - MetadataSerializable(const MetadataSerializable& other) + template + void store(std::string_view x, const T& y) { - m_activeContext.doc.CopyFrom(other.m_activeContext.doc, m_activeContext.doc.GetAllocator()); + Serialize(*this, x, y); } +}; - // copy assignment - MetadataSerializable& operator=(const MetadataSerializable& other) - { - m_activeContext.doc.CopyFrom(other.m_activeContext.doc, m_activeContext.doc.GetAllocator()); - return *this; - } +struct DeserializationContext { + rapidjson::Document doc; - virtual ~MetadataSerializable() + template + T load(std::string_view x) { + T value; + Deserialize(*this, x, value); + return value; } +}; - void SetupSerContext(rapidjson::Document::AllocatorType* alloc = nullptr) - { - m_activeContext.doc.SetObject(); - m_activeContext.allocator = m_activeContext.doc.GetAllocator(); - } - void S() - { - // fixme factor out - } - void Serialize(std::string& name, bool b) +template +class MetadataSerializable +{ +public: + std::string AsString() const { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, bool& b) { b = m_activeDeserContext.doc[name.c_str()].GetBool(); } + rapidjson::StringBuffer strbuf; + rapidjson::PrettyWriter writer(strbuf); + AsDocument().Accept(writer); - void Serialize(std::string& name, uint8_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint8_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); + return strbuf.GetString(); } - void Serialize(std::string& name, uint16_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint16_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); + rapidjson::Document AsDocument() const { + SerializationContext context; + AsDerived().Store(context); + return std::move(context.doc); } - void Serialize(std::string& name, uint32_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint32_t& b) + void LoadFromString(const std::string& s) { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); + DeserializationContext context; + context.doc.Parse(s.c_str()); + AsDerived().Load(context); } - void Serialize(std::string& name, uint64_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint64_t& b) + void LoadFromValue(rapidjson::Value& s) { - b = m_activeDeserContext.doc[name.c_str()].GetUint64(); + DeserializationContext context; + context.doc.CopyFrom(s, context.doc.GetAllocator()); + AsDerived().Load(context); } - void Serialize(std::string& name, int8_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int8_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } + Ref AsMetadata() { return new Metadata(AsString()); } - void Serialize(std::string& name, int16_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int16_t& b) + bool LoadFromMetadata(const Ref& meta) { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); + if (!meta->IsString()) + return false; + LoadFromString(meta->GetString()); + return true; } - void Serialize(std::string& name, int32_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int32_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt(); - } +private: + const Derived& AsDerived() const { return static_cast(*this); } + Derived& AsDerived() { return static_cast(*this); } +}; - void Serialize(std::string& name, int64_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int64_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } +inline void Serialize(SerializationContext& context, std::string_view name, bool b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} - void Serialize(std::string& name, std::string b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value value(b.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, value, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::string& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetString(); - } +inline void Deserialize(DeserializationContext& context, std::string_view name, bool& b) { + b = context.doc[name.data()].GetBool(); +} - void Serialize(std::string& name, std::map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); - } +inline void Serialize(SerializationContext& context, std::string_view name, uint8_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} - void Serialize(std::string& name, std::unordered_map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } +inline void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +inline void Serialize(SerializationContext& context, std::string_view name, uint16_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +inline void Serialize(SerializationContext& context, std::string_view name, uint32_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +inline void Serialize(SerializationContext& context, std::string_view name, uint64_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b) +{ + b = context.doc[name.data()].GetUint64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int8_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int16_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int32_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b) +{ + b = context.doc[name.data()].GetInt(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int64_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} - void Serialize(std::string& name, std::unordered_map b) +inline void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, std::string_view b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value value(b.data(), context.allocator); + context.doc.AddMember(key, value, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::string& b) +{ + b = context.doc[name.data()].GetString(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, const std::map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(_key, m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); } - void Deserialize(std::string& name, std::unordered_map& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); } + context.doc.AddMember(key, bArr, context.allocator); +} - void Serialize(std::string& name, std::unordered_map b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - p.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value p(rapidjson::kArrayType); + rapidjson::Value _key(i.first.c_str(), context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(_key, context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); } - void Deserialize(std::string& name, std::unordered_map& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + p.PushBack(i.second, context.allocator); + bArr.PushBack(p, context.allocator); } + context.doc.AddMember(key, bArr, context.allocator); +} - // std::unordered_map> - void Serialize(std::string& name, std::unordered_map> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value classes(rapidjson::kArrayType); - for (auto& i : b) +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); +} + +// std::unordered_map> +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value classes(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value classArr(rapidjson::kArrayType); + rapidjson::Value classKey(i.first.c_str(), context.allocator); + classArr.PushBack(classKey, context.allocator); + rapidjson::Value membersArr(rapidjson::kArrayType); + for (auto& j : i.second) { - rapidjson::Value classArr(rapidjson::kArrayType); - rapidjson::Value classKey(i.first.c_str(), m_activeContext.allocator); - classArr.PushBack(classKey, m_activeContext.allocator); - rapidjson::Value membersArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value member(rapidjson::kArrayType); - member.PushBack(j.first, m_activeContext.allocator); - member.PushBack(j.second, m_activeContext.allocator); - membersArr.PushBack(member, m_activeContext.allocator); - } - classArr.PushBack(membersArr, m_activeContext.allocator); - classes.PushBack(classArr, m_activeContext.allocator); + rapidjson::Value member(rapidjson::kArrayType); + member.PushBack(j.first, context.allocator); + member.PushBack(j.second, context.allocator); + membersArr.PushBack(member, context.allocator); } - m_activeContext.doc.AddMember(key, classes, m_activeContext.allocator); + classArr.PushBack(membersArr, context.allocator); + classes.PushBack(classArr, context.allocator); } - void Deserialize(std::string& name, std::unordered_map>& b) + context.doc.AddMember(key, classes, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) + std::string key = i.GetArray()[0].GetString(); + std::unordered_map memArray; + for (auto& member : i.GetArray()[1].GetArray()) { - std::string key = i.GetArray()[0].GetString(); - std::unordered_map memArray; - for (auto& member : i.GetArray()[1].GetArray()) - { - memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); - } - b[key] = memArray; + memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); } + b[key] = memArray; } +} - void Deserialize(std::string& name, std::unordered_map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); - } +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); +} - void Serialize(std::string& name, std::vector b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (const auto& s : b) - { - rapidjson::Value value(s.c_str(), m_activeContext.allocator); - bArr.PushBack(value, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::vector& b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (const auto& s : b) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b.emplace_back(i.GetString()); + rapidjson::Value value(s.c_str(), context.allocator); + bArr.PushBack(value, context.allocator); } + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b.emplace_back(i.GetString()); +} - void Serialize(std::string& name, std::vector>> b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - segV.PushBack(i.second.first, m_activeContext.allocator); - segV.PushBack(i.second.second, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + segV.PushBack(i.second.first, context.allocator); + segV.PushBack(i.second.second, context.allocator); + bArr.PushBack(segV, context.allocator); } - void Deserialize(std::string& name, std::vector>>& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::pair> j; - j.first = i.GetArray()[0].GetUint64(); - j.second.first = i.GetArray()[1].GetUint64(); - j.second.second = i.GetArray()[2].GetUint64(); - b.push_back(j); - } + std::pair> j; + j.first = i.GetArray()[0].GetUint64(); + j.second.first = i.GetArray()[1].GetUint64(); + j.second.second = i.GetArray()[2].GetUint64(); + b.push_back(j); } +} - void Serialize(std::string& name, std::vector> b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - segV.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + segV.PushBack(i.second, context.allocator); + bArr.PushBack(segV, context.allocator); } - void Deserialize(std::string& name, std::vector>& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::pair j; - j.first = i.GetArray()[0].GetUint64(); - j.second = i.GetArray()[1].GetBool(); - b.push_back(j); - } + std::pair j; + j.first = i.GetArray()[0].GetUint64(); + j.second = i.GetArray()[1].GetBool(); + b.push_back(j); } +} - void Serialize(std::string& name, std::vector b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - bArr.PushBack(i, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + bArr.PushBack(i, context.allocator); } - void Deserialize(std::string& name, std::vector& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - b.push_back(i.GetUint64()); - } + b.push_back(i.GetUint64()); } +} - // std::unordered_map - void Serialize(std::string& name, std::unordered_map b) +// std::unordered_map +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), m_activeContext.allocator); - p.PushBack(_key, m_activeContext.allocator); - p.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value p(rapidjson::kArrayType); + rapidjson::Value _key(i.first.c_str(), context.allocator); + p.PushBack(_key, context.allocator); + p.PushBack(i.second, context.allocator); + bArr.PushBack(p, context.allocator); } - void Deserialize(std::string& name, std::unordered_map& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); - } + b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); } - // std::vector>>> - void Serialize(std::string& name, std::vector>>> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) +} + +// std::vector>>> +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + rapidjson::Value segArr(rapidjson::kArrayType); + for (auto& j : i.second) { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value segArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value segPair(rapidjson::kArrayType); - segPair.PushBack(j.first, m_activeContext.allocator); - rapidjson::Value segStr(j.second.c_str(), m_activeContext.allocator); - segPair.PushBack(segStr, m_activeContext.allocator); - segArr.PushBack(segPair, m_activeContext.allocator); - } - segV.PushBack(segArr, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); + rapidjson::Value segPair(rapidjson::kArrayType); + segPair.PushBack(j.first, context.allocator); + rapidjson::Value segStr(j.second.c_str(), context.allocator); + segPair.PushBack(segStr, context.allocator); + segArr.PushBack(segPair, context.allocator); } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + segV.PushBack(segArr, context.allocator); + bArr.PushBack(segV, context.allocator); } - void Deserialize(std::string& name, std::vector>>>& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) + std::pair>> j; + j.first = i.GetArray()[0].GetUint64(); + for (auto& k : i.GetArray()[1].GetArray()) { - std::pair>> j; - j.first = i.GetArray()[0].GetUint64(); - for (auto& k : i.GetArray()[1].GetArray()) - { - j.second.push_back({k.GetArray()[0].GetUint64(), k.GetArray()[1].GetString()}); - } - b.push_back(j); + j.second.push_back({k.GetArray()[0].GetUint64(), k.GetArray()[1].GetString()}); } + b.push_back(j); } +} - template - void store(std::string x, T y) - { - Serialize(x, y); - } - - template - T load(std::string x, T y) - { - T val; - Deserialize(x, val); - return val; - } - - rapidjson::Document& GetDoc() - { - S(); - Store(); - return m_activeContext.doc; - } - -public: - virtual void Store() = 0; - virtual void Load() = 0; - - std::string AsString() - { - rapidjson::StringBuffer strbuf; - rapidjson::PrettyWriter writer(strbuf); - GetDoc().Accept(writer); - - std::string s = strbuf.GetString(); - return s; - } - rapidjson::Document& AsDocument() { return GetDoc(); } - void LoadFromString(const std::string& s) - { - m_activeDeserContext.doc.Parse(s.c_str()); - Load(); - } - void LoadFromValue(rapidjson::Value& s) - { - m_activeDeserContext.doc.CopyFrom(s, m_activeDeserContext.doc.GetAllocator()); - Load(); - } - Ref AsMetadata() { return new Metadata(AsString()); } - bool LoadFromMetadata(const Ref& meta) - { - if (!meta->IsString()) - return false; - LoadFromString(meta->GetString()); - return true; - } -}; +} // namespace SharedCacheCore #endif // SHAREDCACHE_METADATASERIALIZABLE_HPP diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index a7c7ffb016..16056827a6 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -3320,3 +3320,407 @@ void InitDSCViewType() g_dscViewType = &type; g_dscRawViewType = &rawType; } + +namespace SharedCacheCore { + +void Serialize(SerializationContext& context, std::string_view name, const mach_header_64& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.magic, context.allocator); + bArr.PushBack(b.cputype, context.allocator); + bArr.PushBack(b.cpusubtype, context.allocator); + bArr.PushBack(b.filetype, context.allocator); + bArr.PushBack(b.ncmds, context.allocator); + bArr.PushBack(b.sizeofcmds, context.allocator); + bArr.PushBack(b.flags, context.allocator); + bArr.PushBack(b.reserved, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, mach_header_64& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.magic = bArr[0].GetUint(); + b.cputype = bArr[1].GetUint(); + b.cpusubtype = bArr[2].GetUint(); + b.filetype = bArr[3].GetUint(); + b.ncmds = bArr[4].GetUint(); + b.sizeofcmds = bArr[5].GetUint(); + b.flags = bArr[6].GetUint(); + b.reserved = bArr[7].GetUint(); +} + +void Serialize(SerializationContext& context, std::string_view name, const symtab_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.symoff, context.allocator); + bArr.PushBack(b.nsyms, context.allocator); + bArr.PushBack(b.stroff, context.allocator); + bArr.PushBack(b.strsize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, symtab_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const dysymtab_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.ilocalsym, context.allocator); + bArr.PushBack(b.nlocalsym, context.allocator); + bArr.PushBack(b.iextdefsym, context.allocator); + bArr.PushBack(b.nextdefsym, context.allocator); + bArr.PushBack(b.iundefsym, context.allocator); + bArr.PushBack(b.nundefsym, context.allocator); + bArr.PushBack(b.tocoff, context.allocator); + bArr.PushBack(b.ntoc, context.allocator); + bArr.PushBack(b.modtaboff, context.allocator); + bArr.PushBack(b.nmodtab, context.allocator); + bArr.PushBack(b.extrefsymoff, context.allocator); + bArr.PushBack(b.nextrefsyms, context.allocator); + bArr.PushBack(b.indirectsymoff, context.allocator); + bArr.PushBack(b.nindirectsyms, context.allocator); + bArr.PushBack(b.extreloff, context.allocator); + bArr.PushBack(b.nextrel, context.allocator); + bArr.PushBack(b.locreloff, context.allocator); + bArr.PushBack(b.nlocrel, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, dysymtab_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const dyld_info_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.rebase_off, context.allocator); + bArr.PushBack(b.rebase_size, context.allocator); + bArr.PushBack(b.bind_off, context.allocator); + bArr.PushBack(b.bind_size, context.allocator); + bArr.PushBack(b.weak_bind_off, context.allocator); + bArr.PushBack(b.weak_bind_size, context.allocator); + bArr.PushBack(b.lazy_bind_off, context.allocator); + bArr.PushBack(b.lazy_bind_size, context.allocator); + bArr.PushBack(b.export_off, context.allocator); + bArr.PushBack(b.export_size, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, dyld_info_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const routines_command_64& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.init_address, context.allocator); + bArr.PushBack(b.init_module, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, routines_command_64& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const function_starts_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.funcoff, context.allocator); + bArr.PushBack(b.funcsize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, function_starts_command& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.cmd = bArr[0].GetUint(); + b.cmdsize = bArr[1].GetUint(); + b.funcoff = bArr[2].GetUint(); + b.funcsize = bArr[3].GetUint(); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.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(), context.allocator), context.allocator); + sArr.PushBack(s.addr, context.allocator); + sArr.PushBack(s.size, context.allocator); + sArr.PushBack(s.offset, context.allocator); + sArr.PushBack(s.align, context.allocator); + sArr.PushBack(s.reloff, context.allocator); + sArr.PushBack(s.nreloc, context.allocator); + sArr.PushBack(s.flags, context.allocator); + sArr.PushBack(s.reserved1, context.allocator); + sArr.PushBack(s.reserved2, context.allocator); + sArr.PushBack(s.reserved3, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + for (auto& s : bArr) + { + section_64 sec; + auto s2 = s.GetArray(); + std::string sectNameStr = s2[0].GetString(); + memset(sec.sectname, 0, 16); + memcpy(sec.sectname, sectNameStr.c_str(), sectNameStr.size()); + std::string segNameStr = s2[1].GetString(); + memset(sec.segname, 0, 16); + 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(SerializationContext& context, std::string_view name, const linkedit_data_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.dataoff, context.allocator); + bArr.PushBack(b.datasize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, linkedit_data_command& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.cmd = bArr[0].GetUint(); + b.cmdsize = bArr[1].GetUint(); + b.dataoff = bArr[2].GetUint(); + b.datasize = bArr[3].GetUint(); +} + +void Serialize(SerializationContext& context, std::string_view name, const segment_command_64& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); + bArr.PushBack(b.vmaddr, context.allocator); + bArr.PushBack(b.vmsize, context.allocator); + bArr.PushBack(b.fileoff, context.allocator); + bArr.PushBack(b.filesize, context.allocator); + bArr.PushBack(b.maxprot, context.allocator); + bArr.PushBack(b.initprot, context.allocator); + bArr.PushBack(b.nsects, context.allocator); + bArr.PushBack(b.flags, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, segment_command_64& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + std::string segNameStr = bArr[0].GetString(); + memset(b.segname, 0, 16); + 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(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); + sArr.PushBack(s.vmaddr, context.allocator); + sArr.PushBack(s.vmsize, context.allocator); + sArr.PushBack(s.fileoff, context.allocator); + sArr.PushBack(s.filesize, context.allocator); + sArr.PushBack(s.maxprot, context.allocator); + sArr.PushBack(s.initprot, context.allocator); + sArr.PushBack(s.nsects, context.allocator); + sArr.PushBack(s.flags, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + for (auto& s : bArr) + { + segment_command_64 sec; + auto s2 = s.GetArray(); + std::string segNameStr = s2[0].GetString(); + memset(sec.segname, 0, 16); + 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(SerializationContext& context, std::string_view name, const build_version_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.platform, context.allocator); + bArr.PushBack(b.minos, context.allocator); + bArr.PushBack(b.sdk, context.allocator); + bArr.PushBack(b.ntools, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, build_version_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& s : b) + { + rapidjson::Value sArr(rapidjson::kArrayType); + sArr.PushBack(s.tool, context.allocator); + sArr.PushBack(s.version, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].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); + } +} + +} // namespace SharedCacheCore diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h index 81c0262039..934cd093f6 100644 --- a/view/sharedcache/core/SharedCache.h +++ b/view/sharedcache/core/SharedCache.h @@ -16,6 +16,31 @@ DECLARE_SHAREDCACHE_API_OBJECT(BNSharedCache, SharedCache); namespace SharedCacheCore { + void Serialize(SerializationContext&, std::string_view name, const mach_header_64& b); + void Deserialize(DeserializationContext&, std::string_view name, mach_header_64& b); + void Serialize(SerializationContext&, std::string_view name, const symtab_command& b); + void Deserialize(DeserializationContext&, std::string_view name, symtab_command& b); + void Serialize(SerializationContext&, std::string_view name, const dysymtab_command& b); + void Deserialize(DeserializationContext&, std::string_view name, dysymtab_command& b); + void Serialize(SerializationContext&, std::string_view name, const dyld_info_command& b); + void Deserialize(DeserializationContext&, std::string_view name, dyld_info_command& b); + void Serialize(SerializationContext&, std::string_view name, const routines_command_64& b); + void Deserialize(DeserializationContext&, std::string_view name, routines_command_64& b); + void Serialize(SerializationContext&, std::string_view name, const function_starts_command& b); + void Deserialize(DeserializationContext&, std::string_view name, function_starts_command& b); + void Serialize(SerializationContext&, std::string_view name, const std::vector& b); + void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); + void Serialize(SerializationContext&, std::string_view name, const linkedit_data_command& b); + void Deserialize(DeserializationContext&, std::string_view name, linkedit_data_command& b); + void Serialize(SerializationContext&, std::string_view name, const segment_command_64& b); + void Deserialize(DeserializationContext&, std::string_view name, segment_command_64& b); + void Serialize(SerializationContext&, std::string_view name, const std::vector& b); + void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); + void Serialize(SerializationContext&, std::string_view name, const build_version_command& b); + void Deserialize(DeserializationContext&, std::string_view name, build_version_command& b); + void Serialize(SerializationContext&, std::string_view name, const std::vector& b); + void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); + enum DSCViewState { DSCViewStateUnloaded, @@ -26,7 +51,7 @@ namespace SharedCacheCore { const std::string SharedCacheMetadataTag = "SHAREDCACHE-SharedCacheData"; - struct MemoryRegion : public MetadataSerializable + struct MemoryRegion : public MetadataSerializable { std::string prettyName; uint64_t start; @@ -36,7 +61,7 @@ namespace SharedCacheCore { bool headerInitialized = false; BNSegmentFlag flags; - void Store() override + void Store(SerializationContext& context) const { MSS(prettyName); MSS(start); @@ -46,7 +71,7 @@ namespace SharedCacheCore { MSS_CAST(flags, uint64_t); } - void Load() override + void Load(DeserializationContext& context) { MSL(prettyName); MSL(start); @@ -57,30 +82,30 @@ namespace SharedCacheCore { } }; - struct CacheImage : public MetadataSerializable + struct CacheImage : public MetadataSerializable { std::string installName; uint64_t headerLocation; std::vector regions; - void Store() override + void Store(SerializationContext& context) const { MSS(installName); MSS(headerLocation); - rapidjson::Value key("regions", m_activeContext.allocator); + rapidjson::Value key("regions", context.allocator); rapidjson::Value bArr(rapidjson::kArrayType); for (auto& region : regions) { - bArr.PushBack(rapidjson::Value(region.AsString().c_str(), m_activeContext.allocator), m_activeContext.allocator); + bArr.PushBack(rapidjson::Value(region.AsString().c_str(), context.allocator), context.allocator); } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + context.doc.AddMember(key, bArr, context.allocator); } - void Load() override + void Load(DeserializationContext& context) { MSL(installName); MSL(headerLocation); - auto bArr = m_activeDeserContext.doc["regions"].GetArray(); + auto bArr = context.doc["regions"].GetArray(); regions.clear(); for (auto& region : bArr) { @@ -91,19 +116,19 @@ namespace SharedCacheCore { } }; - struct BackingCache : public MetadataSerializable + struct BackingCache : public MetadataSerializable { std::string path; bool isPrimary = false; std::vector>> mappings; - void Store() override + void Store(SerializationContext& context) const { MSS(path); MSS(isPrimary); MSS(mappings); } - void Load() override + void Load(DeserializationContext& context) { MSL(path); MSL(isPrimary); @@ -357,7 +382,7 @@ namespace SharedCacheCore { #endif using namespace BinaryNinja; - struct SharedCacheMachOHeader : public MetadataSerializable + struct SharedCacheMachOHeader : public MetadataSerializable { uint64_t textBase = 0; uint64_t loadCommandOffset = 0; @@ -402,419 +427,8 @@ namespace SharedCacheCore { 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].GetUint(); - b.cputype = bArr[1].GetUint(); - b.cpusubtype = bArr[2].GetUint(); - b.filetype = bArr[3].GetUint(); - b.ncmds = bArr[4].GetUint(); - b.sizeofcmds = bArr[5].GetUint(); - b.flags = bArr[6].GetUint(); - b.reserved = bArr[7].GetUint(); - } - - 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(); - memset(sec.sectname, 0, 16); - memcpy(sec.sectname, sectNameStr.c_str(), sectNameStr.size()); - std::string segNameStr = s2[1].GetString(); - memset(sec.segname, 0, 16); - 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(); - memset(b.segname, 0, 16); - 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(); - memset(sec.segname, 0, 16); - 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 + void Store(SerializationContext& context) const { MSS(textBase); MSS(loadCommandOffset); @@ -851,7 +465,7 @@ namespace SharedCacheCore { MSS(functionStartsPresent); MSS(relocatable); } - void Load() override + void Load(DeserializationContext& context) { MSL(textBase); MSL(loadCommandOffset); @@ -906,7 +520,7 @@ namespace SharedCacheCore { static std::atomic sharedCacheReferences = 0; - class SharedCache : public MetadataSerializable + class SharedCache : public MetadataSerializable { IMPLEMENT_SHAREDCACHE_API_OBJECT(BNSharedCache); @@ -938,20 +552,20 @@ namespace SharedCacheCore { iOS16CacheFormat, }; - void Store() override + void Store(SerializationContext& context) const { - m_activeContext.doc.AddMember("metadataVersion", METADATA_VERSION, m_activeContext.allocator); + context.doc.AddMember("metadataVersion", METADATA_VERSION, context.allocator); MSS(m_viewState); MSS_CAST(m_cacheFormat, uint8_t); MSS(m_imageStarts); MSS(m_baseFilePath); rapidjson::Value headers(rapidjson::kArrayType); - for (auto [k, v] : m_headers) + for (auto& [k, v] : m_headers) { - headers.PushBack(v.AsDocument(), m_activeContext.allocator); + headers.PushBack(v.AsDocument(), context.allocator); } - m_activeContext.doc.AddMember("headers", headers, m_activeContext.allocator); + context.doc.AddMember("headers", headers, context.allocator); // std::vector>>>> m_exportInfos // std::vector>>>> exportInfos; rapidjson::Document exportInfos(rapidjson::kArrayType); @@ -963,61 +577,62 @@ namespace SharedCacheCore { for (const auto& pair2 : pair1.second) { rapidjson::Value subSubObj(rapidjson::kObjectType); - subSubObj.AddMember("key", pair2.first, m_activeContext.allocator); - subSubObj.AddMember("val1", pair2.second.first, m_activeContext.allocator); - subSubObj.AddMember("val2", pair2.second.second, m_activeContext.allocator); - subArr.PushBack(subSubObj, m_activeContext.allocator); + subSubObj.AddMember("key", pair2.first, context.allocator); + subSubObj.AddMember("val1", pair2.second.first, context.allocator); + subSubObj.AddMember("val2", pair2.second.second, context.allocator); + subArr.PushBack(subSubObj, context.allocator); } - subObj.AddMember("key", pair1.first, m_activeContext.allocator); - subObj.AddMember("value", subArr, m_activeContext.allocator); + subObj.AddMember("key", pair1.first, context.allocator); + subObj.AddMember("value", subArr, context.allocator); - exportInfos.PushBack(subObj, m_activeContext.allocator); + exportInfos.PushBack(subObj, context.allocator); } - m_activeContext.doc.AddMember("exportInfos", exportInfos, m_activeContext.allocator); + context.doc.AddMember("exportInfos", exportInfos, context.allocator); rapidjson::Value backingCaches(rapidjson::kArrayType); - for (auto bc : m_backingCaches) + for (auto& bc : m_backingCaches) { - backingCaches.PushBack(bc.AsDocument(), m_activeContext.allocator); + backingCaches.PushBack(bc.AsDocument(), context.allocator); } - m_activeContext.doc.AddMember("backingCaches", backingCaches, m_activeContext.allocator); + context.doc.AddMember("backingCaches", backingCaches, context.allocator); rapidjson::Value stubIslands(rapidjson::kArrayType); - for (auto si : m_stubIslandRegions) + for (auto& si : m_stubIslandRegions) { - stubIslands.PushBack(si.AsDocument(), m_activeContext.allocator); + stubIslands.PushBack(si.AsDocument(), context.allocator); } rapidjson::Value images(rapidjson::kArrayType); - for (auto img : m_images) + for (auto& img : m_images) { - images.PushBack(img.AsDocument(), m_activeContext.allocator); + images.PushBack(img.AsDocument(), context.allocator); } - m_activeContext.doc.AddMember("images", images, m_activeContext.allocator); + context.doc.AddMember("images", images, context.allocator); rapidjson::Value regionsMappedIntoMemory(rapidjson::kArrayType); - for (auto r : m_regionsMappedIntoMemory) + for (auto& r : m_regionsMappedIntoMemory) { - regionsMappedIntoMemory.PushBack(r.AsDocument(), m_activeContext.allocator); + regionsMappedIntoMemory.PushBack(r.AsDocument(), context.allocator); } - m_activeContext.doc.AddMember("regionsMappedIntoMemory", regionsMappedIntoMemory, m_activeContext.allocator); - m_activeContext.doc.AddMember("stubIslands", stubIslands, m_activeContext.allocator); + context.doc.AddMember("regionsMappedIntoMemory", regionsMappedIntoMemory, context.allocator); + context.doc.AddMember("stubIslands", stubIslands, context.allocator); rapidjson::Value dyldDataSections(rapidjson::kArrayType); - for (auto si : m_dyldDataRegions) + for (auto& si : m_dyldDataRegions) { - dyldDataSections.PushBack(si.AsDocument(), m_activeContext.allocator); + dyldDataSections.PushBack(si.AsDocument(), context.allocator); } - m_activeContext.doc.AddMember("dyldDataSections", dyldDataSections, m_activeContext.allocator); + context.doc.AddMember("dyldDataSections", dyldDataSections, context.allocator); rapidjson::Value nonImageRegions(rapidjson::kArrayType); - for (auto si : m_nonImageRegions) + for (auto& si : m_nonImageRegions) { - nonImageRegions.PushBack(si.AsDocument(), m_activeContext.allocator); + nonImageRegions.PushBack(si.AsDocument(), context.allocator); } - m_activeContext.doc.AddMember("nonImageRegions", nonImageRegions, m_activeContext.allocator); + context.doc.AddMember("nonImageRegions", nonImageRegions, context.allocator); } - void Load() override + + void Load(DeserializationContext& context) { - if (m_activeDeserContext.doc.HasMember("metadataVersion")) + if (context.doc.HasMember("metadataVersion")) { - if (m_activeDeserContext.doc["metadataVersion"].GetUint() != METADATA_VERSION) + if (context.doc["metadataVersion"].GetUint() != METADATA_VERSION) { m_logger->LogError("Shared Cache metadata version mismatch"); return; @@ -1031,7 +646,7 @@ namespace SharedCacheCore { m_viewState = MSL_CAST(m_viewState, uint8_t, DSCViewState); m_cacheFormat = MSL_CAST(m_cacheFormat, uint8_t, SharedCacheFormat); m_headers.clear(); - for (auto& startAndHeader : m_activeDeserContext.doc["headers"].GetArray()) + for (auto& startAndHeader : context.doc["headers"].GetArray()) { SharedCacheMachOHeader header; header.LoadFromValue(startAndHeader); @@ -1040,7 +655,7 @@ namespace SharedCacheCore { MSL(m_imageStarts); MSL(m_baseFilePath); m_exportInfos.clear(); - for (const auto& obj1 : m_activeDeserContext.doc["exportInfos"].GetArray()) + for (const auto& obj1 : context.doc["exportInfos"].GetArray()) { std::vector>> innerVec; for (const auto& obj2 : obj1["value"].GetArray()) @@ -1052,7 +667,7 @@ namespace SharedCacheCore { m_exportInfos[obj1["key"].GetUint64()] = innerVec; } m_symbolInfos.clear(); - for (auto& symbolInfo : m_activeDeserContext.doc["symbolInfos"].GetArray()) + for (auto& symbolInfo : context.doc["symbolInfos"].GetArray()) { std::vector>> symbolInfoVec; for (auto& symbolInfoPair : symbolInfo.GetArray()) @@ -1060,49 +675,49 @@ namespace SharedCacheCore { symbolInfoVec.push_back({symbolInfoPair[0].GetUint64(), {(BNSymbolType)symbolInfoPair[1].GetUint(), symbolInfoPair[2].GetString()}}); } - m_symbolInfos[symbolInfo[0].GetUint64()] = symbolInfoVec; + m_symbolInfos[symbolInfo[0].GetUint64()] = std::move(symbolInfoVec); } m_backingCaches.clear(); - for (auto& bcV : m_activeDeserContext.doc["backingCaches"].GetArray()) + for (auto& bcV : context.doc["backingCaches"].GetArray()) { BackingCache bc; bc.LoadFromValue(bcV); - m_backingCaches.push_back(bc); + m_backingCaches.push_back(std::move(bc)); } m_images.clear(); - for (auto& imgV : m_activeDeserContext.doc["images"].GetArray()) + for (auto& imgV : context.doc["images"].GetArray()) { CacheImage img; img.LoadFromValue(imgV); - m_images.push_back(img); + m_images.push_back(std::move(img)); } m_regionsMappedIntoMemory.clear(); - for (auto& rV : m_activeDeserContext.doc["regionsMappedIntoMemory"].GetArray()) + for (auto& rV : context.doc["regionsMappedIntoMemory"].GetArray()) { MemoryRegion r; r.LoadFromValue(rV); - m_regionsMappedIntoMemory.push_back(r); + m_regionsMappedIntoMemory.push_back(std::move(r)); } m_stubIslandRegions.clear(); - for (auto& siV : m_activeDeserContext.doc["stubIslands"].GetArray()) + for (auto& siV : context.doc["stubIslands"].GetArray()) { MemoryRegion si; si.LoadFromValue(siV); - m_stubIslandRegions.push_back(si); + m_stubIslandRegions.push_back(std::move(si)); } m_dyldDataRegions.clear(); - for (auto& siV : m_activeDeserContext.doc["dyldDataSections"].GetArray()) + for (auto& siV : context.doc["dyldDataSections"].GetArray()) { MemoryRegion si; si.LoadFromValue(siV); - m_dyldDataRegions.push_back(si); + m_dyldDataRegions.push_back(std::move(si)); } m_nonImageRegions.clear(); - for (auto& siV : m_activeDeserContext.doc["nonImageRegions"].GetArray()) + for (auto& siV : context.doc["nonImageRegions"].GetArray()) { MemoryRegion si; si.LoadFromValue(siV); - m_nonImageRegions.push_back(si); + m_nonImageRegions.push_back(std::move(si)); } m_metadataValid = true; @@ -1186,7 +801,7 @@ namespace SharedCacheCore { DSCViewState State() const { return m_viewState; } explicit SharedCache(BinaryNinja::Ref rawView); - ~SharedCache() override; + virtual ~SharedCache(); std::optional LoadHeaderForAddress( std::shared_ptr vm, uint64_t address, std::string installName); From 36a66387c549c63aa65ad9d4424a6dcb94a0795e Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Wed, 13 Nov 2024 18:43:04 -0800 Subject: [PATCH 2/7] Move implementation of SharedCache::Load / SharedCache::Store into the .cpp file --- view/sharedcache/core/SharedCache.cpp | 175 +++++++++++++++++++++++++- view/sharedcache/core/SharedCache.h | 172 +------------------------ 2 files changed, 176 insertions(+), 171 deletions(-) diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 16056827a6..414d13ad48 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -3323,6 +3323,179 @@ void InitDSCViewType() namespace SharedCacheCore { +void SharedCache::Store(SerializationContext& context) const +{ + context.doc.AddMember("metadataVersion", METADATA_VERSION, context.allocator); + + MSS(m_viewState); + MSS_CAST(m_cacheFormat, uint8_t); + MSS(m_imageStarts); + MSS(m_baseFilePath); + rapidjson::Value headers(rapidjson::kArrayType); + for (auto& [k, v] : m_headers) + { + headers.PushBack(v.AsDocument(), context.allocator); + } + context.doc.AddMember("headers", headers, context.allocator); + // std::vector>>>> + // m_exportInfos std::vector>>>> exportInfos; + rapidjson::Document exportInfos(rapidjson::kArrayType); + + for (const auto& pair1 : m_exportInfos) + { + rapidjson::Value subObj(rapidjson::kObjectType); + rapidjson::Value subArr(rapidjson::kArrayType); + for (const auto& pair2 : pair1.second) + { + rapidjson::Value subSubObj(rapidjson::kObjectType); + subSubObj.AddMember("key", pair2.first, context.allocator); + subSubObj.AddMember("val1", pair2.second.first, context.allocator); + subSubObj.AddMember("val2", pair2.second.second, context.allocator); + subArr.PushBack(subSubObj, context.allocator); + } + + subObj.AddMember("key", pair1.first, context.allocator); + subObj.AddMember("value", subArr, context.allocator); + + exportInfos.PushBack(subObj, context.allocator); + } + context.doc.AddMember("exportInfos", exportInfos, context.allocator); + + rapidjson::Value backingCaches(rapidjson::kArrayType); + for (auto& bc : m_backingCaches) + { + backingCaches.PushBack(bc.AsDocument(), context.allocator); + } + context.doc.AddMember("backingCaches", backingCaches, context.allocator); + rapidjson::Value stubIslands(rapidjson::kArrayType); + for (auto& si : m_stubIslandRegions) + { + stubIslands.PushBack(si.AsDocument(), context.allocator); + } + rapidjson::Value images(rapidjson::kArrayType); + for (auto& img : m_images) + { + images.PushBack(img.AsDocument(), context.allocator); + } + context.doc.AddMember("images", images, context.allocator); + rapidjson::Value regionsMappedIntoMemory(rapidjson::kArrayType); + for (auto& r : m_regionsMappedIntoMemory) + { + regionsMappedIntoMemory.PushBack(r.AsDocument(), context.allocator); + } + context.doc.AddMember("regionsMappedIntoMemory", regionsMappedIntoMemory, context.allocator); + context.doc.AddMember("stubIslands", stubIslands, context.allocator); + rapidjson::Value dyldDataSections(rapidjson::kArrayType); + for (auto& si : m_dyldDataRegions) + { + dyldDataSections.PushBack(si.AsDocument(), context.allocator); + } + context.doc.AddMember("dyldDataSections", dyldDataSections, context.allocator); + rapidjson::Value nonImageRegions(rapidjson::kArrayType); + for (auto& si : m_nonImageRegions) + { + nonImageRegions.PushBack(si.AsDocument(), context.allocator); + } + context.doc.AddMember("nonImageRegions", nonImageRegions, context.allocator); +} + +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; + } + } + else + { + m_logger->LogError("Shared Cache metadata version missing"); + return; + } + m_viewState = MSL_CAST(m_viewState, uint8_t, DSCViewState); + m_cacheFormat = MSL_CAST(m_cacheFormat, uint8_t, SharedCacheFormat); + m_headers.clear(); + for (auto& startAndHeader : context.doc["headers"].GetArray()) + { + SharedCacheMachOHeader header; + header.LoadFromValue(startAndHeader); + m_headers[header.textBase] = header; + } + MSL(m_imageStarts); + MSL(m_baseFilePath); + m_exportInfos.clear(); + for (const auto& obj1 : context.doc["exportInfos"].GetArray()) + { + std::vector>> innerVec; + for (const auto& obj2 : obj1["value"].GetArray()) + { + std::pair innerPair = { + (BNSymbolType)obj2["val1"].GetUint64(), obj2["val2"].GetString()}; + innerVec.push_back({obj2["key"].GetUint64(), innerPair}); + } + + m_exportInfos[obj1["key"].GetUint64()] = innerVec; + } + m_symbolInfos.clear(); + for (auto& symbolInfo : context.doc["symbolInfos"].GetArray()) + { + std::vector>> symbolInfoVec; + for (auto& symbolInfoPair : symbolInfo.GetArray()) + { + symbolInfoVec.push_back({symbolInfoPair[0].GetUint64(), + {(BNSymbolType)symbolInfoPair[1].GetUint(), symbolInfoPair[2].GetString()}}); + } + m_symbolInfos[symbolInfo[0].GetUint64()] = std::move(symbolInfoVec); + } + m_backingCaches.clear(); + for (auto& bcV : context.doc["backingCaches"].GetArray()) + { + BackingCache bc; + bc.LoadFromValue(bcV); + m_backingCaches.push_back(std::move(bc)); + } + m_images.clear(); + for (auto& imgV : context.doc["images"].GetArray()) + { + CacheImage img; + img.LoadFromValue(imgV); + m_images.push_back(std::move(img)); + } + m_regionsMappedIntoMemory.clear(); + for (auto& rV : context.doc["regionsMappedIntoMemory"].GetArray()) + { + MemoryRegion r; + r.LoadFromValue(rV); + m_regionsMappedIntoMemory.push_back(std::move(r)); + } + m_stubIslandRegions.clear(); + for (auto& siV : context.doc["stubIslands"].GetArray()) + { + MemoryRegion si; + si.LoadFromValue(siV); + m_stubIslandRegions.push_back(std::move(si)); + } + m_dyldDataRegions.clear(); + for (auto& siV : context.doc["dyldDataSections"].GetArray()) + { + MemoryRegion si; + si.LoadFromValue(siV); + m_dyldDataRegions.push_back(std::move(si)); + } + m_nonImageRegions.clear(); + for (auto& siV : context.doc["nonImageRegions"].GetArray()) + { + MemoryRegion si; + si.LoadFromValue(siV); + m_nonImageRegions.push_back(std::move(si)); + } + + m_metadataValid = true; +} + void Serialize(SerializationContext& context, std::string_view name, const mach_header_64& b) { rapidjson::Value key(name.data(), context.allocator); @@ -3723,4 +3896,4 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } -} // namespace SharedCacheCore +} // namespace SharedCacheCore diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h index 934cd093f6..8906160c60 100644 --- a/view/sharedcache/core/SharedCache.h +++ b/view/sharedcache/core/SharedCache.h @@ -552,176 +552,8 @@ namespace SharedCacheCore { iOS16CacheFormat, }; - void Store(SerializationContext& context) const - { - context.doc.AddMember("metadataVersion", METADATA_VERSION, context.allocator); - - MSS(m_viewState); - MSS_CAST(m_cacheFormat, uint8_t); - MSS(m_imageStarts); - MSS(m_baseFilePath); - rapidjson::Value headers(rapidjson::kArrayType); - for (auto& [k, v] : m_headers) - { - headers.PushBack(v.AsDocument(), context.allocator); - } - context.doc.AddMember("headers", headers, context.allocator); - // std::vector>>>> m_exportInfos - // std::vector>>>> exportInfos; - rapidjson::Document exportInfos(rapidjson::kArrayType); - - for (const auto& pair1 : m_exportInfos) - { - rapidjson::Value subObj(rapidjson::kObjectType); - rapidjson::Value subArr(rapidjson::kArrayType); - for (const auto& pair2 : pair1.second) - { - rapidjson::Value subSubObj(rapidjson::kObjectType); - subSubObj.AddMember("key", pair2.first, context.allocator); - subSubObj.AddMember("val1", pair2.second.first, context.allocator); - subSubObj.AddMember("val2", pair2.second.second, context.allocator); - subArr.PushBack(subSubObj, context.allocator); - } - - subObj.AddMember("key", pair1.first, context.allocator); - subObj.AddMember("value", subArr, context.allocator); - - exportInfos.PushBack(subObj, context.allocator); - } - context.doc.AddMember("exportInfos", exportInfos, context.allocator); - - rapidjson::Value backingCaches(rapidjson::kArrayType); - for (auto& bc : m_backingCaches) - { - backingCaches.PushBack(bc.AsDocument(), context.allocator); - } - context.doc.AddMember("backingCaches", backingCaches, context.allocator); - rapidjson::Value stubIslands(rapidjson::kArrayType); - for (auto& si : m_stubIslandRegions) - { - stubIslands.PushBack(si.AsDocument(), context.allocator); - } - rapidjson::Value images(rapidjson::kArrayType); - for (auto& img : m_images) - { - images.PushBack(img.AsDocument(), context.allocator); - } - context.doc.AddMember("images", images, context.allocator); - rapidjson::Value regionsMappedIntoMemory(rapidjson::kArrayType); - for (auto& r : m_regionsMappedIntoMemory) - { - regionsMappedIntoMemory.PushBack(r.AsDocument(), context.allocator); - } - context.doc.AddMember("regionsMappedIntoMemory", regionsMappedIntoMemory, context.allocator); - context.doc.AddMember("stubIslands", stubIslands, context.allocator); - rapidjson::Value dyldDataSections(rapidjson::kArrayType); - for (auto& si : m_dyldDataRegions) - { - dyldDataSections.PushBack(si.AsDocument(), context.allocator); - } - context.doc.AddMember("dyldDataSections", dyldDataSections, context.allocator); - rapidjson::Value nonImageRegions(rapidjson::kArrayType); - for (auto& si : m_nonImageRegions) - { - nonImageRegions.PushBack(si.AsDocument(), context.allocator); - } - context.doc.AddMember("nonImageRegions", nonImageRegions, context.allocator); - } - - void Load(DeserializationContext& context) - { - if (context.doc.HasMember("metadataVersion")) - { - if (context.doc["metadataVersion"].GetUint() != METADATA_VERSION) - { - m_logger->LogError("Shared Cache metadata version mismatch"); - return; - } - } - else - { - m_logger->LogError("Shared Cache metadata version missing"); - return; - } - m_viewState = MSL_CAST(m_viewState, uint8_t, DSCViewState); - m_cacheFormat = MSL_CAST(m_cacheFormat, uint8_t, SharedCacheFormat); - m_headers.clear(); - for (auto& startAndHeader : context.doc["headers"].GetArray()) - { - SharedCacheMachOHeader header; - header.LoadFromValue(startAndHeader); - m_headers[header.textBase] = header; - } - MSL(m_imageStarts); - MSL(m_baseFilePath); - m_exportInfos.clear(); - for (const auto& obj1 : context.doc["exportInfos"].GetArray()) - { - std::vector>> innerVec; - for (const auto& obj2 : obj1["value"].GetArray()) - { - std::pair innerPair = { (BNSymbolType)obj2["val1"].GetUint64(), obj2["val2"].GetString() }; - innerVec.push_back({ obj2["key"].GetUint64(), innerPair }); - } - - m_exportInfos[obj1["key"].GetUint64()] = innerVec; - } - m_symbolInfos.clear(); - for (auto& symbolInfo : context.doc["symbolInfos"].GetArray()) - { - std::vector>> symbolInfoVec; - for (auto& symbolInfoPair : symbolInfo.GetArray()) - { - symbolInfoVec.push_back({symbolInfoPair[0].GetUint64(), - {(BNSymbolType)symbolInfoPair[1].GetUint(), symbolInfoPair[2].GetString()}}); - } - m_symbolInfos[symbolInfo[0].GetUint64()] = std::move(symbolInfoVec); - } - m_backingCaches.clear(); - for (auto& bcV : context.doc["backingCaches"].GetArray()) - { - BackingCache bc; - bc.LoadFromValue(bcV); - m_backingCaches.push_back(std::move(bc)); - } - m_images.clear(); - for (auto& imgV : context.doc["images"].GetArray()) - { - CacheImage img; - img.LoadFromValue(imgV); - m_images.push_back(std::move(img)); - } - m_regionsMappedIntoMemory.clear(); - for (auto& rV : context.doc["regionsMappedIntoMemory"].GetArray()) - { - MemoryRegion r; - r.LoadFromValue(rV); - m_regionsMappedIntoMemory.push_back(std::move(r)); - } - m_stubIslandRegions.clear(); - for (auto& siV : context.doc["stubIslands"].GetArray()) - { - MemoryRegion si; - si.LoadFromValue(siV); - m_stubIslandRegions.push_back(std::move(si)); - } - m_dyldDataRegions.clear(); - for (auto& siV : context.doc["dyldDataSections"].GetArray()) - { - MemoryRegion si; - si.LoadFromValue(siV); - m_dyldDataRegions.push_back(std::move(si)); - } - m_nonImageRegions.clear(); - for (auto& siV : context.doc["nonImageRegions"].GetArray()) - { - MemoryRegion si; - si.LoadFromValue(siV); - m_nonImageRegions.push_back(std::move(si)); - } - - m_metadataValid = true; - } + void Store(SerializationContext& context) const; + void Load(DeserializationContext& context); private: Ref m_logger; From 1422f508a50a978e40fef765fe965b1f1ebd89fb Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Fri, 15 Nov 2024 08:31:02 -0800 Subject: [PATCH 3/7] [SharedCache] Move Serialize / Deserialize definitions into .cpp file This ensures only one definition ends up in the final binary and makes compilation a little faster. --- .../sharedcache/core/MetadataSerializable.cpp | 392 ++++++++++++++++ .../sharedcache/core/MetadataSerializable.hpp | 426 ++---------------- 2 files changed, 436 insertions(+), 382 deletions(-) create mode 100644 view/sharedcache/core/MetadataSerializable.cpp diff --git a/view/sharedcache/core/MetadataSerializable.cpp b/view/sharedcache/core/MetadataSerializable.cpp new file mode 100644 index 0000000000..8b7fac431a --- /dev/null +++ b/view/sharedcache/core/MetadataSerializable.cpp @@ -0,0 +1,392 @@ +#include "MetadataSerializable.hpp" + +namespace SharedCacheCore { + +using namespace BinaryNinja; + +struct DeserializationContext; + +void Serialize(SerializationContext& context, std::string_view name, bool b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, bool& b) { + b = context.doc[name.data()].GetBool(); +} + +void Serialize(SerializationContext& context, std::string_view name, uint8_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +void Serialize(SerializationContext& context, std::string_view name, uint16_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +void Serialize(SerializationContext& context, std::string_view name, uint32_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +void Serialize(SerializationContext& context, std::string_view name, uint64_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b) +{ + b = context.doc[name.data()].GetUint64(); +} + +void Serialize(SerializationContext& context, std::string_view name, int8_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +void Serialize(SerializationContext& context, std::string_view name, int16_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +void Serialize(SerializationContext& context, std::string_view name, int32_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b) +{ + b = context.doc[name.data()].GetInt(); +} + +void Serialize(SerializationContext& context, std::string_view name, int64_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +void Serialize(SerializationContext& context, std::string_view name, std::string_view b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value value(b.data(), context.allocator); + context.doc.AddMember(key, value, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::string& b) +{ + b = context.doc[name.data()].GetString(); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value p(rapidjson::kArrayType); + rapidjson::Value _key(i.first.c_str(), context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(_key, context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + p.PushBack(i.second, context.allocator); + bArr.PushBack(p, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); +} + +// std::unordered_map> +void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value classes(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value classArr(rapidjson::kArrayType); + rapidjson::Value classKey(i.first.c_str(), context.allocator); + classArr.PushBack(classKey, context.allocator); + rapidjson::Value membersArr(rapidjson::kArrayType); + for (auto& j : i.second) + { + rapidjson::Value member(rapidjson::kArrayType); + member.PushBack(j.first, context.allocator); + member.PushBack(j.second, context.allocator); + membersArr.PushBack(member, context.allocator); + } + classArr.PushBack(membersArr, context.allocator); + classes.PushBack(classArr, context.allocator); + } + context.doc.AddMember(key, classes, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + { + std::string key = i.GetArray()[0].GetString(); + std::unordered_map memArray; + for (auto& member : i.GetArray()[1].GetArray()) + { + memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); + } + b[key] = memArray; + } +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (const auto& s : b) + { + rapidjson::Value value(s.c_str(), context.allocator); + bArr.PushBack(value, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b.emplace_back(i.GetString()); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + segV.PushBack(i.second.first, context.allocator); + segV.PushBack(i.second.second, context.allocator); + bArr.PushBack(segV, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + { + std::pair> j; + j.first = i.GetArray()[0].GetUint64(); + j.second.first = i.GetArray()[1].GetUint64(); + j.second.second = i.GetArray()[2].GetUint64(); + b.push_back(j); + } +} + +void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + segV.PushBack(i.second, context.allocator); + bArr.PushBack(segV, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + { + std::pair j; + j.first = i.GetArray()[0].GetUint64(); + j.second = i.GetArray()[1].GetBool(); + b.push_back(j); + } +} + +void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + bArr.PushBack(i, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + { + b.push_back(i.GetUint64()); + } +} + +// std::unordered_map +void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value p(rapidjson::kArrayType); + rapidjson::Value _key(i.first.c_str(), context.allocator); + p.PushBack(_key, context.allocator); + p.PushBack(i.second, context.allocator); + bArr.PushBack(p, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + { + b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); + } +} + +// std::vector>>> +void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + rapidjson::Value segArr(rapidjson::kArrayType); + for (auto& j : i.second) + { + rapidjson::Value segPair(rapidjson::kArrayType); + segPair.PushBack(j.first, context.allocator); + rapidjson::Value segStr(j.second.c_str(), context.allocator); + segPair.PushBack(segStr, context.allocator); + segArr.PushBack(segPair, context.allocator); + } + segV.PushBack(segArr, context.allocator); + bArr.PushBack(segV, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + { + std::pair>> j; + j.first = i.GetArray()[0].GetUint64(); + for (auto& k : i.GetArray()[1].GetArray()) + { + j.second.push_back({k.GetArray()[0].GetUint64(), k.GetArray()[1].GetString()}); + } + b.push_back(j); + } +} + +} // namespace SharedCacheCore diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp index 1b7a03d0df..3c3541c474 100644 --- a/view/sharedcache/core/MetadataSerializable.hpp +++ b/view/sharedcache/core/MetadataSerializable.hpp @@ -38,6 +38,7 @@ #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" +#include "../api/sharedcachecore.h" #ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP #define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP @@ -131,388 +132,49 @@ class MetadataSerializable Derived& AsDerived() { return static_cast(*this); } }; -inline void Serialize(SerializationContext& context, std::string_view name, bool b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, bool& b) { - b = context.doc[name.data()].GetBool(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, uint8_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b) -{ - b = static_cast(context.doc[name.data()].GetUint64()); -} - -inline void Serialize(SerializationContext& context, std::string_view name, uint16_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b) -{ - b = static_cast(context.doc[name.data()].GetUint64()); -} - -inline void Serialize(SerializationContext& context, std::string_view name, uint32_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b) -{ - b = static_cast(context.doc[name.data()].GetUint64()); -} - -inline void Serialize(SerializationContext& context, std::string_view name, uint64_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b) -{ - b = context.doc[name.data()].GetUint64(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, int8_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b) -{ - b = context.doc[name.data()].GetInt64(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, int16_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b) -{ - b = context.doc[name.data()].GetInt64(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, int32_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b) -{ - b = context.doc[name.data()].GetInt(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, int64_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b) -{ - b = context.doc[name.data()].GetInt64(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, std::string_view b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value value(b.data(), context.allocator); - context.doc.AddMember(key, value, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::string& b) -{ - b = context.doc[name.data()].GetString(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, context.allocator); - rapidjson::Value value(i.second.c_str(), context.allocator); - p.PushBack(value, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::map& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, context.allocator); - rapidjson::Value value(i.second.c_str(), context.allocator); - p.PushBack(value, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), context.allocator); - rapidjson::Value value(i.second.c_str(), context.allocator); - p.PushBack(_key, context.allocator); - p.PushBack(value, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, context.allocator); - p.PushBack(i.second, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); -} - -// std::unordered_map> -inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value classes(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value classArr(rapidjson::kArrayType); - rapidjson::Value classKey(i.first.c_str(), context.allocator); - classArr.PushBack(classKey, context.allocator); - rapidjson::Value membersArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value member(rapidjson::kArrayType); - member.PushBack(j.first, context.allocator); - member.PushBack(j.second, context.allocator); - membersArr.PushBack(member, context.allocator); - } - classArr.PushBack(membersArr, context.allocator); - classes.PushBack(classArr, context.allocator); - } - context.doc.AddMember(key, classes, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - { - std::string key = i.GetArray()[0].GetString(); - std::unordered_map memArray; - for (auto& member : i.GetArray()[1].GetArray()) - { - memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); - } - b[key] = memArray; - } -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (const auto& s : b) - { - rapidjson::Value value(s.c_str(), context.allocator); - bArr.PushBack(value, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - b.emplace_back(i.GetString()); -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, context.allocator); - segV.PushBack(i.second.first, context.allocator); - segV.PushBack(i.second.second, context.allocator); - bArr.PushBack(segV, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - { - std::pair> j; - j.first = i.GetArray()[0].GetUint64(); - j.second.first = i.GetArray()[1].GetUint64(); - j.second.second = i.GetArray()[2].GetUint64(); - b.push_back(j); - } -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, context.allocator); - segV.PushBack(i.second, context.allocator); - bArr.PushBack(segV, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - { - std::pair j; - j.first = i.GetArray()[0].GetUint64(); - j.second = i.GetArray()[1].GetBool(); - b.push_back(j); - } -} - -inline void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - bArr.PushBack(i, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - { - b.push_back(i.GetUint64()); - } -} - -// std::unordered_map -inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), context.allocator); - p.PushBack(_key, context.allocator); - p.PushBack(i.second, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - { - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); - } -} - -// std::vector>>> -inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, context.allocator); - rapidjson::Value segArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value segPair(rapidjson::kArrayType); - segPair.PushBack(j.first, context.allocator); - rapidjson::Value segStr(j.second.c_str(), context.allocator); - segPair.PushBack(segStr, context.allocator); - segArr.PushBack(segPair, context.allocator); - } - segV.PushBack(segArr, context.allocator); - bArr.PushBack(segV, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b) -{ - for (auto& i : context.doc[name.data()].GetArray()) - { - std::pair>> j; - j.first = i.GetArray()[0].GetUint64(); - for (auto& k : i.GetArray()[1].GetArray()) - { - j.second.push_back({k.GetArray()[0].GetUint64(), k.GetArray()[1].GetString()}); - } - b.push_back(j); - } -} +// These are not part of the FFI API, but are exported so that sharedcacheui can use them. +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, bool b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, bool& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint8_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint16_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint32_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint64_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int8_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int16_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int32_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int64_t b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, std::string_view b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::string& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::map& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::map& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b); } // namespace SharedCacheCore From 9d7282080da9b9cd683d0a2fe669a47303eb70e1 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Fri, 15 Nov 2024 08:35:58 -0800 Subject: [PATCH 4/7] Move duplicated Serialize / Deserialize functions from api / core into MetadataSerializable --- view/sharedcache/api/sharedcache.cpp | 394 ----------------- view/sharedcache/api/sharedcacheapi.h | 26 -- .../sharedcache/core/MetadataSerializable.cpp | 401 ++++++++++++++++++ .../sharedcache/core/MetadataSerializable.hpp | 26 ++ view/sharedcache/core/SharedCache.cpp | 400 ----------------- view/sharedcache/core/SharedCache.h | 25 -- 6 files changed, 427 insertions(+), 845 deletions(-) diff --git a/view/sharedcache/api/sharedcache.cpp b/view/sharedcache/api/sharedcache.cpp index 45ca6377f6..71d190da21 100644 --- a/view/sharedcache/api/sharedcache.cpp +++ b/view/sharedcache/api/sharedcache.cpp @@ -222,398 +222,4 @@ namespace SharedCacheAPI { BNDSCFindSymbolAtAddressAndApplyToAddress(m_object, symbolLocation, targetLocation, triggerReanalysis); } - -void Serialize(SharedCacheCore::SerializationContext& context, std::string_view name, const mach_header_64& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.magic, context.allocator); - bArr.PushBack(b.cputype, context.allocator); - bArr.PushBack(b.cpusubtype, context.allocator); - bArr.PushBack(b.filetype, context.allocator); - bArr.PushBack(b.ncmds, context.allocator); - bArr.PushBack(b.sizeofcmds, context.allocator); - bArr.PushBack(b.flags, context.allocator); - bArr.PushBack(b.reserved, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, mach_header_64& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const symtab_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.symoff, context.allocator); - bArr.PushBack(b.nsyms, context.allocator); - bArr.PushBack(b.stroff, context.allocator); - bArr.PushBack(b.strsize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, symtab_command& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const dysymtab_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.ilocalsym, context.allocator); - bArr.PushBack(b.nlocalsym, context.allocator); - bArr.PushBack(b.iextdefsym, context.allocator); - bArr.PushBack(b.nextdefsym, context.allocator); - bArr.PushBack(b.iundefsym, context.allocator); - bArr.PushBack(b.nundefsym, context.allocator); - bArr.PushBack(b.tocoff, context.allocator); - bArr.PushBack(b.ntoc, context.allocator); - bArr.PushBack(b.modtaboff, context.allocator); - bArr.PushBack(b.nmodtab, context.allocator); - bArr.PushBack(b.extrefsymoff, context.allocator); - bArr.PushBack(b.nextrefsyms, context.allocator); - bArr.PushBack(b.indirectsymoff, context.allocator); - bArr.PushBack(b.nindirectsyms, context.allocator); - bArr.PushBack(b.extreloff, context.allocator); - bArr.PushBack(b.nextrel, context.allocator); - bArr.PushBack(b.locreloff, context.allocator); - bArr.PushBack(b.nlocrel, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, dysymtab_command& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const dyld_info_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.rebase_off, context.allocator); - bArr.PushBack(b.rebase_size, context.allocator); - bArr.PushBack(b.bind_off, context.allocator); - bArr.PushBack(b.bind_size, context.allocator); - bArr.PushBack(b.weak_bind_off, context.allocator); - bArr.PushBack(b.weak_bind_size, context.allocator); - bArr.PushBack(b.lazy_bind_off, context.allocator); - bArr.PushBack(b.lazy_bind_size, context.allocator); - bArr.PushBack(b.export_off, context.allocator); - bArr.PushBack(b.export_size, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, dyld_info_command& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const routines_command_64& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.init_address, context.allocator); - bArr.PushBack(b.init_module, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, routines_command_64& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const function_starts_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.funcoff, context.allocator); - bArr.PushBack(b.funcsize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, function_starts_command& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - b.cmd = bArr[0].GetUint(); - b.cmdsize = bArr[1].GetUint(); - b.funcoff = bArr[2].GetUint(); - b.funcsize = bArr[3].GetUint(); -} - -void Serialize(SharedCacheCore::SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.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(), context.allocator), context.allocator); - sArr.PushBack(s.addr, context.allocator); - sArr.PushBack(s.size, context.allocator); - sArr.PushBack(s.offset, context.allocator); - sArr.PushBack(s.align, context.allocator); - sArr.PushBack(s.reloff, context.allocator); - sArr.PushBack(s.nreloc, context.allocator); - sArr.PushBack(s.flags, context.allocator); - sArr.PushBack(s.reserved1, context.allocator); - sArr.PushBack(s.reserved2, context.allocator); - sArr.PushBack(s.reserved3, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, std::vector& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const linkedit_data_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.dataoff, context.allocator); - bArr.PushBack(b.datasize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, linkedit_data_command& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - b.cmd = bArr[0].GetUint(); - b.cmdsize = bArr[1].GetUint(); - b.dataoff = bArr[2].GetUint(); - b.datasize = bArr[3].GetUint(); -} - -void Serialize(SharedCacheCore::SerializationContext& context, std::string_view name, const segment_command_64& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); - bArr.PushBack(b.vmaddr, context.allocator); - bArr.PushBack(b.vmsize, context.allocator); - bArr.PushBack(b.fileoff, context.allocator); - bArr.PushBack(b.filesize, context.allocator); - bArr.PushBack(b.maxprot, context.allocator); - bArr.PushBack(b.initprot, context.allocator); - bArr.PushBack(b.nsects, context.allocator); - bArr.PushBack(b.flags, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, segment_command_64& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); - sArr.PushBack(s.vmaddr, context.allocator); - sArr.PushBack(s.vmsize, context.allocator); - sArr.PushBack(s.fileoff, context.allocator); - sArr.PushBack(s.filesize, context.allocator); - sArr.PushBack(s.maxprot, context.allocator); - sArr.PushBack(s.initprot, context.allocator); - sArr.PushBack(s.nsects, context.allocator); - sArr.PushBack(s.flags, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, std::vector& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const build_version_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.platform, context.allocator); - bArr.PushBack(b.minos, context.allocator); - bArr.PushBack(b.sdk, context.allocator); - bArr.PushBack(b.ntools, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, build_version_command& b) -{ - auto bArr = context.doc[name.data()].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(SharedCacheCore::SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& s : b) - { - rapidjson::Value sArr(rapidjson::kArrayType); - sArr.PushBack(s.tool, context.allocator); - sArr.PushBack(s.version, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(SharedCacheCore::DeserializationContext& context, std::string_view name, std::vector& b) -{ - auto bArr = context.doc[name.data()].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); - } -} - } // namespace SharedCacheAPI diff --git a/view/sharedcache/api/sharedcacheapi.h b/view/sharedcache/api/sharedcacheapi.h index a9a67a29f4..7b049bc423 100644 --- a/view/sharedcache/api/sharedcacheapi.h +++ b/view/sharedcache/api/sharedcacheapi.h @@ -8,32 +8,6 @@ using namespace BinaryNinja; namespace SharedCacheAPI { - - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const mach_header_64& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, mach_header_64& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const symtab_command& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, symtab_command& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const dysymtab_command& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, dysymtab_command& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const dyld_info_command& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, dyld_info_command& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const routines_command_64& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, routines_command_64& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const function_starts_command& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, function_starts_command& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const std::vector& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, std::vector& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const linkedit_data_command& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, linkedit_data_command& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const segment_command_64& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, segment_command_64& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const std::vector& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, std::vector& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const build_version_command& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, build_version_command& b); - void Serialize(SharedCacheCore::SerializationContext&, std::string_view name, const std::vector& b); - void Deserialize(SharedCacheCore::DeserializationContext&, std::string_view name, std::vector& b); - template class SCRefCountObject { void AddRefInternal() { m_refs.fetch_add(1); } diff --git a/view/sharedcache/core/MetadataSerializable.cpp b/view/sharedcache/core/MetadataSerializable.cpp index 8b7fac431a..1e17279ba5 100644 --- a/view/sharedcache/core/MetadataSerializable.cpp +++ b/view/sharedcache/core/MetadataSerializable.cpp @@ -389,4 +389,405 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } +void Serialize(SerializationContext& context, std::string_view name, const mach_header_64& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.magic, context.allocator); + bArr.PushBack(b.cputype, context.allocator); + bArr.PushBack(b.cpusubtype, context.allocator); + bArr.PushBack(b.filetype, context.allocator); + bArr.PushBack(b.ncmds, context.allocator); + bArr.PushBack(b.sizeofcmds, context.allocator); + bArr.PushBack(b.flags, context.allocator); + bArr.PushBack(b.reserved, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, mach_header_64& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.magic = bArr[0].GetUint(); + b.cputype = bArr[1].GetUint(); + b.cpusubtype = bArr[2].GetUint(); + b.filetype = bArr[3].GetUint(); + b.ncmds = bArr[4].GetUint(); + b.sizeofcmds = bArr[5].GetUint(); + b.flags = bArr[6].GetUint(); + b.reserved = bArr[7].GetUint(); +} + +void Serialize(SerializationContext& context, std::string_view name, const symtab_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.symoff, context.allocator); + bArr.PushBack(b.nsyms, context.allocator); + bArr.PushBack(b.stroff, context.allocator); + bArr.PushBack(b.strsize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, symtab_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const dysymtab_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.ilocalsym, context.allocator); + bArr.PushBack(b.nlocalsym, context.allocator); + bArr.PushBack(b.iextdefsym, context.allocator); + bArr.PushBack(b.nextdefsym, context.allocator); + bArr.PushBack(b.iundefsym, context.allocator); + bArr.PushBack(b.nundefsym, context.allocator); + bArr.PushBack(b.tocoff, context.allocator); + bArr.PushBack(b.ntoc, context.allocator); + bArr.PushBack(b.modtaboff, context.allocator); + bArr.PushBack(b.nmodtab, context.allocator); + bArr.PushBack(b.extrefsymoff, context.allocator); + bArr.PushBack(b.nextrefsyms, context.allocator); + bArr.PushBack(b.indirectsymoff, context.allocator); + bArr.PushBack(b.nindirectsyms, context.allocator); + bArr.PushBack(b.extreloff, context.allocator); + bArr.PushBack(b.nextrel, context.allocator); + bArr.PushBack(b.locreloff, context.allocator); + bArr.PushBack(b.nlocrel, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, dysymtab_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const dyld_info_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.rebase_off, context.allocator); + bArr.PushBack(b.rebase_size, context.allocator); + bArr.PushBack(b.bind_off, context.allocator); + bArr.PushBack(b.bind_size, context.allocator); + bArr.PushBack(b.weak_bind_off, context.allocator); + bArr.PushBack(b.weak_bind_size, context.allocator); + bArr.PushBack(b.lazy_bind_off, context.allocator); + bArr.PushBack(b.lazy_bind_size, context.allocator); + bArr.PushBack(b.export_off, context.allocator); + bArr.PushBack(b.export_size, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, dyld_info_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const routines_command_64& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.init_address, context.allocator); + bArr.PushBack(b.init_module, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, routines_command_64& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const function_starts_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.funcoff, context.allocator); + bArr.PushBack(b.funcsize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, function_starts_command& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.cmd = bArr[0].GetUint(); + b.cmdsize = bArr[1].GetUint(); + b.funcoff = bArr[2].GetUint(); + b.funcsize = bArr[3].GetUint(); +} + +void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.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(), context.allocator), context.allocator); + sArr.PushBack(s.addr, context.allocator); + sArr.PushBack(s.size, context.allocator); + sArr.PushBack(s.offset, context.allocator); + sArr.PushBack(s.align, context.allocator); + sArr.PushBack(s.reloff, context.allocator); + sArr.PushBack(s.nreloc, context.allocator); + sArr.PushBack(s.flags, context.allocator); + sArr.PushBack(s.reserved1, context.allocator); + sArr.PushBack(s.reserved2, context.allocator); + sArr.PushBack(s.reserved3, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + for (auto& s : bArr) + { + section_64 sec; + auto s2 = s.GetArray(); + std::string sectNameStr = s2[0].GetString(); + memset(sec.sectname, 0, 16); + memcpy(sec.sectname, sectNameStr.c_str(), sectNameStr.size()); + std::string segNameStr = s2[1].GetString(); + memset(sec.segname, 0, 16); + 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(SerializationContext& context, std::string_view name, const linkedit_data_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.dataoff, context.allocator); + bArr.PushBack(b.datasize, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, linkedit_data_command& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + b.cmd = bArr[0].GetUint(); + b.cmdsize = bArr[1].GetUint(); + b.dataoff = bArr[2].GetUint(); + b.datasize = bArr[3].GetUint(); +} + +void Serialize(SerializationContext& context, std::string_view name, const segment_command_64& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); + bArr.PushBack(b.vmaddr, context.allocator); + bArr.PushBack(b.vmsize, context.allocator); + bArr.PushBack(b.fileoff, context.allocator); + bArr.PushBack(b.filesize, context.allocator); + bArr.PushBack(b.maxprot, context.allocator); + bArr.PushBack(b.initprot, context.allocator); + bArr.PushBack(b.nsects, context.allocator); + bArr.PushBack(b.flags, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, segment_command_64& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + std::string segNameStr = bArr[0].GetString(); + memset(b.segname, 0, 16); + 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(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); + sArr.PushBack(s.vmaddr, context.allocator); + sArr.PushBack(s.vmsize, context.allocator); + sArr.PushBack(s.fileoff, context.allocator); + sArr.PushBack(s.filesize, context.allocator); + sArr.PushBack(s.maxprot, context.allocator); + sArr.PushBack(s.initprot, context.allocator); + sArr.PushBack(s.nsects, context.allocator); + sArr.PushBack(s.flags, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].GetArray(); + for (auto& s : bArr) + { + segment_command_64 sec; + auto s2 = s.GetArray(); + std::string segNameStr = s2[0].GetString(); + memset(sec.segname, 0, 16); + 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(SerializationContext& context, std::string_view name, const build_version_command& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + bArr.PushBack(b.cmd, context.allocator); + bArr.PushBack(b.cmdsize, context.allocator); + bArr.PushBack(b.platform, context.allocator); + bArr.PushBack(b.minos, context.allocator); + bArr.PushBack(b.sdk, context.allocator); + bArr.PushBack(b.ntools, context.allocator); + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, build_version_command& b) +{ + auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& s : b) + { + rapidjson::Value sArr(rapidjson::kArrayType); + sArr.PushBack(s.tool, context.allocator); + sArr.PushBack(s.version, context.allocator); + bArr.PushBack(sArr, context.allocator); + } + context.doc.AddMember(key, bArr, context.allocator); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + auto bArr = context.doc[name.data()].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); + } +} + + } // namespace SharedCacheCore diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp index 3c3541c474..fa27353495 100644 --- a/view/sharedcache/core/MetadataSerializable.hpp +++ b/view/sharedcache/core/MetadataSerializable.hpp @@ -39,6 +39,7 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" #include "../api/sharedcachecore.h" +#include "view/macho/machoview.h" #ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP #define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP @@ -175,6 +176,31 @@ SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_vi SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const mach_header_64& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, mach_header_64& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const symtab_command& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, symtab_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const dysymtab_command& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, dysymtab_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const dyld_info_command& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, dyld_info_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const routines_command_64& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, routines_command_64& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const function_starts_command& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, function_starts_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const linkedit_data_command& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, linkedit_data_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const segment_command_64& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, segment_command_64& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const build_version_command& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, build_version_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); + } // namespace SharedCacheCore diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 414d13ad48..97cc796863 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -3496,404 +3496,4 @@ void SharedCache::Load(DeserializationContext& context) m_metadataValid = true; } -void Serialize(SerializationContext& context, std::string_view name, const mach_header_64& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.magic, context.allocator); - bArr.PushBack(b.cputype, context.allocator); - bArr.PushBack(b.cpusubtype, context.allocator); - bArr.PushBack(b.filetype, context.allocator); - bArr.PushBack(b.ncmds, context.allocator); - bArr.PushBack(b.sizeofcmds, context.allocator); - bArr.PushBack(b.flags, context.allocator); - bArr.PushBack(b.reserved, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, mach_header_64& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - b.magic = bArr[0].GetUint(); - b.cputype = bArr[1].GetUint(); - b.cpusubtype = bArr[2].GetUint(); - b.filetype = bArr[3].GetUint(); - b.ncmds = bArr[4].GetUint(); - b.sizeofcmds = bArr[5].GetUint(); - b.flags = bArr[6].GetUint(); - b.reserved = bArr[7].GetUint(); -} - -void Serialize(SerializationContext& context, std::string_view name, const symtab_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.symoff, context.allocator); - bArr.PushBack(b.nsyms, context.allocator); - bArr.PushBack(b.stroff, context.allocator); - bArr.PushBack(b.strsize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, symtab_command& b) -{ - auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const dysymtab_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.ilocalsym, context.allocator); - bArr.PushBack(b.nlocalsym, context.allocator); - bArr.PushBack(b.iextdefsym, context.allocator); - bArr.PushBack(b.nextdefsym, context.allocator); - bArr.PushBack(b.iundefsym, context.allocator); - bArr.PushBack(b.nundefsym, context.allocator); - bArr.PushBack(b.tocoff, context.allocator); - bArr.PushBack(b.ntoc, context.allocator); - bArr.PushBack(b.modtaboff, context.allocator); - bArr.PushBack(b.nmodtab, context.allocator); - bArr.PushBack(b.extrefsymoff, context.allocator); - bArr.PushBack(b.nextrefsyms, context.allocator); - bArr.PushBack(b.indirectsymoff, context.allocator); - bArr.PushBack(b.nindirectsyms, context.allocator); - bArr.PushBack(b.extreloff, context.allocator); - bArr.PushBack(b.nextrel, context.allocator); - bArr.PushBack(b.locreloff, context.allocator); - bArr.PushBack(b.nlocrel, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, dysymtab_command& b) -{ - auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const dyld_info_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.rebase_off, context.allocator); - bArr.PushBack(b.rebase_size, context.allocator); - bArr.PushBack(b.bind_off, context.allocator); - bArr.PushBack(b.bind_size, context.allocator); - bArr.PushBack(b.weak_bind_off, context.allocator); - bArr.PushBack(b.weak_bind_size, context.allocator); - bArr.PushBack(b.lazy_bind_off, context.allocator); - bArr.PushBack(b.lazy_bind_size, context.allocator); - bArr.PushBack(b.export_off, context.allocator); - bArr.PushBack(b.export_size, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, dyld_info_command& b) -{ - auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const routines_command_64& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.init_address, context.allocator); - bArr.PushBack(b.init_module, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, routines_command_64& b) -{ - auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const function_starts_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.funcoff, context.allocator); - bArr.PushBack(b.funcsize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, function_starts_command& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - b.cmd = bArr[0].GetUint(); - b.cmdsize = bArr[1].GetUint(); - b.funcoff = bArr[2].GetUint(); - b.funcsize = bArr[3].GetUint(); -} - -void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.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(), context.allocator), context.allocator); - sArr.PushBack(s.addr, context.allocator); - sArr.PushBack(s.size, context.allocator); - sArr.PushBack(s.offset, context.allocator); - sArr.PushBack(s.align, context.allocator); - sArr.PushBack(s.reloff, context.allocator); - sArr.PushBack(s.nreloc, context.allocator); - sArr.PushBack(s.flags, context.allocator); - sArr.PushBack(s.reserved1, context.allocator); - sArr.PushBack(s.reserved2, context.allocator); - sArr.PushBack(s.reserved3, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - for (auto& s : bArr) - { - section_64 sec; - auto s2 = s.GetArray(); - std::string sectNameStr = s2[0].GetString(); - memset(sec.sectname, 0, 16); - memcpy(sec.sectname, sectNameStr.c_str(), sectNameStr.size()); - std::string segNameStr = s2[1].GetString(); - memset(sec.segname, 0, 16); - 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(SerializationContext& context, std::string_view name, const linkedit_data_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.dataoff, context.allocator); - bArr.PushBack(b.datasize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, linkedit_data_command& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - b.cmd = bArr[0].GetUint(); - b.cmdsize = bArr[1].GetUint(); - b.dataoff = bArr[2].GetUint(); - b.datasize = bArr[3].GetUint(); -} - -void Serialize(SerializationContext& context, std::string_view name, const segment_command_64& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); - bArr.PushBack(b.vmaddr, context.allocator); - bArr.PushBack(b.vmsize, context.allocator); - bArr.PushBack(b.fileoff, context.allocator); - bArr.PushBack(b.filesize, context.allocator); - bArr.PushBack(b.maxprot, context.allocator); - bArr.PushBack(b.initprot, context.allocator); - bArr.PushBack(b.nsects, context.allocator); - bArr.PushBack(b.flags, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, segment_command_64& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - std::string segNameStr = bArr[0].GetString(); - memset(b.segname, 0, 16); - 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(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); - sArr.PushBack(s.vmaddr, context.allocator); - sArr.PushBack(s.vmsize, context.allocator); - sArr.PushBack(s.fileoff, context.allocator); - sArr.PushBack(s.filesize, context.allocator); - sArr.PushBack(s.maxprot, context.allocator); - sArr.PushBack(s.initprot, context.allocator); - sArr.PushBack(s.nsects, context.allocator); - sArr.PushBack(s.flags, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) -{ - auto bArr = context.doc[name.data()].GetArray(); - for (auto& s : bArr) - { - segment_command_64 sec; - auto s2 = s.GetArray(); - std::string segNameStr = s2[0].GetString(); - memset(sec.segname, 0, 16); - 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(SerializationContext& context, std::string_view name, const build_version_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.platform, context.allocator); - bArr.PushBack(b.minos, context.allocator); - bArr.PushBack(b.sdk, context.allocator); - bArr.PushBack(b.ntools, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, build_version_command& b) -{ - auto bArr = context.doc[name.data()].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(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& s : b) - { - rapidjson::Value sArr(rapidjson::kArrayType); - sArr.PushBack(s.tool, context.allocator); - sArr.PushBack(s.version, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) -{ - auto bArr = context.doc[name.data()].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); - } -} - } // namespace SharedCacheCore diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h index 8906160c60..0c871c3e21 100644 --- a/view/sharedcache/core/SharedCache.h +++ b/view/sharedcache/core/SharedCache.h @@ -16,31 +16,6 @@ DECLARE_SHAREDCACHE_API_OBJECT(BNSharedCache, SharedCache); namespace SharedCacheCore { - void Serialize(SerializationContext&, std::string_view name, const mach_header_64& b); - void Deserialize(DeserializationContext&, std::string_view name, mach_header_64& b); - void Serialize(SerializationContext&, std::string_view name, const symtab_command& b); - void Deserialize(DeserializationContext&, std::string_view name, symtab_command& b); - void Serialize(SerializationContext&, std::string_view name, const dysymtab_command& b); - void Deserialize(DeserializationContext&, std::string_view name, dysymtab_command& b); - void Serialize(SerializationContext&, std::string_view name, const dyld_info_command& b); - void Deserialize(DeserializationContext&, std::string_view name, dyld_info_command& b); - void Serialize(SerializationContext&, std::string_view name, const routines_command_64& b); - void Deserialize(DeserializationContext&, std::string_view name, routines_command_64& b); - void Serialize(SerializationContext&, std::string_view name, const function_starts_command& b); - void Deserialize(DeserializationContext&, std::string_view name, function_starts_command& b); - void Serialize(SerializationContext&, std::string_view name, const std::vector& b); - void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); - void Serialize(SerializationContext&, std::string_view name, const linkedit_data_command& b); - void Deserialize(DeserializationContext&, std::string_view name, linkedit_data_command& b); - void Serialize(SerializationContext&, std::string_view name, const segment_command_64& b); - void Deserialize(DeserializationContext&, std::string_view name, segment_command_64& b); - void Serialize(SerializationContext&, std::string_view name, const std::vector& b); - void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); - void Serialize(SerializationContext&, std::string_view name, const build_version_command& b); - void Deserialize(DeserializationContext&, std::string_view name, build_version_command& b); - void Serialize(SerializationContext&, std::string_view name, const std::vector& b); - void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); - enum DSCViewState { DSCViewStateUnloaded, From 7c77bfe4a30ecfcae6e7f8d45f3935a875b8a1a0 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Fri, 15 Nov 2024 08:49:18 -0800 Subject: [PATCH 5/7] Switch to SAX-style JSON writing API Building up an in-memory representation of the JSON document is expensive in both CPU and memory. Instead of doing that we can directly write the appropriate types. --- .../sharedcache/core/MetadataSerializable.cpp | 596 +++++------------- .../sharedcache/core/MetadataSerializable.hpp | 147 +++-- view/sharedcache/core/SharedCache.cpp | 85 +-- view/sharedcache/core/SharedCache.h | 8 +- 4 files changed, 302 insertions(+), 534 deletions(-) diff --git a/view/sharedcache/core/MetadataSerializable.cpp b/view/sharedcache/core/MetadataSerializable.cpp index 1e17279ba5..0fa712b17a 100644 --- a/view/sharedcache/core/MetadataSerializable.cpp +++ b/view/sharedcache/core/MetadataSerializable.cpp @@ -2,90 +2,83 @@ namespace SharedCacheCore { -using namespace BinaryNinja; +void Serialize(SerializationContext& context, std::string_view str) { + context.writer.String(str.data(), str.length()); +} -struct DeserializationContext; +void Serialize(SerializationContext& context, const char* value) { + Serialize(context, std::string_view(value)); +} -void Serialize(SerializationContext& context, std::string_view name, bool b) +void Serialize(SerializationContext& context, bool b) { - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); + context.writer.Bool(b); } -void Deserialize(DeserializationContext& context, std::string_view name, bool& b) { - b = context.doc[name.data()].GetBool(); +void Serialize(SerializationContext& context, int8_t value) { + context.writer.Int(value); } -void Serialize(SerializationContext& context, std::string_view name, uint8_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); +void Serialize(SerializationContext& context, uint8_t value) { + context.writer.Uint(value); } -void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b) -{ - b = static_cast(context.doc[name.data()].GetUint64()); +void Serialize(SerializationContext& context, int16_t value) { + context.writer.Int(value); } -void Serialize(SerializationContext& context, std::string_view name, uint16_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); +void Serialize(SerializationContext& context, uint16_t value) { + context.writer.Uint(value); } -void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b) -{ - b = static_cast(context.doc[name.data()].GetUint64()); +void Serialize(SerializationContext& context, int32_t value) { + context.writer.Int(value); } -void Serialize(SerializationContext& context, std::string_view name, uint32_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); +void Serialize(SerializationContext& context, uint32_t value) { + context.writer.Uint(value); } -void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b) -{ - b = static_cast(context.doc[name.data()].GetUint64()); +void Serialize(SerializationContext& context, int64_t value) { + context.writer.Int64(value); } -void Serialize(SerializationContext& context, std::string_view name, uint64_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); +void Serialize(SerializationContext& context, uint64_t value) { + context.writer.Uint64(value); } -void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b) +void Deserialize(DeserializationContext& context, std::string_view name, bool& b) { + b = context.doc[name.data()].GetBool(); +} + +void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b) { - b = context.doc[name.data()].GetUint64(); + b = static_cast(context.doc[name.data()].GetUint64()); } -void Serialize(SerializationContext& context, std::string_view name, int8_t b) +void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b) { - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); + b = static_cast(context.doc[name.data()].GetUint64()); } -void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b) +void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b) { - b = context.doc[name.data()].GetInt64(); + b = static_cast(context.doc[name.data()].GetUint64()); } -void Serialize(SerializationContext& context, std::string_view name, int16_t b) +void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b) { - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); + b = context.doc[name.data()].GetUint64(); } -void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b) +void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b) { b = context.doc[name.data()].GetInt64(); } -void Serialize(SerializationContext& context, std::string_view name, int32_t b) +void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b) { - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); + b = context.doc[name.data()].GetInt64(); } void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b) @@ -93,131 +86,34 @@ void Deserialize(DeserializationContext& context, std::string_view name, int32_t b = context.doc[name.data()].GetInt(); } -void Serialize(SerializationContext& context, std::string_view name, int64_t b) -{ - rapidjson::Value key(name.data(), context.allocator); - context.doc.AddMember(key, b, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b) { b = context.doc[name.data()].GetInt64(); } -void Serialize(SerializationContext& context, std::string_view name, std::string_view b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value value(b.data(), context.allocator); - context.doc.AddMember(key, value, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::string& b) { b = context.doc[name.data()].GetString(); } -void Serialize(SerializationContext& context, std::string_view name, const std::map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, context.allocator); - rapidjson::Value value(i.second.c_str(), context.allocator); - p.PushBack(value, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::map& b) { for (auto& i : context.doc[name.data()].GetArray()) b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); } -void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, context.allocator); - rapidjson::Value value(i.second.c_str(), context.allocator); - p.PushBack(value, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - -void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), context.allocator); - rapidjson::Value value(i.second.c_str(), context.allocator); - p.PushBack(_key, context.allocator); - p.PushBack(value, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) { for (auto& i : context.doc[name.data()].GetArray()) b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); } -void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, context.allocator); - p.PushBack(i.second, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) { for (auto& i : context.doc[name.data()].GetArray()) b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); } -// std::unordered_map> -void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value classes(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value classArr(rapidjson::kArrayType); - rapidjson::Value classKey(i.first.c_str(), context.allocator); - classArr.PushBack(classKey, context.allocator); - rapidjson::Value membersArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value member(rapidjson::kArrayType); - member.PushBack(j.first, context.allocator); - member.PushBack(j.second, context.allocator); - membersArr.PushBack(member, context.allocator); - } - classArr.PushBack(membersArr, context.allocator); - classes.PushBack(classArr, context.allocator); - } - context.doc.AddMember(key, classes, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b) { for (auto& i : context.doc[name.data()].GetArray()) @@ -238,37 +134,20 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::un b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); } -void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (const auto& s : b) - { - rapidjson::Value value(s.c_str(), context.allocator); - bArr.PushBack(value, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) { for (auto& i : context.doc[name.data()].GetArray()) b.emplace_back(i.GetString()); } -void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b) +// Note: This flattens the pair into [first, second.first, second.second] with no nested arrays. +void Serialize(SerializationContext& context, const std::pair>& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, context.allocator); - segV.PushBack(i.second.first, context.allocator); - segV.PushBack(i.second.second, context.allocator); - bArr.PushBack(segV, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.first); + Serialize(context, value.second.first); + Serialize(context, value.second.second); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b) @@ -283,20 +162,6 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } -void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, context.allocator); - segV.PushBack(i.second, context.allocator); - bArr.PushBack(segV, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b) { for (auto& i : context.doc[name.data()].GetArray()) @@ -308,17 +173,6 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } -void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - bArr.PushBack(i, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) { for (auto& i : context.doc[name.data()].GetArray()) @@ -327,22 +181,6 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } -// std::unordered_map -void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), context.allocator); - p.PushBack(_key, context.allocator); - p.PushBack(i.second, context.allocator); - bArr.PushBack(p, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) { for (auto& i : context.doc[name.data()].GetArray()) @@ -351,30 +189,6 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::un } } -// std::vector>>> -void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, context.allocator); - rapidjson::Value segArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value segPair(rapidjson::kArrayType); - segPair.PushBack(j.first, context.allocator); - rapidjson::Value segStr(j.second.c_str(), context.allocator); - segPair.PushBack(segStr, context.allocator); - segArr.PushBack(segPair, context.allocator); - } - segV.PushBack(segArr, context.allocator); - bArr.PushBack(segV, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b) { for (auto& i : context.doc[name.data()].GetArray()) @@ -389,19 +203,17 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } -void Serialize(SerializationContext& context, std::string_view name, const mach_header_64& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.magic, context.allocator); - bArr.PushBack(b.cputype, context.allocator); - bArr.PushBack(b.cpusubtype, context.allocator); - bArr.PushBack(b.filetype, context.allocator); - bArr.PushBack(b.ncmds, context.allocator); - bArr.PushBack(b.sizeofcmds, context.allocator); - bArr.PushBack(b.flags, context.allocator); - bArr.PushBack(b.reserved, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); +void Serialize(SerializationContext& context, const mach_header_64& value) { + context.writer.StartArray(); + Serialize(context, value.magic); + Serialize(context, value.cputype); + Serialize(context, value.cpusubtype); + Serialize(context, value.filetype); + Serialize(context, value.ncmds); + Serialize(context, value.sizeofcmds); + Serialize(context, value.flags); + Serialize(context, value.reserved); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, mach_header_64& b) @@ -417,17 +229,16 @@ void Deserialize(DeserializationContext& context, std::string_view name, mach_he b.reserved = bArr[7].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const symtab_command& b) +void Serialize(SerializationContext& context, const symtab_command& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.symoff, context.allocator); - bArr.PushBack(b.nsyms, context.allocator); - bArr.PushBack(b.stroff, context.allocator); - bArr.PushBack(b.strsize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.symoff); + Serialize(context, value.nsyms); + Serialize(context, value.stroff); + Serialize(context, value.strsize); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, symtab_command& b) @@ -441,31 +252,30 @@ void Deserialize(DeserializationContext& context, std::string_view name, symtab_ b.strsize = bArr[5].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const dysymtab_command& b) -{ - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.ilocalsym, context.allocator); - bArr.PushBack(b.nlocalsym, context.allocator); - bArr.PushBack(b.iextdefsym, context.allocator); - bArr.PushBack(b.nextdefsym, context.allocator); - bArr.PushBack(b.iundefsym, context.allocator); - bArr.PushBack(b.nundefsym, context.allocator); - bArr.PushBack(b.tocoff, context.allocator); - bArr.PushBack(b.ntoc, context.allocator); - bArr.PushBack(b.modtaboff, context.allocator); - bArr.PushBack(b.nmodtab, context.allocator); - bArr.PushBack(b.extrefsymoff, context.allocator); - bArr.PushBack(b.nextrefsyms, context.allocator); - bArr.PushBack(b.indirectsymoff, context.allocator); - bArr.PushBack(b.nindirectsyms, context.allocator); - bArr.PushBack(b.extreloff, context.allocator); - bArr.PushBack(b.nextrel, context.allocator); - bArr.PushBack(b.locreloff, context.allocator); - bArr.PushBack(b.nlocrel, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); +void Serialize(SerializationContext& context, const dysymtab_command& value) +{ + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.ilocalsym); + Serialize(context, value.nlocalsym); + Serialize(context, value.iextdefsym); + Serialize(context, value.nextdefsym); + Serialize(context, value.iundefsym); + Serialize(context, value.nundefsym); + Serialize(context, value.tocoff); + Serialize(context, value.ntoc); + Serialize(context, value.modtaboff); + Serialize(context, value.nmodtab); + Serialize(context, value.extrefsymoff); + Serialize(context, value.nextrefsyms); + Serialize(context, value.indirectsymoff); + Serialize(context, value.nindirectsyms); + Serialize(context, value.extreloff); + Serialize(context, value.nextrel); + Serialize(context, value.locreloff); + Serialize(context, value.nlocrel); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, dysymtab_command& b) @@ -493,23 +303,22 @@ void Deserialize(DeserializationContext& context, std::string_view name, dysymta b.nlocrel = bArr[19].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const dyld_info_command& b) +void Serialize(SerializationContext& context, const dyld_info_command& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.rebase_off, context.allocator); - bArr.PushBack(b.rebase_size, context.allocator); - bArr.PushBack(b.bind_off, context.allocator); - bArr.PushBack(b.bind_size, context.allocator); - bArr.PushBack(b.weak_bind_off, context.allocator); - bArr.PushBack(b.weak_bind_size, context.allocator); - bArr.PushBack(b.lazy_bind_off, context.allocator); - bArr.PushBack(b.lazy_bind_size, context.allocator); - bArr.PushBack(b.export_off, context.allocator); - bArr.PushBack(b.export_size, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.rebase_off); + Serialize(context, value.rebase_size); + Serialize(context, value.bind_off); + Serialize(context, value.bind_size); + Serialize(context, value.weak_bind_off); + Serialize(context, value.weak_bind_size); + Serialize(context, value.lazy_bind_off); + Serialize(context, value.lazy_bind_size); + Serialize(context, value.export_off); + Serialize(context, value.export_size); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, dyld_info_command& b) @@ -529,15 +338,14 @@ void Deserialize(DeserializationContext& context, std::string_view name, dyld_in b.export_size = bArr[11].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const routines_command_64& b) +void Serialize(SerializationContext& context, const routines_command_64& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.init_address, context.allocator); - bArr.PushBack(b.init_module, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.init_address); + Serialize(context, value.init_module); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, routines_command_64& b) @@ -549,15 +357,14 @@ void Deserialize(DeserializationContext& context, std::string_view name, routine b.init_module = bArr[3].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const function_starts_command& b) +void Serialize(SerializationContext& context, const function_starts_command& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.funcoff, context.allocator); - bArr.PushBack(b.funcsize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.funcoff); + Serialize(context, value.funcsize); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, function_starts_command& b) @@ -569,40 +376,26 @@ void Deserialize(DeserializationContext& context, std::string_view name, functio b.funcsize = bArr[3].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +void Serialize(SerializationContext& context, const section_64& value) { - rapidjson::Value key(name.data(), context.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(), context.allocator), context.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(), context.allocator), context.allocator); - sArr.PushBack(s.addr, context.allocator); - sArr.PushBack(s.size, context.allocator); - sArr.PushBack(s.offset, context.allocator); - sArr.PushBack(s.align, context.allocator); - sArr.PushBack(s.reloff, context.allocator); - sArr.PushBack(s.nreloc, context.allocator); - sArr.PushBack(s.flags, context.allocator); - sArr.PushBack(s.reserved1, context.allocator); - sArr.PushBack(s.reserved2, context.allocator); - sArr.PushBack(s.reserved3, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + + std::string_view sectname(value.sectname, 16); + std::string_view segname(value.segname, 16); + + Serialize(context, sectname.substr(0, sectname.find('\0'))); + Serialize(context, segname.substr(0, segname.find('\0'))); + Serialize(context, value.addr); + Serialize(context, value.size); + Serialize(context, value.offset); + Serialize(context, value.align); + Serialize(context, value.reloff); + Serialize(context, value.nreloc); + Serialize(context, value.flags); + Serialize(context, value.reserved1); + Serialize(context, value.reserved2); + Serialize(context, value.reserved3); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) @@ -628,19 +421,18 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve sec.reserved1 = s2[9].GetUint(); sec.reserved2 = s2[10].GetUint(); sec.reserved3 = s2[11].GetUint(); - b.push_back(sec); + b.push_back(std::move(sec)); } } -void Serialize(SerializationContext& context, std::string_view name, const linkedit_data_command& b) +void Serialize(SerializationContext& context, const linkedit_data_command& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.dataoff, context.allocator); - bArr.PushBack(b.datasize, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.dataoff); + Serialize(context, value.datasize); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, linkedit_data_command& b) @@ -652,25 +444,20 @@ void Deserialize(DeserializationContext& context, std::string_view name, linkedi b.datasize = bArr[3].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const segment_command_64& b) +void Serialize(SerializationContext& context, const segment_command_64& value) { - rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); - bArr.PushBack(b.vmaddr, context.allocator); - bArr.PushBack(b.vmsize, context.allocator); - bArr.PushBack(b.fileoff, context.allocator); - bArr.PushBack(b.filesize, context.allocator); - bArr.PushBack(b.maxprot, context.allocator); - bArr.PushBack(b.initprot, context.allocator); - bArr.PushBack(b.nsects, context.allocator); - bArr.PushBack(b.flags, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + std::string_view segname(value.segname, 16); + Serialize(context, segname.substr(0, segname.find('\0'))); + Serialize(context, value.vmaddr); + Serialize(context, value.vmsize); + Serialize(context, value.fileoff); + Serialize(context, value.filesize); + Serialize(context, value.maxprot); + Serialize(context, value.initprot); + Serialize(context, value.nsects); + Serialize(context, value.flags); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, segment_command_64& b) @@ -689,33 +476,6 @@ void Deserialize(DeserializationContext& context, std::string_view name, segment b.flags = bArr[8].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) -{ - rapidjson::Value key(name.data(), context.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(), context.allocator), context.allocator); - sArr.PushBack(s.vmaddr, context.allocator); - sArr.PushBack(s.vmsize, context.allocator); - sArr.PushBack(s.fileoff, context.allocator); - sArr.PushBack(s.filesize, context.allocator); - sArr.PushBack(s.maxprot, context.allocator); - sArr.PushBack(s.initprot, context.allocator); - sArr.PushBack(s.nsects, context.allocator); - sArr.PushBack(s.flags, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); -} - void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) { auto bArr = context.doc[name.data()].GetArray(); @@ -734,21 +494,20 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve sec.initprot = s2[6].GetUint(); sec.nsects = s2[7].GetUint(); sec.flags = s2[8].GetUint(); - b.push_back(sec); + b.push_back(std::move(sec)); } } -void Serialize(SerializationContext& context, std::string_view name, const build_version_command& b) +void Serialize(SerializationContext& context, const build_version_command& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - bArr.PushBack(b.cmd, context.allocator); - bArr.PushBack(b.cmdsize, context.allocator); - bArr.PushBack(b.platform, context.allocator); - bArr.PushBack(b.minos, context.allocator); - bArr.PushBack(b.sdk, context.allocator); - bArr.PushBack(b.ntools, context.allocator); - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.cmd); + Serialize(context, value.cmdsize); + Serialize(context, value.platform); + Serialize(context, value.minos); + Serialize(context, value.sdk); + Serialize(context, value.ntools); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, build_version_command& b) @@ -762,18 +521,12 @@ void Deserialize(DeserializationContext& context, std::string_view name, build_v b.ntools = bArr[5].GetUint(); } -void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +void Serialize(SerializationContext& context, const build_tool_version& value) { - rapidjson::Value key(name.data(), context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& s : b) - { - rapidjson::Value sArr(rapidjson::kArrayType); - sArr.PushBack(s.tool, context.allocator); - sArr.PushBack(s.version, context.allocator); - bArr.PushBack(sArr, context.allocator); - } - context.doc.AddMember(key, bArr, context.allocator); + context.writer.StartArray(); + Serialize(context, value.tool); + Serialize(context, value.version); + context.writer.EndArray(); } void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) @@ -789,5 +542,4 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve } } - } // namespace SharedCacheCore diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp index fa27353495..5a39f5f67b 100644 --- a/view/sharedcache/core/MetadataSerializable.hpp +++ b/view/sharedcache/core/MetadataSerializable.hpp @@ -58,12 +58,10 @@ using namespace BinaryNinja; struct DeserializationContext; struct SerializationContext { - rapidjson::Document doc; - rapidjson::Document::AllocatorType allocator; + rapidjson::StringBuffer buffer; + rapidjson::PrettyWriter writer; - SerializationContext() { - doc.SetObject(); - allocator = doc.GetAllocator(); + SerializationContext() : buffer(), writer(buffer) { } template @@ -91,17 +89,10 @@ class MetadataSerializable public: std::string AsString() const { - rapidjson::StringBuffer strbuf; - rapidjson::PrettyWriter writer(strbuf); - AsDocument().Accept(writer); - - return strbuf.GetString(); - } - - rapidjson::Document AsDocument() const { SerializationContext context; - AsDerived().Store(context); - return std::move(context.doc); + Store(context); + + return context.buffer.GetString(); } void LoadFromString(const std::string& s) @@ -118,7 +109,9 @@ class MetadataSerializable AsDerived().Load(context); } - Ref AsMetadata() { return new Metadata(AsString()); } + Ref AsMetadata() { + return new Metadata(AsString()); + } bool LoadFromMetadata(const Ref& meta) { @@ -128,80 +121,132 @@ class MetadataSerializable return true; } + void Store(SerializationContext& context) const { + context.writer.StartObject(); + AsDerived().Store(context); + context.writer.EndObject(); + } + private: const Derived& AsDerived() const { return static_cast(*this); } Derived& AsDerived() { return static_cast(*this); } }; -// These are not part of the FFI API, but are exported so that sharedcacheui can use them. -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, bool b); +// The functions below are not part of the FFI API, but are exported so they can be shared with sharedcacheui. + +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view str); + +template +inline void Serialize(SerializationContext& context, const MetadataSerializable& value) +{ + value.Store(context); +} + +template +inline void Serialize(SerializationContext& context, std::string_view name, const T& value) +{ + Serialize(context, name); + Serialize(context, value); +} + +template +void Serialize(SerializationContext& context, const std::pair& value) +{ + context.writer.StartArray(); + Serialize(context, value.first); + Serialize(context, value.second); + context.writer.EndArray(); +} + +template +void Serialize(SerializationContext& context, const std::map& value) +{ + context.writer.StartArray(); + for (auto& pair : value) + { + Serialize(context, pair); + } + context.writer.EndArray(); +} + +template +void Serialize(SerializationContext& context, const std::unordered_map& value) +{ + context.writer.StartArray(); + for (auto& pair : value) + { + Serialize(context, pair); + } + context.writer.EndArray(); +} + +template +void Serialize(SerializationContext& context, const std::vector& values) +{ + context.writer.StartArray(); + for (const auto& value : values) + { + Serialize(context, value); + } + context.writer.EndArray(); +} + +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, const char*); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, bool b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, bool& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint8_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, uint8_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint16_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, uint16_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint32_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, uint32_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, uint64_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, uint64_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int8_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, int8_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int16_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, int16_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int32_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, int32_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, int64_t b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, int64_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, std::string_view b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::string& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::map& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::map& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const mach_header_64& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const mach_header_64& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, mach_header_64& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const symtab_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const symtab_command& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, symtab_command& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const dysymtab_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const dysymtab_command& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, dysymtab_command& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const dyld_info_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const dyld_info_command& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, dyld_info_command& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const routines_command_64& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const routines_command_64& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, routines_command_64& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const function_starts_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const function_starts_command& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, function_starts_command& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const section_64& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const linkedit_data_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const linkedit_data_command& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, linkedit_data_command& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const segment_command_64& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const segment_command_64& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, segment_command_64& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const std::vector& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const build_version_command& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const build_version_command& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, build_version_command& b); -SHAREDCACHE_FFI_API void Serialize(SerializationContext&, std::string_view name, const std::vector& b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext&, const build_tool_version& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector& b); - } // namespace SharedCacheCore #endif // SHAREDCACHE_METADATASERIALIZABLE_HPP diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 97cc796863..652365985a 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -3325,79 +3325,50 @@ namespace SharedCacheCore { void SharedCache::Store(SerializationContext& context) const { - context.doc.AddMember("metadataVersion", METADATA_VERSION, context.allocator); + Serialize(context, "metadataVersion", METADATA_VERSION); MSS(m_viewState); MSS_CAST(m_cacheFormat, uint8_t); MSS(m_imageStarts); MSS(m_baseFilePath); - rapidjson::Value headers(rapidjson::kArrayType); + + Serialize(context, "headers"); + context.writer.StartArray(); for (auto& [k, v] : m_headers) { - headers.PushBack(v.AsDocument(), context.allocator); + context.writer.StartObject(); + v.Store(context); + context.writer.EndObject(); } - context.doc.AddMember("headers", headers, context.allocator); - // std::vector>>>> - // m_exportInfos std::vector>>>> exportInfos; - rapidjson::Document exportInfos(rapidjson::kArrayType); + context.writer.EndArray(); + Serialize(context, "exportInfos"); + context.writer.StartArray(); for (const auto& pair1 : m_exportInfos) { - rapidjson::Value subObj(rapidjson::kObjectType); - rapidjson::Value subArr(rapidjson::kArrayType); + context.writer.StartObject(); + Serialize(context, "key", pair1.first); + Serialize(context, "value"); + context.writer.StartArray(); for (const auto& pair2 : pair1.second) { - rapidjson::Value subSubObj(rapidjson::kObjectType); - subSubObj.AddMember("key", pair2.first, context.allocator); - subSubObj.AddMember("val1", pair2.second.first, context.allocator); - subSubObj.AddMember("val2", pair2.second.second, context.allocator); - subArr.PushBack(subSubObj, context.allocator); + context.writer.StartObject(); + Serialize(context, "key", pair2.first); + Serialize(context, "val1", pair2.second.first); + Serialize(context, "val2", pair2.second.second); + context.writer.EndObject(); } - - subObj.AddMember("key", pair1.first, context.allocator); - subObj.AddMember("value", subArr, context.allocator); - - exportInfos.PushBack(subObj, context.allocator); + context.writer.EndArray(); + context.writer.EndObject(); } - context.doc.AddMember("exportInfos", exportInfos, context.allocator); + context.writer.EndArray(); - rapidjson::Value backingCaches(rapidjson::kArrayType); - for (auto& bc : m_backingCaches) - { - backingCaches.PushBack(bc.AsDocument(), context.allocator); - } - context.doc.AddMember("backingCaches", backingCaches, context.allocator); - rapidjson::Value stubIslands(rapidjson::kArrayType); - for (auto& si : m_stubIslandRegions) - { - stubIslands.PushBack(si.AsDocument(), context.allocator); - } - rapidjson::Value images(rapidjson::kArrayType); - for (auto& img : m_images) - { - images.PushBack(img.AsDocument(), context.allocator); - } - context.doc.AddMember("images", images, context.allocator); - rapidjson::Value regionsMappedIntoMemory(rapidjson::kArrayType); - for (auto& r : m_regionsMappedIntoMemory) - { - regionsMappedIntoMemory.PushBack(r.AsDocument(), context.allocator); - } - context.doc.AddMember("regionsMappedIntoMemory", regionsMappedIntoMemory, context.allocator); - context.doc.AddMember("stubIslands", stubIslands, context.allocator); - rapidjson::Value dyldDataSections(rapidjson::kArrayType); - for (auto& si : m_dyldDataRegions) - { - dyldDataSections.PushBack(si.AsDocument(), context.allocator); - } - context.doc.AddMember("dyldDataSections", dyldDataSections, context.allocator); - rapidjson::Value nonImageRegions(rapidjson::kArrayType); - for (auto& si : m_nonImageRegions) - { - nonImageRegions.PushBack(si.AsDocument(), context.allocator); - } - context.doc.AddMember("nonImageRegions", nonImageRegions, context.allocator); + Serialize(context, "backingCaches", m_backingCaches); + Serialize(context, "stubIslands", m_stubIslandRegions); + Serialize(context, "images", m_images); + Serialize(context, "regionsMappedIntoMemory", m_regionsMappedIntoMemory); + Serialize(context, "dyldDataSections", m_dyldDataRegions); + Serialize(context, "nonImageRegions", m_nonImageRegions); } void SharedCache::Load(DeserializationContext& context) diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h index 0c871c3e21..4444f8473a 100644 --- a/view/sharedcache/core/SharedCache.h +++ b/view/sharedcache/core/SharedCache.h @@ -67,13 +67,13 @@ namespace SharedCacheCore { { MSS(installName); MSS(headerLocation); - rapidjson::Value key("regions", context.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); + Serialize(context, "regions"); + context.writer.StartArray(); for (auto& region : regions) { - bArr.PushBack(rapidjson::Value(region.AsString().c_str(), context.allocator), context.allocator); + Serialize(context, region.AsString()); } - context.doc.AddMember(key, bArr, context.allocator); + context.writer.EndArray(); } void Load(DeserializationContext& context) From 9060301b2269fbebcea1696248b705a4eafb4563 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Wed, 20 Nov 2024 18:00:19 -0800 Subject: [PATCH 6/7] Serialization fixes after switch to SAX-style JSON writing API 1. Continue to serialize the `cputype` / `cpusubtype` fields of `mach_header_64` as unsigned, despite them being signed. This preserves compatibility with the existing metadata version. 2. Add the `Serialize` declaration for the special `std::pair>` overload to the header. This ensures it will be favored over the generic `std::pair` template function and preserves the serialization used with the existing metadata version. --- view/sharedcache/core/MetadataSerializable.cpp | 7 +++++-- view/sharedcache/core/MetadataSerializable.hpp | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/view/sharedcache/core/MetadataSerializable.cpp b/view/sharedcache/core/MetadataSerializable.cpp index 0fa712b17a..ad8959f262 100644 --- a/view/sharedcache/core/MetadataSerializable.cpp +++ b/view/sharedcache/core/MetadataSerializable.cpp @@ -206,8 +206,11 @@ void Deserialize(DeserializationContext& context, std::string_view name, std::ve void Serialize(SerializationContext& context, const mach_header_64& value) { context.writer.StartArray(); Serialize(context, value.magic); - Serialize(context, value.cputype); - Serialize(context, value.cpusubtype); + // cputype and cpusubtype are signed but were serialized as unsigned in + // v4.2 (metadata version 2). We continue serializing them as unsigned + // so we don't need to bump the metadata version. + Serialize(context, static_cast(value.cputype)); + Serialize(context, static_cast(value.cpusubtype)); Serialize(context, value.filetype); Serialize(context, value.ncmds); Serialize(context, value.sizeofcmds); diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp index 5a39f5f67b..7b44ccbdbf 100644 --- a/view/sharedcache/core/MetadataSerializable.hpp +++ b/view/sharedcache/core/MetadataSerializable.hpp @@ -211,6 +211,7 @@ SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::strin SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, int64_t b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b); SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, std::string_view b); +SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, const std::pair>& value); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::string& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::map& b); SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b); From 268b5c66e92b90c00747d50a794f628e578864cb Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Wed, 13 Nov 2024 18:40:37 -0800 Subject: [PATCH 7/7] [SharedCache] Use basic copy-on-write for viewStateCache Copying the state from the cache into a new `SharedCache` object is done with a global lock held and is so expensive that it results in much of the shared cache analysis running on a single thread, with others blocked waiting to acquire the lock. The cache now holds a `std::shared_ptr` to the state. New `SharedCache` objects take a reference to the cached state and only create their own copy of it the first time they perform an operation that would mutate it. The cached copy is never mutated, only replaced, so there is no danger of modifying the state out from under a `SharedCache` object. Since the copy happens at first mutation, it is performed without any global locks held. This avoids blocking other threads. This cuts the initial load time of a macOS shared cache from 3 minutes to 70 seconds, and cuts the time taken to load and analyze AppKit from multiple hours to around 14 minutes. --- view/sharedcache/core/SharedCache.cpp | 450 ++++++++++++++------------ view/sharedcache/core/SharedCache.h | 54 ++-- 2 files changed, 274 insertions(+), 230 deletions(-) diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 652365985a..5f0a304c9d 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -53,30 +53,33 @@ int count_trailing_zeros(uint64_t value) { } #endif -struct ViewStateCacheStore { - SharedCache::SharedCacheFormat m_cacheFormat; +struct SharedCache::State +{ + std::unordered_map>>> + exportInfos; + std::unordered_map>>> + symbolInfos; - DSCViewState m_viewState; + std::unordered_map imageStarts; + std::unordered_map headers; - std::unordered_map m_imageStarts; - std::unordered_map m_headers; + std::vector images; - std::vector m_images; - std::vector m_regionsMappedIntoMemory; + std::vector regionsMappedIntoMemory; - std::vector m_backingCaches; - std::vector m_stubIslandRegions; // TODO honestly both of these should be refactored into nonImageRegions. :p - std::vector m_dyldDataRegions; - std::vector m_nonImageRegions; + std::vector backingCaches; - std::string m_baseFilePath; + std::vector stubIslandRegions; // TODO honestly both of these should be refactored into nonImageRegions. :p + std::vector dyldDataRegions; + std::vector nonImageRegions; - std::unordered_map>>> m_exportInfos; - std::unordered_map>>> m_symbolInfos; + std::string baseFilePath; + SharedCacheFormat cacheFormat; + DSCViewState viewState = DSCViewStateUnloaded; }; static std::recursive_mutex viewStateMutex; -static std::unordered_map viewStateCache; +static std::unordered_map> viewStateCache; std::mutex progressMutex; std::unordered_map progressMap; @@ -221,7 +224,9 @@ void SharedCache::PerformInitialLoad() progressMap[m_dscView->GetFile()->GetSessionId()] = LoadProgressLoadingCaches; progressMutex.unlock(); - m_baseFilePath = path; + WillMutateState(); + + MutableState().baseFilePath = path; DataBuffer sig = baseFile->ReadBuffer(0, 4); if (sig.GetLength() != 4) @@ -230,14 +235,14 @@ void SharedCache::PerformInitialLoad() if (strncmp(magic, "dyld", 4) != 0) abort(); - m_cacheFormat = RegularCacheFormat; + MutableState().cacheFormat = RegularCacheFormat; dyld_cache_header primaryCacheHeader {}; size_t header_size = baseFile->ReadUInt32(16); baseFile->Read(&primaryCacheHeader, 0, std::min(header_size, sizeof(dyld_cache_header))); if (primaryCacheHeader.imagesCountOld != 0) - m_cacheFormat = RegularCacheFormat; + MutableState().cacheFormat = RegularCacheFormat; size_t subCacheOff = offsetof(struct dyld_cache_header, subCacheArrayOffset); size_t headerEnd = primaryCacheHeader.mappingOffset; @@ -246,15 +251,15 @@ void SharedCache::PerformInitialLoad() if (primaryCacheHeader.cacheType != 2) { if (std::filesystem::exists(ResolveFilePath(m_dscView, baseFile->Path() + ".01"))) - m_cacheFormat = LargeCacheFormat; + MutableState().cacheFormat = LargeCacheFormat; else - m_cacheFormat = SplitCacheFormat; + MutableState().cacheFormat = SplitCacheFormat; } else - m_cacheFormat = iOS16CacheFormat; + MutableState().cacheFormat = iOS16CacheFormat; } - switch (m_cacheFormat) + switch (State().cacheFormat) { case RegularCacheFormat: { @@ -272,7 +277,7 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.second.second = mapping.size; cache.mappings.push_back(mapRawToAddrAndSize); } - m_backingCaches.push_back(cache); + MutableState().backingCaches.push_back(std::move(cache)); dyld_cache_image_info img {}; @@ -280,7 +285,7 @@ void SharedCache::PerformInitialLoad() { baseFile->Read(&img, primaryCacheHeader.imagesOffsetOld + (i * sizeof(img)), sizeof(img)); auto iname = baseFile->ReadNullTermString(img.pathFileOffset); - m_imageStarts[iname] = img.address; + MutableState().imageStarts[iname] = img.address; } m_logger->LogInfo("Found %d images in the shared cache", primaryCacheHeader.imagesCountOld); @@ -312,7 +317,7 @@ void SharedCache::PerformInitialLoad() std::string segNameStr = std::string(segName); stubIslandRegion.prettyName = "dyld_shared_cache_branch_islands_" + std::to_string(i) + "::" + segNameStr; stubIslandRegion.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable); - m_stubIslandRegions.push_back(stubIslandRegion); + MutableState().stubIslandRegions.push_back(std::move(stubIslandRegion)); } } } @@ -338,9 +343,9 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = mapping.fileOffset; mapRawToAddrAndSize.second.first = mapping.address; mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(mapRawToAddrAndSize); + cache.mappings.push_back(std::move(mapRawToAddrAndSize)); } - m_backingCaches.push_back(cache); + MutableState().backingCaches.push_back(std::move(cache)); dyld_cache_image_info img {}; @@ -348,7 +353,7 @@ void SharedCache::PerformInitialLoad() { baseFile->Read(&img, primaryCacheHeader.imagesOffset + (i * sizeof(img)), sizeof(img)); auto iname = baseFile->ReadNullTermString(img.pathFileOffset); - m_imageStarts[iname] = img.address; + MutableState().imageStarts[iname] = img.address; } if (primaryCacheHeader.branchPoolsCount) @@ -356,7 +361,8 @@ void SharedCache::PerformInitialLoad() std::vector pool {}; for (size_t i = 0; i < primaryCacheHeader.branchPoolsCount; i++) { - m_imageStarts["dyld_shared_cache_branch_islands_" + std::to_string(i)] = baseFile->ReadULong(primaryCacheHeader.branchPoolsOffset + (i * m_dscView->GetAddressSize())); + MutableState().imageStarts["dyld_shared_cache_branch_islands_" + std::to_string(i)] = + baseFile->ReadULong(primaryCacheHeader.branchPoolsOffset + (i * m_dscView->GetAddressSize())); } } std::string mainFileName = base_name(path); @@ -413,7 +419,7 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = subCacheMapping.fileOffset; mapRawToAddrAndSize.second.first = subCacheMapping.address; mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(mapRawToAddrAndSize); + subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); } if (subCacheHeader.mappingCount == 1 && subCacheHeader.imagesCountOld == 0 && subCacheHeader.imagesCount == 0 @@ -427,10 +433,10 @@ void SharedCache::PerformInitialLoad() stubIslandRegion.size = size; stubIslandRegion.prettyName = subCacheFilename + "::_stubs"; stubIslandRegion.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable); - m_stubIslandRegions.push_back(stubIslandRegion); + MutableState().stubIslandRegions.push_back(std::move(stubIslandRegion)); } - m_backingCaches.push_back(subCache); + MutableState().backingCaches.push_back(std::move(subCache)); } break; } @@ -449,9 +455,9 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = mapping.fileOffset; mapRawToAddrAndSize.second.first = mapping.address; mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(mapRawToAddrAndSize); + cache.mappings.push_back(std::move(mapRawToAddrAndSize)); } - m_backingCaches.push_back(cache); + MutableState().backingCaches.push_back(std::move(cache)); dyld_cache_image_info img {}; @@ -459,7 +465,7 @@ void SharedCache::PerformInitialLoad() { baseFile->Read(&img, primaryCacheHeader.imagesOffset + (i * sizeof(img)), sizeof(img)); auto iname = baseFile->ReadNullTermString(img.pathFileOffset); - m_imageStarts[iname] = img.address; + MutableState().imageStarts[iname] = img.address; } if (primaryCacheHeader.branchPoolsCount) @@ -467,7 +473,8 @@ void SharedCache::PerformInitialLoad() std::vector pool {}; for (size_t i = 0; i < primaryCacheHeader.branchPoolsCount; i++) { - m_imageStarts["dyld_shared_cache_branch_islands_" + std::to_string(i)] = baseFile->ReadULong(primaryCacheHeader.branchPoolsOffset + (i * m_dscView->GetAddressSize())); + MutableState().imageStarts["dyld_shared_cache_branch_islands_" + std::to_string(i)] = + baseFile->ReadULong(primaryCacheHeader.branchPoolsOffset + (i * m_dscView->GetAddressSize())); } } @@ -508,10 +515,10 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = subCacheMapping.fileOffset; mapRawToAddrAndSize.second.first = subCacheMapping.address; mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(mapRawToAddrAndSize); + subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); } - m_backingCaches.push_back(subCache); + MutableState().backingCaches.push_back(std::move(subCache)); if (subCacheHeader.mappingCount == 1 && subCacheHeader.imagesCountOld == 0 && subCacheHeader.imagesCount == 0 && subCacheHeader.imagesTextOffset == 0) @@ -524,7 +531,7 @@ void SharedCache::PerformInitialLoad() stubIslandRegion.size = size; stubIslandRegion.prettyName = subCacheFilename + "::_stubs"; stubIslandRegion.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable); - m_stubIslandRegions.push_back(stubIslandRegion); + MutableState().stubIslandRegions.push_back(std::move(stubIslandRegion)); } } @@ -554,10 +561,10 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = subCacheMapping.fileOffset; mapRawToAddrAndSize.second.first = subCacheMapping.address; mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(mapRawToAddrAndSize); + subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); } - m_backingCaches.push_back(subCache); + MutableState().backingCaches.push_back(std::move(subCache)); break; } case iOS16CacheFormat: @@ -575,10 +582,10 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = mapping.fileOffset; mapRawToAddrAndSize.second.first = mapping.address; mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(mapRawToAddrAndSize); + cache.mappings.push_back(std::move(mapRawToAddrAndSize)); } - m_backingCaches.push_back(cache); + MutableState().backingCaches.push_back(std::move(cache)); dyld_cache_image_info img {}; @@ -586,7 +593,7 @@ void SharedCache::PerformInitialLoad() { baseFile->Read(&img, primaryCacheHeader.imagesOffset + (i * sizeof(img)), sizeof(img)); auto iname = baseFile->ReadNullTermString(img.pathFileOffset); - m_imageStarts[iname] = img.address; + MutableState().imageStarts[iname] = img.address; } if (primaryCacheHeader.branchPoolsCount) @@ -594,7 +601,8 @@ void SharedCache::PerformInitialLoad() std::vector pool {}; for (size_t i = 0; i < primaryCacheHeader.branchPoolsCount; i++) { - m_imageStarts["dyld_shared_cache_branch_islands_" + std::to_string(i)] = baseFile->ReadULong(primaryCacheHeader.branchPoolsOffset + (i * m_dscView->GetAddressSize())); + MutableState().imageStarts["dyld_shared_cache_branch_islands_" + std::to_string(i)] = + baseFile->ReadULong(primaryCacheHeader.branchPoolsOffset + (i * m_dscView->GetAddressSize())); } } @@ -657,7 +665,7 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = subCacheMapping.fileOffset; mapRawToAddrAndSize.second.first = subCacheMapping.address; mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(mapRawToAddrAndSize); + subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); if (subCachePath.find(".dylddata") != std::string::npos) { @@ -669,11 +677,11 @@ void SharedCache::PerformInitialLoad() dyldDataRegion.size = size; dyldDataRegion.prettyName = subCacheFilename + "::_data" + std::to_string(j); dyldDataRegion.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable); - m_dyldDataRegions.push_back(dyldDataRegion); + MutableState().dyldDataRegions.push_back(std::move(dyldDataRegion)); } } - m_backingCaches.push_back(subCache); + MutableState().backingCaches.push_back(std::move(subCache)); if (subCacheHeader.mappingCount == 1 && subCacheHeader.imagesCountOld == 0 && subCacheHeader.imagesCount == 0 && subCacheHeader.imagesTextOffset == 0) @@ -686,7 +694,7 @@ void SharedCache::PerformInitialLoad() stubIslandRegion.size = size; stubIslandRegion.prettyName = subCacheFilename + "::_stubs"; stubIslandRegion.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable); - m_stubIslandRegions.push_back(stubIslandRegion); + MutableState().stubIslandRegions.push_back(std::move(stubIslandRegion)); } } @@ -718,10 +726,10 @@ void SharedCache::PerformInitialLoad() mapRawToAddrAndSize.first = subCacheMapping.fileOffset; mapRawToAddrAndSize.second.first = subCacheMapping.address; mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(mapRawToAddrAndSize); + subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); } - m_backingCaches.push_back(subCache); + MutableState().backingCaches.push_back(std::move(subCache)); } catch (...) {} @@ -741,7 +749,7 @@ void SharedCache::PerformInitialLoad() m_logger->LogError("Failed to map VM pages for Shared Cache on initial load, this is fatal."); return; } - for (const auto &start : m_imageStarts) + for (const auto& start : State().imageStarts) { try { auto imageHeader = SharedCache::LoadHeaderForAddress(vm, start.second, start.first); @@ -752,7 +760,7 @@ void SharedCache::PerformInitialLoad() auto mapping = vm->MappingAtAddress(imageHeader->linkeditSegment.vmaddr); imageHeader->exportTriePath = mapping.first.filePath; } - m_headers[start.second] = imageHeader.value(); + MutableState().headers[start.second] = imageHeader.value(); CacheImage image; image.installName = start.first; image.headerLocation = start.second; @@ -781,14 +789,14 @@ void SharedCache::PerformInitialLoad() // if we're positive we have an entry point for some reason, force the segment // executable. this helps with kernel images. - for (auto &entryPoint: imageHeader->m_entryPoints) + for (auto &entryPoint : imageHeader->m_entryPoints) if (segment.vmaddr <= entryPoint && (entryPoint < (segment.vmaddr + segment.filesize))) flags |= SegmentExecutable; sectionRegion.flags = (BNSegmentFlag)flags; image.regions.push_back(sectionRegion); } - m_images.push_back(image); + MutableState().images.push_back(image); } else { @@ -801,9 +809,9 @@ void SharedCache::PerformInitialLoad() } } - m_logger->LogInfo("Loaded %d Mach-O headers", m_headers.size()); + m_logger->LogInfo("Loaded %d Mach-O headers", State().headers.size()); - for (const auto& cache : m_backingCaches) + for (const auto& cache : State().backingCaches) { size_t i = 0; for (const auto& mapping : cache.mappings) @@ -814,15 +822,15 @@ void SharedCache::PerformInitialLoad() region.prettyName = base_name(cache.path) + "::" + std::to_string(i); // FIXME flags!!! BackingCache.mapping needs refactored to store this information! region.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable); - m_nonImageRegions.push_back(region); + MutableState().nonImageRegions.push_back(std::move(region)); i++; } } // Iterate through each Mach-O header - if (!m_dyldDataRegions.empty()) + if (!State().dyldDataRegions.empty()) { - for (const auto& [headerKey, header] : m_headers) + for (const auto& [headerKey, header] : State().headers) { // Iterate through each segment of the header for (const auto& segment : header.segments) @@ -831,7 +839,7 @@ void SharedCache::PerformInitialLoad() uint64_t segmentEnd = segmentStart + segment.vmsize; // Iterate through each region in m_dyldDataRegions - for (auto it = m_dyldDataRegions.begin(); it != m_dyldDataRegions.end();) + for (auto it = State().dyldDataRegions.begin(); it != State().dyldDataRegions.end();) { uint64_t regionStart = it->start; uint64_t regionSize = it->size; @@ -864,12 +872,12 @@ void SharedCache::PerformInitialLoad() } // Erase the original region - it = m_dyldDataRegions.erase(it); + it = MutableState().dyldDataRegions.erase(it); // Insert the new regions (if any) for (const auto& newRegion : newRegions) { - it = m_dyldDataRegions.insert(it, newRegion); + it = MutableState().dyldDataRegions.insert(it, newRegion); ++it; // Move iterator to the next position } } @@ -883,9 +891,9 @@ void SharedCache::PerformInitialLoad() } // Iterate through each Mach-O header - if (!m_nonImageRegions.empty()) + if (!State().nonImageRegions.empty()) { - for (const auto& [headerKey, header] : m_headers) + for (const auto& [headerKey, header] : State().headers) { // Iterate through each segment of the header for (const auto& segment : header.segments) @@ -894,7 +902,7 @@ void SharedCache::PerformInitialLoad() uint64_t segmentEnd = segmentStart + segment.vmsize; // Iterate through each region in m_dyldDataRegions - for (auto it = m_nonImageRegions.begin(); it != m_nonImageRegions.end();) + for (auto it = State().nonImageRegions.begin(); it != State().nonImageRegions.end();) { uint64_t regionStart = it->start; uint64_t regionSize = it->size; @@ -927,12 +935,12 @@ void SharedCache::PerformInitialLoad() } // Erase the original region - it = m_nonImageRegions.erase(it); + it = MutableState().nonImageRegions.erase(it); // Insert the new regions (if any) for (const auto& newRegion : newRegions) { - it = m_nonImageRegions.insert(it, newRegion); + it = MutableState().nonImageRegions.insert(it, newRegion); ++it; // Move iterator to the next position } } @@ -959,7 +967,7 @@ std::shared_ptr SharedCache::GetVMMap(bool mapPages) if (mapPages) { - for (const auto& cache : m_backingCaches) + for (const auto& cache : State().backingCaches) { for (const auto& mapping : cache.mappings) { @@ -980,22 +988,10 @@ void SharedCache::DeserializeFromRawView() if (m_dscView->QueryMetadata(SharedCacheMetadataTag)) { std::unique_lock viewStateCacheLock(viewStateMutex); - if (viewStateCache.find(m_dscView->GetFile()->GetSessionId()) != viewStateCache.end()) - { - auto c = viewStateCache[m_dscView->GetFile()->GetSessionId()]; - m_imageStarts = c.m_imageStarts; - m_cacheFormat = c.m_cacheFormat; - m_backingCaches = c.m_backingCaches; - m_viewState = c.m_viewState; - m_headers = c.m_headers; - m_images = c.m_images; - m_regionsMappedIntoMemory = c.m_regionsMappedIntoMemory; - m_stubIslandRegions = c.m_stubIslandRegions; - m_dyldDataRegions = c.m_dyldDataRegions; - m_nonImageRegions = c.m_nonImageRegions; - m_baseFilePath = c.m_baseFilePath; - m_exportInfos = c.m_exportInfos; - m_symbolInfos = c.m_symbolInfos; + if (auto it = viewStateCache.find(m_dscView->GetFile()->GetSessionId()); it != viewStateCache.end()) + { + m_state = it->second; + m_stateIsShared = true; m_metadataValid = true; } else @@ -1005,14 +1001,16 @@ void SharedCache::DeserializeFromRawView() if (!m_metadataValid) { m_logger->LogError("Failed to deserialize Shared Cache metadata"); - m_viewState = DSCViewStateUnloaded; + WillMutateState(); + MutableState().viewState = DSCViewStateUnloaded; } } else { m_metadataValid = true; - m_viewState = DSCViewStateUnloaded; - m_images.clear(); // fixme ?? + WillMutateState(); + MutableState().viewState = DSCViewStateUnloaded; + MutableState().images.clear(); // fixme ?? } } @@ -1029,12 +1027,14 @@ void SharedCache::ParseAndApplySlideInfoForFile(std::shared_ptrSlideInfoWasApplied()) return; + + WillMutateState(); std::vector> rewrites; dyld_cache_header baseHeader; file->Read(&baseHeader, 0, sizeof(dyld_cache_header)); uint64_t base = UINT64_MAX; - for (const auto& backingCache : m_backingCaches) + for (const auto& backingCache : State().backingCaches) { for (const auto& mapping : backingCache.mappings) { @@ -1365,42 +1365,39 @@ SharedCache::SharedCache(BinaryNinja::Ref dscView) : m_ DeserializeFromRawView(); if (!m_metadataValid) return; - if (m_viewState == DSCViewStateUnloaded) + if (State().viewState == DSCViewStateUnloaded) { - if (m_viewState == DSCViewStateUnloaded) + std::unique_lock lock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); + try { + PerformInitialLoad(); + } + catch (...) { - std::unique_lock lock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); - try { - PerformInitialLoad(); - } - catch (...) - { - m_logger->LogError("Failed to perform initial load of Shared Cache"); - } + m_logger->LogError("Failed to perform initial load of Shared Cache"); + } - auto settings = m_dscView->GetLoadSettings(VIEW_NAME); - bool autoLoadLibsystem = true; - if (settings && settings->Contains("loader.dsc.autoLoadLibSystem")) - { - autoLoadLibsystem = settings->Get("loader.dsc.autoLoadLibSystem", m_dscView); - } - if (autoLoadLibsystem) + auto settings = m_dscView->GetLoadSettings(VIEW_NAME); + bool autoLoadLibsystem = true; + if (settings && settings->Contains("loader.dsc.autoLoadLibSystem")) + { + autoLoadLibsystem = settings->Get("loader.dsc.autoLoadLibSystem", m_dscView); + } + if (autoLoadLibsystem) + { + for (const auto& [_, header] : State().headers) { - for (const auto& [_, header] : m_headers) + if (header.installName.find("libsystem_c.dylib") != std::string::npos) { - if (header.installName.find("libsystem_c.dylib") != std::string::npos) - { - lock.unlock(); - m_logger->LogInfo("Loading core libsystem_c.dylib library"); - LoadImageWithInstallName(header.installName); - lock.lock(); - break; - } + lock.unlock(); + m_logger->LogInfo("Loading core libsystem_c.dylib library"); + LoadImageWithInstallName(header.installName); + lock.lock(); + break; } } - m_viewState = DSCViewStateLoaded; - SaveToDSCView(); } + MutableState().viewState = DSCViewStateLoaded; + SaveToDSCView(); } else { @@ -1430,7 +1427,7 @@ SharedCache* SharedCache::GetFromDSCView(BinaryNinja::Ref SharedCache::GetImageStart(std::string installName) { - for (const auto& [name, start] : m_imageStarts) + for (const auto& [name, start] : State().imageStarts) { if (name == installName) { @@ -1445,7 +1442,7 @@ std::optional SharedCache::HeaderForAddress(uint64_t add // We _could_ mark each page with the image start? :grimacing emoji: // But that'd require mapping pages :grimacing emoji: :grimacing emoji: // There's not really any other hacks that could make this faster, that I can think of... - for (const auto& [start, header] : m_headers) + for (const auto& [start, header] : State().headers) { for (const auto& segment : header.segments) { @@ -1460,21 +1457,21 @@ std::optional SharedCache::HeaderForAddress(uint64_t add std::string SharedCache::NameForAddress(uint64_t address) { - for (const auto& stubIsland : m_stubIslandRegions) + for (const auto& stubIsland : State().stubIslandRegions) { if (stubIsland.start <= address && stubIsland.start + stubIsland.size > address) { return stubIsland.prettyName; } } - for (const auto& dyldData : m_dyldDataRegions) + for (const auto& dyldData : State().dyldDataRegions) { if (dyldData.start <= address && dyldData.start + dyldData.size > address) { return dyldData.prettyName; } } - for (const auto& nonImageRegion : m_nonImageRegions) + for (const auto& nonImageRegion : State().nonImageRegions) { if (nonImageRegion.start <= address && nonImageRegion.start + nonImageRegion.size > address) { @@ -1508,7 +1505,7 @@ std::string SharedCache::ImageNameForAddress(uint64_t address) bool SharedCache::LoadImageContainingAddress(uint64_t address) { - for (const auto& [start, header] : m_headers) + for (const auto& [start, header] : State().headers) { for (const auto& segment : header.segments) { @@ -1526,6 +1523,8 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) { std::unique_lock lock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); DeserializeFromRawView(); + WillMutateState(); + auto vm = GetVMMap(); if (!vm) { @@ -1537,13 +1536,13 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) CacheImage* targetImage = nullptr; MemoryRegion* targetSegment = nullptr; - for (auto& image : m_images) + for (auto& image : MutableState().images) { for (auto& region : image.regions) { if (region.start <= address && region.start + region.size > address) { - targetHeader = m_headers[image.headerLocation]; + targetHeader = MutableState().headers[image.headerLocation]; targetImage = ℑ targetSegment = ®ion; break; @@ -1554,7 +1553,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) } if (!targetSegment) { - for (auto& stubIsland : m_stubIslandRegions) + for (auto& stubIsland : MutableState().stubIslandRegions) { if (stubIsland.start <= address && stubIsland.start + stubIsland.size > address) { @@ -1583,7 +1582,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) stubIsland.rawViewOffsetIfLoaded = rawViewEnd; - m_regionsMappedIntoMemory.push_back(stubIsland); + MutableState().regionsMappedIntoMemory.push_back(stubIsland); SaveToDSCView(); @@ -1594,7 +1593,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) } } - for (auto& dyldData : m_dyldDataRegions) + for (auto& dyldData : MutableState().dyldDataRegions) { if (dyldData.start <= address && dyldData.start + dyldData.size > address) { @@ -1622,7 +1621,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) dyldData.loaded = true; dyldData.rawViewOffsetIfLoaded = rawViewEnd; - m_regionsMappedIntoMemory.push_back(dyldData); + MutableState().regionsMappedIntoMemory.push_back(dyldData); SaveToDSCView(); @@ -1633,7 +1632,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) } } - for (auto& region : m_nonImageRegions) + for (auto& region : MutableState().nonImageRegions) { if (region.start <= address && region.start + region.size > address) { @@ -1660,7 +1659,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) region.loaded = true; region.rawViewOffsetIfLoaded = rawViewEnd; - m_regionsMappedIntoMemory.push_back(region); + MutableState().regionsMappedIntoMemory.push_back(region); SaveToDSCView(); @@ -1696,7 +1695,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) targetSegment->loaded = true; targetSegment->rawViewOffsetIfLoaded = rawViewEnd; - m_regionsMappedIntoMemory.push_back(*targetSegment); + MutableState().regionsMappedIntoMemory.push_back(*targetSegment); SaveToDSCView(); @@ -1720,12 +1719,14 @@ bool SharedCache::LoadImageWithInstallName(std::string installName) std::unique_lock lock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); DeserializeFromRawView(); + WillMutateState(); + m_logger->LogInfo("Loading image %s", installName.c_str()); auto vm = GetVMMap(); CacheImage* targetImage = nullptr; - for (auto& cacheImage : m_images) + for (auto& cacheImage : MutableState().images) { if (cacheImage.installName == installName) { @@ -1733,11 +1734,15 @@ bool SharedCache::LoadImageWithInstallName(std::string installName) break; } } - - auto header = m_headers[targetImage->headerLocation]; + auto it = State().headers.find(targetImage->headerLocation); + if (it == State().headers.end()) + { + return false; + } + const auto& header = it->second; auto id = m_dscView->BeginUndoActions(); - m_viewState = DSCViewStateLoadedWithImages; + MutableState().viewState = DSCViewStateLoadedWithImages; auto reader = VMReader(vm); reader.Seek(targetImage->headerLocation); @@ -1770,7 +1775,7 @@ bool SharedCache::LoadImageWithInstallName(std::string installName) region.loaded = true; region.rawViewOffsetIfLoaded = rawViewEnd; - m_regionsMappedIntoMemory.push_back(region); + MutableState().regionsMappedIntoMemory.push_back(region); m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, region.size, rawViewEnd, region.size, region.flags); m_dscView->AddUserSegment(region.start, region.size, rawViewEnd, region.size, region.flags); @@ -2260,6 +2265,7 @@ std::optional SharedCache::LoadHeaderForAddress(std::sha void SharedCache::InitializeHeader( Ref view, VM* vm, SharedCacheMachOHeader header, std::vector regionsToLoad) { + WillMutateState(); Ref settings = view->GetLoadSettings(VIEW_NAME); bool applyFunctionStarts = true; @@ -2629,7 +2635,7 @@ void SharedCache::InitializeHeader( view->DefineAutoSymbol(symbolObj); symbolInfos.push_back({sym.n_value, {type, symbol}}); } - m_symbolInfos[header.textBase] = symbolInfos; + MutableState().symbolInfos[header.textBase] = symbolInfos; } if (header.exportTriePresent && header.linkeditPresent && vm->AddressIsMapped(header.linkeditSegment.vmaddr)) @@ -2675,7 +2681,7 @@ void SharedCache::InitializeHeader( else view->DefineAutoSymbol(symbol); } - m_exportInfos[header.textBase] = exportMapping; + MutableState().exportInfos[header.textBase] = std::move(exportMapping); } view->EndBulkModifySymbols(); @@ -2782,7 +2788,7 @@ std::vector> SharedCache::ParseExportTrie(std::shared_ptr SharedCache::GetAvailableImages() { std::vector installNames; - for (const auto& header : m_headers) + for (const auto& header : State().headers) { installNames.push_back(header.second.installName); } @@ -2792,10 +2798,12 @@ std::vector SharedCache::GetAvailableImages() std::vector>> SharedCache::LoadAllSymbolsAndWait() { + WillMutateState(); + std::unique_lock initialLoadBlock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); std::vector>> symbols; - for (const auto& img : m_images) + for (const auto& img : State().images) { auto header = HeaderForAddress(img.headerLocation); std::shared_ptr mapping; @@ -2814,7 +2822,7 @@ std::vector>> SharedCache::LoadAllSymbolsAndW exportMapping.push_back({sym->GetAddress(), {sym->GetType(), sym->GetRawName()}}); symbols.push_back({img.installName, sym}); } - m_exportInfos[header->textBase] = exportMapping; + MutableState().exportInfos[header->textBase] = std::move(exportMapping); } SaveToDSCView(); @@ -2836,17 +2844,22 @@ std::string SharedCache::SerializedImageHeaderForAddress(uint64_t address) std::string SharedCache::SerializedImageHeaderForName(std::string name) { - auto header = HeaderForAddress(m_imageStarts[name]); - if (header) + if (auto it = State().imageStarts.find(name); it != State().imageStarts.end()) { - return header->AsString(); + if (auto header = HeaderForAddress(it->second)) + { + return header->AsString(); + } } return ""; } -void SharedCache::FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis) +void SharedCache::FindSymbolAtAddrAndApplyToAddr( + uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis) { + WillMutateState(); + std::string prefix = ""; if (symbolLocation != targetLocation) prefix = "j_"; @@ -2933,7 +2946,7 @@ void SharedCache::FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64 } { std::unique_lock _lock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); - m_exportInfos[header->textBase] = exportMapping; + MutableState().exportInfos[header->textBase] = std::move(exportMapping); } m_dscView->EndBulkModifySymbols(); m_dscView->ForgetUndoActions(id); @@ -2948,22 +2961,16 @@ bool SharedCache::SaveToDSCView() auto data = AsMetadata(); m_dscView->StoreMetadata(SharedCacheMetadataTag, data); m_dscView->GetParentView()->GetParentView()->StoreMetadata(SharedCacheMetadataTag, data); + + // 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(std::move(*m_state)); + m_state = cachedState; + m_stateIsShared = true; + std::unique_lock viewStateCacheLock(viewStateMutex); - ViewStateCacheStore c; - c.m_imageStarts = m_imageStarts; - c.m_cacheFormat = m_cacheFormat; - c.m_backingCaches = m_backingCaches; - c.m_viewState = m_viewState; - c.m_headers = m_headers; - c.m_images = m_images; - c.m_regionsMappedIntoMemory = m_regionsMappedIntoMemory; - c.m_stubIslandRegions = m_stubIslandRegions; - c.m_dyldDataRegions = m_dyldDataRegions; - c.m_nonImageRegions = m_nonImageRegions; - c.m_baseFilePath = m_baseFilePath; - c.m_exportInfos = m_exportInfos; - c.m_symbolInfos = m_symbolInfos; - viewStateCache[m_dscView->GetFile()->GetSessionId()] = c; + viewStateCache[m_dscView->GetFile()->GetSessionId()] = std::move(cachedState); m_metadataValid = true; @@ -2974,7 +2981,7 @@ bool SharedCache::SaveToDSCView() std::vector SharedCache::GetMappedRegions() const { std::unique_lock lock(viewSpecificMutexes[m_dscView->GetFile()->GetSessionId()].viewOperationsThatInfluenceMetadataMutex); - return m_regionsMappedIntoMemory; + return State().regionsMappedIntoMemory; } extern "C" @@ -3120,7 +3127,7 @@ extern "C" { if (cache->object) { - return (BNDSCViewState)cache->object->State(); + return (BNDSCViewState)cache->object->ViewState(); } return BNDSCViewState::Unloaded; @@ -3327,14 +3334,14 @@ void SharedCache::Store(SerializationContext& context) const { Serialize(context, "metadataVersion", METADATA_VERSION); - MSS(m_viewState); - MSS_CAST(m_cacheFormat, uint8_t); - MSS(m_imageStarts); - MSS(m_baseFilePath); + Serialize(context, "m_viewState", State().viewState); + Serialize(context, "m_cacheFormat", State().cacheFormat); + Serialize(context, "m_imageStarts", State().imageStarts); + Serialize(context, "m_baseFilePath", State().baseFilePath); Serialize(context, "headers"); context.writer.StartArray(); - for (auto& [k, v] : m_headers) + for (auto& [k, v] : State().headers) { context.writer.StartObject(); v.Store(context); @@ -3344,7 +3351,7 @@ void SharedCache::Store(SerializationContext& context) const Serialize(context, "exportInfos"); context.writer.StartArray(); - for (const auto& pair1 : m_exportInfos) + for (const auto& pair1 : State().exportInfos) { context.writer.StartObject(); Serialize(context, "key", pair1.first); @@ -3363,12 +3370,12 @@ void SharedCache::Store(SerializationContext& context) const } context.writer.EndArray(); - Serialize(context, "backingCaches", m_backingCaches); - Serialize(context, "stubIslands", m_stubIslandRegions); - Serialize(context, "images", m_images); - Serialize(context, "regionsMappedIntoMemory", m_regionsMappedIntoMemory); - Serialize(context, "dyldDataSections", m_dyldDataRegions); - Serialize(context, "nonImageRegions", m_nonImageRegions); + Serialize(context, "backingCaches", State().backingCaches); + Serialize(context, "stubIslands", State().stubIslandRegions); + Serialize(context, "images", State().images); + Serialize(context, "regionsMappedIntoMemory", State().regionsMappedIntoMemory); + Serialize(context, "dyldDataSections", State().dyldDataRegions); + Serialize(context, "nonImageRegions", State().nonImageRegions); } void SharedCache::Load(DeserializationContext& context) @@ -3386,18 +3393,23 @@ void SharedCache::Load(DeserializationContext& context) m_logger->LogError("Shared Cache metadata version missing"); return; } - m_viewState = MSL_CAST(m_viewState, uint8_t, DSCViewState); - m_cacheFormat = MSL_CAST(m_cacheFormat, uint8_t, SharedCacheFormat); - m_headers.clear(); + + m_stateIsShared = false; + m_state = std::make_shared(); + + MutableState().viewState = static_cast(context.load("m_viewState")); + MutableState().cacheFormat = static_cast(context.load("m_cacheFormat")); + for (auto& startAndHeader : context.doc["headers"].GetArray()) { SharedCacheMachOHeader header; header.LoadFromValue(startAndHeader); - m_headers[header.textBase] = header; + MutableState().headers[header.textBase] = std::move(header); } - MSL(m_imageStarts); - MSL(m_baseFilePath); - m_exportInfos.clear(); + + Deserialize(context, "m_imageStarts", MutableState().imageStarts); + Deserialize(context, "m_baseFilePath", MutableState().baseFilePath); + for (const auto& obj1 : context.doc["exportInfos"].GetArray()) { std::vector>> innerVec; @@ -3408,9 +3420,9 @@ void SharedCache::Load(DeserializationContext& context) innerVec.push_back({obj2["key"].GetUint64(), innerPair}); } - m_exportInfos[obj1["key"].GetUint64()] = innerVec; + MutableState().exportInfos[obj1["key"].GetUint64()] = std::move(innerVec); } - m_symbolInfos.clear(); + for (auto& symbolInfo : context.doc["symbolInfos"].GetArray()) { std::vector>> symbolInfoVec; @@ -3419,52 +3431,94 @@ void SharedCache::Load(DeserializationContext& context) symbolInfoVec.push_back({symbolInfoPair[0].GetUint64(), {(BNSymbolType)symbolInfoPair[1].GetUint(), symbolInfoPair[2].GetString()}}); } - m_symbolInfos[symbolInfo[0].GetUint64()] = std::move(symbolInfoVec); + MutableState().symbolInfos[symbolInfo[0].GetUint64()] = std::move(symbolInfoVec); } - m_backingCaches.clear(); + for (auto& bcV : context.doc["backingCaches"].GetArray()) { BackingCache bc; bc.LoadFromValue(bcV); - m_backingCaches.push_back(std::move(bc)); + MutableState().backingCaches.push_back(std::move(bc)); } - m_images.clear(); + for (auto& imgV : context.doc["images"].GetArray()) { CacheImage img; img.LoadFromValue(imgV); - m_images.push_back(std::move(img)); + MutableState().images.push_back(std::move(img)); } - m_regionsMappedIntoMemory.clear(); + for (auto& rV : context.doc["regionsMappedIntoMemory"].GetArray()) { MemoryRegion r; r.LoadFromValue(rV); - m_regionsMappedIntoMemory.push_back(std::move(r)); + MutableState().regionsMappedIntoMemory.push_back(std::move(r)); } - m_stubIslandRegions.clear(); + for (auto& siV : context.doc["stubIslands"].GetArray()) { MemoryRegion si; si.LoadFromValue(siV); - m_stubIslandRegions.push_back(std::move(si)); + MutableState().stubIslandRegions.push_back(std::move(si)); } - m_dyldDataRegions.clear(); + for (auto& siV : context.doc["dyldDataSections"].GetArray()) { MemoryRegion si; si.LoadFromValue(siV); - m_dyldDataRegions.push_back(std::move(si)); + MutableState().dyldDataRegions.push_back(std::move(si)); } - m_nonImageRegions.clear(); + for (auto& siV : context.doc["nonImageRegions"].GetArray()) { MemoryRegion si; si.LoadFromValue(siV); - m_nonImageRegions.push_back(std::move(si)); + MutableState().nonImageRegions.push_back(std::move(si)); } m_metadataValid = true; } +__attribute__((always_inline)) void SharedCache::AssertMutable() const +{ + if (m_stateIsShared) + { + abort(); + } +} + +void SharedCache::WillMutateState() +{ + if (!m_state) + { + m_state = std::make_shared(); + } + else if (m_stateIsShared) + { + m_state = std::make_shared(*m_state); + } + m_stateIsShared = false; +} + + +const std::vector& SharedCache::BackingCaches() const +{ + return State().backingCaches; +} + +DSCViewState SharedCache::ViewState() const +{ + return State().viewState; +} + +const std::unordered_map& SharedCache::AllImageStarts() const +{ + return State().imageStarts; +} + +const std::unordered_map& SharedCache::AllImageHeaders() const +{ + return State().headers; +} + } // namespace SharedCacheCore diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h index 4444f8473a..ac24b529f4 100644 --- a/view/sharedcache/core/SharedCache.h +++ b/view/sharedcache/core/SharedCache.h @@ -530,37 +530,21 @@ namespace SharedCacheCore { void Store(SerializationContext& context) const; void Load(DeserializationContext& context); + struct State; + private: Ref m_logger; /* VIEW STATE BEGIN -- SERIALIZE ALL OF THIS AND STORE IT IN RAW VIEW */ // Updated as the view is loaded further, more images are added, etc - DSCViewState m_viewState = DSCViewStateUnloaded; - std::unordered_map>>> - m_exportInfos; - std::unordered_map>>> - m_symbolInfos; - // --- + // NOTE: Access via `State()` or `MutableState()` below. + // `WillMutateState()` must be called before the first access to `MutableState()`. + std::shared_ptr m_state; + bool m_stateIsShared = false; // Serialized once by PerformInitialLoad and available after m_viewState == Loaded bool m_metadataValid = false; - std::string m_baseFilePath; - SharedCacheFormat m_cacheFormat; - - std::unordered_map m_imageStarts; - std::unordered_map m_headers; - - std::vector m_images; - - std::vector m_regionsMappedIntoMemory; - - std::vector m_backingCaches; - - std::vector m_stubIslandRegions; - std::vector m_dyldDataRegions; - std::vector m_nonImageRegions; - /* VIEWSTATE END -- NOTHING PAST THIS IS SERIALIZED */ /* API VIEW START */ @@ -592,20 +576,17 @@ namespace SharedCacheCore { std::vector>> LoadAllSymbolsAndWait(); - std::unordered_map AllImageStarts() const { return m_imageStarts; } - std::unordered_map AllImageHeaders() const { return m_headers; } + const std::unordered_map& AllImageStarts() const; + const std::unordered_map& AllImageHeaders() const; std::string SerializedImageHeaderForAddress(uint64_t address); std::string SerializedImageHeaderForName(std::string name); void FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis); - std::vector BackingCaches() const { + const std::vector& BackingCaches() const; - return m_backingCaches; - } - - DSCViewState State() const { return m_viewState; } + DSCViewState ViewState() const; explicit SharedCache(BinaryNinja::Ref rawView); virtual ~SharedCache(); @@ -614,12 +595,21 @@ namespace SharedCacheCore { std::shared_ptr vm, uint64_t address, std::string installName); void InitializeHeader( Ref view, VM* vm, SharedCacheMachOHeader header, std::vector regionsToLoad); - void ReadExportNode(std::vector>& symbolList, SharedCacheMachOHeader& header, DataBuffer& buffer, uint64_t textBase, - const std::string& currentText, size_t cursor, uint32_t endGuard); + void ReadExportNode(std::vector>& symbolList, SharedCacheMachOHeader& header, DataBuffer& buffer, + uint64_t textBase, const std::string& currentText, size_t cursor, uint32_t endGuard); std::vector> ParseExportTrie( std::shared_ptr linkeditFile, SharedCacheMachOHeader header); - }; + const State& State() const { return *m_state; } + struct State& MutableState() { AssertMutable(); return *m_state; } + + void AssertMutable() const; + + // Ensures that the state is uniquely owned, copying it if it is not. + // Must be called before first access to `MutableState()` after the state + // is loaded from the cache. Can safely be called multiple times. + void WillMutateState(); + }; }