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::getDataDirectory(uint32_t Index
,
941 const data_directory
*&Res
) const {
942 // Error if there's no data directory or the index is out of range.
943 if (!DataDirectory
) {
945 return object_error::parse_failed
;
947 assert(PE32Header
|| PE32PlusHeader
);
948 uint32_t NumEnt
= PE32Header
? PE32Header
->NumberOfRvaAndSize
949 : PE32PlusHeader
->NumberOfRvaAndSize
;
950 if (Index
>= NumEnt
) {
952 return object_error::parse_failed
;
954 Res
= &DataDirectory
[Index
];
955 return std::error_code();
958 std::error_code
COFFObjectFile::getSection(int32_t Index
,
959 const coff_section
*&Result
) const {
961 if (COFF::isReservedSectionNumber(Index
))
962 return std::error_code();
963 if (static_cast<uint32_t>(Index
) <= getNumberOfSections()) {
964 // We already verified the section table data, so no need to check again.
965 Result
= SectionTable
+ (Index
- 1);
966 return std::error_code();
968 return object_error::parse_failed
;
971 std::error_code
COFFObjectFile::getSection(StringRef SectionName
,
972 const coff_section
*&Result
) const {
974 for (const SectionRef
&Section
: sections()) {
975 auto NameOrErr
= Section
.getName();
977 return errorToErrorCode(NameOrErr
.takeError());
979 if (*NameOrErr
== SectionName
) {
980 Result
= getCOFFSection(Section
);
981 return std::error_code();
984 return object_error::parse_failed
;
987 std::error_code
COFFObjectFile::getString(uint32_t Offset
,
988 StringRef
&Result
) const {
989 if (StringTableSize
<= 4)
990 // Tried to get a string from an empty string table.
991 return object_error::parse_failed
;
992 if (Offset
>= StringTableSize
)
993 return object_error::unexpected_eof
;
994 Result
= StringRef(StringTable
+ Offset
);
995 return std::error_code();
998 std::error_code
COFFObjectFile::getSymbolName(COFFSymbolRef Symbol
,
999 StringRef
&Res
) const {
1000 return getSymbolName(Symbol
.getGeneric(), Res
);
1003 std::error_code
COFFObjectFile::getSymbolName(const coff_symbol_generic
*Symbol
,
1004 StringRef
&Res
) const {
1005 // Check for string table entry. First 4 bytes are 0.
1006 if (Symbol
->Name
.Offset
.Zeroes
== 0) {
1007 if (std::error_code EC
= getString(Symbol
->Name
.Offset
.Offset
, Res
))
1009 return std::error_code();
1012 if (Symbol
->Name
.ShortName
[COFF::NameSize
- 1] == 0)
1013 // Null terminated, let ::strlen figure out the length.
1014 Res
= StringRef(Symbol
->Name
.ShortName
);
1016 // Not null terminated, use all 8 bytes.
1017 Res
= StringRef(Symbol
->Name
.ShortName
, COFF::NameSize
);
1018 return std::error_code();
1022 COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol
) const {
1023 const uint8_t *Aux
= nullptr;
1025 size_t SymbolSize
= getSymbolTableEntrySize();
1026 if (Symbol
.getNumberOfAuxSymbols() > 0) {
1027 // AUX data comes immediately after the symbol in COFF
1028 Aux
= reinterpret_cast<const uint8_t *>(Symbol
.getRawPtr()) + SymbolSize
;
1030 // Verify that the Aux symbol points to a valid entry in the symbol table.
1031 uintptr_t Offset
= uintptr_t(Aux
) - uintptr_t(base());
1032 if (Offset
< getPointerToSymbolTable() ||
1034 getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize
))
1035 report_fatal_error("Aux Symbol data was outside of symbol table.");
1037 assert((Offset
- getPointerToSymbolTable()) % SymbolSize
== 0 &&
1038 "Aux Symbol data did not point to the beginning of a symbol");
1041 return makeArrayRef(Aux
, Symbol
.getNumberOfAuxSymbols() * SymbolSize
);
1044 uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol
) const {
1046 reinterpret_cast<uintptr_t>(Symbol
.getRawPtr()) - getSymbolTable();
1047 assert(Offset
% getSymbolTableEntrySize() == 0 &&
1048 "Symbol did not point to the beginning of a symbol");
1049 size_t Index
= Offset
/ getSymbolTableEntrySize();
1050 assert(Index
< getNumberOfSymbols());
1055 COFFObjectFile::getSectionName(const coff_section
*Sec
) const {
1057 if (Sec
->Name
[COFF::NameSize
- 1] == 0)
1058 // Null terminated, let ::strlen figure out the length.
1061 // Not null terminated, use all 8 bytes.
1062 Name
= StringRef(Sec
->Name
, COFF::NameSize
);
1064 // Check for string table entry. First byte is '/'.
1065 if (Name
.startswith("/")) {
1067 if (Name
.startswith("//")) {
1068 if (decodeBase64StringEntry(Name
.substr(2), Offset
))
1069 return createStringError(object_error::parse_failed
,
1070 "inalid section name");
1072 if (Name
.substr(1).getAsInteger(10, Offset
))
1073 return createStringError(object_error::parse_failed
,
1074 "invalid section name");
1076 if (std::error_code EC
= getString(Offset
, Name
))
1077 return errorCodeToError(EC
);
1083 uint64_t COFFObjectFile::getSectionSize(const coff_section
*Sec
) const {
1084 // SizeOfRawData and VirtualSize change what they represent depending on
1085 // whether or not we have an executable image.
1087 // For object files, SizeOfRawData contains the size of section's data;
1088 // VirtualSize should be zero but isn't due to buggy COFF writers.
1090 // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1091 // actual section size is in VirtualSize. It is possible for VirtualSize to
1092 // be greater than SizeOfRawData; the contents past that point should be
1093 // considered to be zero.
1095 return std::min(Sec
->VirtualSize
, Sec
->SizeOfRawData
);
1096 return Sec
->SizeOfRawData
;
1099 Error
COFFObjectFile::getSectionContents(const coff_section
*Sec
,
1100 ArrayRef
<uint8_t> &Res
) const {
1101 // In COFF, a virtual section won't have any in-file
1102 // content, so the file pointer to the content will be zero.
1103 if (Sec
->PointerToRawData
== 0)
1104 return Error::success();
1105 // The only thing that we need to verify is that the contents is contained
1106 // within the file bounds. We don't need to make sure it doesn't cover other
1107 // data, as there's nothing that says that is not allowed.
1108 uintptr_t ConStart
= uintptr_t(base()) + Sec
->PointerToRawData
;
1109 uint32_t SectionSize
= getSectionSize(Sec
);
1110 if (checkOffset(Data
, ConStart
, SectionSize
))
1111 return make_error
<BinaryError
>();
1112 Res
= makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart
), SectionSize
);
1113 return Error::success();
1116 const coff_relocation
*COFFObjectFile::toRel(DataRefImpl Rel
) const {
1117 return reinterpret_cast<const coff_relocation
*>(Rel
.p
);
1120 void COFFObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
1121 Rel
.p
= reinterpret_cast<uintptr_t>(
1122 reinterpret_cast<const coff_relocation
*>(Rel
.p
) + 1);
1125 uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
1126 const coff_relocation
*R
= toRel(Rel
);
1127 return R
->VirtualAddress
;
1130 symbol_iterator
COFFObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
1131 const coff_relocation
*R
= toRel(Rel
);
1133 if (R
->SymbolTableIndex
>= getNumberOfSymbols())
1134 return symbol_end();
1136 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable16
+ R
->SymbolTableIndex
);
1137 else if (SymbolTable32
)
1138 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable32
+ R
->SymbolTableIndex
);
1140 llvm_unreachable("no symbol table pointer!");
1141 return symbol_iterator(SymbolRef(Ref
, this));
1144 uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel
) const {
1145 const coff_relocation
* R
= toRel(Rel
);
1149 const coff_section
*
1150 COFFObjectFile::getCOFFSection(const SectionRef
&Section
) const {
1151 return toSec(Section
.getRawDataRefImpl());
1154 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const DataRefImpl
&Ref
) const {
1156 return toSymb
<coff_symbol16
>(Ref
);
1158 return toSymb
<coff_symbol32
>(Ref
);
1159 llvm_unreachable("no symbol table pointer!");
1162 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const SymbolRef
&Symbol
) const {
1163 return getCOFFSymbol(Symbol
.getRawDataRefImpl());
1166 const coff_relocation
*
1167 COFFObjectFile::getCOFFRelocation(const RelocationRef
&Reloc
) const {
1168 return toRel(Reloc
.getRawDataRefImpl());
1171 ArrayRef
<coff_relocation
>
1172 COFFObjectFile::getRelocations(const coff_section
*Sec
) const {
1173 return {getFirstReloc(Sec
, Data
, base()),
1174 getNumberOfRelocations(Sec
, Data
, base())};
1177 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1178 case COFF::reloc_type: \
1181 StringRef
COFFObjectFile::getRelocationTypeName(uint16_t Type
) const {
1182 switch (getMachine()) {
1183 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1185 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE
);
1186 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64
);
1187 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32
);
1188 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB
);
1189 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32
);
1190 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1
);
1191 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2
);
1192 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3
);
1193 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4
);
1194 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5
);
1195 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION
);
1196 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL
);
1197 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7
);
1198 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN
);
1199 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32
);
1200 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR
);
1201 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32
);
1206 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1208 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE
);
1209 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32
);
1210 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB
);
1211 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24
);
1212 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11
);
1213 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN
);
1214 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24
);
1215 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11
);
1216 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32
);
1217 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION
);
1218 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL
);
1219 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A
);
1220 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T
);
1221 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T
);
1222 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T
);
1223 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T
);
1224 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR
);
1229 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1231 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE
);
1232 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32
);
1233 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB
);
1234 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26
);
1235 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21
);
1236 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21
);
1237 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A
);
1238 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L
);
1239 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL
);
1240 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A
);
1241 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A
);
1242 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L
);
1243 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN
);
1244 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION
);
1245 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64
);
1246 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19
);
1247 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14
);
1248 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32
);
1253 case COFF::IMAGE_FILE_MACHINE_I386
:
1255 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE
);
1256 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16
);
1257 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16
);
1258 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32
);
1259 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB
);
1260 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12
);
1261 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION
);
1262 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL
);
1263 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN
);
1264 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7
);
1265 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32
);
1275 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1277 void COFFObjectFile::getRelocationTypeName(
1278 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
1279 const coff_relocation
*Reloc
= toRel(Rel
);
1280 StringRef Res
= getRelocationTypeName(Reloc
->Type
);
1281 Result
.append(Res
.begin(), Res
.end());
1284 bool COFFObjectFile::isRelocatableObject() const {
1285 return !DataDirectory
;
1288 StringRef
COFFObjectFile::mapDebugSectionName(StringRef Name
) const {
1289 return StringSwitch
<StringRef
>(Name
)
1290 .Case("eh_fram", "eh_frame")
1294 bool ImportDirectoryEntryRef::
1295 operator==(const ImportDirectoryEntryRef
&Other
) const {
1296 return ImportTable
== Other
.ImportTable
&& Index
== Other
.Index
;
1299 void ImportDirectoryEntryRef::moveNext() {
1301 if (ImportTable
[Index
].isNull()) {
1303 ImportTable
= nullptr;
1307 std::error_code
ImportDirectoryEntryRef::getImportTableEntry(
1308 const coff_import_directory_table_entry
*&Result
) const {
1309 return getObject(Result
, OwningObject
->Data
, ImportTable
+ Index
);
1312 static imported_symbol_iterator
1313 makeImportedSymbolIterator(const COFFObjectFile
*Object
,
1314 uintptr_t Ptr
, int Index
) {
1315 if (Object
->getBytesInAddress() == 4) {
1316 auto *P
= reinterpret_cast<const import_lookup_table_entry32
*>(Ptr
);
1317 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1319 auto *P
= reinterpret_cast<const import_lookup_table_entry64
*>(Ptr
);
1320 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1323 static imported_symbol_iterator
1324 importedSymbolBegin(uint32_t RVA
, const COFFObjectFile
*Object
) {
1325 uintptr_t IntPtr
= 0;
1326 Object
->getRvaPtr(RVA
, IntPtr
);
1327 return makeImportedSymbolIterator(Object
, IntPtr
, 0);
1330 static imported_symbol_iterator
1331 importedSymbolEnd(uint32_t RVA
, const COFFObjectFile
*Object
) {
1332 uintptr_t IntPtr
= 0;
1333 Object
->getRvaPtr(RVA
, IntPtr
);
1334 // Forward the pointer to the last entry which is null.
1336 if (Object
->getBytesInAddress() == 4) {
1337 auto *Entry
= reinterpret_cast<ulittle32_t
*>(IntPtr
);
1341 auto *Entry
= reinterpret_cast<ulittle64_t
*>(IntPtr
);
1345 return makeImportedSymbolIterator(Object
, IntPtr
, Index
);
1348 imported_symbol_iterator
1349 ImportDirectoryEntryRef::imported_symbol_begin() const {
1350 return importedSymbolBegin(ImportTable
[Index
].ImportAddressTableRVA
,
1354 imported_symbol_iterator
1355 ImportDirectoryEntryRef::imported_symbol_end() const {
1356 return importedSymbolEnd(ImportTable
[Index
].ImportAddressTableRVA
,
1360 iterator_range
<imported_symbol_iterator
>
1361 ImportDirectoryEntryRef::imported_symbols() const {
1362 return make_range(imported_symbol_begin(), imported_symbol_end());
1365 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_begin() const {
1366 return importedSymbolBegin(ImportTable
[Index
].ImportLookupTableRVA
,
1370 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_end() const {
1371 return importedSymbolEnd(ImportTable
[Index
].ImportLookupTableRVA
,
1375 iterator_range
<imported_symbol_iterator
>
1376 ImportDirectoryEntryRef::lookup_table_symbols() const {
1377 return make_range(lookup_table_begin(), lookup_table_end());
1380 std::error_code
ImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1381 uintptr_t IntPtr
= 0;
1382 if (std::error_code EC
=
1383 OwningObject
->getRvaPtr(ImportTable
[Index
].NameRVA
, IntPtr
))
1385 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1386 return std::error_code();
1390 ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result
) const {
1391 Result
= ImportTable
[Index
].ImportLookupTableRVA
;
1392 return std::error_code();
1396 ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result
) const {
1397 Result
= ImportTable
[Index
].ImportAddressTableRVA
;
1398 return std::error_code();
1401 bool DelayImportDirectoryEntryRef::
1402 operator==(const DelayImportDirectoryEntryRef
&Other
) const {
1403 return Table
== Other
.Table
&& Index
== Other
.Index
;
1406 void DelayImportDirectoryEntryRef::moveNext() {
1410 imported_symbol_iterator
1411 DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1412 return importedSymbolBegin(Table
[Index
].DelayImportNameTable
,
1416 imported_symbol_iterator
1417 DelayImportDirectoryEntryRef::imported_symbol_end() const {
1418 return importedSymbolEnd(Table
[Index
].DelayImportNameTable
,
1422 iterator_range
<imported_symbol_iterator
>
1423 DelayImportDirectoryEntryRef::imported_symbols() const {
1424 return make_range(imported_symbol_begin(), imported_symbol_end());
1427 std::error_code
DelayImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1428 uintptr_t IntPtr
= 0;
1429 if (std::error_code EC
= OwningObject
->getRvaPtr(Table
[Index
].Name
, IntPtr
))
1431 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1432 return std::error_code();
1435 std::error_code
DelayImportDirectoryEntryRef::
1436 getDelayImportTable(const delay_import_directory_table_entry
*&Result
) const {
1437 Result
= &Table
[Index
];
1438 return std::error_code();
1441 std::error_code
DelayImportDirectoryEntryRef::
1442 getImportAddress(int AddrIndex
, uint64_t &Result
) const {
1443 uint32_t RVA
= Table
[Index
].DelayImportAddressTable
+
1444 AddrIndex
* (OwningObject
->is64() ? 8 : 4);
1445 uintptr_t IntPtr
= 0;
1446 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1448 if (OwningObject
->is64())
1449 Result
= *reinterpret_cast<const ulittle64_t
*>(IntPtr
);
1451 Result
= *reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1452 return std::error_code();
1455 bool ExportDirectoryEntryRef::
1456 operator==(const ExportDirectoryEntryRef
&Other
) const {
1457 return ExportTable
== Other
.ExportTable
&& Index
== Other
.Index
;
1460 void ExportDirectoryEntryRef::moveNext() {
1464 // Returns the name of the current export symbol. If the symbol is exported only
1465 // by ordinal, the empty string is set as a result.
1466 std::error_code
ExportDirectoryEntryRef::getDllName(StringRef
&Result
) const {
1467 uintptr_t IntPtr
= 0;
1468 if (std::error_code EC
=
1469 OwningObject
->getRvaPtr(ExportTable
->NameRVA
, IntPtr
))
1471 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1472 return std::error_code();
1475 // Returns the starting ordinal number.
1477 ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result
) const {
1478 Result
= ExportTable
->OrdinalBase
;
1479 return std::error_code();
1482 // Returns the export ordinal of the current export symbol.
1483 std::error_code
ExportDirectoryEntryRef::getOrdinal(uint32_t &Result
) const {
1484 Result
= ExportTable
->OrdinalBase
+ Index
;
1485 return std::error_code();
1488 // Returns the address of the current export symbol.
1489 std::error_code
ExportDirectoryEntryRef::getExportRVA(uint32_t &Result
) const {
1490 uintptr_t IntPtr
= 0;
1491 if (std::error_code EC
=
1492 OwningObject
->getRvaPtr(ExportTable
->ExportAddressTableRVA
, IntPtr
))
1494 const export_address_table_entry
*entry
=
1495 reinterpret_cast<const export_address_table_entry
*>(IntPtr
);
1496 Result
= entry
[Index
].ExportRVA
;
1497 return std::error_code();
1500 // Returns the name of the current export symbol. If the symbol is exported only
1501 // by ordinal, the empty string is set as a result.
1503 ExportDirectoryEntryRef::getSymbolName(StringRef
&Result
) const {
1504 uintptr_t IntPtr
= 0;
1505 if (std::error_code EC
=
1506 OwningObject
->getRvaPtr(ExportTable
->OrdinalTableRVA
, IntPtr
))
1508 const ulittle16_t
*Start
= reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1510 uint32_t NumEntries
= ExportTable
->NumberOfNamePointers
;
1512 for (const ulittle16_t
*I
= Start
, *E
= Start
+ NumEntries
;
1513 I
< E
; ++I
, ++Offset
) {
1516 if (std::error_code EC
=
1517 OwningObject
->getRvaPtr(ExportTable
->NamePointerRVA
, IntPtr
))
1519 const ulittle32_t
*NamePtr
= reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1520 if (std::error_code EC
= OwningObject
->getRvaPtr(NamePtr
[Offset
], IntPtr
))
1522 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1523 return std::error_code();
1526 return std::error_code();
1529 std::error_code
ExportDirectoryEntryRef::isForwarder(bool &Result
) const {
1530 const data_directory
*DataEntry
;
1531 if (auto EC
= OwningObject
->getDataDirectory(COFF::EXPORT_TABLE
, DataEntry
))
1534 if (auto EC
= getExportRVA(RVA
))
1536 uint32_t Begin
= DataEntry
->RelativeVirtualAddress
;
1537 uint32_t End
= DataEntry
->RelativeVirtualAddress
+ DataEntry
->Size
;
1538 Result
= (Begin
<= RVA
&& RVA
< End
);
1539 return std::error_code();
1542 std::error_code
ExportDirectoryEntryRef::getForwardTo(StringRef
&Result
) const {
1544 if (auto EC
= getExportRVA(RVA
))
1546 uintptr_t IntPtr
= 0;
1547 if (auto EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1549 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1550 return std::error_code();
1553 bool ImportedSymbolRef::
1554 operator==(const ImportedSymbolRef
&Other
) const {
1555 return Entry32
== Other
.Entry32
&& Entry64
== Other
.Entry64
1556 && Index
== Other
.Index
;
1559 void ImportedSymbolRef::moveNext() {
1564 ImportedSymbolRef::getSymbolName(StringRef
&Result
) const {
1567 // If a symbol is imported only by ordinal, it has no name.
1568 if (Entry32
[Index
].isOrdinal())
1569 return std::error_code();
1570 RVA
= Entry32
[Index
].getHintNameRVA();
1572 if (Entry64
[Index
].isOrdinal())
1573 return std::error_code();
1574 RVA
= Entry64
[Index
].getHintNameRVA();
1576 uintptr_t IntPtr
= 0;
1577 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1579 // +2 because the first two bytes is hint.
1580 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
+ 2));
1581 return std::error_code();
1584 std::error_code
ImportedSymbolRef::isOrdinal(bool &Result
) const {
1586 Result
= Entry32
[Index
].isOrdinal();
1588 Result
= Entry64
[Index
].isOrdinal();
1589 return std::error_code();
1592 std::error_code
ImportedSymbolRef::getHintNameRVA(uint32_t &Result
) const {
1594 Result
= Entry32
[Index
].getHintNameRVA();
1596 Result
= Entry64
[Index
].getHintNameRVA();
1597 return std::error_code();
1600 std::error_code
ImportedSymbolRef::getOrdinal(uint16_t &Result
) const {
1603 if (Entry32
[Index
].isOrdinal()) {
1604 Result
= Entry32
[Index
].getOrdinal();
1605 return std::error_code();
1607 RVA
= Entry32
[Index
].getHintNameRVA();
1609 if (Entry64
[Index
].isOrdinal()) {
1610 Result
= Entry64
[Index
].getOrdinal();
1611 return std::error_code();
1613 RVA
= Entry64
[Index
].getHintNameRVA();
1615 uintptr_t IntPtr
= 0;
1616 if (std::error_code EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
))
1618 Result
= *reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1619 return std::error_code();
1622 Expected
<std::unique_ptr
<COFFObjectFile
>>
1623 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object
) {
1625 std::unique_ptr
<COFFObjectFile
> Ret(new COFFObjectFile(Object
, EC
));
1627 return errorCodeToError(EC
);
1628 return std::move(Ret
);
1631 bool BaseRelocRef::operator==(const BaseRelocRef
&Other
) const {
1632 return Header
== Other
.Header
&& Index
== Other
.Index
;
1635 void BaseRelocRef::moveNext() {
1636 // Header->BlockSize is the size of the current block, including the
1637 // size of the header itself.
1638 uint32_t Size
= sizeof(*Header
) +
1639 sizeof(coff_base_reloc_block_entry
) * (Index
+ 1);
1640 if (Size
== Header
->BlockSize
) {
1641 // .reloc contains a list of base relocation blocks. Each block
1642 // consists of the header followed by entries. The header contains
1643 // how many entories will follow. When we reach the end of the
1644 // current block, proceed to the next block.
1645 Header
= reinterpret_cast<const coff_base_reloc_block_header
*>(
1646 reinterpret_cast<const uint8_t *>(Header
) + Size
);
1653 std::error_code
BaseRelocRef::getType(uint8_t &Type
) const {
1654 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1655 Type
= Entry
[Index
].getType();
1656 return std::error_code();
1659 std::error_code
BaseRelocRef::getRVA(uint32_t &Result
) const {
1660 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1661 Result
= Header
->PageRVA
+ Entry
[Index
].getOffset();
1662 return std::error_code();
1665 #define RETURN_IF_ERROR(Expr) \
1669 return std::move(E); \
1672 Expected
<ArrayRef
<UTF16
>>
1673 ResourceSectionRef::getDirStringAtOffset(uint32_t Offset
) {
1674 BinaryStreamReader Reader
= BinaryStreamReader(BBS
);
1675 Reader
.setOffset(Offset
);
1677 RETURN_IF_ERROR(Reader
.readInteger(Length
));
1678 ArrayRef
<UTF16
> RawDirString
;
1679 RETURN_IF_ERROR(Reader
.readArray(RawDirString
, Length
));
1680 return RawDirString
;
1683 Expected
<ArrayRef
<UTF16
>>
1684 ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry
&Entry
) {
1685 return getDirStringAtOffset(Entry
.Identifier
.getNameOffset());
1688 Expected
<const coff_resource_dir_table
&>
1689 ResourceSectionRef::getTableAtOffset(uint32_t Offset
) {
1690 const coff_resource_dir_table
*Table
= nullptr;
1692 BinaryStreamReader
Reader(BBS
);
1693 Reader
.setOffset(Offset
);
1694 RETURN_IF_ERROR(Reader
.readObject(Table
));
1695 assert(Table
!= nullptr);
1699 Expected
<const coff_resource_dir_entry
&>
1700 ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset
) {
1701 const coff_resource_dir_entry
*Entry
= nullptr;
1703 BinaryStreamReader
Reader(BBS
);
1704 Reader
.setOffset(Offset
);
1705 RETURN_IF_ERROR(Reader
.readObject(Entry
));
1706 assert(Entry
!= nullptr);
1710 Expected
<const coff_resource_data_entry
&>
1711 ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset
) {
1712 const coff_resource_data_entry
*Entry
= nullptr;
1714 BinaryStreamReader
Reader(BBS
);
1715 Reader
.setOffset(Offset
);
1716 RETURN_IF_ERROR(Reader
.readObject(Entry
));
1717 assert(Entry
!= nullptr);
1721 Expected
<const coff_resource_dir_table
&>
1722 ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry
&Entry
) {
1723 assert(Entry
.Offset
.isSubDir());
1724 return getTableAtOffset(Entry
.Offset
.value());
1727 Expected
<const coff_resource_data_entry
&>
1728 ResourceSectionRef::getEntryData(const coff_resource_dir_entry
&Entry
) {
1729 assert(!Entry
.Offset
.isSubDir());
1730 return getDataEntryAtOffset(Entry
.Offset
.value());
1733 Expected
<const coff_resource_dir_table
&> ResourceSectionRef::getBaseTable() {
1734 return getTableAtOffset(0);
1737 Expected
<const coff_resource_dir_entry
&>
1738 ResourceSectionRef::getTableEntry(const coff_resource_dir_table
&Table
,
1740 if (Index
>= (uint32_t)(Table
.NumberOfNameEntries
+ Table
.NumberOfIDEntries
))
1741 return createStringError(object_error::parse_failed
, "index out of range");
1742 const uint8_t *TablePtr
= reinterpret_cast<const uint8_t *>(&Table
);
1743 ptrdiff_t TableOffset
= TablePtr
- BBS
.data().data();
1744 return getTableEntryAtOffset(TableOffset
+ sizeof(Table
) +
1745 Index
* sizeof(coff_resource_dir_entry
));
1748 Error
ResourceSectionRef::load(const COFFObjectFile
*O
) {
1749 for (const SectionRef
&S
: O
->sections()) {
1750 Expected
<StringRef
> Name
= S
.getName();
1752 return Name
.takeError();
1754 if (*Name
== ".rsrc" || *Name
== ".rsrc$01")
1757 return createStringError(object_error::parse_failed
,
1758 "no resource section found");
1761 Error
ResourceSectionRef::load(const COFFObjectFile
*O
, const SectionRef
&S
) {
1764 Expected
<StringRef
> Contents
= Section
.getContents();
1766 return Contents
.takeError();
1767 BBS
= BinaryByteStream(*Contents
, support::little
);
1768 const coff_section
*COFFSect
= Obj
->getCOFFSection(Section
);
1769 ArrayRef
<coff_relocation
> OrigRelocs
= Obj
->getRelocations(COFFSect
);
1770 Relocs
.reserve(OrigRelocs
.size());
1771 for (const coff_relocation
&R
: OrigRelocs
)
1772 Relocs
.push_back(&R
);
1773 std::sort(Relocs
.begin(), Relocs
.end(),
1774 [](const coff_relocation
*A
, const coff_relocation
*B
) {
1775 return A
->VirtualAddress
< B
->VirtualAddress
;
1777 return Error::success();
1781 ResourceSectionRef::getContents(const coff_resource_data_entry
&Entry
) {
1783 return createStringError(object_error::parse_failed
, "no object provided");
1785 // Find a potential relocation at the DataRVA field (first member of
1786 // the coff_resource_data_entry struct).
1787 const uint8_t *EntryPtr
= reinterpret_cast<const uint8_t *>(&Entry
);
1788 ptrdiff_t EntryOffset
= EntryPtr
- BBS
.data().data();
1789 coff_relocation RelocTarget
{ulittle32_t(EntryOffset
), ulittle32_t(0),
1791 auto RelocsForOffset
=
1792 std::equal_range(Relocs
.begin(), Relocs
.end(), &RelocTarget
,
1793 [](const coff_relocation
*A
, const coff_relocation
*B
) {
1794 return A
->VirtualAddress
< B
->VirtualAddress
;
1797 if (RelocsForOffset
.first
!= RelocsForOffset
.second
) {
1798 // We found a relocation with the right offset. Check that it does have
1799 // the expected type.
1800 const coff_relocation
&R
= **RelocsForOffset
.first
;
1802 switch (Obj
->getMachine()) {
1803 case COFF::IMAGE_FILE_MACHINE_I386
:
1804 RVAReloc
= COFF::IMAGE_REL_I386_DIR32NB
;
1806 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1807 RVAReloc
= COFF::IMAGE_REL_AMD64_ADDR32NB
;
1809 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1810 RVAReloc
= COFF::IMAGE_REL_ARM_ADDR32NB
;
1812 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1813 RVAReloc
= COFF::IMAGE_REL_ARM64_ADDR32NB
;
1816 return createStringError(object_error::parse_failed
,
1817 "unsupported architecture");
1819 if (R
.Type
!= RVAReloc
)
1820 return createStringError(object_error::parse_failed
,
1821 "unexpected relocation type");
1822 // Get the relocation's symbol
1823 Expected
<COFFSymbolRef
> Sym
= Obj
->getSymbol(R
.SymbolTableIndex
);
1825 return Sym
.takeError();
1826 const coff_section
*Section
= nullptr;
1827 // And the symbol's section
1828 if (std::error_code EC
= Obj
->getSection(Sym
->getSectionNumber(), Section
))
1829 return errorCodeToError(EC
);
1830 // Add the initial value of DataRVA to the symbol's offset to find the
1831 // data it points at.
1832 uint64_t Offset
= Entry
.DataRVA
+ Sym
->getValue();
1833 ArrayRef
<uint8_t> Contents
;
1834 if (Error E
= Obj
->getSectionContents(Section
, Contents
))
1835 return std::move(E
);
1836 if (Offset
+ Entry
.DataSize
> Contents
.size())
1837 return createStringError(object_error::parse_failed
,
1838 "data outside of section");
1839 // Return a reference to the data inside the section.
1840 return StringRef(reinterpret_cast<const char *>(Contents
.data()) + Offset
,
1843 // Relocatable objects need a relocation for the DataRVA field.
1844 if (Obj
->isRelocatableObject())
1845 return createStringError(object_error::parse_failed
,
1846 "no relocation found for DataRVA");
1848 // Locate the section that contains the address that DataRVA points at.
1849 uint64_t VA
= Entry
.DataRVA
+ Obj
->getImageBase();
1850 for (const SectionRef
&S
: Obj
->sections()) {
1851 if (VA
>= S
.getAddress() &&
1852 VA
+ Entry
.DataSize
<= S
.getAddress() + S
.getSize()) {
1853 uint64_t Offset
= VA
- S
.getAddress();
1854 Expected
<StringRef
> Contents
= S
.getContents();
1856 return Contents
.takeError();
1857 return Contents
->slice(Offset
, Offset
+ Entry
.DataSize
);
1860 return createStringError(object_error::parse_failed
,
1861 "address not found in image");