1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
//
// 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<T>` subclass:
* ```
class MyClass : public MetadataSerializable<MyClass> {
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
`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"
#include "../api/sharedcachecore.h"
#include "view/macho/machoview.h"
#ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP
#define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP
namespace SharedCacheCore {
#define MSS(name) context.store(#name, name)
#define MSS_CAST(name, type) context.store(#name, (type) name)
#define MSS_SUBCLASS(name) Serialize(context, #name, name)
#define MSL(name) name = context.load<decltype(name)>(#name)
#define MSL_CAST(name, storedType, type) name = (type)context.load<storedType>(#name)
#define MSL_SUBCLASS(name) Deserialize(context, #name, name)
using namespace BinaryNinja;
struct DeserializationContext;
struct SerializationContext {
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer;
SerializationContext() : buffer(), writer(buffer) {
}
template <typename T>
void store(std::string_view x, const T& y)
{
Serialize(*this, x, y);
}
};
struct DeserializationContext {
rapidjson::Document doc;
template <typename T>
T load(std::string_view x)
{
T value;
Deserialize(*this, x, value);
return value;
}
};
template <typename Derived>
class MetadataSerializable
{
public:
std::string AsString() const
{
SerializationContext context;
Store(context);
return context.buffer.GetString();
}
void LoadFromString(const std::string& s)
{
DeserializationContext context;
context.doc.Parse(s.c_str());
AsDerived().Load(context);
}
void LoadFromValue(rapidjson::Value& s)
{
DeserializationContext context;
context.doc.CopyFrom(s, context.doc.GetAllocator());
AsDerived().Load(context);
}
Ref<Metadata> AsMetadata() {
return new Metadata(AsString());
}
bool LoadFromMetadata(const Ref<Metadata>& meta)
{
if (!meta->IsString())
return false;
LoadFromString(meta->GetString());
return true;
}
void Store(SerializationContext& context) const {
context.writer.StartObject();
AsDerived().Store(context);
context.writer.EndObject();
}
private:
const Derived& AsDerived() const { return static_cast<const Derived&>(*this); }
Derived& AsDerived() { return static_cast<Derived&>(*this); }
};
// 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 <typename T>
inline void Serialize(SerializationContext& context, const MetadataSerializable<T>& value)
{
value.Store(context);
}
template <typename T>
inline void Serialize(SerializationContext& context, std::string_view name, const T& value)
{
Serialize(context, name);
Serialize(context, value);
}
template <typename First, typename Second>
void Serialize(SerializationContext& context, const std::pair<First, Second>& value)
{
context.writer.StartArray();
Serialize(context, value.first);
Serialize(context, value.second);
context.writer.EndArray();
}
template <typename K, typename V>
void Serialize(SerializationContext& context, const std::map<K, V>& value)
{
context.writer.StartArray();
for (auto& pair : value)
{
Serialize(context, pair);
}
context.writer.EndArray();
}
template <typename K, typename V>
void Serialize(SerializationContext& context, const std::unordered_map<K, V>& value)
{
context.writer.StartArray();
for (auto& pair : value)
{
Serialize(context, pair);
}
context.writer.EndArray();
}
template <typename T>
void Serialize(SerializationContext& context, const std::vector<T>& 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, uint8_t b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint8_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, uint32_t b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, uint32_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, int8_t b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int8_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, int32_t b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, int32_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 b);
SHAREDCACHE_FFI_API void Serialize(SerializationContext& context, const std::pair<uint64_t, std::pair<uint64_t, uint64_t>>& 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<uint64_t, std::string>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map<uint64_t, std::string>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map<uint64_t, uint64_t>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map<std::string, std::unordered_map<uint64_t, uint64_t>>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map<std::string, std::string>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector<std::string>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector<std::pair<uint64_t, std::pair<uint64_t, uint64_t>>>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector<std::pair<uint64_t, bool>>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector<uint64_t>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map<std::string, uint64_t>& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext& context, std::string_view name, std::vector<std::pair<uint64_t, std::vector<std::pair<uint64_t, std::string>>>>& 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&, const symtab_command& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, symtab_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&, 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&, 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&, 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&, const section_64& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector<section_64>& 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&, const segment_command_64& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, segment_command_64& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector<segment_command_64>& 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&, const build_tool_version& b);
SHAREDCACHE_FFI_API void Deserialize(DeserializationContext&, std::string_view name, std::vector<build_tool_version>& b);
} // namespace SharedCacheCore
#endif // SHAREDCACHE_METADATASERIALIZABLE_HPP
|