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 Expected
<StringRef
> COFFObjectFile::getSectionName(DataRefImpl Ref
) const {
273 const coff_section
*Sec
= toSec(Ref
);
274 return getSectionName(Sec
);
277 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref
) const {
278 const coff_section
*Sec
= toSec(Ref
);
279 uint64_t Result
= Sec
->VirtualAddress
;
281 // The section VirtualAddress does not include ImageBase, and we want to
282 // return virtual addresses.
283 Result
+= getImageBase();
287 uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec
) const {
288 return toSec(Sec
) - SectionTable
;
291 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref
) const {
292 return getSectionSize(toSec(Ref
));
295 Expected
<ArrayRef
<uint8_t>>
296 COFFObjectFile::getSectionContents(DataRefImpl Ref
) const {
297 const coff_section
*Sec
= toSec(Ref
);
298 ArrayRef
<uint8_t> Res
;
299 if (Error E
= getSectionContents(Sec
, Res
))
304 uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref
) const {
305 const coff_section
*Sec
= toSec(Ref
);
306 return Sec
->getAlignment();
309 bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
313 bool COFFObjectFile::isSectionText(DataRefImpl Ref
) const {
314 const coff_section
*Sec
= toSec(Ref
);
315 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_CODE
;
318 bool COFFObjectFile::isSectionData(DataRefImpl Ref
) const {
319 const coff_section
*Sec
= toSec(Ref
);
320 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
323 bool COFFObjectFile::isSectionBSS(DataRefImpl Ref
) const {
324 const coff_section
*Sec
= toSec(Ref
);
325 const uint32_t BssFlags
= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
326 COFF::IMAGE_SCN_MEM_READ
|
327 COFF::IMAGE_SCN_MEM_WRITE
;
328 return (Sec
->Characteristics
& BssFlags
) == BssFlags
;
331 unsigned COFFObjectFile::getSectionID(SectionRef Sec
) const {
333 uintptr_t(Sec
.getRawDataRefImpl().p
) - uintptr_t(SectionTable
);
334 assert((Offset
% sizeof(coff_section
)) == 0);
335 return (Offset
/ sizeof(coff_section
)) + 1;
338 bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref
) const {
339 const coff_section
*Sec
= toSec(Ref
);
340 // In COFF, a virtual section won't have any in-file
341 // content, so the file pointer to the content will be zero.
342 return Sec
->PointerToRawData
== 0;
345 static uint32_t getNumberOfRelocations(const coff_section
*Sec
,
346 MemoryBufferRef M
, const uint8_t *base
) {
347 // The field for the number of relocations in COFF section table is only
348 // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
349 // NumberOfRelocations field, and the actual relocation count is stored in the
350 // VirtualAddress field in the first relocation entry.
351 if (Sec
->hasExtendedRelocations()) {
352 const coff_relocation
*FirstReloc
;
353 if (getObject(FirstReloc
, M
, reinterpret_cast<const coff_relocation
*>(
354 base
+ Sec
->PointerToRelocations
)))
356 // -1 to exclude this first relocation entry.
357 return FirstReloc
->VirtualAddress
- 1;
359 return Sec
->NumberOfRelocations
;
362 static const coff_relocation
*
363 getFirstReloc(const coff_section
*Sec
, MemoryBufferRef M
, const uint8_t *Base
) {
364 uint64_t NumRelocs
= getNumberOfRelocations(Sec
, M
, Base
);
367 auto begin
= reinterpret_cast<const coff_relocation
*>(
368 Base
+ Sec
->PointerToRelocations
);
369 if (Sec
->hasExtendedRelocations()) {
370 // Skip the first relocation entry repurposed to store the number of
374 if (Binary::checkOffset(M
, uintptr_t(begin
),
375 sizeof(coff_relocation
) * NumRelocs
))
380 relocation_iterator
COFFObjectFile::section_rel_begin(DataRefImpl Ref
) const {
381 const coff_section
*Sec
= toSec(Ref
);
382 const coff_relocation
*begin
= getFirstReloc(Sec
, Data
, base());
383 if (begin
&& Sec
->VirtualAddress
!= 0)
384 report_fatal_error("Sections with relocations should have an address of 0");
386 Ret
.p
= reinterpret_cast<uintptr_t>(begin
);
387 return relocation_iterator(RelocationRef(Ret
, this));
390 relocation_iterator
COFFObjectFile::section_rel_end(DataRefImpl Ref
) const {
391 const coff_section
*Sec
= toSec(Ref
);
392 const coff_relocation
*I
= getFirstReloc(Sec
, Data
, base());
394 I
+= getNumberOfRelocations(Sec
, Data
, base());
396 Ret
.p
= reinterpret_cast<uintptr_t>(I
);
397 return relocation_iterator(RelocationRef(Ret
, this));
400 // Initialize the pointer to the symbol table.
401 std::error_code
COFFObjectFile::initSymbolTablePtr() {
403 if (std::error_code EC
= getObject(
404 SymbolTable16
, Data
, base() + getPointerToSymbolTable(),
405 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
408 if (COFFBigObjHeader
)
409 if (std::error_code EC
= getObject(
410 SymbolTable32
, Data
, base() + getPointerToSymbolTable(),
411 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
414 // Find string table. The first four byte of the string table contains the
415 // total size of the string table, including the size field itself. If the
416 // string table is empty, the value of the first four byte would be 4.
417 uint32_t StringTableOffset
= getPointerToSymbolTable() +
418 getNumberOfSymbols() * getSymbolTableEntrySize();
419 const uint8_t *StringTableAddr
= base() + StringTableOffset
;
420 const ulittle32_t
*StringTableSizePtr
;
421 if (std::error_code EC
= getObject(StringTableSizePtr
, Data
, StringTableAddr
))
423 StringTableSize
= *StringTableSizePtr
;
424 if (std::error_code EC
=
425 getObject(StringTable
, Data
, StringTableAddr
, StringTableSize
))
428 // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
429 // tools like cvtres write a size of 0 for an empty table instead of 4.
430 if (StringTableSize
< 4)
433 // Check that the string table is null terminated if has any in it.
434 if (StringTableSize
> 4 && StringTable
[StringTableSize
- 1] != 0)
435 return object_error::parse_failed
;
436 return std::error_code();
439 uint64_t COFFObjectFile::getImageBase() const {
441 return PE32Header
->ImageBase
;
442 else if (PE32PlusHeader
)
443 return PE32PlusHeader
->ImageBase
;
444 // This actually comes up in practice.
448 // Returns the file offset for the given VA.
449 std::error_code
COFFObjectFile::getVaPtr(uint64_t Addr
, uintptr_t &Res
) const {
450 uint64_t ImageBase
= getImageBase();
451 uint64_t Rva
= Addr
- ImageBase
;
452 assert(Rva
<= UINT32_MAX
);
453 return getRvaPtr((uint32_t)Rva
, Res
);
456 // Returns the file offset for the given RVA.
457 std::error_code
COFFObjectFile::getRvaPtr(uint32_t Addr
, uintptr_t &Res
) const {
458 for (const SectionRef
&S
: sections()) {
459 const coff_section
*Section
= getCOFFSection(S
);
460 uint32_t SectionStart
= Section
->VirtualAddress
;
461 uint32_t SectionEnd
= Section
->VirtualAddress
+ Section
->VirtualSize
;
462 if (SectionStart
<= Addr
&& Addr
< SectionEnd
) {
463 uint32_t Offset
= Addr
- SectionStart
;
464 Res
= uintptr_t(base()) + Section
->PointerToRawData
+ Offset
;
465 return std::error_code();
468 return object_error::parse_failed
;
472 COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA
, uint32_t Size
,
473 ArrayRef
<uint8_t> &Contents
) const {
474 for (const SectionRef
&S
: sections()) {
475 const coff_section
*Section
= getCOFFSection(S
);
476 uint32_t SectionStart
= Section
->VirtualAddress
;
477 // Check if this RVA is within the section bounds. Be careful about integer
479 uint32_t OffsetIntoSection
= RVA
- SectionStart
;
480 if (SectionStart
<= RVA
&& OffsetIntoSection
< Section
->VirtualSize
&&
481 Size
<= Section
->VirtualSize
- OffsetIntoSection
) {
483 uintptr_t(base()) + Section
->PointerToRawData
+ OffsetIntoSection
;
485 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(Begin
), Size
);
486 return std::error_code();
489 return object_error::parse_failed
;
492 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
494 std::error_code
COFFObjectFile::getHintName(uint32_t Rva
, uint16_t &Hint
,
495 StringRef
&Name
) const {
496 uintptr_t IntPtr
= 0;
497 if (std::error_code EC
= getRvaPtr(Rva
, IntPtr
))
499 const uint8_t *Ptr
= reinterpret_cast<const uint8_t *>(IntPtr
);
500 Hint
= *reinterpret_cast<const ulittle16_t
*>(Ptr
);
501 Name
= StringRef(reinterpret_cast<const char *>(Ptr
+ 2));
502 return std::error_code();
506 COFFObjectFile::getDebugPDBInfo(const debug_directory
*DebugDir
,
507 const codeview::DebugInfo
*&PDBInfo
,
508 StringRef
&PDBFileName
) const {
509 ArrayRef
<uint8_t> InfoBytes
;
510 if (std::error_code EC
= getRvaAndSizeAsBytes(
511 DebugDir
->AddressOfRawData
, DebugDir
->SizeOfData
, InfoBytes
))
513 if (InfoBytes
.size() < sizeof(*PDBInfo
) + 1)
514 return object_error::parse_failed
;
515 PDBInfo
= reinterpret_cast<const codeview::DebugInfo
*>(InfoBytes
.data());
516 InfoBytes
= InfoBytes
.drop_front(sizeof(*PDBInfo
));
517 PDBFileName
= StringRef(reinterpret_cast<const char *>(InfoBytes
.data()),
519 // Truncate the name at the first null byte. Ignore any padding.
520 PDBFileName
= PDBFileName
.split('\0').first
;
521 return std::error_code();
525 COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo
*&PDBInfo
,
526 StringRef
&PDBFileName
) const {
527 for (const debug_directory
&D
: debug_directories())
528 if (D
.Type
== COFF::IMAGE_DEBUG_TYPE_CODEVIEW
)
529 return getDebugPDBInfo(&D
, PDBInfo
, PDBFileName
);
530 // If we get here, there is no PDB info to return.
532 PDBFileName
= StringRef();
533 return std::error_code();
536 // Find the import table.
537 std::error_code
COFFObjectFile::initImportTablePtr() {
538 // First, we get the RVA of the import table. If the file lacks a pointer to
539 // the import table, do nothing.
540 const data_directory
*DataEntry
;
541 if (getDataDirectory(COFF::IMPORT_TABLE
, DataEntry
))
542 return std::error_code();
544 // Do nothing if the pointer to import table is NULL.
545 if (DataEntry
->RelativeVirtualAddress
== 0)
546 return std::error_code();
548 uint32_t ImportTableRva
= DataEntry
->RelativeVirtualAddress
;
550 // Find the section that contains the RVA. This is needed because the RVA is
551 // the import table's memory address which is different from its file offset.
552 uintptr_t IntPtr
= 0;
553 if (std::error_code EC
= getRvaPtr(ImportTableRva
, IntPtr
))
555 if (std::error_code EC
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
557 ImportDirectory
= reinterpret_cast<
558 const coff_import_directory_table_entry
*>(IntPtr
);
559 return std::error_code();
562 // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
563 std::error_code
COFFObjectFile::initDelayImportTablePtr() {
564 const data_directory
*DataEntry
;
565 if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR
, DataEntry
))
566 return std::error_code();
567 if (DataEntry
->RelativeVirtualAddress
== 0)
568 return std::error_code();
570 uint32_t RVA
= DataEntry
->RelativeVirtualAddress
;
571 NumberOfDelayImportDirectory
= DataEntry
->Size
/
572 sizeof(delay_import_directory_table_entry
) - 1;
574 uintptr_t IntPtr
= 0;
575 if (std::error_code EC
= getRvaPtr(RVA
, IntPtr
))
577 DelayImportDirectory
= reinterpret_cast<
578 const delay_import_directory_table_entry
*>(IntPtr
);
579 return std::error_code();
582 // Find the export table.
583 std::error_code
COFFObjectFile::initExportTablePtr() {
584 // First, we get the RVA of the export table. If the file lacks a pointer to
585 // the export table, do nothing.
586 const data_directory
*DataEntry
;
587 if (getDataDirectory(COFF::EXPORT_TABLE
, DataEntry
))
588 return std::error_code();
590 // Do nothing if the pointer to export table is NULL.
591 if (DataEntry
->RelativeVirtualAddress
== 0)
592 return std::error_code();
594 uint32_t ExportTableRva
= DataEntry
->RelativeVirtualAddress
;
595 uintptr_t IntPtr
= 0;
596 if (std::error_code EC
= getRvaPtr(ExportTableRva
, IntPtr
))
599 reinterpret_cast<const export_directory_table_entry
*>(IntPtr
);
600 return std::error_code();
603 std::error_code
COFFObjectFile::initBaseRelocPtr() {
604 const data_directory
*DataEntry
;
605 if (getDataDirectory(COFF::BASE_RELOCATION_TABLE
, DataEntry
))
606 return std::error_code();
607 if (DataEntry
->RelativeVirtualAddress
== 0)
608 return std::error_code();
610 uintptr_t IntPtr
= 0;
611 if (std::error_code EC
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
))
613 BaseRelocHeader
= reinterpret_cast<const coff_base_reloc_block_header
*>(
615 BaseRelocEnd
= reinterpret_cast<coff_base_reloc_block_header
*>(
616 IntPtr
+ DataEntry
->Size
);
617 // FIXME: Verify the section containing BaseRelocHeader has at least
618 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
619 return std::error_code();
622 std::error_code
COFFObjectFile::initDebugDirectoryPtr() {
623 // Get the RVA of the debug directory. Do nothing if it does not exist.
624 const data_directory
*DataEntry
;
625 if (getDataDirectory(COFF::DEBUG_DIRECTORY
, DataEntry
))
626 return std::error_code();
628 // Do nothing if the RVA is NULL.
629 if (DataEntry
->RelativeVirtualAddress
== 0)
630 return std::error_code();
632 // Check that the size is a multiple of the entry size.
633 if (DataEntry
->Size
% sizeof(debug_directory
) != 0)
634 return object_error::parse_failed
;
636 uintptr_t IntPtr
= 0;
637 if (std::error_code EC
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
))
639 DebugDirectoryBegin
= reinterpret_cast<const debug_directory
*>(IntPtr
);
640 DebugDirectoryEnd
= reinterpret_cast<const debug_directory
*>(
641 IntPtr
+ DataEntry
->Size
);
642 // FIXME: Verify the section containing DebugDirectoryBegin has at least
643 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
644 return std::error_code();
647 std::error_code
COFFObjectFile::initLoadConfigPtr() {
648 // Get the RVA of the debug directory. Do nothing if it does not exist.
649 const data_directory
*DataEntry
;
650 if (getDataDirectory(COFF::LOAD_CONFIG_TABLE
, DataEntry
))
651 return std::error_code();
653 // Do nothing if the RVA is NULL.
654 if (DataEntry
->RelativeVirtualAddress
== 0)
655 return std::error_code();
656 uintptr_t IntPtr
= 0;
657 if (std::error_code EC
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
))
660 LoadConfig
= (const void *)IntPtr
;
661 return std::error_code();
664 COFFObjectFile::COFFObjectFile(MemoryBufferRef Object
, std::error_code
&EC
)
665 : ObjectFile(Binary::ID_COFF
, Object
), COFFHeader(nullptr),
666 COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
667 DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
668 SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
669 ImportDirectory(nullptr),
670 DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
671 ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
672 DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
673 // Check that we at least have enough room for a header.
674 if (!checkSize(Data
, EC
, sizeof(coff_file_header
)))
677 // The current location in the file where we are looking at.
680 // PE header is optional and is present only in executables. If it exists,
681 // it is placed right after COFF header.
682 bool HasPEHeader
= false;
684 // Check if this is a PE/COFF file.
685 if (checkSize(Data
, EC
, sizeof(dos_header
) + sizeof(COFF::PEMagic
))) {
686 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
687 // PE signature to find 'normal' COFF header.
688 const auto *DH
= reinterpret_cast<const dos_header
*>(base());
689 if (DH
->Magic
[0] == 'M' && DH
->Magic
[1] == 'Z') {
690 CurPtr
= DH
->AddressOfNewExeHeader
;
691 // Check the PE magic bytes. ("PE\0\0")
692 if (memcmp(base() + CurPtr
, COFF::PEMagic
, sizeof(COFF::PEMagic
)) != 0) {
693 EC
= object_error::parse_failed
;
696 CurPtr
+= sizeof(COFF::PEMagic
); // Skip the PE magic bytes.
701 if ((EC
= getObject(COFFHeader
, Data
, base() + CurPtr
)))
704 // It might be a bigobj file, let's check. Note that COFF bigobj and COFF
705 // import libraries share a common prefix but bigobj is more restrictive.
706 if (!HasPEHeader
&& COFFHeader
->Machine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
&&
707 COFFHeader
->NumberOfSections
== uint16_t(0xffff) &&
708 checkSize(Data
, EC
, sizeof(coff_bigobj_file_header
))) {
709 if ((EC
= getObject(COFFBigObjHeader
, Data
, base() + CurPtr
)))
712 // Verify that we are dealing with bigobj.
713 if (COFFBigObjHeader
->Version
>= COFF::BigObjHeader::MinBigObjectVersion
&&
714 std::memcmp(COFFBigObjHeader
->UUID
, COFF::BigObjMagic
,
715 sizeof(COFF::BigObjMagic
)) == 0) {
716 COFFHeader
= nullptr;
717 CurPtr
+= sizeof(coff_bigobj_file_header
);
719 // It's not a bigobj.
720 COFFBigObjHeader
= nullptr;
724 // The prior checkSize call may have failed. This isn't a hard error
725 // because we were just trying to sniff out bigobj.
726 EC
= std::error_code();
727 CurPtr
+= sizeof(coff_file_header
);
729 if (COFFHeader
->isImportLibrary())
734 const pe32_header
*Header
;
735 if ((EC
= getObject(Header
, Data
, base() + CurPtr
)))
738 const uint8_t *DataDirAddr
;
739 uint64_t DataDirSize
;
740 if (Header
->Magic
== COFF::PE32Header::PE32
) {
742 DataDirAddr
= base() + CurPtr
+ sizeof(pe32_header
);
743 DataDirSize
= sizeof(data_directory
) * PE32Header
->NumberOfRvaAndSize
;
744 } else if (Header
->Magic
== COFF::PE32Header::PE32_PLUS
) {
745 PE32PlusHeader
= reinterpret_cast<const pe32plus_header
*>(Header
);
746 DataDirAddr
= base() + CurPtr
+ sizeof(pe32plus_header
);
747 DataDirSize
= sizeof(data_directory
) * PE32PlusHeader
->NumberOfRvaAndSize
;
749 // It's neither PE32 nor PE32+.
750 EC
= object_error::parse_failed
;
753 if ((EC
= getObject(DataDirectory
, Data
, DataDirAddr
, DataDirSize
)))
758 CurPtr
+= COFFHeader
->SizeOfOptionalHeader
;
760 if ((EC
= getObject(SectionTable
, Data
, base() + CurPtr
,
761 (uint64_t)getNumberOfSections() * sizeof(coff_section
))))
764 // Initialize the pointer to the symbol table.
765 if (getPointerToSymbolTable() != 0) {
766 if ((EC
= initSymbolTablePtr())) {
767 SymbolTable16
= nullptr;
768 SymbolTable32
= nullptr;
769 StringTable
= nullptr;
773 // We had better not have any symbols if we don't have a symbol table.
774 if (getNumberOfSymbols() != 0) {
775 EC
= object_error::parse_failed
;
780 // Initialize the pointer to the beginning of the import table.
781 if ((EC
= initImportTablePtr()))
783 if ((EC
= initDelayImportTablePtr()))
786 // Initialize the pointer to the export table.
787 if ((EC
= initExportTablePtr()))
790 // Initialize the pointer to the base relocation table.
791 if ((EC
= initBaseRelocPtr()))
794 // Initialize the pointer to the export table.
795 if ((EC
= initDebugDirectoryPtr()))
798 if ((EC
= initLoadConfigPtr()))
801 EC
= std::error_code();
804 basic_symbol_iterator
COFFObjectFile::symbol_begin() const {
806 Ret
.p
= getSymbolTable();
807 return basic_symbol_iterator(SymbolRef(Ret
, this));
810 basic_symbol_iterator
COFFObjectFile::symbol_end() const {
811 // The symbol table ends where the string table begins.
813 Ret
.p
= reinterpret_cast<uintptr_t>(StringTable
);
814 return basic_symbol_iterator(SymbolRef(Ret
, this));
817 import_directory_iterator
COFFObjectFile::import_directory_begin() const {
818 if (!ImportDirectory
)
819 return import_directory_end();
820 if (ImportDirectory
->isNull())
821 return import_directory_end();
822 return import_directory_iterator(
823 ImportDirectoryEntryRef(ImportDirectory
, 0, this));
826 import_directory_iterator
COFFObjectFile::import_directory_end() const {
827 return import_directory_iterator(
828 ImportDirectoryEntryRef(nullptr, -1, this));
831 delay_import_directory_iterator
832 COFFObjectFile::delay_import_directory_begin() const {
833 return delay_import_directory_iterator(
834 DelayImportDirectoryEntryRef(DelayImportDirectory
, 0, this));
837 delay_import_directory_iterator
838 COFFObjectFile::delay_import_directory_end() const {
839 return delay_import_directory_iterator(
840 DelayImportDirectoryEntryRef(
841 DelayImportDirectory
, NumberOfDelayImportDirectory
, this));
844 export_directory_iterator
COFFObjectFile::export_directory_begin() const {
845 return export_directory_iterator(
846 ExportDirectoryEntryRef(ExportDirectory
, 0, this));
849 export_directory_iterator
COFFObjectFile::export_directory_end() const {
850 if (!ExportDirectory
)
851 return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
852 ExportDirectoryEntryRef
Ref(ExportDirectory
,
853 ExportDirectory
->AddressTableEntries
, this);
854 return export_directory_iterator(Ref
);
857 section_iterator
COFFObjectFile::section_begin() const {
859 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
);
860 return section_iterator(SectionRef(Ret
, this));
863 section_iterator
COFFObjectFile::section_end() const {
866 COFFHeader
&& COFFHeader
->isImportLibrary() ? 0 : getNumberOfSections();
867 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
+ NumSections
);
868 return section_iterator(SectionRef(Ret
, this));
871 base_reloc_iterator
COFFObjectFile::base_reloc_begin() const {
872 return base_reloc_iterator(BaseRelocRef(BaseRelocHeader
, this));
875 base_reloc_iterator
COFFObjectFile::base_reloc_end() const {
876 return base_reloc_iterator(BaseRelocRef(BaseRelocEnd
, this));
879 uint8_t COFFObjectFile::getBytesInAddress() const {
880 return getArch() == Triple::x86_64
|| getArch() == Triple::aarch64
? 8 : 4;
883 StringRef
COFFObjectFile::getFileFormatName() const {
884 switch(getMachine()) {
885 case COFF::IMAGE_FILE_MACHINE_I386
:
887 case COFF::IMAGE_FILE_MACHINE_AMD64
:
888 return "COFF-x86-64";
889 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
891 case COFF::IMAGE_FILE_MACHINE_ARM64
:
894 return "COFF-<unknown arch>";
898 Triple::ArchType
COFFObjectFile::getArch() const {
899 switch (getMachine()) {
900 case COFF::IMAGE_FILE_MACHINE_I386
:
902 case COFF::IMAGE_FILE_MACHINE_AMD64
:
903 return Triple::x86_64
;
904 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
905 return Triple::thumb
;
906 case COFF::IMAGE_FILE_MACHINE_ARM64
:
907 return Triple::aarch64
;
909 return Triple::UnknownArch
;
913 Expected
<uint64_t> COFFObjectFile::getStartAddress() const {
915 return PE32Header
->AddressOfEntryPoint
;
919 iterator_range
<import_directory_iterator
>
920 COFFObjectFile::import_directories() const {
921 return make_range(import_directory_begin(), import_directory_end());
924 iterator_range
<delay_import_directory_iterator
>
925 COFFObjectFile::delay_import_directories() const {
926 return make_range(delay_import_directory_begin(),
927 delay_import_directory_end());
930 iterator_range
<export_directory_iterator
>
931 COFFObjectFile::export_directories() const {
932 return make_range(export_directory_begin(), export_directory_end());
935 iterator_range
<base_reloc_iterator
> COFFObjectFile::base_relocs() const {
936 return make_range(base_reloc_begin(), base_reloc_end());
940 COFFObjectFile::getCOFFHeader(const coff_file_header
*&Res
) const {
942 return std::error_code();
946 COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header
*&Res
) const {
947 Res
= COFFBigObjHeader
;
948 return std::error_code();
951 std::error_code
COFFObjectFile::getPE32Header(const pe32_header
*&Res
) const {
953 return std::error_code();
957 COFFObjectFile::getPE32PlusHeader(const pe32plus_header
*&Res
) const {
958 Res
= PE32PlusHeader
;
959 return std::error_code();
963 COFFObjectFile::getDataDirectory(uint32_t Index
,
964 const data_directory
*&Res
) const {
965 // Error if there's no data directory or the index is out of range.
966 if (!DataDirectory
) {
968 return object_error::parse_failed
;
970 assert(PE32Header
|| PE32PlusHeader
);
971 uint32_t NumEnt
= PE32Header
? PE32Header
->NumberOfRvaAndSize
972 : PE32PlusHeader
->NumberOfRvaAndSize
;
973 if (Index
>= NumEnt
) {
975 return object_error::parse_failed
;
977 Res
= &DataDirectory
[Index
];
978 return std::error_code();
981 std::error_code
COFFObjectFile::getSection(int32_t Index
,
982 const coff_section
*&Result
) const {
984 if (COFF::isReservedSectionNumber(Index
))
985 return std::error_code();
986 if (static_cast<uint32_t>(Index
) <= getNumberOfSections()) {
987 // We already verified the section table data, so no need to check again.
988 Result
= SectionTable
+ (Index
- 1);
989 return std::error_code();
991 return object_error::parse_failed
;
994 std::error_code
COFFObjectFile::getSection(StringRef SectionName
,
995 const coff_section
*&Result
) const {
998 for (const SectionRef
&Section
: sections()) {
999 if (std::error_code E
= Section
.getName(SecName
))
1001 if (SecName
== SectionName
) {
1002 Result
= getCOFFSection(Section
);
1003 return std::error_code();
1006 return object_error::parse_failed
;
1009 std::error_code
COFFObjectFile::getString(uint32_t Offset
,
1010 StringRef
&Result
) const {
1011 if (StringTableSize
<= 4)
1012 // Tried to get a string from an empty string table.
1013 return object_error::parse_failed
;
1014 if (Offset
>= StringTableSize
)
1015 return object_error::unexpected_eof
;
1016 Result
= StringRef(StringTable
+ Offset
);
1017 return std::error_code();
1020 std::error_code
COFFObjectFile::getSymbolName(COFFSymbolRef Symbol
,
1021 StringRef
&Res
) const {
1022 return getSymbolName(Symbol
.getGeneric(), Res
);
1025 std::error_code
COFFObjectFile::getSymbolName(const coff_symbol_generic
*Symbol
,
1026 StringRef
&Res
) const {
1027 // Check for string table entry. First 4 bytes are 0.
1028 if (Symbol
->Name
.Offset
.Zeroes
== 0) {
1029 if (std::error_code EC
= getString(Symbol
->Name
.Offset
.Offset
, Res
))
1031 return std::error_code();
1034 if (Symbol
->Name
.ShortName
[COFF::NameSize
- 1] == 0)
1035 // Null terminated, let ::strlen figure out the length.
1036 Res
= StringRef(Symbol
->Name
.ShortName
);
1038 // Not null terminated, use all 8 bytes.
1039 Res
= StringRef(Symbol
->Name
.ShortName
, COFF::NameSize
);
1040 return std::error_code();
1044 COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol
) const {
1045 const uint8_t *Aux
= nullptr;
1047 size_t SymbolSize
= getSymbolTableEntrySize();
1048 if (Symbol
.getNumberOfAuxSymbols() > 0) {
1049 // AUX data comes immediately after the symbol in COFF
1050 Aux
= reinterpret_cast<const uint8_t *>(Symbol
.getRawPtr()) + SymbolSize
;
1052 // Verify that the Aux symbol points to a valid entry in the symbol table.
1053 uintptr_t Offset
= uintptr_t(Aux
) - uintptr_t(base());
1054 if (Offset
< getPointerToSymbolTable() ||
1056 getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize
))
1057 report_fatal_error("Aux Symbol data was outside of symbol table.");
1059 assert((Offset
- getPointerToSymbolTable()) % SymbolSize
== 0 &&
1060 "Aux Symbol data did not point to the beginning of a symbol");
1063 return makeArrayRef(Aux
, Symbol
.getNumberOfAuxSymbols() * SymbolSize
);
1066 uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol
) const {
1068 reinterpret_cast<uintptr_t>(Symbol
.getRawPtr()) - getSymbolTable();
1069 assert(Offset
% getSymbolTableEntrySize() == 0 &&
1070 "Symbol did not point to the beginning of a symbol");
1071 size_t Index
= Offset
/ getSymbolTableEntrySize();
1072 assert(Index
< getNumberOfSymbols());
1077 COFFObjectFile::getSectionName(const coff_section
*Sec
) const {
1079 if (Sec
->Name
[COFF::NameSize
- 1] == 0)
1080 // Null terminated, let ::strlen figure out the length.
1083 // Not null terminated, use all 8 bytes.
1084 Name
= StringRef(Sec
->Name
, COFF::NameSize
);
1086 // Check for string table entry. First byte is '/'.
1087 if (Name
.startswith("/")) {
1089 if (Name
.startswith("//")) {
1090 if (decodeBase64StringEntry(Name
.substr(2), Offset
))
1091 return createStringError(object_error::parse_failed
,
1092 "inalid section name");
1094 if (Name
.substr(1).getAsInteger(10, Offset
))
1095 return createStringError(object_error::parse_failed
,
1096 "invalid section name");
1098 if (std::error_code EC
= getString(Offset
, Name
))
1099 return errorCodeToError(EC
);
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
;
1121 Error
COFFObjectFile::getSectionContents(const coff_section
*Sec
,
1122 ArrayRef
<uint8_t> &Res
) const {
1123 // In COFF, a virtual section won't have any in-file
1124 // content, so the file pointer to the content will be zero.
1125 if (Sec
->PointerToRawData
== 0)
1126 return Error::success();
1127 // The only thing that we need to verify is that the contents is contained
1128 // within the file bounds. We don't need to make sure it doesn't cover other
1129 // data, as there's nothing that says that is not allowed.
1130 uintptr_t ConStart
= uintptr_t(base()) + Sec
->PointerToRawData
;
1131 uint32_t SectionSize
= getSectionSize(Sec
);
1132 if (checkOffset(Data
, ConStart
, SectionSize
))
1133 return make_error
<BinaryError
>();
1134 Res
= makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart
), SectionSize
);
1135 return Error::success();
1138 const coff_relocation
*COFFObjectFile::toRel(DataRefImpl Rel
) const {
1139 return reinterpret_cast<const coff_relocation
*>(Rel
.p
);
1142 void COFFObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
1143 Rel
.p
= reinterpret_cast<uintptr_t>(
1144 reinterpret_cast<const coff_relocation
*>(Rel
.p
) + 1);
1147 uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
1148 const coff_relocation
*R
= toRel(Rel
);
1149 return R
->VirtualAddress
;
1152 symbol_iterator
COFFObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
1153 const coff_relocation
*R
= toRel(Rel
);
1155 if (R
->SymbolTableIndex
>= getNumberOfSymbols())
1156 return symbol_end();
1158 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable16
+ R
->SymbolTableIndex
);
1159 else if (SymbolTable32
)
1160 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable32
+ R
->SymbolTableIndex
);
1162 llvm_unreachable("no symbol table pointer!");
1163 return symbol_iterator(SymbolRef(Ref
, this));
1166 uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel
) const {
1167 const coff_relocation
* R
= toRel(Rel
);
1171 const coff_section
*
1172 COFFObjectFile::getCOFFSection(const SectionRef
&Section
) const {
1173 return toSec(Section
.getRawDataRefImpl());
1176 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const DataRefImpl
&Ref
) const {
1178 return toSymb
<coff_symbol16
>(Ref
);
1180 return toSymb
<coff_symbol32
>(Ref
);
1181 llvm_unreachable("no symbol table pointer!");
1184 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const SymbolRef
&Symbol
) const {
1185 return getCOFFSymbol(Symbol
.getRawDataRefImpl());
1188 const coff_relocation
*
1189 COFFObjectFile::getCOFFRelocation(const RelocationRef
&Reloc
) const {
1190 return toRel(Reloc
.getRawDataRefImpl());
1193 ArrayRef
<coff_relocation
>
1194 COFFObjectFile::getRelocations(const coff_section
*Sec
) const {
1195 return {getFirstReloc(Sec
, Data
, base()),
1196 getNumberOfRelocations(Sec
, Data
, base())};
1199 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1200 case COFF::reloc_type: \
1203 StringRef
COFFObjectFile::getRelocationTypeName(uint16_t Type
) const {
1204 switch (getMachine()) {
1205 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1207 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE
);
1208 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64
);
1209 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32
);
1210 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB
);
1211 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32
);
1212 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1
);
1213 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2
);
1214 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3
);
1215 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4
);
1216 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5
);
1217 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION
);
1218 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL
);
1219 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7
);
1220 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN
);
1221 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32
);
1222 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR
);
1223 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32
);
1228 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1230 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE
);
1231 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32
);
1232 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB
);
1233 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24
);
1234 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11
);
1235 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN
);
1236 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24
);
1237 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11
);
1238 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32
);
1239 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION
);
1240 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL
);
1241 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A
);
1242 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T
);
1243 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T
);
1244 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T
);
1245 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T
);
1246 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR
);
1251 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1253 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE
);
1254 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32
);
1255 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB
);
1256 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26
);
1257 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21
);
1258 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21
);
1259 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A
);
1260 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L
);
1261 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL
);
1262 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A
);
1263 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A
);
1264 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L
);
1265 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN
);
1266 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION
);
1267 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64
);
1268 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19
);
1269 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14
);
1270 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32
);
1275 case COFF::IMAGE_FILE_MACHINE_I386
:
1277 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE
);
1278 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16
);
1279 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16
);
1280 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32
);
1281 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB
);
1282 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12
);
1283 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION
);
1284 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL
);
1285 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN
);
1286 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7
);
1287 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32
);
1297 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1299 void COFFObjectFile::getRelocationTypeName(
1300 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
1301 const coff_relocation
*Reloc
= toRel(Rel
);
1302 StringRef Res
= getRelocationTypeName(Reloc
->Type
);
1303 Result
.append(Res
.begin(), Res
.end());
1306 bool COFFObjectFile::isRelocatableObject() const {
1307 return !DataDirectory
;
1310 StringRef
COFFObjectFile::mapDebugSectionName(StringRef Name
) const {
1311 return StringSwitch
<StringRef
>(Name
)
1312 .Case("eh_fram", "eh_frame")
1316 bool ImportDirectoryEntryRef::
1317 operator==(const ImportDirectoryEntryRef
&Other
) const {
1318 return ImportTable
== Other
.ImportTable
&& Index
== Other
.Index
;
1321 void ImportDirectoryEntryRef::moveNext() {
1323 if (ImportTable
[Index
].isNull()) {
1325 ImportTable
= nullptr;
1329 std::error_code
ImportDirectoryEntryRef::getImportTableEntry(
1330 const coff_import_directory_table_entry
*&Result
) const {
1331 return getObject(Result
, OwningObject
->Data
, ImportTable
+ Index
);
1334 static imported_symbol_iterator
1335 makeImportedSymbolIterator(const COFFObjectFile
*Object
,
1336 uintptr_t Ptr
, int Index
) {
1337 if (Object
->getBytesInAddress() == 4) {
1338 auto *P
= reinterpret_cast<const import_lookup_table_entry32
*>(Ptr
);
1339 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1341 auto *P
= reinterpret_cast<const import_lookup_table_entry64
*>(Ptr
);
1342 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1345 static imported_symbol_iterator
1346 importedSymbolBegin(uint32_t RVA
, const COFFObjectFile
*Object
) {
1347 uintptr_t IntPtr
= 0;
1348 Object
->getRvaPtr(RVA
, IntPtr
);
1349 return makeImportedSymbolIterator(Object
, IntPtr
, 0);
1352 static imported_symbol_iterator
1353 importedSymbolEnd(uint32_t RVA
, const COFFObjectFile
*Object
) {
1354 uintptr_t IntPtr
= 0;
1355 Object
->getRvaPtr(RVA
, IntPtr
);
1356 // Forward the pointer to the last entry which is null.
1358 if (Object
->getBytesInAddress() == 4) {
1359 auto *Entry
= reinterpret_cast<ulittle32_t
*>(IntPtr
);
1363 auto *Entry
= reinterpret_cast<ulittle64_t
*>(IntPtr
);
1367 return makeImportedSymbolIterator(Object
, IntPtr
, Index
);
1370 imported_symbol_iterator
1371 ImportDirectoryEntryRef::imported_symbol_begin() const {
1372 return importedSymbolBegin(ImportTable
[Index
].ImportAddressTableRVA
,
1376 imported_symbol_iterator
1377 ImportDirectoryEntryRef::imported_symbol_end() const {
1378 return importedSymbolEnd(ImportTable
[Index
].ImportAddressTableRVA
,
1382 iterator_range
<imported_symbol_iterator
>
1383 ImportDirectoryEntryRef::imported_symbols() const {
1384 return make_range(imported_symbol_begin(), imported_symbol_end());
1387 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_begin() const {
1388 return importedSymbolBegin(ImportTable
[Index
].ImportLookupTableRVA
,
1392 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_end() const {
1393 return importedSymbolEnd(ImportTable
[Index
].ImportLookupTableRVA
,
1397 iterator_range
<imported_symbol_iterator
>
1398 ImportDirectoryEntryRef::lookup_table_symbols() const {
1399 return make_range(lookup_table_begin(), lookup_table_end());
1402 std::error_code
ImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1403 uintptr_t IntPtr
= 0;
1404 if (std::error_code EC
=
1405 OwningObject
->getRvaPtr(ImportTable
[Index
].NameRVA
, IntPtr
))
1407 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1408 return std::error_code();
1412 ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result
) const {
1413 Result
= ImportTable
[Index
].ImportLookupTableRVA
;
1414 return std::error_code();
1418 ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result
) const {
1419 Result
= ImportTable
[Index
].ImportAddressTableRVA
;
1420 return std::error_code();
1423 bool DelayImportDirectoryEntryRef::
1424 operator==(const DelayImportDirectoryEntryRef
&Other
) const {
1425 return Table
== Other
.Table
&& Index
== Other
.Index
;
1428 void DelayImportDirectoryEntryRef::moveNext() {
1432 imported_symbol_iterator
1433 DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1434 return importedSymbolBegin(Table
[Index
].DelayImportNameTable
,
1438 imported_symbol_iterator
1439 DelayImportDirectoryEntryRef::imported_symbol_end() const {
1440 return importedSymbolEnd(Table
[Index
].DelayImportNameTable
,
1444 iterator_range
<imported_symbol_iterator
>
1445 DelayImportDirectoryEntryRef::imported_symbols() const {
1446 return make_range(imported_symbol_begin(), imported_symbol_end());
1449 std::error_code
DelayImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1450 uintptr_t IntPtr
= 0;
1451 if (std::error_code EC
= OwningObject
->getRvaPtr(Table
[Index
].Name
, IntPtr
))
1453 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1454 return std::error_code();
1457 std::error_code
DelayImportDirectoryEntryRef::
1458 getDelayImportTable(const delay_import_directory_table_entry
*&Result
) const {
1459 Result
= &Table
[Index
];
1460 return std::error_code();
1463 std::error_code
DelayImportDirectoryEntryRef::
1464 getImportAddress(int AddrIndex
, uint64_t &Result
) const {
1465 uint32_t RVA
= Table
[Index
].DelayImportAddressTable
+
1466 AddrIndex
* (OwningObject
->is64() ? 8 : 4);
1467 uintptr_t IntPtr
= 0;
1468 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1470 if (OwningObject
->is64())
1471 Result
= *reinterpret_cast<const ulittle64_t
*>(IntPtr
);
1473 Result
= *reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1474 return std::error_code();
1477 bool ExportDirectoryEntryRef::
1478 operator==(const ExportDirectoryEntryRef
&Other
) const {
1479 return ExportTable
== Other
.ExportTable
&& Index
== Other
.Index
;
1482 void ExportDirectoryEntryRef::moveNext() {
1486 // Returns the name of the current export symbol. If the symbol is exported only
1487 // by ordinal, the empty string is set as a result.
1488 std::error_code
ExportDirectoryEntryRef::getDllName(StringRef
&Result
) const {
1489 uintptr_t IntPtr
= 0;
1490 if (std::error_code EC
=
1491 OwningObject
->getRvaPtr(ExportTable
->NameRVA
, IntPtr
))
1493 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1494 return std::error_code();
1497 // Returns the starting ordinal number.
1499 ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result
) const {
1500 Result
= ExportTable
->OrdinalBase
;
1501 return std::error_code();
1504 // Returns the export ordinal of the current export symbol.
1505 std::error_code
ExportDirectoryEntryRef::getOrdinal(uint32_t &Result
) const {
1506 Result
= ExportTable
->OrdinalBase
+ Index
;
1507 return std::error_code();
1510 // Returns the address of the current export symbol.
1511 std::error_code
ExportDirectoryEntryRef::getExportRVA(uint32_t &Result
) const {
1512 uintptr_t IntPtr
= 0;
1513 if (std::error_code EC
=
1514 OwningObject
->getRvaPtr(ExportTable
->ExportAddressTableRVA
, IntPtr
))
1516 const export_address_table_entry
*entry
=
1517 reinterpret_cast<const export_address_table_entry
*>(IntPtr
);
1518 Result
= entry
[Index
].ExportRVA
;
1519 return std::error_code();
1522 // Returns the name of the current export symbol. If the symbol is exported only
1523 // by ordinal, the empty string is set as a result.
1525 ExportDirectoryEntryRef::getSymbolName(StringRef
&Result
) const {
1526 uintptr_t IntPtr
= 0;
1527 if (std::error_code EC
=
1528 OwningObject
->getRvaPtr(ExportTable
->OrdinalTableRVA
, IntPtr
))
1530 const ulittle16_t
*Start
= reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1532 uint32_t NumEntries
= ExportTable
->NumberOfNamePointers
;
1534 for (const ulittle16_t
*I
= Start
, *E
= Start
+ NumEntries
;
1535 I
< E
; ++I
, ++Offset
) {
1538 if (std::error_code EC
=
1539 OwningObject
->getRvaPtr(ExportTable
->NamePointerRVA
, IntPtr
))
1541 const ulittle32_t
*NamePtr
= reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1542 if (std::error_code EC
= OwningObject
->getRvaPtr(NamePtr
[Offset
], IntPtr
))
1544 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1545 return std::error_code();
1548 return std::error_code();
1551 std::error_code
ExportDirectoryEntryRef::isForwarder(bool &Result
) const {
1552 const data_directory
*DataEntry
;
1553 if (auto EC
= OwningObject
->getDataDirectory(COFF::EXPORT_TABLE
, DataEntry
))
1556 if (auto EC
= getExportRVA(RVA
))
1558 uint32_t Begin
= DataEntry
->RelativeVirtualAddress
;
1559 uint32_t End
= DataEntry
->RelativeVirtualAddress
+ DataEntry
->Size
;
1560 Result
= (Begin
<= RVA
&& RVA
< End
);
1561 return std::error_code();
1564 std::error_code
ExportDirectoryEntryRef::getForwardTo(StringRef
&Result
) const {
1566 if (auto EC
= getExportRVA(RVA
))
1568 uintptr_t IntPtr
= 0;
1569 if (auto EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1571 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1572 return std::error_code();
1575 bool ImportedSymbolRef::
1576 operator==(const ImportedSymbolRef
&Other
) const {
1577 return Entry32
== Other
.Entry32
&& Entry64
== Other
.Entry64
1578 && Index
== Other
.Index
;
1581 void ImportedSymbolRef::moveNext() {
1586 ImportedSymbolRef::getSymbolName(StringRef
&Result
) const {
1589 // If a symbol is imported only by ordinal, it has no name.
1590 if (Entry32
[Index
].isOrdinal())
1591 return std::error_code();
1592 RVA
= Entry32
[Index
].getHintNameRVA();
1594 if (Entry64
[Index
].isOrdinal())
1595 return std::error_code();
1596 RVA
= Entry64
[Index
].getHintNameRVA();
1598 uintptr_t IntPtr
= 0;
1599 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1601 // +2 because the first two bytes is hint.
1602 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
+ 2));
1603 return std::error_code();
1606 std::error_code
ImportedSymbolRef::isOrdinal(bool &Result
) const {
1608 Result
= Entry32
[Index
].isOrdinal();
1610 Result
= Entry64
[Index
].isOrdinal();
1611 return std::error_code();
1614 std::error_code
ImportedSymbolRef::getHintNameRVA(uint32_t &Result
) const {
1616 Result
= Entry32
[Index
].getHintNameRVA();
1618 Result
= Entry64
[Index
].getHintNameRVA();
1619 return std::error_code();
1622 std::error_code
ImportedSymbolRef::getOrdinal(uint16_t &Result
) const {
1625 if (Entry32
[Index
].isOrdinal()) {
1626 Result
= Entry32
[Index
].getOrdinal();
1627 return std::error_code();
1629 RVA
= Entry32
[Index
].getHintNameRVA();
1631 if (Entry64
[Index
].isOrdinal()) {
1632 Result
= Entry64
[Index
].getOrdinal();
1633 return std::error_code();
1635 RVA
= Entry64
[Index
].getHintNameRVA();
1637 uintptr_t IntPtr
= 0;
1638 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1640 Result
= *reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1641 return std::error_code();
1644 Expected
<std::unique_ptr
<COFFObjectFile
>>
1645 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object
) {
1647 std::unique_ptr
<COFFObjectFile
> Ret(new COFFObjectFile(Object
, EC
));
1649 return errorCodeToError(EC
);
1650 return std::move(Ret
);
1653 bool BaseRelocRef::operator==(const BaseRelocRef
&Other
) const {
1654 return Header
== Other
.Header
&& Index
== Other
.Index
;
1657 void BaseRelocRef::moveNext() {
1658 // Header->BlockSize is the size of the current block, including the
1659 // size of the header itself.
1660 uint32_t Size
= sizeof(*Header
) +
1661 sizeof(coff_base_reloc_block_entry
) * (Index
+ 1);
1662 if (Size
== Header
->BlockSize
) {
1663 // .reloc contains a list of base relocation blocks. Each block
1664 // consists of the header followed by entries. The header contains
1665 // how many entories will follow. When we reach the end of the
1666 // current block, proceed to the next block.
1667 Header
= reinterpret_cast<const coff_base_reloc_block_header
*>(
1668 reinterpret_cast<const uint8_t *>(Header
) + Size
);
1675 std::error_code
BaseRelocRef::getType(uint8_t &Type
) const {
1676 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1677 Type
= Entry
[Index
].getType();
1678 return std::error_code();
1681 std::error_code
BaseRelocRef::getRVA(uint32_t &Result
) const {
1682 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1683 Result
= Header
->PageRVA
+ Entry
[Index
].getOffset();
1684 return std::error_code();
1687 #define RETURN_IF_ERROR(E) \
1691 Expected
<ArrayRef
<UTF16
>>
1692 ResourceSectionRef::getDirStringAtOffset(uint32_t Offset
) {
1693 BinaryStreamReader Reader
= BinaryStreamReader(BBS
);
1694 Reader
.setOffset(Offset
);
1696 RETURN_IF_ERROR(Reader
.readInteger(Length
));
1697 ArrayRef
<UTF16
> RawDirString
;
1698 RETURN_IF_ERROR(Reader
.readArray(RawDirString
, Length
));
1699 return RawDirString
;
1702 Expected
<ArrayRef
<UTF16
>>
1703 ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry
&Entry
) {
1704 return getDirStringAtOffset(Entry
.Identifier
.getNameOffset());
1707 Expected
<const coff_resource_dir_table
&>
1708 ResourceSectionRef::getTableAtOffset(uint32_t Offset
) {
1709 const coff_resource_dir_table
*Table
= nullptr;
1711 BinaryStreamReader
Reader(BBS
);
1712 Reader
.setOffset(Offset
);
1713 RETURN_IF_ERROR(Reader
.readObject(Table
));
1714 assert(Table
!= nullptr);
1718 Expected
<const coff_resource_dir_table
&>
1719 ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry
&Entry
) {
1720 return getTableAtOffset(Entry
.Offset
.value());
1723 Expected
<const coff_resource_dir_table
&> ResourceSectionRef::getBaseTable() {
1724 return getTableAtOffset(0);