Line data Source code
1 : //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file declares the COFFObjectFile class.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "llvm/ADT/ArrayRef.h"
15 : #include "llvm/ADT/StringRef.h"
16 : #include "llvm/ADT/Triple.h"
17 : #include "llvm/ADT/iterator_range.h"
18 : #include "llvm/BinaryFormat/COFF.h"
19 : #include "llvm/Object/Binary.h"
20 : #include "llvm/Object/COFF.h"
21 : #include "llvm/Object/Error.h"
22 : #include "llvm/Object/ObjectFile.h"
23 : #include "llvm/Support/BinaryStreamReader.h"
24 : #include "llvm/Support/Endian.h"
25 : #include "llvm/Support/Error.h"
26 : #include "llvm/Support/ErrorHandling.h"
27 : #include "llvm/Support/MathExtras.h"
28 : #include "llvm/Support/MemoryBuffer.h"
29 : #include <algorithm>
30 : #include <cassert>
31 : #include <cstddef>
32 : #include <cstdint>
33 : #include <cstring>
34 : #include <limits>
35 : #include <memory>
36 : #include <system_error>
37 :
38 : using namespace llvm;
39 : using namespace object;
40 :
41 : using support::ulittle16_t;
42 : using support::ulittle32_t;
43 : using support::ulittle64_t;
44 : using support::little16_t;
45 :
46 : // Returns false if size is greater than the buffer size. And sets ec.
47 0 : static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
48 1926 : if (M.getBufferSize() < Size) {
49 : EC = object_error::unexpected_eof;
50 0 : return false;
51 : }
52 : return true;
53 : }
54 :
55 : // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
56 : // Returns unexpected_eof if error.
57 : template <typename T>
58 0 : static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
59 : const void *Ptr,
60 : const uint64_t Size = sizeof(T)) {
61 0 : uintptr_t Addr = uintptr_t(Ptr);
62 0 : if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
63 0 : return EC;
64 0 : Obj = reinterpret_cast<const T *>(Addr);
65 0 : return std::error_code();
66 : }
67 0 :
68 : // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
69 : // prefixed slashes.
70 0 : static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
71 0 : assert(Str.size() <= 6 && "String too long, possible overflow.");
72 0 : if (Str.size() > 6)
73 0 : return true;
74 0 :
75 : uint64_t Value = 0;
76 0 : while (!Str.empty()) {
77 : unsigned CharVal;
78 : if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
79 0 : CharVal = Str[0] - 'A';
80 0 : else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
81 0 : CharVal = Str[0] - 'a' + 26;
82 0 : else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
83 0 : CharVal = Str[0] - '0' + 52;
84 : else if (Str[0] == '+') // 62
85 0 : CharVal = 62;
86 : else if (Str[0] == '/') // 63
87 : CharVal = 63;
88 0 : else
89 0 : return true;
90 0 :
91 0 : Value = (Value * 64) + CharVal;
92 0 : Str = Str.substr(1);
93 : }
94 0 :
95 : if (Value > std::numeric_limits<uint32_t>::max())
96 : return true;
97 0 :
98 0 : Result = static_cast<uint32_t>(Value);
99 0 : return false;
100 0 : }
101 0 :
102 : template <typename coff_symbol_type>
103 0 : const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
104 : const coff_symbol_type *Addr =
105 : reinterpret_cast<const coff_symbol_type *>(Ref.p);
106 0 :
107 0 : assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
108 0 : #ifndef NDEBUG
109 0 : // Verify that the symbol points to a valid entry in the symbol table.
110 0 : uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
111 :
112 0 : assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
113 : "Symbol did not point to the beginning of a symbol");
114 : #endif
115 0 :
116 0 : return Addr;
117 0 : }
118 0 :
119 0 : const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
120 : const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
121 0 :
122 : #ifndef NDEBUG
123 : // Verify that the section points to a valid entry in the section table.
124 0 : if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
125 0 : report_fatal_error("Section was outside of section table.");
126 0 :
127 0 : uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
128 0 : assert(Offset % sizeof(coff_section) == 0 &&
129 : "Section did not point to the beginning of a section");
130 0 : #endif
131 :
132 : return Addr;
133 0 : }
134 0 :
135 0 : void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
136 0 : auto End = reinterpret_cast<uintptr_t>(StringTable);
137 0 : if (SymbolTable16) {
138 : const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
139 0 : Symb += 1 + Symb->NumberOfAuxSymbols;
140 : Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
141 : } else if (SymbolTable32) {
142 0 : const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
143 0 : Symb += 1 + Symb->NumberOfAuxSymbols;
144 0 : Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
145 0 : } else {
146 0 : llvm_unreachable("no symbol table pointer!");
147 : }
148 0 : }
149 :
150 : Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
151 0 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
152 0 : StringRef Result;
153 0 : if (std::error_code EC = getSymbolName(Symb, Result))
154 0 : return errorCodeToError(EC);
155 0 : return Result;
156 : }
157 0 :
158 : uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
159 : return getCOFFSymbol(Ref).getValue();
160 0 : }
161 0 :
162 0 : uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
163 0 : // MSVC/link.exe seems to align symbols to the next-power-of-2
164 0 : // up to 32 bytes.
165 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
166 : return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
167 : }
168 :
169 1 : Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
170 : uint64_t Result = getSymbolValue(Ref);
171 1 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
172 : int32_t SectionNumber = Symb.getSectionNumber();
173 :
174 : if (Symb.isAnyUndefined() || Symb.isCommon() ||
175 7 : COFF::isReservedSectionNumber(SectionNumber))
176 : return Result;
177 12 :
178 3 : const coff_section *Section = nullptr;
179 3 : if (std::error_code EC = getSection(SectionNumber, Section))
180 2 : return errorCodeToError(EC);
181 1 : Result += Section->VirtualAddress;
182 1 :
183 0 : // The section VirtualAddress does not include ImageBase, and we want to
184 : // return virtual addresses.
185 0 : Result += getImageBase();
186 :
187 : return Result;
188 : }
189 :
190 6 : Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
191 6 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
192 : int32_t SectionNumber = Symb.getSectionNumber();
193 :
194 1 : if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
195 : return SymbolRef::ST_Function;
196 : if (Symb.isAnyUndefined())
197 1 : return SymbolRef::ST_Unknown;
198 1 : if (Symb.isCommon())
199 : return SymbolRef::ST_Data;
200 : if (Symb.isFileRecord())
201 : return SymbolRef::ST_File;
202 0 :
203 17984 : // TODO: perhaps we need a new symbol type ST_Section.
204 0 : if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
205 : return SymbolRef::ST_Debug;
206 :
207 : if (!COFF::isReservedSectionNumber(SectionNumber))
208 : return SymbolRef::ST_Data;
209 :
210 : return SymbolRef::ST_Other;
211 : }
212 :
213 : uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
214 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
215 0 : uint32_t Result = SymbolRef::SF_None;
216 :
217 0 : if (Symb.isExternal() || Symb.isWeakExternal())
218 0 : Result |= SymbolRef::SF_Global;
219 0 :
220 : if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
221 : Result |= SymbolRef::SF_Weak;
222 : if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
223 : Result |= SymbolRef::SF_Undefined;
224 : }
225 :
226 : if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
227 : Result |= SymbolRef::SF_Absolute;
228 :
229 : if (Symb.isFileRecord())
230 0 : Result |= SymbolRef::SF_FormatSpecific;
231 :
232 0 : if (Symb.isSectionDefinition())
233 0 : Result |= SymbolRef::SF_FormatSpecific;
234 0 :
235 : if (Symb.isCommon())
236 : Result |= SymbolRef::SF_Common;
237 :
238 : if (Symb.isUndefined())
239 : Result |= SymbolRef::SF_Undefined;
240 :
241 : return Result;
242 : }
243 :
244 : uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
245 0 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
246 : return Symb.getValue();
247 : }
248 177486 :
249 177486 : Expected<section_iterator>
250 : COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
251 : COFFSymbolRef Symb = getCOFFSymbol(Ref);
252 : if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
253 : return section_end();
254 : const coff_section *Sec = nullptr;
255 : if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
256 : return errorCodeToError(EC);
257 : DataRefImpl Ret;
258 : Ret.p = reinterpret_cast<uintptr_t>(Sec);
259 : return section_iterator(SectionRef(Ret, this));
260 : }
261 177486 :
262 : unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
263 : COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
264 4148 : return Symb.getSectionNumber();
265 4148 : }
266 4148 :
267 : void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
268 4144 : const coff_section *Sec = toSec(Ref);
269 4144 : Sec += 1;
270 4 : Ref.p = reinterpret_cast<uintptr_t>(Sec);
271 : }
272 4 :
273 4 : std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
274 : StringRef &Result) const {
275 0 : const coff_section *Sec = toSec(Ref);
276 : return getSectionName(Sec, Result);
277 4148 : }
278 :
279 2764 : uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
280 2764 : const coff_section *Sec = toSec(Ref);
281 2764 : uint64_t Result = Sec->VirtualAddress;
282 2764 :
283 0 : // The section VirtualAddress does not include ImageBase, and we want to
284 : // return virtual addresses.
285 : Result += getImageBase();
286 : return Result;
287 900 : }
288 900 :
289 : uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
290 : return toSec(Sec) - SectionTable;
291 0 : }
292 :
293 : uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
294 0 : return getSectionSize(toSec(Ref));
295 0 : }
296 :
297 : std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
298 745 : StringRef &Result) const {
299 745 : const coff_section *Sec = toSec(Ref);
300 745 : ArrayRef<uint8_t> Res;
301 745 : std::error_code EC = getSectionContents(Sec, Res);
302 : Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
303 745 : return EC;
304 : }
305 :
306 : uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
307 621 : const coff_section *Sec = toSec(Ref);
308 621 : return Sec->getAlignment();
309 0 : }
310 621 :
311 : bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
312 : return false;
313 : }
314 621 :
315 : bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
316 : const coff_section *Sec = toSec(Ref);
317 : return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
318 : }
319 136 :
320 136 : bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
321 136 : const coff_section *Sec = toSec(Ref);
322 : return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
323 136 : }
324 :
325 120 : bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
326 : const coff_section *Sec = toSec(Ref);
327 120 : const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
328 : COFF::IMAGE_SCN_MEM_READ |
329 120 : COFF::IMAGE_SCN_MEM_WRITE;
330 : return (Sec->Characteristics & BssFlags) == BssFlags;
331 : }
332 :
333 120 : unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
334 : uintptr_t Offset =
335 : uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
336 86 : assert((Offset % sizeof(coff_section)) == 0);
337 : return (Offset / sizeof(coff_section)) + 1;
338 : }
339 :
340 : bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
341 : const coff_section *Sec = toSec(Ref);
342 6285 : // In COFF, a virtual section won't have any in-file
343 6285 : // content, so the file pointer to the content will be zero.
344 : return Sec->PointerToRawData == 0;
345 : }
346 6285 :
347 : static uint32_t getNumberOfRelocations(const coff_section *Sec,
348 : MemoryBufferRef M, const uint8_t *base) {
349 6285 : // The field for the number of relocations in COFF section table is only
350 59 : // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
351 59 : // NumberOfRelocations field, and the actual relocation count is stored in the
352 29 : // VirtualAddress field in the first relocation entry.
353 : if (Sec->hasExtendedRelocations()) {
354 : const coff_relocation *FirstReloc;
355 6285 : if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
356 186 : base + Sec->PointerToRelocations)))
357 : return 0;
358 6285 : // -1 to exclude this first relocation entry.
359 8 : return FirstReloc->VirtualAddress - 1;
360 : }
361 6285 : return Sec->NumberOfRelocations;
362 2086 : }
363 :
364 6285 : static const coff_relocation *
365 7 : getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
366 : uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
367 6285 : if (!NumRelocs)
368 752 : return nullptr;
369 : auto begin = reinterpret_cast<const coff_relocation *>(
370 6285 : Base + Sec->PointerToRelocations);
371 : if (Sec->hasExtendedRelocations()) {
372 : // Skip the first relocation entry repurposed to store the number of
373 4 : // relocations.
374 4 : begin++;
375 4 : }
376 : if (Binary::checkOffset(M, uintptr_t(begin),
377 : sizeof(coff_relocation) * NumRelocs))
378 : return nullptr;
379 1962 : return begin;
380 1962 : }
381 1962 :
382 318 : relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
383 1644 : const coff_section *Sec = toSec(Ref);
384 1644 : const coff_relocation *begin = getFirstReloc(Sec, Data, base());
385 0 : if (begin && Sec->VirtualAddress != 0)
386 : report_fatal_error("Sections with relocations should have an address of 0");
387 1644 : DataRefImpl Ret;
388 6576 : Ret.p = reinterpret_cast<uintptr_t>(begin);
389 : return relocation_iterator(RelocationRef(Ret, this));
390 : }
391 210 :
392 210 : relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
393 210 : const coff_section *Sec = toSec(Ref);
394 : const coff_relocation *I = getFirstReloc(Sec, Data, base());
395 : if (I)
396 8259 : I += getNumberOfRelocations(Sec, Data, base());
397 8259 : DataRefImpl Ret;
398 8259 : Ret.p = reinterpret_cast<uintptr_t>(I);
399 8259 : return relocation_iterator(RelocationRef(Ret, this));
400 8259 : }
401 :
402 3534 : // Initialize the pointer to the symbol table.
403 : std::error_code COFFObjectFile::initSymbolTablePtr() {
404 3534 : if (COFFHeader)
405 3534 : if (std::error_code EC = getObject(
406 : SymbolTable16, Data, base() + getPointerToSymbolTable(),
407 : (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
408 727 : return EC;
409 727 :
410 727 : if (COFFBigObjHeader)
411 : if (std::error_code EC = getObject(
412 : SymbolTable32, Data, base() + getPointerToSymbolTable(),
413 : (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
414 727 : return EC;
415 727 :
416 : // Find string table. The first four byte of the string table contains the
417 : // total size of the string table, including the size field itself. If the
418 196 : // string table is empty, the value of the first four byte would be 4.
419 196 : uint32_t StringTableOffset = getPointerToSymbolTable() +
420 : getNumberOfSymbols() * getSymbolTableEntrySize();
421 : const uint8_t *StringTableAddr = base() + StringTableOffset;
422 150560 : const ulittle32_t *StringTableSizePtr;
423 150560 : if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
424 : return EC;
425 : StringTableSize = *StringTableSizePtr;
426 841 : if (std::error_code EC =
427 : getObject(StringTable, Data, StringTableAddr, StringTableSize))
428 841 : return EC;
429 841 :
430 841 : // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
431 841 : // tools like cvtres write a size of 0 for an empty table instead of 4.
432 841 : if (StringTableSize < 4)
433 : StringTableSize = 4;
434 :
435 34 : // Check that the string table is null terminated if has any in it.
436 34 : if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
437 34 : return object_error::parse_failed;
438 : return std::error_code();
439 : }
440 132 :
441 132 : uint64_t COFFObjectFile::getImageBase() const {
442 : if (PE32Header)
443 : return PE32Header->ImageBase;
444 342 : else if (PE32PlusHeader)
445 342 : return PE32PlusHeader->ImageBase;
446 342 : // This actually comes up in practice.
447 : return 0;
448 : }
449 41 :
450 41 : // Returns the file offset for the given VA.
451 41 : std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
452 : uint64_t ImageBase = getImageBase();
453 : uint64_t Rva = Addr - ImageBase;
454 515 : assert(Rva <= UINT32_MAX);
455 515 : return getRvaPtr((uint32_t)Rva, Res);
456 : }
457 :
458 : // Returns the file offset for the given RVA.
459 515 : std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
460 : for (const SectionRef &S : sections()) {
461 : const coff_section *Section = getCOFFSection(S);
462 354 : uint32_t SectionStart = Section->VirtualAddress;
463 : uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
464 354 : if (SectionStart <= Addr && Addr < SectionEnd) {
465 : uint32_t Offset = Addr - SectionStart;
466 354 : Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
467 : return std::error_code();
468 : }
469 725 : }
470 725 : return object_error::parse_failed;
471 : }
472 :
473 725 : std::error_code
474 : COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
475 : ArrayRef<uint8_t> &Contents) const {
476 0 : for (const SectionRef &S : sections()) {
477 : const coff_section *Section = getCOFFSection(S);
478 : uint32_t SectionStart = Section->VirtualAddress;
479 : // Check if this RVA is within the section bounds. Be careful about integer
480 : // overflow.
481 : uint32_t OffsetIntoSection = RVA - SectionStart;
482 : if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
483 : Size <= Section->VirtualSize - OffsetIntoSection) {
484 0 : uintptr_t Begin =
485 0 : uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
486 0 : Contents =
487 : ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
488 0 : return std::error_code();
489 : }
490 0 : }
491 : return object_error::parse_failed;
492 : }
493 :
494 0 : // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
495 0 : // table entry.
496 0 : std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
497 0 : StringRef &Name) const {
498 : uintptr_t IntPtr = 0;
499 0 : if (std::error_code EC = getRvaPtr(Rva, IntPtr))
500 : return EC;
501 : const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
502 : Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
503 0 : Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
504 : return std::error_code();
505 0 : }
506 0 :
507 0 : std::error_code
508 : COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
509 : const codeview::DebugInfo *&PDBInfo,
510 : StringRef &PDBFileName) const {
511 1300 : ArrayRef<uint8_t> InfoBytes;
512 1300 : if (std::error_code EC = getRvaAndSizeAsBytes(
513 1300 : DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
514 1300 : return EC;
515 1 : if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
516 : return object_error::parse_failed;
517 1299 : PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
518 3897 : InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
519 : PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
520 : InfoBytes.size());
521 1300 : // Truncate the name at the first null byte. Ignore any padding.
522 1300 : PDBFileName = PDBFileName.split('\0').first;
523 1300 : return std::error_code();
524 1300 : }
525 660 :
526 : std::error_code
527 1300 : COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
528 3900 : StringRef &PDBFileName) const {
529 : for (const debug_directory &D : debug_directories())
530 : if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
531 : return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
532 1594 : // If we get here, there is no PDB info to return.
533 1594 : PDBInfo = nullptr;
534 1593 : PDBFileName = StringRef();
535 1593 : return std::error_code();
536 3186 : }
537 0 :
538 : // Find the import table.
539 1594 : std::error_code COFFObjectFile::initImportTablePtr() {
540 1 : // First, we get the RVA of the import table. If the file lacks a pointer to
541 1 : // the import table, do nothing.
542 3 : const data_directory *DataEntry;
543 0 : if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
544 : return std::error_code();
545 :
546 : // Do nothing if the pointer to import table is NULL.
547 : if (DataEntry->RelativeVirtualAddress == 0)
548 1594 : return std::error_code();
549 1594 :
550 1594 : uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
551 :
552 1594 : // Find the section that contains the RVA. This is needed because the RVA is
553 0 : // the import table's memory address which is different from its file offset.
554 1594 : uintptr_t IntPtr = 0;
555 1594 : if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
556 1594 : return EC;
557 0 : if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
558 : return EC;
559 : ImportDirectory = reinterpret_cast<
560 : const coff_import_directory_table_entry *>(IntPtr);
561 1594 : return std::error_code();
562 19 : }
563 :
564 : // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
565 1594 : std::error_code COFFObjectFile::initDelayImportTablePtr() {
566 0 : const data_directory *DataEntry;
567 1594 : if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
568 : return std::error_code();
569 : if (DataEntry->RelativeVirtualAddress == 0)
570 1689 : return std::error_code();
571 1689 :
572 106 : uint32_t RVA = DataEntry->RelativeVirtualAddress;
573 1583 : NumberOfDelayImportDirectory = DataEntry->Size /
574 464 : sizeof(delay_import_directory_table_entry) - 1;
575 :
576 : uintptr_t IntPtr = 0;
577 : if (std::error_code EC = getRvaPtr(RVA, IntPtr))
578 : return EC;
579 : DelayImportDirectory = reinterpret_cast<
580 40 : const delay_import_directory_table_entry *>(IntPtr);
581 40 : return std::error_code();
582 40 : }
583 :
584 40 : // Find the export table.
585 : std::error_code COFFObjectFile::initExportTablePtr() {
586 : // First, we get the RVA of the export table. If the file lacks a pointer to
587 : // the export table, do nothing.
588 3243 : const data_directory *DataEntry;
589 6673 : if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
590 6673 : return std::error_code();
591 :
592 6673 : // Do nothing if the pointer to export table is NULL.
593 6673 : if (DataEntry->RelativeVirtualAddress == 0)
594 3243 : return std::error_code();
595 6486 :
596 3243 : uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
597 : uintptr_t IntPtr = 0;
598 : if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
599 0 : return EC;
600 : ExportDirectory =
601 : reinterpret_cast<const export_directory_table_entry *>(IntPtr);
602 : return std::error_code();
603 21 : }
604 :
605 43 : std::error_code COFFObjectFile::initBaseRelocPtr() {
606 43 : const data_directory *DataEntry;
607 : if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
608 : return std::error_code();
609 : if (DataEntry->RelativeVirtualAddress == 0)
610 43 : return std::error_code();
611 43 :
612 21 : uintptr_t IntPtr = 0;
613 : if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
614 21 : return EC;
615 21 : BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
616 21 : IntPtr);
617 21 : BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
618 : IntPtr + DataEntry->Size);
619 : // FIXME: Verify the section containing BaseRelocHeader has at least
620 0 : // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
621 : return std::error_code();
622 : }
623 :
624 : std::error_code COFFObjectFile::initDebugDirectoryPtr() {
625 70 : // Get the RVA of the debug directory. Do nothing if it does not exist.
626 : const data_directory *DataEntry;
627 70 : if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
628 70 : return std::error_code();
629 0 :
630 70 : // Do nothing if the RVA is NULL.
631 70 : if (DataEntry->RelativeVirtualAddress == 0)
632 140 : return std::error_code();
633 70 :
634 : // Check that the size is a multiple of the entry size.
635 : if (DataEntry->Size % sizeof(debug_directory) != 0)
636 : return object_error::parse_failed;
637 20 :
638 : uintptr_t IntPtr = 0;
639 : if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
640 20 : return EC;
641 20 : DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
642 20 : DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
643 0 : IntPtr + DataEntry->Size);
644 20 : // FIXME: Verify the section containing DebugDirectoryBegin has at least
645 0 : // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
646 20 : return std::error_code();
647 20 : }
648 20 :
649 : std::error_code COFFObjectFile::initLoadConfigPtr() {
650 : // Get the RVA of the debug directory. Do nothing if it does not exist.
651 20 : const data_directory *DataEntry;
652 20 : if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
653 : return std::error_code();
654 :
655 : // Do nothing if the RVA is NULL.
656 0 : if (DataEntry->RelativeVirtualAddress == 0)
657 : return std::error_code();
658 0 : uintptr_t IntPtr = 0;
659 0 : if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
660 0 : return EC;
661 :
662 0 : LoadConfig = (const void *)IntPtr;
663 0 : return std::error_code();
664 0 : }
665 :
666 : COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
667 : : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
668 1926 : COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
669 : DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
670 : SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
671 : ImportDirectory(nullptr),
672 1926 : DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
673 1599 : ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
674 : DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
675 : // Check that we at least have enough room for a header.
676 654 : if (!checkSize(Data, EC, sizeof(coff_file_header)))
677 271 : return;
678 :
679 : // The current location in the file where we are looking at.
680 : uint64_t CurPtr = 0;
681 :
682 : // PE header is optional and is present only in executables. If it exists,
683 56 : // it is placed right after COFF header.
684 56 : bool HasPEHeader = false;
685 0 :
686 112 : // Check if this is a PE/COFF file.
687 0 : if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
688 56 : // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
689 : // PE signature to find 'normal' COFF header.
690 56 : const auto *DH = reinterpret_cast<const dos_header *>(base());
691 : if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
692 : CurPtr = DH->AddressOfNewExeHeader;
693 : // Check the PE magic bytes. ("PE\0\0")
694 1926 : if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
695 : EC = object_error::parse_failed;
696 1926 : return;
697 1599 : }
698 654 : CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
699 315 : HasPEHeader = true;
700 : }
701 : }
702 24 :
703 12 : if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
704 : return;
705 12 :
706 12 : // It might be a bigobj file, let's check. Note that COFF bigobj and COFF
707 0 : // import libraries share a common prefix but bigobj is more restrictive.
708 12 : if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
709 : COFFHeader->NumberOfSections == uint16_t(0xffff) &&
710 12 : checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
711 : if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
712 : return;
713 :
714 1926 : // Verify that we are dealing with bigobj.
715 : if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
716 : std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
717 : sizeof(COFF::BigObjMagic)) == 0) {
718 1926 : COFFHeader = nullptr;
719 1599 : CurPtr += sizeof(coff_bigobj_file_header);
720 : } else {
721 : // It's not a bigobj.
722 654 : COFFBigObjHeader = nullptr;
723 280 : }
724 : }
725 : if (COFFHeader) {
726 47 : // The prior checkSize call may have failed. This isn't a hard error
727 47 : // because we were just trying to sniff out bigobj.
728 0 : EC = std::error_code();
729 47 : CurPtr += sizeof(coff_file_header);
730 :
731 47 : if (COFFHeader->isImportLibrary())
732 : return;
733 : }
734 1926 :
735 : if (HasPEHeader) {
736 1926 : const pe32_header *Header;
737 1599 : if ((EC = getObject(Header, Data, base() + CurPtr)))
738 654 : return;
739 230 :
740 : const uint8_t *DataDirAddr;
741 97 : uint64_t DataDirSize;
742 97 : if (Header->Magic == COFF::PE32Header::PE32) {
743 0 : PE32Header = Header;
744 97 : DataDirAddr = base() + CurPtr + sizeof(pe32_header);
745 : DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
746 97 : } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
747 194 : PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
748 : DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
749 : DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
750 97 : } else {
751 : // It's neither PE32 nor PE32+.
752 : EC = object_error::parse_failed;
753 1926 : return;
754 : }
755 : if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
756 1926 : return;
757 1599 : }
758 :
759 : if (COFFHeader)
760 654 : CurPtr += COFFHeader->SizeOfOptionalHeader;
761 282 :
762 : if ((EC = getObject(SectionTable, Data, base() + CurPtr,
763 : (uint64_t)getNumberOfSections() * sizeof(coff_section))))
764 45 : return;
765 0 :
766 : // Initialize the pointer to the symbol table.
767 45 : if (getPointerToSymbolTable() != 0) {
768 45 : if ((EC = initSymbolTablePtr())) {
769 0 : SymbolTable16 = nullptr;
770 45 : SymbolTable32 = nullptr;
771 45 : StringTable = nullptr;
772 90 : StringTableSize = 0;
773 : }
774 : } else {
775 45 : // We had better not have any symbols if we don't have a symbol table.
776 : if (getNumberOfSymbols() != 0) {
777 : EC = object_error::parse_failed;
778 1926 : return;
779 : }
780 : }
781 1926 :
782 1599 : // Initialize the pointer to the beginning of the import table.
783 : if ((EC = initImportTablePtr()))
784 : return;
785 654 : if ((EC = initDelayImportTablePtr()))
786 297 : return;
787 30 :
788 30 : // Initialize the pointer to the export table.
789 0 : if ((EC = initExportTablePtr()))
790 : return;
791 30 :
792 30 : // Initialize the pointer to the base relocation table.
793 : if ((EC = initBaseRelocPtr()))
794 : return;
795 1926 :
796 : // Initialize the pointer to the export table.
797 : if ((EC = initDebugDirectoryPtr()))
798 : return;
799 :
800 : if ((EC = initLoadConfigPtr()))
801 : return;
802 :
803 1926 : EC = std::error_code();
804 : }
805 1926 :
806 0 : basic_symbol_iterator COFFObjectFile::symbol_begin() const {
807 : DataRefImpl Ret;
808 : Ret.p = getSymbolTable();
809 : return basic_symbol_iterator(SymbolRef(Ret, this));
810 : }
811 :
812 : basic_symbol_iterator COFFObjectFile::symbol_end() const {
813 : // The symbol table ends where the string table begins.
814 : DataRefImpl Ret;
815 : Ret.p = reinterpret_cast<uintptr_t>(StringTable);
816 : return basic_symbol_iterator(SymbolRef(Ret, this));
817 : }
818 :
819 : import_directory_iterator COFFObjectFile::import_directory_begin() const {
820 1923 : if (!ImportDirectory)
821 327 : return import_directory_end();
822 : if (ImportDirectory->isNull())
823 327 : return import_directory_end();
824 : return import_directory_iterator(
825 0 : ImportDirectoryEntryRef(ImportDirectory, 0, this));
826 : }
827 327 :
828 : import_directory_iterator COFFObjectFile::import_directory_end() const {
829 : return import_directory_iterator(
830 : ImportDirectoryEntryRef(nullptr, -1, this));
831 : }
832 1926 :
833 : delay_import_directory_iterator
834 : COFFObjectFile::delay_import_directory_begin() const {
835 : return delay_import_directory_iterator(
836 : DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
837 3198 : }
838 1926 :
839 1 : delay_import_directory_iterator
840 1 : COFFObjectFile::delay_import_directory_end() const {
841 : return delay_import_directory_iterator(
842 : DelayImportDirectoryEntryRef(
843 : DelayImportDirectory, NumberOfDelayImportDirectory, this));
844 2 : }
845 1 :
846 : export_directory_iterator COFFObjectFile::export_directory_begin() const {
847 1 : return export_directory_iterator(
848 1 : ExportDirectoryEntryRef(ExportDirectory, 0, this));
849 : }
850 :
851 0 : export_directory_iterator COFFObjectFile::export_directory_end() const {
852 : if (!ExportDirectory)
853 : return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
854 1926 : ExportDirectoryEntryRef Ref(ExportDirectory,
855 : ExportDirectory->AddressTableEntries, this);
856 : return export_directory_iterator(Ref);
857 1925 : }
858 1925 :
859 : section_iterator COFFObjectFile::section_begin() const {
860 1925 : DataRefImpl Ret;
861 : Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
862 : return section_iterator(SectionRef(Ret, this));
863 : }
864 1926 :
865 : section_iterator COFFObjectFile::section_end() const {
866 327 : DataRefImpl Ret;
867 0 : int NumSections =
868 : COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
869 : Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
870 : return section_iterator(SectionRef(Ret, this));
871 654 : }
872 100 :
873 100 : base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
874 100 : return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
875 227 : }
876 227 :
877 227 : base_reloc_iterator COFFObjectFile::base_reloc_end() const {
878 227 : return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
879 : }
880 :
881 : uint8_t COFFObjectFile::getBytesInAddress() const {
882 0 : return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
883 : }
884 327 :
885 : StringRef COFFObjectFile::getFileFormatName() const {
886 : switch(getMachine()) {
887 : case COFF::IMAGE_FILE_MACHINE_I386:
888 1926 : return "COFF-i386";
889 1925 : case COFF::IMAGE_FILE_MACHINE_AMD64:
890 : return "COFF-x86-64";
891 3852 : case COFF::IMAGE_FILE_MACHINE_ARMNT:
892 3852 : return "COFF-ARM";
893 : case COFF::IMAGE_FILE_MACHINE_ARM64:
894 : return "COFF-ARM64";
895 : default:
896 3852 : return "COFF-<unknown arch>";
897 1594 : }
898 0 : }
899 0 :
900 0 : Triple::ArchType COFFObjectFile::getArch() const {
901 0 : switch (getMachine()) {
902 : case COFF::IMAGE_FILE_MACHINE_I386:
903 : return Triple::x86;
904 : case COFF::IMAGE_FILE_MACHINE_AMD64:
905 0 : return Triple::x86_64;
906 : case COFF::IMAGE_FILE_MACHINE_ARMNT:
907 0 : return Triple::thumb;
908 : case COFF::IMAGE_FILE_MACHINE_ARM64:
909 : return Triple::aarch64;
910 : default:
911 : return Triple::UnknownArch;
912 1926 : }
913 : }
914 1926 :
915 : Expected<uint64_t> COFFObjectFile::getStartAddress() const {
916 : if (PE32Header)
917 : return PE32Header->AddressOfEntryPoint;
918 1926 : return 0;
919 : }
920 :
921 : iterator_range<import_directory_iterator>
922 1926 : COFFObjectFile::import_directories() const {
923 : return make_range(import_directory_begin(), import_directory_end());
924 : }
925 :
926 1926 : iterator_range<delay_import_directory_iterator>
927 : COFFObjectFile::delay_import_directories() const {
928 : return make_range(delay_import_directory_begin(),
929 1926 : delay_import_directory_end());
930 : }
931 :
932 1926 : iterator_range<export_directory_iterator>
933 : COFFObjectFile::export_directories() const {
934 : return make_range(export_directory_begin(), export_directory_end());
935 797 : }
936 :
937 797 : iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
938 2391 : return make_range(base_reloc_begin(), base_reloc_end());
939 : }
940 :
941 3556 : std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
942 : Res = PE32Header;
943 : return std::error_code();
944 3556 : }
945 10668 :
946 : std::error_code
947 : COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
948 52 : Res = PE32PlusHeader;
949 52 : return std::error_code();
950 30 : }
951 :
952 0 : std::error_code
953 : COFFObjectFile::getDataDirectory(uint32_t Index,
954 : const data_directory *&Res) const {
955 : // Error if there's no data directory or the index is out of range.
956 : if (!DataDirectory) {
957 82 : Res = nullptr;
958 : return object_error::parse_failed;
959 82 : }
960 : assert(PE32Header || PE32PlusHeader);
961 : uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
962 : : PE32PlusHeader->NumberOfRvaAndSize;
963 23 : if (Index >= NumEnt) {
964 : Res = nullptr;
965 46 : return object_error::parse_failed;
966 : }
967 : Res = &DataDirectory[Index];
968 : return std::error_code();
969 23 : }
970 :
971 : std::error_code COFFObjectFile::getSection(int32_t Index,
972 46 : const coff_section *&Result) const {
973 : Result = nullptr;
974 : if (COFF::isReservedSectionNumber(Index))
975 118 : return std::error_code();
976 : if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
977 236 : // We already verified the section table data, so no need to check again.
978 : Result = SectionTable + (Index - 1);
979 : return std::error_code();
980 118 : }
981 118 : return object_error::parse_failed;
982 : }
983 :
984 : std::error_code COFFObjectFile::getSection(StringRef SectionName,
985 40 : const coff_section *&Result) const {
986 : Result = nullptr;
987 : StringRef SecName;
988 4189 : for (const SectionRef &Section : sections()) {
989 : if (std::error_code E = Section.getName(SecName))
990 4189 : return E;
991 12567 : if (SecName == SectionName) {
992 : Result = getCOFFSection(Section);
993 : return std::error_code();
994 5936 : }
995 : }
996 : return object_error::parse_failed;
997 11872 : }
998 5936 :
999 17808 : std::error_code COFFObjectFile::getString(uint32_t Offset,
1000 : StringRef &Result) const {
1001 : if (StringTableSize <= 4)
1002 14 : // Tried to get a string from an empty string table.
1003 14 : return object_error::parse_failed;
1004 : if (Offset >= StringTableSize)
1005 : return object_error::unexpected_eof;
1006 14 : Result = StringRef(StringTable + Offset);
1007 14 : return std::error_code();
1008 : }
1009 :
1010 703 : std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
1011 703 : StringRef &Res) const {
1012 : return getSymbolName(Symbol.getGeneric(), Res);
1013 : }
1014 677 :
1015 1354 : std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1016 : StringRef &Res) const {
1017 250 : // Check for string table entry. First 4 bytes are 0.
1018 : if (Symbol->Name.Offset.Zeroes == 0) {
1019 351 : if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
1020 : return EC;
1021 45 : return std::error_code();
1022 : }
1023 28 :
1024 : if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
1025 3 : // Null terminated, let ::strlen figure out the length.
1026 : Res = StringRef(Symbol->Name.ShortName);
1027 : else
1028 : // Not null terminated, use all 8 bytes.
1029 152873 : Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
1030 305746 : return std::error_code();
1031 : }
1032 :
1033 151337 : ArrayRef<uint8_t>
1034 151337 : COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
1035 375 : const uint8_t *Aux = nullptr;
1036 375 :
1037 254 : size_t SymbolSize = getSymbolTableEntrySize();
1038 254 : if (Symbol.getNumberOfAuxSymbols() > 0) {
1039 9 : // AUX data comes immediately after the symbol in COFF
1040 9 : Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
1041 : #ifndef NDEBUG
1042 : // Verify that the Aux symbol points to a valid entry in the symbol table.
1043 : uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
1044 5 : if (Offset < getPointerToSymbolTable() ||
1045 5 : Offset >=
1046 : getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
1047 : report_fatal_error("Aux Symbol data was outside of symbol table.");
1048 :
1049 : assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
1050 : "Aux Symbol data did not point to the beginning of a symbol");
1051 26 : #endif
1052 26 : }
1053 : return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
1054 : }
1055 :
1056 23 : std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
1057 : StringRef &Res) const {
1058 23 : StringRef Name;
1059 : if (Sec->Name[COFF::NameSize - 1] == 0)
1060 : // Null terminated, let ::strlen figure out the length.
1061 : Name = Sec->Name;
1062 92 : else
1063 92 : // Not null terminated, use all 8 bytes.
1064 : Name = StringRef(Sec->Name, COFF::NameSize);
1065 :
1066 14 : // Check for string table entry. First byte is '/'.
1067 14 : if (Name.startswith("/")) {
1068 : uint32_t Offset;
1069 : if (Name.startswith("//")) {
1070 194 : if (decodeBase64StringEntry(Name.substr(2), Offset))
1071 194 : return object_error::parse_failed;
1072 194 : } else {
1073 : if (Name.substr(1).getAsInteger(10, Offset))
1074 : return object_error::parse_failed;
1075 : }
1076 166 : if (std::error_code EC = getString(Offset, Name))
1077 166 : return EC;
1078 166 : }
1079 :
1080 : Res = Name;
1081 : return std::error_code();
1082 13446 : }
1083 :
1084 : uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1085 13446 : // SizeOfRawData and VirtualSize change what they represent depending on
1086 9594 : // whether or not we have an executable image.
1087 9594 : //
1088 : // For object files, SizeOfRawData contains the size of section's data;
1089 : // VirtualSize should be zero but isn't due to buggy COFF writers.
1090 3852 : //
1091 3852 : // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1092 3852 : // actual section size is in VirtualSize. It is possible for VirtualSize to
1093 0 : // be greater than SizeOfRawData; the contents past that point should be
1094 0 : // considered to be zero.
1095 : if (getDOSHeader())
1096 3852 : return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1097 3852 : return Sec->SizeOfRawData;
1098 : }
1099 :
1100 7316 : std::error_code
1101 : COFFObjectFile::getSectionContents(const coff_section *Sec,
1102 7316 : ArrayRef<uint8_t> &Res) const {
1103 7316 : // In COFF, a virtual section won't have any in-file
1104 62 : // content, so the file pointer to the content will be zero.
1105 14508 : if (Sec->PointerToRawData == 0)
1106 : return std::error_code();
1107 7254 : // The only thing that we need to verify is that the contents is contained
1108 7254 : // within the file bounds. We don't need to make sure it doesn't cover other
1109 : // data, as there's nothing that says that is not allowed.
1110 0 : uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1111 : uint32_t SectionSize = getSectionSize(Sec);
1112 : if (checkOffset(Data, ConStart, SectionSize))
1113 0 : return object_error::parse_failed;
1114 : Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1115 0 : return std::error_code();
1116 0 : }
1117 0 :
1118 0 : const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1119 0 : return reinterpret_cast<const coff_relocation*>(Rel.p);
1120 : }
1121 0 :
1122 0 : void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1123 : Rel.p = reinterpret_cast<uintptr_t>(
1124 : reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1125 0 : }
1126 :
1127 : uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
1128 2955 : const coff_relocation *R = toRel(Rel);
1129 : return R->VirtualAddress;
1130 2955 : }
1131 :
1132 0 : symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1133 2955 : const coff_relocation *R = toRel(Rel);
1134 0 : DataRefImpl Ref;
1135 5910 : if (R->SymbolTableIndex >= getNumberOfSymbols())
1136 2955 : return symbol_end();
1137 : if (SymbolTable16)
1138 : Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
1139 5514 : else if (SymbolTable32)
1140 : Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
1141 5518 : else
1142 : llvm_unreachable("no symbol table pointer!");
1143 : return symbol_iterator(SymbolRef(Ref, this));
1144 5777 : }
1145 :
1146 : uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1147 5777 : const coff_relocation* R = toRel(Rel);
1148 2367 : return R->Type;
1149 0 : }
1150 2367 :
1151 : const coff_section *
1152 : COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
1153 3410 : return toSec(Section.getRawDataRefImpl());
1154 : }
1155 5354 :
1156 : COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
1157 : if (SymbolTable16)
1158 733 : return toSymb<coff_symbol16>(Ref);
1159 3410 : if (SymbolTable32)
1160 : return toSymb<coff_symbol32>(Ref);
1161 : llvm_unreachable("no symbol table pointer!");
1162 : }
1163 351 :
1164 : COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
1165 : return getCOFFSymbol(Symbol.getRawDataRefImpl());
1166 351 : }
1167 351 :
1168 : const coff_relocation *
1169 351 : COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
1170 : return toRel(Reloc.getRawDataRefImpl());
1171 : }
1172 :
1173 : ArrayRef<coff_relocation>
1174 : COFFObjectFile::getRelocations(const coff_section *Sec) const {
1175 : return {getFirstReloc(Sec, Data, base()),
1176 : getNumberOfRelocations(Sec, Data, base())};
1177 : }
1178 :
1179 : #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1180 : case COFF::reloc_type: \
1181 : return #reloc_type;
1182 351 :
1183 : StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
1184 : switch (getMachine()) {
1185 8514 : case COFF::IMAGE_FILE_MACHINE_AMD64:
1186 : switch (Type) {
1187 8514 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1188 8514 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1189 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1190 12410 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1191 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1192 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1193 2309 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1194 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1195 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1196 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1197 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1198 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1199 1 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1200 0 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1201 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1202 587 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1203 0 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1204 : default:
1205 588 : return "Unknown";
1206 0 : }
1207 : break;
1208 : case COFF::IMAGE_FILE_MACHINE_ARMNT:
1209 8514 : switch (Type) {
1210 8514 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
1211 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
1212 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
1213 153604 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
1214 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
1215 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
1216 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
1217 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1218 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
1219 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
1220 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
1221 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
1222 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
1223 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
1224 150301 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1225 150302 : default:
1226 3303 : return "Unknown";
1227 : }
1228 : break;
1229 : case COFF::IMAGE_FILE_MACHINE_ARM64:
1230 3058 : switch (Type) {
1231 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
1232 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
1233 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
1234 3058 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
1235 14 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
1236 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
1237 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
1238 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
1239 3044 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
1240 3044 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
1241 3044 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
1242 0 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
1243 3044 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
1244 3044 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
1245 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
1246 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
1247 19159 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1248 19159 : default:
1249 : return "Unknown";
1250 : }
1251 2800 : break;
1252 2800 : case COFF::IMAGE_FILE_MACHINE_I386:
1253 2800 : switch (Type) {
1254 2800 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1255 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1256 16727 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1257 16727 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1258 16727 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1259 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1260 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1261 1463 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1262 1463 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1263 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1264 1463 : LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1265 2 : default:
1266 1461 : return "Unknown";
1267 1461 : }
1268 0 : break;
1269 0 : default:
1270 : return "Unknown";
1271 0 : }
1272 4383 : }
1273 :
1274 : #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1275 523 :
1276 523 : void COFFObjectFile::getRelocationTypeName(
1277 523 : DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1278 : const coff_relocation *Reloc = toRel(Rel);
1279 : StringRef Res = getRelocationTypeName(Reloc->Type);
1280 : Result.append(Res.begin(), Res.end());
1281 9112 : }
1282 9112 :
1283 : bool COFFObjectFile::isRelocatableObject() const {
1284 : return !DataDirectory;
1285 13836 : }
1286 13836 :
1287 13832 : bool ImportDirectoryEntryRef::
1288 4 : operator==(const ImportDirectoryEntryRef &Other) const {
1289 4 : return ImportTable == Other.ImportTable && Index == Other.Index;
1290 0 : }
1291 :
1292 : void ImportDirectoryEntryRef::moveNext() {
1293 830 : ++Index;
1294 830 : if (ImportTable[Index].isNull()) {
1295 : Index = -1;
1296 : ImportTable = nullptr;
1297 : }
1298 60 : }
1299 60 :
1300 : std::error_code ImportDirectoryEntryRef::getImportTableEntry(
1301 : const coff_import_directory_table_entry *&Result) const {
1302 : return getObject(Result, OwningObject->Data, ImportTable + Index);
1303 2069 : }
1304 :
1305 2069 : static imported_symbol_iterator
1306 : makeImportedSymbolIterator(const COFFObjectFile *Object,
1307 : uintptr_t Ptr, int Index) {
1308 : if (Object->getBytesInAddress() == 4) {
1309 : auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
1310 : return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1311 : }
1312 389 : auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
1313 778 : return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1314 150 : }
1315 150 :
1316 1 : static imported_symbol_iterator
1317 2 : importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1318 6 : uintptr_t IntPtr = 0;
1319 58 : Object->getRvaPtr(RVA, IntPtr);
1320 28 : return makeImportedSymbolIterator(Object, IntPtr, 0);
1321 1 : }
1322 1 :
1323 1 : static imported_symbol_iterator
1324 1 : importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1325 1 : uintptr_t IntPtr = 0;
1326 21 : Object->getRvaPtr(RVA, IntPtr);
1327 24 : // Forward the pointer to the last entry which is null.
1328 1 : int Index = 0;
1329 1 : if (Object->getBytesInAddress() == 4) {
1330 1 : auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1331 1 : while (*Entry++)
1332 1 : ++Index;
1333 : } else {
1334 0 : auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1335 : while (*Entry++)
1336 : ++Index;
1337 34 : }
1338 34 : return makeImportedSymbolIterator(Object, IntPtr, Index);
1339 0 : }
1340 5 :
1341 9 : imported_symbol_iterator
1342 0 : ImportDirectoryEntryRef::imported_symbol_begin() const {
1343 0 : return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
1344 0 : OwningObject);
1345 0 : }
1346 0 :
1347 2 : imported_symbol_iterator
1348 11 : ImportDirectoryEntryRef::imported_symbol_end() const {
1349 0 : return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
1350 3 : OwningObject);
1351 1 : }
1352 2 :
1353 1 : iterator_range<imported_symbol_iterator>
1354 : ImportDirectoryEntryRef::imported_symbols() const {
1355 0 : return make_range(imported_symbol_begin(), imported_symbol_end());
1356 : }
1357 :
1358 33 : imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
1359 33 : return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
1360 0 : OwningObject);
1361 1 : }
1362 12 :
1363 1 : imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
1364 4 : return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
1365 1 : OwningObject);
1366 2 : }
1367 4 :
1368 1 : iterator_range<imported_symbol_iterator>
1369 1 : ImportDirectoryEntryRef::lookup_table_symbols() const {
1370 1 : return make_range(lookup_table_begin(), lookup_table_end());
1371 1 : }
1372 0 :
1373 1 : std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1374 1 : uintptr_t IntPtr = 0;
1375 1 : if (std::error_code EC =
1376 1 : OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1377 : return EC;
1378 0 : Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1379 : return std::error_code();
1380 : }
1381 172 :
1382 172 : std::error_code
1383 3 : ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const {
1384 2 : Result = ImportTable[Index].ImportLookupTableRVA;
1385 2 : return std::error_code();
1386 37 : }
1387 26 :
1388 2 : std::error_code
1389 27 : ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
1390 35 : Result = ImportTable[Index].ImportAddressTableRVA;
1391 2 : return std::error_code();
1392 2 : }
1393 34 :
1394 : bool DelayImportDirectoryEntryRef::
1395 0 : operator==(const DelayImportDirectoryEntryRef &Other) const {
1396 : return Table == Other.Table && Index == Other.Index;
1397 : }
1398 :
1399 0 : void DelayImportDirectoryEntryRef::moveNext() {
1400 : ++Index;
1401 : }
1402 :
1403 : imported_symbol_iterator
1404 : DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1405 386 : return importedSymbolBegin(Table[Index].DelayImportNameTable,
1406 : OwningObject);
1407 386 : }
1408 386 :
1409 772 : imported_symbol_iterator
1410 386 : DelayImportDirectoryEntryRef::imported_symbol_end() const {
1411 : return importedSymbolEnd(Table[Index].DelayImportNameTable,
1412 27905 : OwningObject);
1413 27905 : }
1414 :
1415 : iterator_range<imported_symbol_iterator>
1416 80 : DelayImportDirectoryEntryRef::imported_symbols() const {
1417 : return make_range(imported_symbol_begin(), imported_symbol_end());
1418 80 : }
1419 :
1420 : std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
1421 28 : uintptr_t IntPtr = 0;
1422 28 : if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
1423 28 : return EC;
1424 20 : Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1425 20 : return std::error_code();
1426 : }
1427 28 :
1428 : std::error_code DelayImportDirectoryEntryRef::
1429 4 : getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
1430 : Result = Table;
1431 4 : return std::error_code();
1432 : }
1433 :
1434 : std::error_code DelayImportDirectoryEntryRef::
1435 : getImportAddress(int AddrIndex, uint64_t &Result) const {
1436 : uint32_t RVA = Table[Index].DelayImportAddressTable +
1437 66 : AddrIndex * (OwningObject->is64() ? 8 : 4);
1438 13 : uintptr_t IntPtr = 0;
1439 13 : if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1440 : return EC;
1441 20 : if (OwningObject->is64())
1442 20 : Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1443 : else
1444 : Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
1445 : return std::error_code();
1446 33 : }
1447 33 :
1448 33 : bool ExportDirectoryEntryRef::
1449 33 : operator==(const ExportDirectoryEntryRef &Other) const {
1450 : return ExportTable == Other.ExportTable && Index == Other.Index;
1451 : }
1452 :
1453 33 : void ExportDirectoryEntryRef::moveNext() {
1454 33 : ++Index;
1455 33 : }
1456 :
1457 : // Returns the name of the current export symbol. If the symbol is exported only
1458 33 : // by ordinal, the empty string is set as a result.
1459 13 : std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1460 204 : uintptr_t IntPtr = 0;
1461 89 : if (std::error_code EC =
1462 : OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1463 20 : return EC;
1464 122 : Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1465 41 : return std::error_code();
1466 : }
1467 33 :
1468 : // Returns the starting ordinal number.
1469 : std::error_code
1470 : ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1471 4 : Result = ExportTable->OrdinalBase;
1472 4 : return std::error_code();
1473 8 : }
1474 :
1475 : // Returns the export ordinal of the current export symbol.
1476 : std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1477 4 : Result = ExportTable->OrdinalBase + Index;
1478 4 : return std::error_code();
1479 8 : }
1480 :
1481 : // Returns the address of the current export symbol.
1482 : std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1483 4 : uintptr_t IntPtr = 0;
1484 4 : if (std::error_code EC =
1485 : OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1486 : return EC;
1487 23 : const export_address_table_entry *entry =
1488 23 : reinterpret_cast<const export_address_table_entry *>(IntPtr);
1489 46 : Result = entry[Index].ExportRVA;
1490 : return std::error_code();
1491 : }
1492 23 :
1493 23 : // Returns the name of the current export symbol. If the symbol is exported only
1494 46 : // by ordinal, the empty string is set as a result.
1495 : std::error_code
1496 : ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1497 : uintptr_t IntPtr = 0;
1498 23 : if (std::error_code EC =
1499 23 : OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1500 : return EC;
1501 : const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1502 28 :
1503 28 : uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1504 28 : int Offset = 0;
1505 56 : for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1506 0 : I < E; ++I, ++Offset) {
1507 56 : if (*I != Index)
1508 28 : continue;
1509 : if (std::error_code EC =
1510 : OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1511 : return EC;
1512 23 : const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1513 46 : if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1514 23 : return EC;
1515 : Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1516 : return std::error_code();
1517 : }
1518 23 : Result = "";
1519 46 : return std::error_code();
1520 23 : }
1521 :
1522 : std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
1523 29 : const data_directory *DataEntry;
1524 : if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
1525 29 : return EC;
1526 : uint32_t RVA;
1527 : if (auto EC = getExportRVA(RVA))
1528 6 : return EC;
1529 6 : uint32_t Begin = DataEntry->RelativeVirtualAddress;
1530 6 : uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
1531 : Result = (Begin <= RVA && RVA < End);
1532 : return std::error_code();
1533 6 : }
1534 6 :
1535 12 : std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
1536 : uint32_t RVA;
1537 : if (auto EC = getExportRVA(RVA))
1538 : return EC;
1539 6 : uintptr_t IntPtr = 0;
1540 6 : if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
1541 12 : return EC;
1542 : Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1543 : return std::error_code();
1544 : }
1545 6 :
1546 6 : bool ImportedSymbolRef::
1547 : operator==(const ImportedSymbolRef &Other) const {
1548 : return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1549 6 : && Index == Other.Index;
1550 6 : }
1551 12 :
1552 0 : void ImportedSymbolRef::moveNext() {
1553 12 : ++Index;
1554 6 : }
1555 :
1556 : std::error_code
1557 6 : ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1558 : uint32_t RVA;
1559 6 : if (Entry32) {
1560 6 : // If a symbol is imported only by ordinal, it has no name.
1561 : if (Entry32[Index].isOrdinal())
1562 : return std::error_code();
1563 11 : RVA = Entry32[Index].getHintNameRVA();
1564 : } else {
1565 11 : if (Entry64[Index].isOrdinal())
1566 11 : return std::error_code();
1567 11 : RVA = Entry64[Index].getHintNameRVA();
1568 11 : }
1569 0 : uintptr_t IntPtr = 0;
1570 11 : if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1571 12 : return EC;
1572 : // +2 because the first two bytes is hint.
1573 10 : Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
1574 11 : return std::error_code();
1575 : }
1576 :
1577 789 : std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1578 : if (Entry32)
1579 789 : Result = Entry32[Index].isOrdinal();
1580 : else
1581 : Result = Entry64[Index].isOrdinal();
1582 648 : return std::error_code();
1583 648 : }
1584 648 :
1585 : std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1586 : if (Entry32)
1587 : Result = Entry32[Index].getHintNameRVA();
1588 23 : else
1589 23 : Result = Entry64[Index].getHintNameRVA();
1590 23 : return std::error_code();
1591 46 : }
1592 0 :
1593 46 : std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1594 23 : uint32_t RVA;
1595 : if (Entry32) {
1596 : if (Entry32[Index].isOrdinal()) {
1597 : Result = Entry32[Index].getOrdinal();
1598 : return std::error_code();
1599 23 : }
1600 46 : RVA = Entry32[Index].getHintNameRVA();
1601 23 : } else {
1602 : if (Entry64[Index].isOrdinal()) {
1603 : Result = Entry64[Index].getOrdinal();
1604 : return std::error_code();
1605 158 : }
1606 316 : RVA = Entry64[Index].getHintNameRVA();
1607 158 : }
1608 : uintptr_t IntPtr = 0;
1609 : if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1610 : return EC;
1611 759 : Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
1612 759 : return std::error_code();
1613 759 : }
1614 1518 :
1615 0 : Expected<std::unique_ptr<COFFObjectFile>>
1616 759 : ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1617 : std::error_code EC;
1618 1518 : std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1619 759 : if (EC)
1620 : return errorCodeToError(EC);
1621 : return std::move(Ret);
1622 : }
1623 :
1624 : bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
1625 648 : return Header == Other.Header && Index == Other.Index;
1626 648 : }
1627 648 :
1628 1296 : void BaseRelocRef::moveNext() {
1629 0 : // Header->BlockSize is the size of the current block, including the
1630 648 : // size of the header itself.
1631 : uint32_t Size = sizeof(*Header) +
1632 648 : sizeof(coff_base_reloc_block_entry) * (Index + 1);
1633 : if (Size == Header->BlockSize) {
1634 60216 : // .reloc contains a list of base relocation blocks. Each block
1635 60216 : // consists of the header followed by entries. The header contains
1636 60161 : // how many entories will follow. When we reach the end of the
1637 : // current block, proceed to the next block.
1638 593 : Header = reinterpret_cast<const coff_base_reloc_block_header *>(
1639 1186 : reinterpret_cast<const uint8_t *>(Header) + Size);
1640 0 : Index = 0;
1641 593 : } else {
1642 1186 : ++Index;
1643 0 : }
1644 1186 : }
1645 593 :
1646 : std::error_code BaseRelocRef::getType(uint8_t &Type) const {
1647 55 : auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
1648 55 : Type = Entry[Index].getType();
1649 : return std::error_code();
1650 : }
1651 109 :
1652 : std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
1653 109 : auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
1654 0 : Result = Header->PageRVA + Entry[Index].getOffset();
1655 : return std::error_code();
1656 109 : }
1657 0 :
1658 109 : #define RETURN_IF_ERROR(E) \
1659 109 : if (E) \
1660 216 : return E;
1661 109 :
1662 : Expected<ArrayRef<UTF16>>
1663 : ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1664 2 : BinaryStreamReader Reader = BinaryStreamReader(BBS);
1665 : Reader.setOffset(Offset);
1666 2 : uint16_t Length;
1667 0 : RETURN_IF_ERROR(Reader.readInteger(Length));
1668 2 : ArrayRef<UTF16> RawDirString;
1669 2 : RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1670 0 : return RawDirString;
1671 4 : }
1672 2 :
1673 : Expected<ArrayRef<UTF16>>
1674 : ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1675 163 : return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1676 : }
1677 163 :
1678 326 : Expected<const coff_resource_dir_table &>
1679 : ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1680 : const coff_resource_dir_table *Table = nullptr;
1681 130 :
1682 130 : BinaryStreamReader Reader(BBS);
1683 130 : Reader.setOffset(Offset);
1684 : RETURN_IF_ERROR(Reader.readObject(Table));
1685 : assert(Table != nullptr);
1686 60 : return *Table;
1687 : }
1688 60 :
1689 : Expected<const coff_resource_dir_table &>
1690 38 : ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1691 1 : return getTableAtOffset(Entry.Offset.value());
1692 : }
1693 :
1694 82 : Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1695 6 : return getTableAtOffset(0);
1696 : }
|