Skip to content

Commit ff8a82f

Browse files
committed
[aarch64] frankenmerge with dev
1 parent 9cafe66 commit ff8a82f

File tree

10 files changed

+1923
-2983
lines changed

10 files changed

+1923
-2983
lines changed

objectivec/objc.cpp

Lines changed: 1583 additions & 0 deletions
Large diffs are not rendered by default.

objectivec/objc.h

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
#pragma once
2+
3+
#include <binaryninjaapi.h>
4+
5+
namespace BinaryNinja {
6+
// This set of structs is based on the objc4 source,
7+
// however pointers have been replaced with view_ptr_t
8+
9+
// Used for pointers within BinaryView, primarily to make it far more clear in typedefs
10+
// whether the size of a field can vary between architectures.
11+
// These should _not_ be used in sizeof or direct Read() calls.
12+
typedef uint64_t view_ptr_t;
13+
14+
typedef struct {
15+
view_ptr_t name;
16+
view_ptr_t types;
17+
view_ptr_t imp;
18+
} method_t;
19+
typedef struct {
20+
uint32_t name;
21+
uint32_t types;
22+
uint32_t imp;
23+
} method_entry_t;
24+
typedef struct {
25+
view_ptr_t offset;
26+
view_ptr_t name;
27+
view_ptr_t type;
28+
uint32_t alignmentRaw;
29+
uint32_t size;
30+
} ivar_t;
31+
typedef struct {
32+
view_ptr_t name;
33+
view_ptr_t attributes;
34+
} property_t;
35+
typedef struct {
36+
uint32_t entsizeAndFlags;
37+
uint32_t count;
38+
} method_list_t;
39+
typedef struct {
40+
uint32_t entsizeAndFlags;
41+
uint32_t count;
42+
} ivar_list_t;
43+
typedef struct {
44+
uint32_t entsizeAndFlags;
45+
uint32_t count;
46+
} property_list_t;
47+
typedef struct {
48+
uint64_t count;
49+
} protocol_list_t;
50+
struct relative_list_list_entry_t {
51+
uint64_t imageIndex: 16;
52+
int64_t listOffset: 48;
53+
};
54+
typedef struct {
55+
view_ptr_t isa;
56+
view_ptr_t mangledName;
57+
view_ptr_t protocols;
58+
view_ptr_t instanceMethods;
59+
view_ptr_t classMethods;
60+
view_ptr_t optionalInstanceMethods;
61+
view_ptr_t optionalClassMethods;
62+
view_ptr_t instanceProperties;
63+
uint32_t size;
64+
uint32_t flags;
65+
} protocol_t;
66+
typedef struct {
67+
uint32_t flags;
68+
uint32_t instanceStart;
69+
uint32_t instanceSize;
70+
uint32_t reserved;
71+
view_ptr_t ivarLayout;
72+
view_ptr_t name;
73+
view_ptr_t baseMethods;
74+
view_ptr_t baseProtocols;
75+
view_ptr_t ivars;
76+
view_ptr_t weakIvarLayout;
77+
view_ptr_t baseProperties;
78+
} class_ro_t;
79+
typedef struct {
80+
view_ptr_t isa;
81+
view_ptr_t super;
82+
view_ptr_t cache;
83+
view_ptr_t vtable;
84+
view_ptr_t data;
85+
} class_t;
86+
typedef struct {
87+
view_ptr_t name;
88+
view_ptr_t cls;
89+
view_ptr_t instanceMethods;
90+
view_ptr_t classMethods;
91+
view_ptr_t protocols;
92+
view_ptr_t instanceProperties;
93+
} category_t;
94+
typedef struct {
95+
view_ptr_t receiver;
96+
view_ptr_t current_class;
97+
} objc_super2;
98+
typedef struct {
99+
view_ptr_t imp;
100+
view_ptr_t sel;
101+
} message_ref_t;
102+
103+
struct Method {
104+
std::string name;
105+
std::string types;
106+
view_ptr_t imp;
107+
};
108+
109+
struct Ivar {
110+
uint32_t offset;
111+
std::string name;
112+
std::string type;
113+
uint32_t alignment;
114+
uint32_t size;
115+
};
116+
117+
struct Property {
118+
std::string name;
119+
std::string attributes;
120+
};
121+
122+
struct ClassBase {
123+
std::map<uint64_t, Method> methodList;
124+
std::map<uint64_t, Ivar> ivarList;
125+
};
126+
127+
struct Class {
128+
std::string name;
129+
ClassBase instanceClass;
130+
ClassBase metaClass;
131+
132+
// Loaded by type processing
133+
QualifiedName associatedName;
134+
};
135+
136+
class Protocol {
137+
public:
138+
std::string name;
139+
std::vector<QualifiedName> protocols;
140+
ClassBase instanceMethods;
141+
ClassBase classMethods;
142+
ClassBase optionalInstanceMethods;
143+
ClassBase optionalClassMethods;
144+
};
145+
146+
struct QualifiedNameOrType {
147+
BinaryNinja::Ref<BinaryNinja::Type> type = nullptr;
148+
BinaryNinja::QualifiedName name;
149+
size_t ptrCount = 0;
150+
};
151+
152+
class ObjCReader {
153+
public:
154+
virtual ~ObjCReader() = default;
155+
156+
/*! Read from the current cursor position into buffer `dest` and advance the cursor that many bytes
157+
158+
\throws Exception
159+
\param dest Address to write the read bytes to
160+
\param len Number of bytes to write
161+
*/
162+
virtual void Read(void* dest, size_t len) = 0;
163+
164+
/*! Read a null-terminated string from the current cursor position
165+
166+
\throws Exception
167+
\return the string
168+
*/
169+
virtual std::string ReadCString(size_t maxLength = -1) = 0;
170+
171+
/*! Read a uint8_t from the current cursor position and advance the cursor by 1 byte
172+
173+
\throws Exception
174+
\return The read value
175+
*/
176+
virtual uint8_t Read8() = 0;
177+
178+
/*! Read a uint16_t from the current cursor position and advance the cursor by 2 bytes
179+
180+
\throws Exception
181+
\return The read value
182+
*/
183+
virtual uint16_t Read16() = 0;
184+
185+
/*! Read a uint32_t from the current cursor position and advance the cursor by 4 bytes
186+
187+
\throws Exception
188+
\return The read value
189+
*/
190+
virtual uint32_t Read32() = 0;
191+
192+
/*! Read a uint64_t from the current cursor position and advance the cursor by 8 bytes
193+
194+
\throws Exception
195+
\return The read value
196+
*/
197+
virtual uint64_t Read64() = 0;
198+
199+
/*! Read a int8_t from the current cursor position and advance the cursor by 1 byte
200+
201+
\throws Exception
202+
\return The read value
203+
*/
204+
virtual int8_t ReadS8() = 0;
205+
206+
/*! Read a int16_t from the current cursor position and advance the cursor by 2 bytes
207+
208+
\throws Exception
209+
\return The read value
210+
*/
211+
virtual int16_t ReadS16() = 0;
212+
213+
/*! Read a int32_t from the current cursor position and advance the cursor by 4 bytes
214+
215+
\throws Exception
216+
\return The read value
217+
*/
218+
virtual int32_t ReadS32() = 0;
219+
220+
/*! Read a int64_t from the current cursor position and advance the cursor by 8 bytes
221+
222+
\throws Exception
223+
\return The read value
224+
*/
225+
virtual int64_t ReadS64() = 0;
226+
227+
/*! Read a pointer from the current cursor position and advance it that many bytes
228+
229+
\throws Exception
230+
\return The value that was read
231+
*/
232+
virtual uint64_t ReadPointer() = 0;
233+
234+
/*! Get the current cursor position
235+
236+
\return The current cursor position
237+
*/
238+
virtual uint64_t GetOffset() const = 0;
239+
240+
/*! Set the cursor position
241+
242+
\param offset The new cursor position
243+
*/
244+
virtual void Seek(uint64_t offset) = 0;
245+
246+
/*! Set the cursor position, relative to the current position
247+
248+
\param offset Offset to the current cursor position
249+
*/
250+
virtual void SeekRelative(int64_t offset) = 0;
251+
};
252+
253+
class ObjCProcessor {
254+
struct Types {
255+
QualifiedName relativePtr;
256+
QualifiedName id;
257+
QualifiedName sel;
258+
QualifiedName BOOL;
259+
QualifiedName nsInteger;
260+
QualifiedName nsuInteger;
261+
QualifiedName cgFloat;
262+
QualifiedName cfStringFlag;
263+
QualifiedName cfString;
264+
QualifiedName cfStringUTF16;
265+
QualifiedName imageInfoFlags;
266+
QualifiedName imageInfoSwiftVersion;
267+
QualifiedName imageInfo;
268+
QualifiedName methodEntry;
269+
QualifiedName method;
270+
QualifiedName methodList;
271+
QualifiedName classRO;
272+
QualifiedName cls;
273+
QualifiedName category;
274+
QualifiedName protocol;
275+
QualifiedName protocolList;
276+
QualifiedName ivar;
277+
QualifiedName ivarList;
278+
} m_typeNames;
279+
280+
bool m_isBackedByDatabase;
281+
// TODO(WeiN76LQh): this is to avoid a bug with defining a classes protocol list in the DSC plugin. Remove once fixed
282+
bool m_skipClassBaseProtocols;
283+
284+
SymbolQueue* m_symbolQueue = nullptr;
285+
std::map<uint64_t, Class> m_classes;
286+
std::map<uint64_t, Class> m_categories;
287+
std::map<uint64_t, Protocol> m_protocols;
288+
std::unordered_map<uint64_t, std::string> m_selectorCache;
289+
std::unordered_map<uint64_t, Method> m_localMethods;
290+
291+
// Required for workflow_objc type heuristics, should be removed when that is no longer a thing.
292+
std::map<uint64_t, std::string> m_selRefToName;
293+
std::map<uint64_t, std::vector<uint64_t>> m_selRefToImplementations;
294+
std::map<uint64_t, std::vector<uint64_t>> m_selToImplementations;
295+
// --
296+
297+
uint64_t ReadPointerAccountingForRelocations(ObjCReader* reader);
298+
std::unordered_map<uint64_t, uint64_t> m_relocationPointerRewrites;
299+
300+
static Ref<Metadata> SerializeMethod(uint64_t loc, const Method& method);
301+
static Ref<Metadata> SerializeClass(uint64_t loc, const Class& cls);
302+
Ref<Metadata> SerializeMetadata();
303+
304+
std::vector<QualifiedNameOrType> ParseEncodedType(const std::string& type);
305+
void DefineObjCSymbol(BNSymbolType symbolType, QualifiedName typeName, const std::string& name, uint64_t addr, bool deferred);
306+
void DefineObjCSymbol(BNSymbolType symbolType, Ref<Type> type, const std::string& name, uint64_t addr, bool deferred);
307+
void ReadIvarList(ObjCReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start);
308+
void ReadMethodList(ObjCReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start);
309+
void ReadListOfMethodLists(ObjCReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start);
310+
void LoadClasses(ObjCReader* reader, Ref<Section> listSection);
311+
void LoadCategories(ObjCReader* reader, Ref<Section> listSection);
312+
void LoadProtocols(ObjCReader* reader, Ref<Section> listSection);
313+
void GenerateClassTypes();
314+
bool ApplyMethodType(Class& cls, Method& method, bool isInstanceMethod);
315+
void ApplyMethodTypes(Class& cls);
316+
317+
Ref<Section> GetSectionForImage(std::optional<std::string> imageName, const char* sectionName);
318+
void PostProcessObjCSections(ObjCReader* reader, std::optional<std::string> imageName);
319+
320+
protected:
321+
Ref<BinaryView> m_data;
322+
Ref<Logger> m_logger;
323+
324+
virtual uint64_t GetObjCRelativeMethodBaseAddress(ObjCReader* reader);
325+
virtual void GetRelativeMethod(ObjCReader* reader, method_t& meth);
326+
virtual std::shared_ptr<ObjCReader> GetReader() = 0;
327+
// Because an objective-c processor might have access to other non-view symbols that we want to retrieve.
328+
// By default, this will just get symbol at the address in the view.
329+
virtual Ref<Symbol> GetSymbol(uint64_t address);
330+
331+
public:
332+
virtual ~ObjCProcessor() = default;
333+
334+
ObjCProcessor(BinaryView* data, const char* loggerName, bool isBackedByDatabase, bool skipClassBaseProtocols = false);
335+
void ProcessObjCData(std::optional<std::string> imageName);
336+
void ProcessCFStrings(std::optional<std::string> imageName);
337+
void AddRelocatedPointer(uint64_t location, uint64_t rewrite);
338+
};
339+
}
340+

0 commit comments

Comments
 (0)