-
Notifications
You must be signed in to change notification settings - Fork 289
Expand file tree
/
Copy pathcoffview.h
More file actions
374 lines (337 loc) · 10.6 KB
/
Copy pathcoffview.h
File metadata and controls
374 lines (337 loc) · 10.6 KB
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#pragma once
#include "binaryninjaapi.h"
#include "peview.h"
#include <exception>
#ifdef WIN32
#pragma warning(disable: 4005)
#endif
#define IMAGE_SYM_TYPE_NULL 0 // No type information or unknown base type.
#define IMAGE_SYM_TYPE_VOID 1 // Used with void pointers and functions.
#define IMAGE_SYM_TYPE_CHAR 2 // A character (signed byte).
#define IMAGE_SYM_TYPE_SHORT 3 // A 2-byte signed integer.
#define IMAGE_SYM_TYPE_INT 4 // A natural integer type on the target.
#define IMAGE_SYM_TYPE_LONG 5 // A 4-byte signed integer.
#define IMAGE_SYM_TYPE_FLOAT 6 // A 4-byte floating-point number.
#define IMAGE_SYM_TYPE_DOUBLE 7 // An 8-byte floating-point number.
#define IMAGE_SYM_TYPE_STRUCT 8 // A structure.
#define IMAGE_SYM_TYPE_UNION 9 // An union.
#define IMAGE_SYM_TYPE_ENUM 10 // An enumerated type.
#define IMAGE_SYM_TYPE_MOE 11 // A member of enumeration (a specific value).
#define IMAGE_SYM_TYPE_BYTE 12 // A byte; unsigned 1-byte integer.
#define IMAGE_SYM_TYPE_WORD 13 // A word; unsigned 2-byte integer.
#define IMAGE_SYM_TYPE_UINT 14 // An unsigned integer of natural size.
#define IMAGE_SYM_TYPE_DWORD 15 // An unsigned 4-byte integer.
#define MS_IMAGE_SYM_TYPE_FUNCTION 0x20 // Microsoft-specific
#define IMAGE_REL_I386_ABSOLUTE 0x0000
#define IMAGE_REL_I386_DIR16 0x0001
#define IMAGE_REL_I386_REL16 0x0002
#define IMAGE_REL_I386_DIR32 0x0006
#define IMAGE_REL_I386_DIR32NB 0x0007
#define IMAGE_REL_I386_SEG12 0x0009
#define IMAGE_REL_I386_SECTION 0x000A
#define IMAGE_REL_I386_SECREL 0x000B
#define IMAGE_REL_I386_TOKEN 0x000C
#define IMAGE_REL_I386_SECREL7 0x000D
#define IMAGE_REL_I386_REL32 0x0014
#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
#define IMAGE_REL_AMD64_ADDR64 0x0001
#define IMAGE_REL_AMD64_ADDR32 0x0002
#define IMAGE_REL_AMD64_ADDR32NB 0x0003
#define IMAGE_REL_AMD64_REL32 0x0004
#define IMAGE_REL_AMD64_REL32_1 0x0005
#define IMAGE_REL_AMD64_REL32_2 0x0006
#define IMAGE_REL_AMD64_REL32_3 0x0007
#define IMAGE_REL_AMD64_REL32_4 0x0008
#define IMAGE_REL_AMD64_REL32_5 0x0009
#define IMAGE_REL_AMD64_SECTION 0x000A
#define IMAGE_REL_AMD64_SECREL 0x000B
#define IMAGE_REL_AMD64_SECREL7 0x000C
#define IMAGE_REL_AMD64_TOKEN 0x000D
#define IMAGE_REL_AMD64_SREL32 0x000E
#define IMAGE_REL_AMD64_PAIR 0x000F
#define IMAGE_REL_AMD64_SSPAN32 0x0010
#define IMAGE_REL_ARM_ABSOLUTE 0x0000
#define IMAGE_REL_ARM_ADDR32 0x0001
#define IMAGE_REL_ARM_ADDR32NB 0x0002
#define IMAGE_REL_ARM_BRANCH24 0x0003
#define IMAGE_REL_ARM_BRANCH11 0x0004
#define IMAGE_REL_ARM_BLX24 0x0008
#define IMAGE_REL_ARM_BLX11 0x0009
#define IMAGE_REL_ARM_REL32 0x000A
#define IMAGE_REL_ARM_SECTION 0x000E
#define IMAGE_REL_ARM_SECREL 0x000F
#define IMAGE_REL_ARM_MOV32 0x0010
#define IMAGE_REL_THUMB_MOV32 0x0011
#define IMAGE_REL_THUMB_BRANCH20 0x0012
#define IMAGE_REL_THUMB_UNUSED 0x0013
#define IMAGE_REL_THUMB_BRANCH24 0x0014
#define IMAGE_REL_THUMB_BLX23 0x0015
#define IMAGE_REL_ARM_PAIR 0x0016
// The following names for armv7/thumb2 relocations are from LLVM source,
// but are commented out in favor of the names defined above,
// which correspond to Microsoft PE Format documentation:
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators
// #define IMAGE_REL_ARM_ABSOLUTE 0x0000
// #define IMAGE_REL_ARM_ADDR32 0x0001
// #define IMAGE_REL_ARM_ADDR32NB 0x0002
// #define IMAGE_REL_ARM_BRANCH24 0x0003
// #define IMAGE_REL_ARM_BRANCH11 0x0004
// #define IMAGE_REL_ARM_TOKEN 0x0005
// #define IMAGE_REL_ARM_BLX24 0x0008
// #define IMAGE_REL_ARM_BLX11 0x0009
// #define IMAGE_REL_ARM_REL32 0x000A
// #define IMAGE_REL_ARM_SECTION 0x000E
// #define IMAGE_REL_ARM_SECREL 0x000F
// #define IMAGE_REL_ARM_MOV32A 0x0010
// #define IMAGE_REL_ARM_MOV32T 0x0011
// #define IMAGE_REL_ARM_BRANCH20T 0x0012
// #define IMAGE_REL_ARM_BRANCH24T 0x0014
// #define IMAGE_REL_ARM_BLX23T 0x0015
// #define IMAGE_REL_ARM_PAIR 0x0016
#define IMAGE_REL_ARM64_ABSOLUTE 0x0000
#define IMAGE_REL_ARM64_ADDR32 0x0001
#define IMAGE_REL_ARM64_ADDR32NB 0x0002
#define IMAGE_REL_ARM64_BRANCH26 0x0003
#define IMAGE_REL_ARM64_PAGEBASE_REL21 0x0004
#define IMAGE_REL_ARM64_REL21 0x0005
#define IMAGE_REL_ARM64_PAGEOFFSET_12A 0x0006
#define IMAGE_REL_ARM64_PAGEOFFSET_12L 0x0007
#define IMAGE_REL_ARM64_SECREL 0x0008
#define IMAGE_REL_ARM64_SECREL_LOW12A 0x0009
#define IMAGE_REL_ARM64_SECREL_HIGH12A 0x000A
#define IMAGE_REL_ARM64_SECREL_LOW12L 0x000B
#define IMAGE_REL_ARM64_TOKEN 0x000C
#define IMAGE_REL_ARM64_SECTION 0x000D
#define IMAGE_REL_ARM64_ADDR64 0x000E
#define IMAGE_REL_ARM64_BRANCH19 0x000F
#define IMAGE_REL_ARM64_BRANCH14 0x0010
#define IMAGE_REL_ARM64_REL32 0x0011
namespace BinaryNinja
{
class COFFFormatException: public std::exception
{
std::string m_message;
public:
COFFFormatException(const std::string& msg = "invalid format"): m_message(msg) {}
virtual const char* what() const NOEXCEPT { return m_message.c_str(); }
};
#pragma pack(push, 2)
struct COFFHeader
{
uint16_t machine;
uint16_t sectionCount;
uint32_t timestamp;
uint32_t coffSymbolTable;
uint32_t coffSymbolCount;
uint16_t optionalHeaderSize;
uint16_t characteristics;
};
// Use this for sizeof
struct COFFSectionHeader
{
uint8_t name[8];
union
{
uint32_t virtualSize;
uint32_t physicalAddress;
};
uint32_t virtualAddress;
uint32_t sizeOfRawData;
uint32_t pointerToRawData;
uint32_t pointerToRelocs;
uint32_t pointerToLineNumbers;
uint16_t relocCount;
uint16_t lineNumberCount;
uint32_t characteristics;
};
// Can only find reference to this alernate COFF header in the LLVM source and docs:
// https://llvm.org/doxygen/structllvm_1_1COFF_1_1BigObjHeader.html
// https://github.com/llvm/llvm-project/commit/44f51e511374f467d70c37324a8e5bbf2ea270d8#diff-c8c9ae93373622c2303ca157ecdc8bf16204567b57e391381ed4740e0c38c82aR67-R82
struct BigObj_COFFHeader
{
uint16_t sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0).
uint16_t sig2; ///< Must be 0xFFFF.
uint16_t version;
uint16_t machine;
uint32_t timestamp;
uint8_t UUID[16];
uint32_t unused1;
uint32_t unused2;
uint32_t unused3;
uint32_t unused4;
uint32_t sectionCount;
uint32_t coffSymbolTable;
uint32_t coffSymbolCount;
};
struct COFFSection
{
std::string name;
union
{
uint32_t virtualSize;
uint32_t physicalAddress;
};
uint32_t virtualAddress;
uint32_t sizeOfRawData;
uint32_t pointerToRawData;
uint32_t pointerToRelocs;
uint32_t pointerToLineNumbers;
uint16_t relocCount;
uint16_t lineNumberCount;
uint32_t characteristics;
};
template<typename SectionCountType> struct _COFFSymbol
{
union
{
char shortName[8];
struct {
uint32_t zeroes;
uint32_t offset;
} longName;
} name;
uint32_t value;
// 1-based index into section table
SectionCountType sectionNumber;
uint16_t type;
uint8_t storageClass;
uint8_t numberOfAuxSymbols;
};
using COFFSymbol16 = _COFFSymbol<uint16_t>;
using COFFSymbol32 = _COFFSymbol<uint32_t>;
struct COFFSymbol
{
union
{
char shortName[8];
struct {
uint32_t zeroes;
uint32_t offset;
} longName;
} name;
uint32_t value;
// 1-based index into section table
union { int16_t i16; int32_t i32; } sectionNumber;
uint16_t type;
uint8_t storageClass;
uint8_t numberOfAuxSymbols;
};
struct COFFAuxFunctionDefinition
{
uint32_t tagIndex;
uint32_t totalSize;
uint32_t pointerToLineNumber;
uint32_t pointerToNextFunction;
uint8_t unused[2];
};
struct COFFAux_bf_And_ef_Symbol
{
uint8_t unused0[4];
uint16_t lineNumber;
uint8_t unused6[6];
uint32_t pointerToNextFunction;
uint8_t unused16[2];
};
struct COFFAuxWeakExternal
{
uint32_t tagIndex;
uint32_t characteristics;
uint8_t unused[10];
};
struct COFFAuxFile
{
uint8_t fileName[18];
};
#pragma pack(push, 1)
struct COFFAuxSectionDefinition
{
uint32_t length;
uint16_t numberOfRelocations;
uint16_t numberOfLineNumbers;
uint32_t checkSum;
uint16_t number;
uint8_t selection;
union {
uint8_t unused3[3];
struct
{
uint8_t unused;
uint16_t numberHighPart;
};
};
};
#pragma pack(pop)
union COFFAuxSymbolRecord
{
COFFAuxFunctionDefinition functionDefinition;
COFFAux_bf_And_ef_Symbol bf_And_ef_Symbol;
COFFAuxWeakExternal weakExternal;
COFFAuxFile file;
COFFAuxSectionDefinition sectionDefinition;
};
struct COFFRelocation
{
uint32_t virtualAddress;
uint32_t symbolTableIndex;
// union
// {
// enum x64_coff_reloc_type x64_type;
// enum arm_coff_reloc_type arm_type;
// enum x86_coff_reloc_type x86_type;
uint16_t type;
// };
// COFFRelocation(uint32_t va, uint32_t i, uint16_t t) : virtualAddress(va), symbolTableIndex(i), type(t) {}
};
struct COFF_PdataFunctionTableEntry
{
uint32_t beginAddress;
uint32_t endAddress;
uint32_t unwindInformation;
};
#pragma pack(pop)
class COFFView : public BinaryView
{
bool m_parseOnly;
uint64_t m_entryPoint;
uint64_t m_imageBase;
uint32_t m_sizeOfHeaders;
std::vector<COFFSection> m_sections;
std::vector<COFFRelocation> m_relocs;
Ref<Architecture> m_arch;
Ref<Logger> m_logger;
bool m_is64;
bool m_extractMangledTypes;
bool m_simplifyTemplates;
bool m_relocatable = false;
virtual uint64_t PerformGetEntryPoint() const override;
virtual bool PerformIsExecutable() const override { return true; }
virtual BNEndianness PerformGetDefaultEndianness() const override { return LittleEndian; }
virtual bool PerformIsRelocatable() const override { return m_relocatable; }
virtual size_t PerformGetAddressSize() const override;
uint64_t RVAToFileOffset(uint64_t rva, bool except = true);
uint32_t GetRVACharacteristics(uint64_t rva);
std::string ReadString(uint64_t rva);
uint16_t Read16(uint64_t rva);
uint32_t Read32(uint64_t rva);
uint64_t Read64(uint64_t rva);
void AddCOFFSymbol(BNSymbolType type, const std::string& dll, const std::string& name, uint64_t addr,
BNSymbolBinding binding = NoBinding, uint64_t ordinal = 0, TypeLibrary* lib = nullptr);
// void COFFView::GetRelocs(BinaryReader& reader, const vector<COFFSection>& sections, vector<COFFRelocation>& result, const QualifiedName& coffRelocTypeName, const map<uint64_t, string>& symbolNames);
public:
COFFView(BinaryView* data, bool parseOnly = false);
virtual bool Init() override;
};
class COFFViewType: public BinaryViewType
{
Ref<Logger> m_logger;
public:
COFFViewType();
virtual Ref<BinaryView> Create(BinaryView* data) override;
virtual Ref<BinaryView> Parse(BinaryView* data) override;
virtual bool IsTypeValidForData(BinaryView* data) override;
virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override;
static bool IsValidMachineType(uint16_t machineType);
static bool IsSupportedMachineType(uint16_t machineType);
};
void InitCOFFViewType();
}