1 //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file declares the COFFObjectFile class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/ADT/iterator_range.h"
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/COFF.h"
20 #include "llvm/Object/Error.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/BinaryStreamReader.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/MathExtras.h"
27 #include "llvm/Support/MemoryBuffer.h"
35 #include <system_error>
38 using namespace object
;
40 using support::ulittle16_t
;
41 using support::ulittle32_t
;
42 using support::ulittle64_t
;
43 using support::little16_t
;
45 // Returns false if size is greater than the buffer size. And sets ec.
46 static bool checkSize(MemoryBufferRef M
, std::error_code
&EC
, uint64_t Size
) {
47 if (M
.getBufferSize() < Size
) {
48 EC
= object_error::unexpected_eof
;
54 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
55 // Returns unexpected_eof if error.
57 static std::error_code
getObject(const T
*&Obj
, MemoryBufferRef M
,
59 const uint64_t Size
= sizeof(T
)) {
60 uintptr_t Addr
= uintptr_t(Ptr
);
61 if (std::error_code EC
= Binary::checkOffset(M
, Addr
, Size
))
63 Obj
= reinterpret_cast<const T
*>(Addr
);
64 return std::error_code();
67 // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
69 static bool decodeBase64StringEntry(StringRef Str
, uint32_t &Result
) {
70 assert(Str
.size() <= 6 && "String too long, possible overflow.");
75 while (!Str
.empty()) {
77 if (Str
[0] >= 'A' && Str
[0] <= 'Z') // 0..25
78 CharVal
= Str
[0] - 'A';
79 else if (Str
[0] >= 'a' && Str
[0] <= 'z') // 26..51
80 CharVal
= Str
[0] - 'a' + 26;
81 else if (Str
[0] >= '0' && Str
[0] <= '9') // 52..61
82 CharVal
= Str
[0] - '0' + 52;
83 else if (Str
[0] == '+') // 62
85 else if (Str
[0] == '/') // 63
90 Value
= (Value
* 64) + CharVal
;
94 if (Value
> std::numeric_limits
<uint32_t>::max())
97 Result
= static_cast<uint32_t>(Value
);
101 template <typename coff_symbol_type
>
102 const coff_symbol_type
*COFFObjectFile::toSymb(DataRefImpl Ref
) const {
103 const coff_symbol_type
*Addr
=
104 reinterpret_cast<const coff_symbol_type
*>(Ref
.p
);
106 assert(!checkOffset(Data
, uintptr_t(Addr
), sizeof(*Addr
)));
108 // Verify that the symbol points to a valid entry in the symbol table.
109 uintptr_t Offset
= uintptr_t(Addr
) - uintptr_t(base());
111 assert((Offset
- getPointerToSymbolTable()) % sizeof(coff_symbol_type
) == 0 &&
112 "Symbol did not point to the beginning of a symbol");
118 const coff_section
*COFFObjectFile::toSec(DataRefImpl Ref
) const {
119 const coff_section
*Addr
= reinterpret_cast<const coff_section
*>(Ref
.p
);
122 // Verify that the section points to a valid entry in the section table.
123 if (Addr
< SectionTable
|| Addr
>= (SectionTable
+ getNumberOfSections()))
124 report_fatal_error("Section was outside of section table.");
126 uintptr_t Offset
= uintptr_t(Addr
) - uintptr_t(SectionTable
);
127 assert(Offset
% sizeof(coff_section
) == 0 &&
128 "Section did not point to the beginning of a section");
134 void COFFObjectFile::moveSymbolNext(DataRefImpl
&Ref
) const {
135 auto End
= reinterpret_cast<uintptr_t>(StringTable
);
137 const coff_symbol16
*Symb
= toSymb
<coff_symbol16
>(Ref
);
138 Symb
+= 1 + Symb
->NumberOfAuxSymbols
;
139 Ref
.p
= std::min(reinterpret_cast<uintptr_t>(Symb
), End
);
140 } else if (SymbolTable32
) {
141 const coff_symbol32
*Symb
= toSymb
<coff_symbol32
>(Ref
);
142 Symb
+= 1 + Symb
->NumberOfAuxSymbols
;
143 Ref
.p
= std::min(reinterpret_cast<uintptr_t>(Symb
), End
);
145 llvm_unreachable("no symbol table pointer!");
149 Expected
<StringRef
> COFFObjectFile::getSymbolName(DataRefImpl Ref
) const {
150 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
152 if (std::error_code EC
= getSymbolName(Symb
, Result
))
153 return errorCodeToError(EC
);
157 uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref
) const {
158 return getCOFFSymbol(Ref
).getValue();
161 uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref
) const {
162 // MSVC/link.exe seems to align symbols to the next-power-of-2
164 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
165 return std::min(uint64_t(32), PowerOf2Ceil(Symb
.getValue()));
168 Expected
<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref
) const {
169 uint64_t Result
= getSymbolValue(Ref
);
170 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
171 int32_t SectionNumber
= Symb
.getSectionNumber();
173 if (Symb
.isAnyUndefined() || Symb
.isCommon() ||
174 COFF::isReservedSectionNumber(SectionNumber
))
177 const coff_section
*Section
= nullptr;
178 if (std::error_code EC
= getSection(SectionNumber
, Section
))
179 return errorCodeToError(EC
);
180 Result
+= Section
->VirtualAddress
;
182 // The section VirtualAddress does not include ImageBase, and we want to
183 // return virtual addresses.
184 Result
+= getImageBase();
189 Expected
<SymbolRef::Type
> COFFObjectFile::getSymbolType(DataRefImpl Ref
) const {
190 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
191 int32_t SectionNumber
= Symb
.getSectionNumber();
193 if (Symb
.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION
)
194 return SymbolRef::ST_Function
;
195 if (Symb
.isAnyUndefined())
196 return SymbolRef::ST_Unknown
;
198 return SymbolRef::ST_Data
;
199 if (Symb
.isFileRecord())
200 return SymbolRef::ST_File
;
202 // TODO: perhaps we need a new symbol type ST_Section.
203 if (SectionNumber
== COFF::IMAGE_SYM_DEBUG
|| Symb
.isSectionDefinition())
204 return SymbolRef::ST_Debug
;
206 if (!COFF::isReservedSectionNumber(SectionNumber
))
207 return SymbolRef::ST_Data
;
209 return SymbolRef::ST_Other
;
212 uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref
) const {
213 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
214 uint32_t Result
= SymbolRef::SF_None
;
216 if (Symb
.isExternal() || Symb
.isWeakExternal())
217 Result
|= SymbolRef::SF_Global
;
219 if (const coff_aux_weak_external
*AWE
= Symb
.getWeakExternal()) {
220 Result
|= SymbolRef::SF_Weak
;
221 if (AWE
->Characteristics
!= COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
)
222 Result
|= SymbolRef::SF_Undefined
;
225 if (Symb
.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE
)
226 Result
|= SymbolRef::SF_Absolute
;
228 if (Symb
.isFileRecord())
229 Result
|= SymbolRef::SF_FormatSpecific
;
231 if (Symb
.isSectionDefinition())
232 Result
|= SymbolRef::SF_FormatSpecific
;
235 Result
|= SymbolRef::SF_Common
;
237 if (Symb
.isUndefined())
238 Result
|= SymbolRef::SF_Undefined
;
243 uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref
) const {
244 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
245 return Symb
.getValue();
248 Expected
<section_iterator
>
249 COFFObjectFile::getSymbolSection(DataRefImpl Ref
) const {
250 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
251 if (COFF::isReservedSectionNumber(Symb
.getSectionNumber()))
252 return section_end();
253 const coff_section
*Sec
= nullptr;
254 if (std::error_code EC
= getSection(Symb
.getSectionNumber(), Sec
))
255 return errorCodeToError(EC
);
257 Ret
.p
= reinterpret_cast<uintptr_t>(Sec
);
258 return section_iterator(SectionRef(Ret
, this));
261 unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
262 COFFSymbolRef Symb
= getCOFFSymbol(Sym
.getRawDataRefImpl());
263 return Symb
.getSectionNumber();
266 void COFFObjectFile::moveSectionNext(DataRefImpl
&Ref
) const {
267 const coff_section
*Sec
= toSec(Ref
);
269 Ref
.p
= reinterpret_cast<uintptr_t>(Sec
);
272 std::error_code
COFFObjectFile::getSectionName(DataRefImpl Ref
,
273 StringRef
&Result
) const {
274 const coff_section
*Sec
= toSec(Ref
);
275 return getSectionName(Sec
, Result
);
278 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref
) const {
279 const coff_section
*Sec
= toSec(Ref
);
280 uint64_t Result
= Sec
->VirtualAddress
;
282 // The section VirtualAddress does not include ImageBase, and we want to
283 // return virtual addresses.
284 Result
+= getImageBase();
288 uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec
) const {
289 return toSec(Sec
) - SectionTable
;
292 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref
) const {
293 return getSectionSize(toSec(Ref
));
296 std::error_code
COFFObjectFile::getSectionContents(DataRefImpl Ref
,
297 StringRef
&Result
) const {
298 const coff_section
*Sec
= toSec(Ref
);
299 ArrayRef
<uint8_t> Res
;
300 std::error_code EC
= getSectionContents(Sec
, Res
);
301 Result
= StringRef(reinterpret_cast<const char*>(Res
.data()), Res
.size());
305 uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref
) const {
306 const coff_section
*Sec
= toSec(Ref
);
307 return Sec
->getAlignment();
310 bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
314 bool COFFObjectFile::isSectionText(DataRefImpl Ref
) const {
315 const coff_section
*Sec
= toSec(Ref
);
316 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_CODE
;
319 bool COFFObjectFile::isSectionData(DataRefImpl Ref
) const {
320 const coff_section
*Sec
= toSec(Ref
);
321 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
324 bool COFFObjectFile::isSectionBSS(DataRefImpl Ref
) const {
325 const coff_section
*Sec
= toSec(Ref
);
326 const uint32_t BssFlags
= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
327 COFF::IMAGE_SCN_MEM_READ
|
328 COFF::IMAGE_SCN_MEM_WRITE
;
329 return (Sec
->Characteristics
& BssFlags
) == BssFlags
;
332 unsigned COFFObjectFile::getSectionID(SectionRef Sec
) const {
334 uintptr_t(Sec
.getRawDataRefImpl().p
) - uintptr_t(SectionTable
);
335 assert((Offset
% sizeof(coff_section
)) == 0);
336 return (Offset
/ sizeof(coff_section
)) + 1;
339 bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref
) const {
340 const coff_section
*Sec
= toSec(Ref
);
341 // In COFF, a virtual section won't have any in-file
342 // content, so the file pointer to the content will be zero.
343 return Sec
->PointerToRawData
== 0;
346 static uint32_t getNumberOfRelocations(const coff_section
*Sec
,
347 MemoryBufferRef M
, const uint8_t *base
) {
348 // The field for the number of relocations in COFF section table is only
349 // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
350 // NumberOfRelocations field, and the actual relocation count is stored in the
351 // VirtualAddress field in the first relocation entry.
352 if (Sec
->hasExtendedRelocations()) {
353 const coff_relocation
*FirstReloc
;
354 if (getObject(FirstReloc
, M
, reinterpret_cast<const coff_relocation
*>(
355 base
+ Sec
->PointerToRelocations
)))
357 // -1 to exclude this first relocation entry.
358 return FirstReloc
->VirtualAddress
- 1;
360 return Sec
->NumberOfRelocations
;
363 static const coff_relocation
*
364 getFirstReloc(const coff_section
*Sec
, MemoryBufferRef M
, const uint8_t *Base
) {
365 uint64_t NumRelocs
= getNumberOfRelocations(Sec
, M
, Base
);
368 auto begin
= reinterpret_cast<const coff_relocation
*>(
369 Base
+ Sec
->PointerToRelocations
);
370 if (Sec
->hasExtendedRelocations()) {
371 // Skip the first relocation entry repurposed to store the number of
375 if (Binary::checkOffset(M
, uintptr_t(begin
),
376 sizeof(coff_relocation
) * NumRelocs
))
381 relocation_iterator
COFFObjectFile::section_rel_begin(DataRefImpl Ref
) const {
382 const coff_section
*Sec
= toSec(Ref
);
383 const coff_relocation
*begin
= getFirstReloc(Sec
, Data
, base());
384 if (begin
&& Sec
->VirtualAddress
!= 0)
385 report_fatal_error("Sections with relocations should have an address of 0");
387 Ret
.p
= reinterpret_cast<uintptr_t>(begin
);
388 return relocation_iterator(RelocationRef(Ret
, this));
391 relocation_iterator
COFFObjectFile::section_rel_end(DataRefImpl Ref
) const {
392 const coff_section
*Sec
= toSec(Ref
);
393 const coff_relocation
*I
= getFirstReloc(Sec
, Data
, base());
395 I
+= getNumberOfRelocations(Sec
, Data
, base());
397 Ret
.p
= reinterpret_cast<uintptr_t>(I
);
398 return relocation_iterator(RelocationRef(Ret
, this));
401 // Initialize the pointer to the symbol table.
402 std::error_code
COFFObjectFile::initSymbolTablePtr() {
404 if (std::error_code EC
= getObject(
405 SymbolTable16
, Data
, base() + getPointerToSymbolTable(),
406 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
409 if (COFFBigObjHeader
)
410 if (std::error_code EC
= getObject(
411 SymbolTable32
, Data
, base() + getPointerToSymbolTable(),
412 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
415 // Find string table. The first four byte of the string table contains the
416 // total size of the string table, including the size field itself. If the
417 // string table is empty, the value of the first four byte would be 4.
418 uint32_t StringTableOffset
= getPointerToSymbolTable() +
419 getNumberOfSymbols() * getSymbolTableEntrySize();
420 const uint8_t *StringTableAddr
= base() + StringTableOffset
;
421 const ulittle32_t
*StringTableSizePtr
;
422 if (std::error_code EC
= getObject(StringTableSizePtr
, Data
, StringTableAddr
))
424 StringTableSize
= *StringTableSizePtr
;
425 if (std::error_code EC
=
426 getObject(StringTable
, Data
, StringTableAddr
, StringTableSize
))
429 // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
430 // tools like cvtres write a size of 0 for an empty table instead of 4.
431 if (StringTableSize
< 4)
434 // Check that the string table is null terminated if has any in it.
435 if (StringTableSize
> 4 && StringTable
[StringTableSize
- 1] != 0)
436 return object_error::parse_failed
;
437 return std::error_code();
440 uint64_t COFFObjectFile::getImageBase() const {
442 return PE32Header
->ImageBase
;
443 else if (PE32PlusHeader
)
444 return PE32PlusHeader
->ImageBase
;
445 // This actually comes up in practice.
449 // Returns the file offset for the given VA.
450 std::error_code
COFFObjectFile::getVaPtr(uint64_t Addr
, uintptr_t &Res
) const {
451 uint64_t ImageBase
= getImageBase();
452 uint64_t Rva
= Addr
- ImageBase
;
453 assert(Rva
<= UINT32_MAX
);
454 return getRvaPtr((uint32_t)Rva
, Res
);
457 // Returns the file offset for the given RVA.
458 std::error_code
COFFObjectFile::getRvaPtr(uint32_t Addr
, uintptr_t &Res
) const {
459 for (const SectionRef
&S
: sections()) {
460 const coff_section
*Section
= getCOFFSection(S
);
461 uint32_t SectionStart
= Section
->VirtualAddress
;
462 uint32_t SectionEnd
= Section
->VirtualAddress
+ Section
->VirtualSize
;
463 if (SectionStart
<= Addr
&& Addr
< SectionEnd
) {
464 uint32_t Offset
= Addr
- SectionStart
;
465 Res
= uintptr_t(base()) + Section
->PointerToRawData
+ Offset
;
466 return std::error_code();
469 return object_error::parse_failed
;
473 COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA
, uint32_t Size
,
474 ArrayRef
<uint8_t> &Contents
) const {
475 for (const SectionRef
&S
: sections()) {
476 const coff_section
*Section
= getCOFFSection(S
);
477 uint32_t SectionStart
= Section
->VirtualAddress
;
478 // Check if this RVA is within the section bounds. Be careful about integer
480 uint32_t OffsetIntoSection
= RVA
- SectionStart
;
481 if (SectionStart
<= RVA
&& OffsetIntoSection
< Section
->VirtualSize
&&
482 Size
<= Section
->VirtualSize
- OffsetIntoSection
) {
484 uintptr_t(base()) + Section
->PointerToRawData
+ OffsetIntoSection
;
486 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(Begin
), Size
);
487 return std::error_code();
490 return object_error::parse_failed
;
493 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
495 std::error_code
COFFObjectFile::getHintName(uint32_t Rva
, uint16_t &Hint
,
496 StringRef
&Name
) const {
497 uintptr_t IntPtr
= 0;
498 if (std::error_code EC
= getRvaPtr(Rva
, IntPtr
))
500 const uint8_t *Ptr
= reinterpret_cast<const uint8_t *>(IntPtr
);
501 Hint
= *reinterpret_cast<const ulittle16_t
*>(Ptr
);
502 Name
= StringRef(reinterpret_cast<const char *>(Ptr
+ 2));
503 return std::error_code();
507 COFFObjectFile::getDebugPDBInfo(const debug_directory
*DebugDir
,
508 const codeview::DebugInfo
*&PDBInfo
,
509 StringRef
&PDBFileName
) const {
510 ArrayRef
<uint8_t> InfoBytes
;
511 if (std::error_code EC
= getRvaAndSizeAsBytes(
512 DebugDir
->AddressOfRawData
, DebugDir
->SizeOfData
, InfoBytes
))
514 if (InfoBytes
.size() < sizeof(*PDBInfo
) + 1)
515 return object_error::parse_failed
;
516 PDBInfo
= reinterpret_cast<const codeview::DebugInfo
*>(InfoBytes
.data());
517 InfoBytes
= InfoBytes
.drop_front(sizeof(*PDBInfo
));
518 PDBFileName
= StringRef(reinterpret_cast<const char *>(InfoBytes
.data()),
520 // Truncate the name at the first null byte. Ignore any padding.
521 PDBFileName
= PDBFileName
.split('\0').first
;
522 return std::error_code();
526 COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo
*&PDBInfo
,
527 StringRef
&PDBFileName
) const {
528 for (const debug_directory
&D
: debug_directories())
529 if (D
.Type
== COFF::IMAGE_DEBUG_TYPE_CODEVIEW
)
530 return getDebugPDBInfo(&D
, PDBInfo
, PDBFileName
);
531 // If we get here, there is no PDB info to return.
533 PDBFileName
= StringRef();
534 return std::error_code();
537 // Find the import table.
538 std::error_code
COFFObjectFile::initImportTablePtr() {
539 // First, we get the RVA of the import table. If the file lacks a pointer to
540 // the import table, do nothing.
541 const data_directory
*DataEntry
;
542 if (getDataDirectory(COFF::IMPORT_TABLE
, DataEntry
))
543 return std::error_code();
545 // Do nothing if the pointer to import table is NULL.
546 if (DataEntry
->RelativeVirtualAddress
== 0)
547 return std::error_code();
549 uint32_t ImportTableRva
= DataEntry
->RelativeVirtualAddress
;
551 // Find the section that contains the RVA. This is needed because the RVA is
552 // the import table's memory address which is different from its file offset.
553 uintptr_t IntPtr
= 0;
554 if (std::error_code EC
= getRvaPtr(ImportTableRva
, IntPtr
))
556 if (std::error_code EC
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
558 ImportDirectory
= reinterpret_cast<
559 const coff_import_directory_table_entry
*>(IntPtr
);
560 return std::error_code();
563 // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
564 std::error_code
COFFObjectFile::initDelayImportTablePtr() {
565 const data_directory
*DataEntry
;
566 if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR
, DataEntry
))
567 return std::error_code();
568 if (DataEntry
->RelativeVirtualAddress
== 0)
569 return std::error_code();
571 uint32_t RVA
= DataEntry
->RelativeVirtualAddress
;
572 NumberOfDelayImportDirectory
= DataEntry
->Size
/
573 sizeof(delay_import_directory_table_entry
) - 1;
575 uintptr_t IntPtr
= 0;
576 if (std::error_code EC
= getRvaPtr(RVA
, IntPtr
))
578 DelayImportDirectory
= reinterpret_cast<
579 const delay_import_directory_table_entry
*>(IntPtr
);
580 return std::error_code();
583 // Find the export table.
584 std::error_code
COFFObjectFile::initExportTablePtr() {
585 // First, we get the RVA of the export table. If the file lacks a pointer to
586 // the export table, do nothing.
587 const data_directory
*DataEntry
;
588 if (getDataDirectory(COFF::EXPORT_TABLE
, DataEntry
))
589 return std::error_code();
591 // Do nothing if the pointer to export table is NULL.
592 if (DataEntry
->RelativeVirtualAddress
== 0)
593 return std::error_code();
595 uint32_t ExportTableRva
= DataEntry
->RelativeVirtualAddress
;
596 uintptr_t IntPtr
= 0;
597 if (std::error_code EC
= getRvaPtr(ExportTableRva
, IntPtr
))
600 reinterpret_cast<const export_directory_table_entry
*>(IntPtr
);
601 return std::error_code();
604 std::error_code
COFFObjectFile::initBaseRelocPtr() {
605 const data_directory
*DataEntry
;
606 if (getDataDirectory(COFF::BASE_RELOCATION_TABLE
, DataEntry
))
607 return std::error_code();
608 if (DataEntry
->RelativeVirtualAddress
== 0)
609 return std::error_code();
611 uintptr_t IntPtr
= 0;
612 if (std::error_code EC
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
))
614 BaseRelocHeader
= reinterpret_cast<const coff_base_reloc_block_header
*>(
616 BaseRelocEnd
= reinterpret_cast<coff_base_reloc_block_header
*>(
617 IntPtr
+ DataEntry
->Size
);
618 // FIXME: Verify the section containing BaseRelocHeader has at least
619 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
620 return std::error_code();
623 std::error_code
COFFObjectFile::initDebugDirectoryPtr() {
624 // Get the RVA of the debug directory. Do nothing if it does not exist.
625 const data_directory
*DataEntry
;
626 if (getDataDirectory(COFF::DEBUG_DIRECTORY
, DataEntry
))
627 return std::error_code();
629 // Do nothing if the RVA is NULL.
630 if (DataEntry
->RelativeVirtualAddress
== 0)
631 return std::error_code();
633 // Check that the size is a multiple of the entry size.
634 if (DataEntry
->Size
% sizeof(debug_directory
) != 0)
635 return object_error::parse_failed
;
637 uintptr_t IntPtr
= 0;
638 if (std::error_code EC
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
))
640 DebugDirectoryBegin
= reinterpret_cast<const debug_directory
*>(IntPtr
);
641 DebugDirectoryEnd
= reinterpret_cast<const debug_directory
*>(
642 IntPtr
+ DataEntry
->Size
);
643 // FIXME: Verify the section containing DebugDirectoryBegin has at least
644 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
645 return std::error_code();
648 std::error_code
COFFObjectFile::initLoadConfigPtr() {
649 // Get the RVA of the debug directory. Do nothing if it does not exist.
650 const data_directory
*DataEntry
;
651 if (getDataDirectory(COFF::LOAD_CONFIG_TABLE
, DataEntry
))
652 return std::error_code();
654 // Do nothing if the RVA is NULL.
655 if (DataEntry
->RelativeVirtualAddress
== 0)
656 return std::error_code();
657 uintptr_t IntPtr
= 0;
658 if (std::error_code EC
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
))
661 LoadConfig
= (const void *)IntPtr
;
662 return std::error_code();
665 COFFObjectFile::COFFObjectFile(MemoryBufferRef Object
, std::error_code
&EC
)
666 : ObjectFile(Binary::ID_COFF
, Object
), COFFHeader(nullptr),
667 COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
668 DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
669 SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
670 ImportDirectory(nullptr),
671 DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
672 ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
673 DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
674 // Check that we at least have enough room for a header.
675 if (!checkSize(Data
, EC
, sizeof(coff_file_header
)))
678 // The current location in the file where we are looking at.
681 // PE header is optional and is present only in executables. If it exists,
682 // it is placed right after COFF header.
683 bool HasPEHeader
= false;
685 // Check if this is a PE/COFF file.
686 if (checkSize(Data
, EC
, sizeof(dos_header
) + sizeof(COFF::PEMagic
))) {
687 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
688 // PE signature to find 'normal' COFF header.
689 const auto *DH
= reinterpret_cast<const dos_header
*>(base());
690 if (DH
->Magic
[0] == 'M' && DH
->Magic
[1] == 'Z') {
691 CurPtr
= DH
->AddressOfNewExeHeader
;
692 // Check the PE magic bytes. ("PE\0\0")
693 if (memcmp(base() + CurPtr
, COFF::PEMagic
, sizeof(COFF::PEMagic
)) != 0) {
694 EC
= object_error::parse_failed
;
697 CurPtr
+= sizeof(COFF::PEMagic
); // Skip the PE magic bytes.
702 if ((EC
= getObject(COFFHeader
, Data
, base() + CurPtr
)))
705 // It might be a bigobj file, let's check. Note that COFF bigobj and COFF
706 // import libraries share a common prefix but bigobj is more restrictive.
707 if (!HasPEHeader
&& COFFHeader
->Machine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
&&
708 COFFHeader
->NumberOfSections
== uint16_t(0xffff) &&
709 checkSize(Data
, EC
, sizeof(coff_bigobj_file_header
))) {
710 if ((EC
= getObject(COFFBigObjHeader
, Data
, base() + CurPtr
)))
713 // Verify that we are dealing with bigobj.
714 if (COFFBigObjHeader
->Version
>= COFF::BigObjHeader::MinBigObjectVersion
&&
715 std::memcmp(COFFBigObjHeader
->UUID
, COFF::BigObjMagic
,
716 sizeof(COFF::BigObjMagic
)) == 0) {
717 COFFHeader
= nullptr;
718 CurPtr
+= sizeof(coff_bigobj_file_header
);
720 // It's not a bigobj.
721 COFFBigObjHeader
= nullptr;
725 // The prior checkSize call may have failed. This isn't a hard error
726 // because we were just trying to sniff out bigobj.
727 EC
= std::error_code();
728 CurPtr
+= sizeof(coff_file_header
);
730 if (COFFHeader
->isImportLibrary())
735 const pe32_header
*Header
;
736 if ((EC
= getObject(Header
, Data
, base() + CurPtr
)))
739 const uint8_t *DataDirAddr
;
740 uint64_t DataDirSize
;
741 if (Header
->Magic
== COFF::PE32Header::PE32
) {
743 DataDirAddr
= base() + CurPtr
+ sizeof(pe32_header
);
744 DataDirSize
= sizeof(data_directory
) * PE32Header
->NumberOfRvaAndSize
;
745 } else if (Header
->Magic
== COFF::PE32Header::PE32_PLUS
) {
746 PE32PlusHeader
= reinterpret_cast<const pe32plus_header
*>(Header
);
747 DataDirAddr
= base() + CurPtr
+ sizeof(pe32plus_header
);
748 DataDirSize
= sizeof(data_directory
) * PE32PlusHeader
->NumberOfRvaAndSize
;
750 // It's neither PE32 nor PE32+.
751 EC
= object_error::parse_failed
;
754 if ((EC
= getObject(DataDirectory
, Data
, DataDirAddr
, DataDirSize
)))
759 CurPtr
+= COFFHeader
->SizeOfOptionalHeader
;
761 if ((EC
= getObject(SectionTable
, Data
, base() + CurPtr
,
762 (uint64_t)getNumberOfSections() * sizeof(coff_section
))))
765 // Initialize the pointer to the symbol table.
766 if (getPointerToSymbolTable() != 0) {
767 if ((EC
= initSymbolTablePtr())) {
768 SymbolTable16
= nullptr;
769 SymbolTable32
= nullptr;
770 StringTable
= nullptr;
774 // We had better not have any symbols if we don't have a symbol table.
775 if (getNumberOfSymbols() != 0) {
776 EC
= object_error::parse_failed
;
781 // Initialize the pointer to the beginning of the import table.
782 if ((EC
= initImportTablePtr()))
784 if ((EC
= initDelayImportTablePtr()))
787 // Initialize the pointer to the export table.
788 if ((EC
= initExportTablePtr()))
791 // Initialize the pointer to the base relocation table.
792 if ((EC
= initBaseRelocPtr()))
795 // Initialize the pointer to the export table.
796 if ((EC
= initDebugDirectoryPtr()))
799 if ((EC
= initLoadConfigPtr()))
802 EC
= std::error_code();
805 basic_symbol_iterator
COFFObjectFile::symbol_begin() const {
807 Ret
.p
= getSymbolTable();
808 return basic_symbol_iterator(SymbolRef(Ret
, this));
811 basic_symbol_iterator
COFFObjectFile::symbol_end() const {
812 // The symbol table ends where the string table begins.
814 Ret
.p
= reinterpret_cast<uintptr_t>(StringTable
);
815 return basic_symbol_iterator(SymbolRef(Ret
, this));
818 import_directory_iterator
COFFObjectFile::import_directory_begin() const {
819 if (!ImportDirectory
)
820 return import_directory_end();
821 if (ImportDirectory
->isNull())
822 return import_directory_end();
823 return import_directory_iterator(
824 ImportDirectoryEntryRef(ImportDirectory
, 0, this));
827 import_directory_iterator
COFFObjectFile::import_directory_end() const {
828 return import_directory_iterator(
829 ImportDirectoryEntryRef(nullptr, -1, this));
832 delay_import_directory_iterator
833 COFFObjectFile::delay_import_directory_begin() const {
834 return delay_import_directory_iterator(
835 DelayImportDirectoryEntryRef(DelayImportDirectory
, 0, this));
838 delay_import_directory_iterator
839 COFFObjectFile::delay_import_directory_end() const {
840 return delay_import_directory_iterator(
841 DelayImportDirectoryEntryRef(
842 DelayImportDirectory
, NumberOfDelayImportDirectory
, this));
845 export_directory_iterator
COFFObjectFile::export_directory_begin() const {
846 return export_directory_iterator(
847 ExportDirectoryEntryRef(ExportDirectory
, 0, this));
850 export_directory_iterator
COFFObjectFile::export_directory_end() const {
851 if (!ExportDirectory
)
852 return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
853 ExportDirectoryEntryRef
Ref(ExportDirectory
,
854 ExportDirectory
->AddressTableEntries
, this);
855 return export_directory_iterator(Ref
);
858 section_iterator
COFFObjectFile::section_begin() const {
860 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
);
861 return section_iterator(SectionRef(Ret
, this));
864 section_iterator
COFFObjectFile::section_end() const {
867 COFFHeader
&& COFFHeader
->isImportLibrary() ? 0 : getNumberOfSections();
868 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
+ NumSections
);
869 return section_iterator(SectionRef(Ret
, this));
872 base_reloc_iterator
COFFObjectFile::base_reloc_begin() const {
873 return base_reloc_iterator(BaseRelocRef(BaseRelocHeader
, this));
876 base_reloc_iterator
COFFObjectFile::base_reloc_end() const {
877 return base_reloc_iterator(BaseRelocRef(BaseRelocEnd
, this));
880 uint8_t COFFObjectFile::getBytesInAddress() const {
881 return getArch() == Triple::x86_64
|| getArch() == Triple::aarch64
? 8 : 4;
884 StringRef
COFFObjectFile::getFileFormatName() const {
885 switch(getMachine()) {
886 case COFF::IMAGE_FILE_MACHINE_I386
:
888 case COFF::IMAGE_FILE_MACHINE_AMD64
:
889 return "COFF-x86-64";
890 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
892 case COFF::IMAGE_FILE_MACHINE_ARM64
:
895 return "COFF-<unknown arch>";
899 Triple::ArchType
COFFObjectFile::getArch() const {
900 switch (getMachine()) {
901 case COFF::IMAGE_FILE_MACHINE_I386
:
903 case COFF::IMAGE_FILE_MACHINE_AMD64
:
904 return Triple::x86_64
;
905 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
906 return Triple::thumb
;
907 case COFF::IMAGE_FILE_MACHINE_ARM64
:
908 return Triple::aarch64
;
910 return Triple::UnknownArch
;
914 Expected
<uint64_t> COFFObjectFile::getStartAddress() const {
916 return PE32Header
->AddressOfEntryPoint
;
920 iterator_range
<import_directory_iterator
>
921 COFFObjectFile::import_directories() const {
922 return make_range(import_directory_begin(), import_directory_end());
925 iterator_range
<delay_import_directory_iterator
>
926 COFFObjectFile::delay_import_directories() const {
927 return make_range(delay_import_directory_begin(),
928 delay_import_directory_end());
931 iterator_range
<export_directory_iterator
>
932 COFFObjectFile::export_directories() const {
933 return make_range(export_directory_begin(), export_directory_end());
936 iterator_range
<base_reloc_iterator
> COFFObjectFile::base_relocs() const {
937 return make_range(base_reloc_begin(), base_reloc_end());
941 COFFObjectFile::getCOFFHeader(const coff_file_header
*&Res
) const {
943 return std::error_code();
947 COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header
*&Res
) const {
948 Res
= COFFBigObjHeader
;
949 return std::error_code();
952 std::error_code
COFFObjectFile::getPE32Header(const pe32_header
*&Res
) const {
954 return std::error_code();
958 COFFObjectFile::getPE32PlusHeader(const pe32plus_header
*&Res
) const {
959 Res
= PE32PlusHeader
;
960 return std::error_code();
964 COFFObjectFile::getDataDirectory(uint32_t Index
,
965 const data_directory
*&Res
) const {
966 // Error if there's no data directory or the index is out of range.
967 if (!DataDirectory
) {
969 return object_error::parse_failed
;
971 assert(PE32Header
|| PE32PlusHeader
);
972 uint32_t NumEnt
= PE32Header
? PE32Header
->NumberOfRvaAndSize
973 : PE32PlusHeader
->NumberOfRvaAndSize
;
974 if (Index
>= NumEnt
) {
976 return object_error::parse_failed
;
978 Res
= &DataDirectory
[Index
];
979 return std::error_code();
982 std::error_code
COFFObjectFile::getSection(int32_t Index
,
983 const coff_section
*&Result
) const {
985 if (COFF::isReservedSectionNumber(Index
))
986 return std::error_code();
987 if (static_cast<uint32_t>(Index
) <= getNumberOfSections()) {
988 // We already verified the section table data, so no need to check again.
989 Result
= SectionTable
+ (Index
- 1);
990 return std::error_code();
992 return object_error::parse_failed
;
995 std::error_code
COFFObjectFile::getSection(StringRef SectionName
,
996 const coff_section
*&Result
) const {
999 for (const SectionRef
&Section
: sections()) {
1000 if (std::error_code E
= Section
.getName(SecName
))
1002 if (SecName
== SectionName
) {
1003 Result
= getCOFFSection(Section
);
1004 return std::error_code();
1007 return object_error::parse_failed
;
1010 std::error_code
COFFObjectFile::getString(uint32_t Offset
,
1011 StringRef
&Result
) const {
1012 if (StringTableSize
<= 4)
1013 // Tried to get a string from an empty string table.
1014 return object_error::parse_failed
;
1015 if (Offset
>= StringTableSize
)
1016 return object_error::unexpected_eof
;
1017 Result
= StringRef(StringTable
+ Offset
);
1018 return std::error_code();
1021 std::error_code
COFFObjectFile::getSymbolName(COFFSymbolRef Symbol
,
1022 StringRef
&Res
) const {
1023 return getSymbolName(Symbol
.getGeneric(), Res
);
1026 std::error_code
COFFObjectFile::getSymbolName(const coff_symbol_generic
*Symbol
,
1027 StringRef
&Res
) const {
1028 // Check for string table entry. First 4 bytes are 0.
1029 if (Symbol
->Name
.Offset
.Zeroes
== 0) {
1030 if (std::error_code EC
= getString(Symbol
->Name
.Offset
.Offset
, Res
))
1032 return std::error_code();
1035 if (Symbol
->Name
.ShortName
[COFF::NameSize
- 1] == 0)
1036 // Null terminated, let ::strlen figure out the length.
1037 Res
= StringRef(Symbol
->Name
.ShortName
);
1039 // Not null terminated, use all 8 bytes.
1040 Res
= StringRef(Symbol
->Name
.ShortName
, COFF::NameSize
);
1041 return std::error_code();
1045 COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol
) const {
1046 const uint8_t *Aux
= nullptr;
1048 size_t SymbolSize
= getSymbolTableEntrySize();
1049 if (Symbol
.getNumberOfAuxSymbols() > 0) {
1050 // AUX data comes immediately after the symbol in COFF
1051 Aux
= reinterpret_cast<const uint8_t *>(Symbol
.getRawPtr()) + SymbolSize
;
1053 // Verify that the Aux symbol points to a valid entry in the symbol table.
1054 uintptr_t Offset
= uintptr_t(Aux
) - uintptr_t(base());
1055 if (Offset
< getPointerToSymbolTable() ||
1057 getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize
))
1058 report_fatal_error("Aux Symbol data was outside of symbol table.");
1060 assert((Offset
- getPointerToSymbolTable()) % SymbolSize
== 0 &&
1061 "Aux Symbol data did not point to the beginning of a symbol");
1064 return makeArrayRef(Aux
, Symbol
.getNumberOfAuxSymbols() * SymbolSize
);
1067 uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol
) const {
1069 reinterpret_cast<uintptr_t>(Symbol
.getRawPtr()) - getSymbolTable();
1070 assert(Offset
% getSymbolTableEntrySize() == 0 &&
1071 "Symbol did not point to the beginning of a symbol");
1072 size_t Index
= Offset
/ getSymbolTableEntrySize();
1073 assert(Index
< getNumberOfSymbols());
1077 std::error_code
COFFObjectFile::getSectionName(const coff_section
*Sec
,
1078 StringRef
&Res
) const {
1080 if (Sec
->Name
[COFF::NameSize
- 1] == 0)
1081 // Null terminated, let ::strlen figure out the length.
1084 // Not null terminated, use all 8 bytes.
1085 Name
= StringRef(Sec
->Name
, COFF::NameSize
);
1087 // Check for string table entry. First byte is '/'.
1088 if (Name
.startswith("/")) {
1090 if (Name
.startswith("//")) {
1091 if (decodeBase64StringEntry(Name
.substr(2), Offset
))
1092 return object_error::parse_failed
;
1094 if (Name
.substr(1).getAsInteger(10, Offset
))
1095 return object_error::parse_failed
;
1097 if (std::error_code EC
= getString(Offset
, Name
))
1102 return std::error_code();
1105 uint64_t COFFObjectFile::getSectionSize(const coff_section
*Sec
) const {
1106 // SizeOfRawData and VirtualSize change what they represent depending on
1107 // whether or not we have an executable image.
1109 // For object files, SizeOfRawData contains the size of section's data;
1110 // VirtualSize should be zero but isn't due to buggy COFF writers.
1112 // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1113 // actual section size is in VirtualSize. It is possible for VirtualSize to
1114 // be greater than SizeOfRawData; the contents past that point should be
1115 // considered to be zero.
1117 return std::min(Sec
->VirtualSize
, Sec
->SizeOfRawData
);
1118 return Sec
->SizeOfRawData
;
1122 COFFObjectFile::getSectionContents(const coff_section
*Sec
,
1123 ArrayRef
<uint8_t> &Res
) const {
1124 // In COFF, a virtual section won't have any in-file
1125 // content, so the file pointer to the content will be zero.
1126 if (Sec
->PointerToRawData
== 0)
1127 return std::error_code();
1128 // The only thing that we need to verify is that the contents is contained
1129 // within the file bounds. We don't need to make sure it doesn't cover other
1130 // data, as there's nothing that says that is not allowed.
1131 uintptr_t ConStart
= uintptr_t(base()) + Sec
->PointerToRawData
;
1132 uint32_t SectionSize
= getSectionSize(Sec
);
1133 if (checkOffset(Data
, ConStart
, SectionSize
))
1134 return object_error::parse_failed
;
1135 Res
= makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart
), SectionSize
);
1136 return std::error_code();
1139 const coff_relocation
*COFFObjectFile::toRel(DataRefImpl Rel
) const {
1140 return reinterpret_cast<const coff_relocation
*>(Rel
.p
);
1143 void COFFObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
1144 Rel
.p
= reinterpret_cast<uintptr_t>(
1145 reinterpret_cast<const coff_relocation
*>(Rel
.p
) + 1);
1148 uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
1149 const coff_relocation
*R
= toRel(Rel
);
1150 return R
->VirtualAddress
;
1153 symbol_iterator
COFFObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
1154 const coff_relocation
*R
= toRel(Rel
);
1156 if (R
->SymbolTableIndex
>= getNumberOfSymbols())
1157 return symbol_end();
1159 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable16
+ R
->SymbolTableIndex
);
1160 else if (SymbolTable32
)
1161 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable32
+ R
->SymbolTableIndex
);
1163 llvm_unreachable("no symbol table pointer!");
1164 return symbol_iterator(SymbolRef(Ref
, this));
1167 uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel
) const {
1168 const coff_relocation
* R
= toRel(Rel
);
1172 const coff_section
*
1173 COFFObjectFile::getCOFFSection(const SectionRef
&Section
) const {
1174 return toSec(Section
.getRawDataRefImpl());
1177 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const DataRefImpl
&Ref
) const {
1179 return toSymb
<coff_symbol16
>(Ref
);
1181 return toSymb
<coff_symbol32
>(Ref
);
1182 llvm_unreachable("no symbol table pointer!");
1185 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const SymbolRef
&Symbol
) const {
1186 return getCOFFSymbol(Symbol
.getRawDataRefImpl());
1189 const coff_relocation
*
1190 COFFObjectFile::getCOFFRelocation(const RelocationRef
&Reloc
) const {
1191 return toRel(Reloc
.getRawDataRefImpl());
1194 ArrayRef
<coff_relocation
>
1195 COFFObjectFile::getRelocations(const coff_section
*Sec
) const {
1196 return {getFirstReloc(Sec
, Data
, base()),
1197 getNumberOfRelocations(Sec
, Data
, base())};
1200 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1201 case COFF::reloc_type: \
1204 StringRef
COFFObjectFile::getRelocationTypeName(uint16_t Type
) const {
1205 switch (getMachine()) {
1206 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1208 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE
);
1209 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64
);
1210 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32
);
1211 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB
);
1212 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32
);
1213 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1
);
1214 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2
);
1215 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3
);
1216 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4
);
1217 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5
);
1218 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION
);
1219 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL
);
1220 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7
);
1221 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN
);
1222 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32
);
1223 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR
);
1224 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32
);
1229 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1231 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE
);
1232 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32
);
1233 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB
);
1234 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24
);
1235 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11
);
1236 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN
);
1237 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24
);
1238 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11
);
1239 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32
);
1240 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION
);
1241 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL
);
1242 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A
);
1243 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T
);
1244 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T
);
1245 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T
);
1246 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T
);
1247 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR
);
1252 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1254 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE
);
1255 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32
);
1256 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB
);
1257 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26
);
1258 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21
);
1259 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21
);
1260 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A
);
1261 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L
);
1262 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL
);
1263 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A
);
1264 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A
);
1265 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L
);
1266 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN
);
1267 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION
);
1268 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64
);
1269 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19
);
1270 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14
);
1271 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32
);
1276 case COFF::IMAGE_FILE_MACHINE_I386
:
1278 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE
);
1279 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16
);
1280 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16
);
1281 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32
);
1282 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB
);
1283 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12
);
1284 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION
);
1285 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL
);
1286 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN
);
1287 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7
);
1288 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32
);
1298 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1300 void COFFObjectFile::getRelocationTypeName(
1301 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
1302 const coff_relocation
*Reloc
= toRel(Rel
);
1303 StringRef Res
= getRelocationTypeName(Reloc
->Type
);
1304 Result
.append(Res
.begin(), Res
.end());
1307 bool COFFObjectFile::isRelocatableObject() const {
1308 return !DataDirectory
;
1311 StringRef
COFFObjectFile::mapDebugSectionName(StringRef Name
) const {
1312 return StringSwitch
<StringRef
>(Name
)
1313 .Case("eh_fram", "eh_frame")
1317 bool ImportDirectoryEntryRef::
1318 operator==(const ImportDirectoryEntryRef
&Other
) const {
1319 return ImportTable
== Other
.ImportTable
&& Index
== Other
.Index
;
1322 void ImportDirectoryEntryRef::moveNext() {
1324 if (ImportTable
[Index
].isNull()) {
1326 ImportTable
= nullptr;
1330 std::error_code
ImportDirectoryEntryRef::getImportTableEntry(
1331 const coff_import_directory_table_entry
*&Result
) const {
1332 return getObject(Result
, OwningObject
->Data
, ImportTable
+ Index
);
1335 static imported_symbol_iterator
1336 makeImportedSymbolIterator(const COFFObjectFile
*Object
,
1337 uintptr_t Ptr
, int Index
) {
1338 if (Object
->getBytesInAddress() == 4) {
1339 auto *P
= reinterpret_cast<const import_lookup_table_entry32
*>(Ptr
);
1340 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1342 auto *P
= reinterpret_cast<const import_lookup_table_entry64
*>(Ptr
);
1343 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1346 static imported_symbol_iterator
1347 importedSymbolBegin(uint32_t RVA
, const COFFObjectFile
*Object
) {
1348 uintptr_t IntPtr
= 0;
1349 Object
->getRvaPtr(RVA
, IntPtr
);
1350 return makeImportedSymbolIterator(Object
, IntPtr
, 0);
1353 static imported_symbol_iterator
1354 importedSymbolEnd(uint32_t RVA
, const COFFObjectFile
*Object
) {
1355 uintptr_t IntPtr
= 0;
1356 Object
->getRvaPtr(RVA
, IntPtr
);
1357 // Forward the pointer to the last entry which is null.
1359 if (Object
->getBytesInAddress() == 4) {
1360 auto *Entry
= reinterpret_cast<ulittle32_t
*>(IntPtr
);
1364 auto *Entry
= reinterpret_cast<ulittle64_t
*>(IntPtr
);
1368 return makeImportedSymbolIterator(Object
, IntPtr
, Index
);
1371 imported_symbol_iterator
1372 ImportDirectoryEntryRef::imported_symbol_begin() const {
1373 return importedSymbolBegin(ImportTable
[Index
].ImportAddressTableRVA
,
1377 imported_symbol_iterator
1378 ImportDirectoryEntryRef::imported_symbol_end() const {
1379 return importedSymbolEnd(ImportTable
[Index
].ImportAddressTableRVA
,
1383 iterator_range
<imported_symbol_iterator
>
1384 ImportDirectoryEntryRef::imported_symbols() const {
1385 return make_range(imported_symbol_begin(), imported_symbol_end());
1388 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_begin() const {
1389 return importedSymbolBegin(ImportTable
[Index
].ImportLookupTableRVA
,
1393 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_end() const {
1394 return importedSymbolEnd(ImportTable
[Index
].ImportLookupTableRVA
,
1398 iterator_range
<imported_symbol_iterator
>
1399 ImportDirectoryEntryRef::lookup_table_symbols() const {
1400 return make_range(lookup_table_begin(), lookup_table_end());
1403 std::error_code
ImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1404 uintptr_t IntPtr
= 0;
1405 if (std::error_code EC
=
1406 OwningObject
->getRvaPtr(ImportTable
[Index
].NameRVA
, IntPtr
))
1408 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1409 return std::error_code();
1413 ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result
) const {
1414 Result
= ImportTable
[Index
].ImportLookupTableRVA
;
1415 return std::error_code();
1419 ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result
) const {
1420 Result
= ImportTable
[Index
].ImportAddressTableRVA
;
1421 return std::error_code();
1424 bool DelayImportDirectoryEntryRef::
1425 operator==(const DelayImportDirectoryEntryRef
&Other
) const {
1426 return Table
== Other
.Table
&& Index
== Other
.Index
;
1429 void DelayImportDirectoryEntryRef::moveNext() {
1433 imported_symbol_iterator
1434 DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1435 return importedSymbolBegin(Table
[Index
].DelayImportNameTable
,
1439 imported_symbol_iterator
1440 DelayImportDirectoryEntryRef::imported_symbol_end() const {
1441 return importedSymbolEnd(Table
[Index
].DelayImportNameTable
,
1445 iterator_range
<imported_symbol_iterator
>
1446 DelayImportDirectoryEntryRef::imported_symbols() const {
1447 return make_range(imported_symbol_begin(), imported_symbol_end());
1450 std::error_code
DelayImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1451 uintptr_t IntPtr
= 0;
1452 if (std::error_code EC
= OwningObject
->getRvaPtr(Table
[Index
].Name
, IntPtr
))
1454 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1455 return std::error_code();
1458 std::error_code
DelayImportDirectoryEntryRef::
1459 getDelayImportTable(const delay_import_directory_table_entry
*&Result
) const {
1461 return std::error_code();
1464 std::error_code
DelayImportDirectoryEntryRef::
1465 getImportAddress(int AddrIndex
, uint64_t &Result
) const {
1466 uint32_t RVA
= Table
[Index
].DelayImportAddressTable
+
1467 AddrIndex
* (OwningObject
->is64() ? 8 : 4);
1468 uintptr_t IntPtr
= 0;
1469 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1471 if (OwningObject
->is64())
1472 Result
= *reinterpret_cast<const ulittle64_t
*>(IntPtr
);
1474 Result
= *reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1475 return std::error_code();
1478 bool ExportDirectoryEntryRef::
1479 operator==(const ExportDirectoryEntryRef
&Other
) const {
1480 return ExportTable
== Other
.ExportTable
&& Index
== Other
.Index
;
1483 void ExportDirectoryEntryRef::moveNext() {
1487 // Returns the name of the current export symbol. If the symbol is exported only
1488 // by ordinal, the empty string is set as a result.
1489 std::error_code
ExportDirectoryEntryRef::getDllName(StringRef
&Result
) const {
1490 uintptr_t IntPtr
= 0;
1491 if (std::error_code EC
=
1492 OwningObject
->getRvaPtr(ExportTable
->NameRVA
, IntPtr
))
1494 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1495 return std::error_code();
1498 // Returns the starting ordinal number.
1500 ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result
) const {
1501 Result
= ExportTable
->OrdinalBase
;
1502 return std::error_code();
1505 // Returns the export ordinal of the current export symbol.
1506 std::error_code
ExportDirectoryEntryRef::getOrdinal(uint32_t &Result
) const {
1507 Result
= ExportTable
->OrdinalBase
+ Index
;
1508 return std::error_code();
1511 // Returns the address of the current export symbol.
1512 std::error_code
ExportDirectoryEntryRef::getExportRVA(uint32_t &Result
) const {
1513 uintptr_t IntPtr
= 0;
1514 if (std::error_code EC
=
1515 OwningObject
->getRvaPtr(ExportTable
->ExportAddressTableRVA
, IntPtr
))
1517 const export_address_table_entry
*entry
=
1518 reinterpret_cast<const export_address_table_entry
*>(IntPtr
);
1519 Result
= entry
[Index
].ExportRVA
;
1520 return std::error_code();
1523 // Returns the name of the current export symbol. If the symbol is exported only
1524 // by ordinal, the empty string is set as a result.
1526 ExportDirectoryEntryRef::getSymbolName(StringRef
&Result
) const {
1527 uintptr_t IntPtr
= 0;
1528 if (std::error_code EC
=
1529 OwningObject
->getRvaPtr(ExportTable
->OrdinalTableRVA
, IntPtr
))
1531 const ulittle16_t
*Start
= reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1533 uint32_t NumEntries
= ExportTable
->NumberOfNamePointers
;
1535 for (const ulittle16_t
*I
= Start
, *E
= Start
+ NumEntries
;
1536 I
< E
; ++I
, ++Offset
) {
1539 if (std::error_code EC
=
1540 OwningObject
->getRvaPtr(ExportTable
->NamePointerRVA
, IntPtr
))
1542 const ulittle32_t
*NamePtr
= reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1543 if (std::error_code EC
= OwningObject
->getRvaPtr(NamePtr
[Offset
], IntPtr
))
1545 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1546 return std::error_code();
1549 return std::error_code();
1552 std::error_code
ExportDirectoryEntryRef::isForwarder(bool &Result
) const {
1553 const data_directory
*DataEntry
;
1554 if (auto EC
= OwningObject
->getDataDirectory(COFF::EXPORT_TABLE
, DataEntry
))
1557 if (auto EC
= getExportRVA(RVA
))
1559 uint32_t Begin
= DataEntry
->RelativeVirtualAddress
;
1560 uint32_t End
= DataEntry
->RelativeVirtualAddress
+ DataEntry
->Size
;
1561 Result
= (Begin
<= RVA
&& RVA
< End
);
1562 return std::error_code();
1565 std::error_code
ExportDirectoryEntryRef::getForwardTo(StringRef
&Result
) const {
1567 if (auto EC
= getExportRVA(RVA
))
1569 uintptr_t IntPtr
= 0;
1570 if (auto EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1572 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1573 return std::error_code();
1576 bool ImportedSymbolRef::
1577 operator==(const ImportedSymbolRef
&Other
) const {
1578 return Entry32
== Other
.Entry32
&& Entry64
== Other
.Entry64
1579 && Index
== Other
.Index
;
1582 void ImportedSymbolRef::moveNext() {
1587 ImportedSymbolRef::getSymbolName(StringRef
&Result
) const {
1590 // If a symbol is imported only by ordinal, it has no name.
1591 if (Entry32
[Index
].isOrdinal())
1592 return std::error_code();
1593 RVA
= Entry32
[Index
].getHintNameRVA();
1595 if (Entry64
[Index
].isOrdinal())
1596 return std::error_code();
1597 RVA
= Entry64
[Index
].getHintNameRVA();
1599 uintptr_t IntPtr
= 0;
1600 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1602 // +2 because the first two bytes is hint.
1603 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
+ 2));
1604 return std::error_code();
1607 std::error_code
ImportedSymbolRef::isOrdinal(bool &Result
) const {
1609 Result
= Entry32
[Index
].isOrdinal();
1611 Result
= Entry64
[Index
].isOrdinal();
1612 return std::error_code();
1615 std::error_code
ImportedSymbolRef::getHintNameRVA(uint32_t &Result
) const {
1617 Result
= Entry32
[Index
].getHintNameRVA();
1619 Result
= Entry64
[Index
].getHintNameRVA();
1620 return std::error_code();
1623 std::error_code
ImportedSymbolRef::getOrdinal(uint16_t &Result
) const {
1626 if (Entry32
[Index
].isOrdinal()) {
1627 Result
= Entry32
[Index
].getOrdinal();
1628 return std::error_code();
1630 RVA
= Entry32
[Index
].getHintNameRVA();
1632 if (Entry64
[Index
].isOrdinal()) {
1633 Result
= Entry64
[Index
].getOrdinal();
1634 return std::error_code();
1636 RVA
= Entry64
[Index
].getHintNameRVA();
1638 uintptr_t IntPtr
= 0;
1639 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1641 Result
= *reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1642 return std::error_code();
1645 Expected
<std::unique_ptr
<COFFObjectFile
>>
1646 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object
) {
1648 std::unique_ptr
<COFFObjectFile
> Ret(new COFFObjectFile(Object
, EC
));
1650 return errorCodeToError(EC
);
1651 return std::move(Ret
);
1654 bool BaseRelocRef::operator==(const BaseRelocRef
&Other
) const {
1655 return Header
== Other
.Header
&& Index
== Other
.Index
;
1658 void BaseRelocRef::moveNext() {
1659 // Header->BlockSize is the size of the current block, including the
1660 // size of the header itself.
1661 uint32_t Size
= sizeof(*Header
) +
1662 sizeof(coff_base_reloc_block_entry
) * (Index
+ 1);
1663 if (Size
== Header
->BlockSize
) {
1664 // .reloc contains a list of base relocation blocks. Each block
1665 // consists of the header followed by entries. The header contains
1666 // how many entories will follow. When we reach the end of the
1667 // current block, proceed to the next block.
1668 Header
= reinterpret_cast<const coff_base_reloc_block_header
*>(
1669 reinterpret_cast<const uint8_t *>(Header
) + Size
);
1676 std::error_code
BaseRelocRef::getType(uint8_t &Type
) const {
1677 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1678 Type
= Entry
[Index
].getType();
1679 return std::error_code();
1682 std::error_code
BaseRelocRef::getRVA(uint32_t &Result
) const {
1683 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1684 Result
= Header
->PageRVA
+ Entry
[Index
].getOffset();
1685 return std::error_code();
1688 #define RETURN_IF_ERROR(E) \
1692 Expected
<ArrayRef
<UTF16
>>
1693 ResourceSectionRef::getDirStringAtOffset(uint32_t Offset
) {
1694 BinaryStreamReader Reader
= BinaryStreamReader(BBS
);
1695 Reader
.setOffset(Offset
);
1697 RETURN_IF_ERROR(Reader
.readInteger(Length
));
1698 ArrayRef
<UTF16
> RawDirString
;
1699 RETURN_IF_ERROR(Reader
.readArray(RawDirString
, Length
));
1700 return RawDirString
;
1703 Expected
<ArrayRef
<UTF16
>>
1704 ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry
&Entry
) {
1705 return getDirStringAtOffset(Entry
.Identifier
.getNameOffset());
1708 Expected
<const coff_resource_dir_table
&>
1709 ResourceSectionRef::getTableAtOffset(uint32_t Offset
) {
1710 const coff_resource_dir_table
*Table
= nullptr;
1712 BinaryStreamReader
Reader(BBS
);
1713 Reader
.setOffset(Offset
);
1714 RETURN_IF_ERROR(Reader
.readObject(Table
));
1715 assert(Table
!= nullptr);
1719 Expected
<const coff_resource_dir_table
&>
1720 ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry
&Entry
) {
1721 return getTableAtOffset(Entry
.Offset
.value());
1724 Expected
<const coff_resource_dir_table
&> ResourceSectionRef::getBaseTable() {
1725 return getTableAtOffset(0);