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/StringSwitch.h"
16 #include "llvm/ADT/iterator_range.h"
17 #include "llvm/Object/Binary.h"
18 #include "llvm/Object/COFF.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Object/WindowsMachineFlag.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/MemoryBufferRef.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 Error
getObject(const T
*&Obj
, MemoryBufferRef M
, const void *Ptr
,
58 const uint64_t Size
= sizeof(T
)) {
59 uintptr_t Addr
= reinterpret_cast<uintptr_t>(Ptr
);
60 if (Error E
= Binary::checkOffset(M
, Addr
, Size
))
62 Obj
= reinterpret_cast<const T
*>(Addr
);
63 return Error::success();
66 // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
68 static bool decodeBase64StringEntry(StringRef Str
, uint32_t &Result
) {
69 assert(Str
.size() <= 6 && "String too long, possible overflow.");
74 while (!Str
.empty()) {
76 if (Str
[0] >= 'A' && Str
[0] <= 'Z') // 0..25
77 CharVal
= Str
[0] - 'A';
78 else if (Str
[0] >= 'a' && Str
[0] <= 'z') // 26..51
79 CharVal
= Str
[0] - 'a' + 26;
80 else if (Str
[0] >= '0' && Str
[0] <= '9') // 52..61
81 CharVal
= Str
[0] - '0' + 52;
82 else if (Str
[0] == '+') // 62
84 else if (Str
[0] == '/') // 63
89 Value
= (Value
* 64) + CharVal
;
93 if (Value
> std::numeric_limits
<uint32_t>::max())
96 Result
= static_cast<uint32_t>(Value
);
100 template <typename coff_symbol_type
>
101 const coff_symbol_type
*COFFObjectFile::toSymb(DataRefImpl Ref
) const {
102 const coff_symbol_type
*Addr
=
103 reinterpret_cast<const coff_symbol_type
*>(Ref
.p
);
105 assert(!checkOffset(Data
, reinterpret_cast<uintptr_t>(Addr
), sizeof(*Addr
)));
107 // Verify that the symbol points to a valid entry in the symbol table.
109 reinterpret_cast<uintptr_t>(Addr
) - reinterpret_cast<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
= reinterpret_cast<uintptr_t>(Addr
) -
127 reinterpret_cast<uintptr_t>(SectionTable
);
128 assert(Offset
% sizeof(coff_section
) == 0 &&
129 "Section did not point to the beginning of a section");
135 void COFFObjectFile::moveSymbolNext(DataRefImpl
&Ref
) const {
136 auto End
= reinterpret_cast<uintptr_t>(StringTable
);
138 const coff_symbol16
*Symb
= toSymb
<coff_symbol16
>(Ref
);
139 Symb
+= 1 + Symb
->NumberOfAuxSymbols
;
140 Ref
.p
= std::min(reinterpret_cast<uintptr_t>(Symb
), End
);
141 } else if (SymbolTable32
) {
142 const coff_symbol32
*Symb
= toSymb
<coff_symbol32
>(Ref
);
143 Symb
+= 1 + Symb
->NumberOfAuxSymbols
;
144 Ref
.p
= std::min(reinterpret_cast<uintptr_t>(Symb
), End
);
146 llvm_unreachable("no symbol table pointer!");
150 Expected
<StringRef
> COFFObjectFile::getSymbolName(DataRefImpl Ref
) const {
151 return getSymbolName(getCOFFSymbol(Ref
));
154 uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref
) const {
155 return getCOFFSymbol(Ref
).getValue();
158 uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref
) const {
159 // MSVC/link.exe seems to align symbols to the next-power-of-2
161 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
162 return std::min(uint64_t(32), PowerOf2Ceil(Symb
.getValue()));
165 Expected
<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref
) const {
166 uint64_t Result
= cantFail(getSymbolValue(Ref
));
167 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
168 int32_t SectionNumber
= Symb
.getSectionNumber();
170 if (Symb
.isAnyUndefined() || Symb
.isCommon() ||
171 COFF::isReservedSectionNumber(SectionNumber
))
174 Expected
<const coff_section
*> Section
= getSection(SectionNumber
);
176 return Section
.takeError();
177 Result
+= (*Section
)->VirtualAddress
;
179 // The section VirtualAddress does not include ImageBase, and we want to
180 // return virtual addresses.
181 Result
+= getImageBase();
186 Expected
<SymbolRef::Type
> COFFObjectFile::getSymbolType(DataRefImpl Ref
) const {
187 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
188 int32_t SectionNumber
= Symb
.getSectionNumber();
190 if (Symb
.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION
)
191 return SymbolRef::ST_Function
;
192 if (Symb
.isAnyUndefined())
193 return SymbolRef::ST_Unknown
;
195 return SymbolRef::ST_Data
;
196 if (Symb
.isFileRecord())
197 return SymbolRef::ST_File
;
199 // TODO: perhaps we need a new symbol type ST_Section.
200 if (SectionNumber
== COFF::IMAGE_SYM_DEBUG
|| Symb
.isSectionDefinition())
201 return SymbolRef::ST_Debug
;
203 if (!COFF::isReservedSectionNumber(SectionNumber
))
204 return SymbolRef::ST_Data
;
206 return SymbolRef::ST_Other
;
209 Expected
<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref
) const {
210 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
211 uint32_t Result
= SymbolRef::SF_None
;
213 if (Symb
.isExternal() || Symb
.isWeakExternal())
214 Result
|= SymbolRef::SF_Global
;
216 if (const coff_aux_weak_external
*AWE
= Symb
.getWeakExternal()) {
217 Result
|= SymbolRef::SF_Weak
;
218 if (AWE
->Characteristics
!= COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
)
219 Result
|= SymbolRef::SF_Undefined
;
222 if (Symb
.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE
)
223 Result
|= SymbolRef::SF_Absolute
;
225 if (Symb
.isFileRecord())
226 Result
|= SymbolRef::SF_FormatSpecific
;
228 if (Symb
.isSectionDefinition())
229 Result
|= SymbolRef::SF_FormatSpecific
;
232 Result
|= SymbolRef::SF_Common
;
234 if (Symb
.isUndefined())
235 Result
|= SymbolRef::SF_Undefined
;
240 uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref
) const {
241 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
242 return Symb
.getValue();
245 Expected
<section_iterator
>
246 COFFObjectFile::getSymbolSection(DataRefImpl Ref
) const {
247 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
248 if (COFF::isReservedSectionNumber(Symb
.getSectionNumber()))
249 return section_end();
250 Expected
<const coff_section
*> Sec
= getSection(Symb
.getSectionNumber());
252 return Sec
.takeError();
254 Ret
.p
= reinterpret_cast<uintptr_t>(*Sec
);
255 return section_iterator(SectionRef(Ret
, this));
258 unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
259 COFFSymbolRef Symb
= getCOFFSymbol(Sym
.getRawDataRefImpl());
260 return Symb
.getSectionNumber();
263 void COFFObjectFile::moveSectionNext(DataRefImpl
&Ref
) const {
264 const coff_section
*Sec
= toSec(Ref
);
266 Ref
.p
= reinterpret_cast<uintptr_t>(Sec
);
269 Expected
<StringRef
> COFFObjectFile::getSectionName(DataRefImpl Ref
) const {
270 const coff_section
*Sec
= toSec(Ref
);
271 return getSectionName(Sec
);
274 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref
) const {
275 const coff_section
*Sec
= toSec(Ref
);
276 uint64_t Result
= Sec
->VirtualAddress
;
278 // The section VirtualAddress does not include ImageBase, and we want to
279 // return virtual addresses.
280 Result
+= getImageBase();
284 uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec
) const {
285 return toSec(Sec
) - SectionTable
;
288 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref
) const {
289 return getSectionSize(toSec(Ref
));
292 Expected
<ArrayRef
<uint8_t>>
293 COFFObjectFile::getSectionContents(DataRefImpl Ref
) const {
294 const coff_section
*Sec
= toSec(Ref
);
295 ArrayRef
<uint8_t> Res
;
296 if (Error E
= getSectionContents(Sec
, Res
))
301 uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref
) const {
302 const coff_section
*Sec
= toSec(Ref
);
303 return Sec
->getAlignment();
306 bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
310 bool COFFObjectFile::isSectionText(DataRefImpl Ref
) const {
311 const coff_section
*Sec
= toSec(Ref
);
312 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_CODE
;
315 bool COFFObjectFile::isSectionData(DataRefImpl Ref
) const {
316 const coff_section
*Sec
= toSec(Ref
);
317 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
320 bool COFFObjectFile::isSectionBSS(DataRefImpl Ref
) const {
321 const coff_section
*Sec
= toSec(Ref
);
322 const uint32_t BssFlags
= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
323 COFF::IMAGE_SCN_MEM_READ
|
324 COFF::IMAGE_SCN_MEM_WRITE
;
325 return (Sec
->Characteristics
& BssFlags
) == BssFlags
;
328 // The .debug sections are the only debug sections for COFF
329 // (\see MCObjectFileInfo.cpp).
330 bool COFFObjectFile::isDebugSection(DataRefImpl Ref
) const {
331 Expected
<StringRef
> SectionNameOrErr
= getSectionName(Ref
);
332 if (!SectionNameOrErr
) {
333 // TODO: Report the error message properly.
334 consumeError(SectionNameOrErr
.takeError());
337 StringRef SectionName
= SectionNameOrErr
.get();
338 return SectionName
.starts_with(".debug");
341 unsigned COFFObjectFile::getSectionID(SectionRef Sec
) const {
343 Sec
.getRawDataRefImpl().p
- reinterpret_cast<uintptr_t>(SectionTable
);
344 assert((Offset
% sizeof(coff_section
)) == 0);
345 return (Offset
/ sizeof(coff_section
)) + 1;
348 bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref
) const {
349 const coff_section
*Sec
= toSec(Ref
);
350 // In COFF, a virtual section won't have any in-file
351 // content, so the file pointer to the content will be zero.
352 return Sec
->PointerToRawData
== 0;
355 static uint32_t getNumberOfRelocations(const coff_section
*Sec
,
356 MemoryBufferRef M
, const uint8_t *base
) {
357 // The field for the number of relocations in COFF section table is only
358 // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
359 // NumberOfRelocations field, and the actual relocation count is stored in the
360 // VirtualAddress field in the first relocation entry.
361 if (Sec
->hasExtendedRelocations()) {
362 const coff_relocation
*FirstReloc
;
363 if (Error E
= getObject(FirstReloc
, M
,
364 reinterpret_cast<const coff_relocation
*>(
365 base
+ Sec
->PointerToRelocations
))) {
366 consumeError(std::move(E
));
369 // -1 to exclude this first relocation entry.
370 return FirstReloc
->VirtualAddress
- 1;
372 return Sec
->NumberOfRelocations
;
375 static const coff_relocation
*
376 getFirstReloc(const coff_section
*Sec
, MemoryBufferRef M
, const uint8_t *Base
) {
377 uint64_t NumRelocs
= getNumberOfRelocations(Sec
, M
, Base
);
380 auto begin
= reinterpret_cast<const coff_relocation
*>(
381 Base
+ Sec
->PointerToRelocations
);
382 if (Sec
->hasExtendedRelocations()) {
383 // Skip the first relocation entry repurposed to store the number of
387 if (auto E
= Binary::checkOffset(M
, reinterpret_cast<uintptr_t>(begin
),
388 sizeof(coff_relocation
) * NumRelocs
)) {
389 consumeError(std::move(E
));
395 relocation_iterator
COFFObjectFile::section_rel_begin(DataRefImpl Ref
) const {
396 const coff_section
*Sec
= toSec(Ref
);
397 const coff_relocation
*begin
= getFirstReloc(Sec
, Data
, base());
398 if (begin
&& Sec
->VirtualAddress
!= 0)
399 report_fatal_error("Sections with relocations should have an address of 0");
401 Ret
.p
= reinterpret_cast<uintptr_t>(begin
);
402 return relocation_iterator(RelocationRef(Ret
, this));
405 relocation_iterator
COFFObjectFile::section_rel_end(DataRefImpl Ref
) const {
406 const coff_section
*Sec
= toSec(Ref
);
407 const coff_relocation
*I
= getFirstReloc(Sec
, Data
, base());
409 I
+= getNumberOfRelocations(Sec
, Data
, base());
411 Ret
.p
= reinterpret_cast<uintptr_t>(I
);
412 return relocation_iterator(RelocationRef(Ret
, this));
415 // Initialize the pointer to the symbol table.
416 Error
COFFObjectFile::initSymbolTablePtr() {
418 if (Error E
= getObject(
419 SymbolTable16
, Data
, base() + getPointerToSymbolTable(),
420 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
423 if (COFFBigObjHeader
)
424 if (Error E
= getObject(
425 SymbolTable32
, Data
, base() + getPointerToSymbolTable(),
426 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
429 // Find string table. The first four byte of the string table contains the
430 // total size of the string table, including the size field itself. If the
431 // string table is empty, the value of the first four byte would be 4.
432 uint32_t StringTableOffset
= getPointerToSymbolTable() +
433 getNumberOfSymbols() * getSymbolTableEntrySize();
434 const uint8_t *StringTableAddr
= base() + StringTableOffset
;
435 const ulittle32_t
*StringTableSizePtr
;
436 if (Error E
= getObject(StringTableSizePtr
, Data
, StringTableAddr
))
438 StringTableSize
= *StringTableSizePtr
;
439 if (Error E
= getObject(StringTable
, Data
, StringTableAddr
, StringTableSize
))
442 // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
443 // tools like cvtres write a size of 0 for an empty table instead of 4.
444 if (StringTableSize
< 4)
447 // Check that the string table is null terminated if has any in it.
448 if (StringTableSize
> 4 && StringTable
[StringTableSize
- 1] != 0)
449 return createStringError(object_error::parse_failed
,
450 "string table missing null terminator");
451 return Error::success();
454 uint64_t COFFObjectFile::getImageBase() const {
456 return PE32Header
->ImageBase
;
457 else if (PE32PlusHeader
)
458 return PE32PlusHeader
->ImageBase
;
459 // This actually comes up in practice.
463 // Returns the file offset for the given VA.
464 Error
COFFObjectFile::getVaPtr(uint64_t Addr
, uintptr_t &Res
) const {
465 uint64_t ImageBase
= getImageBase();
466 uint64_t Rva
= Addr
- ImageBase
;
467 assert(Rva
<= UINT32_MAX
);
468 return getRvaPtr((uint32_t)Rva
, Res
);
471 // Returns the file offset for the given RVA.
472 Error
COFFObjectFile::getRvaPtr(uint32_t Addr
, uintptr_t &Res
,
473 const char *ErrorContext
) const {
474 for (const SectionRef
&S
: sections()) {
475 const coff_section
*Section
= getCOFFSection(S
);
476 uint32_t SectionStart
= Section
->VirtualAddress
;
477 uint32_t SectionEnd
= Section
->VirtualAddress
+ Section
->VirtualSize
;
478 if (SectionStart
<= Addr
&& Addr
< SectionEnd
) {
479 // A table/directory entry can be pointing to somewhere in a stripped
480 // section, in an object that went through `objcopy --only-keep-debug`.
481 // In this case we don't want to cause the parsing of the object file to
482 // fail, otherwise it will be impossible to use this object as debug info
483 // in LLDB. Return SectionStrippedError here so that
484 // COFFObjectFile::initialize can ignore the error.
485 // Somewhat common binaries may have RVAs pointing outside of the
486 // provided raw data. Instead of rejecting the binaries, just
487 // treat the section as stripped for these purposes.
488 if (Section
->SizeOfRawData
< Section
->VirtualSize
&&
489 Addr
>= SectionStart
+ Section
->SizeOfRawData
) {
490 return make_error
<SectionStrippedError
>();
492 uint32_t Offset
= Addr
- SectionStart
;
493 Res
= reinterpret_cast<uintptr_t>(base()) + Section
->PointerToRawData
+
495 return Error::success();
499 return createStringError(object_error::parse_failed
,
500 "RVA 0x%" PRIx32
" for %s not found", Addr
,
502 return createStringError(object_error::parse_failed
,
503 "RVA 0x%" PRIx32
" not found", Addr
);
506 Error
COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA
, uint32_t Size
,
507 ArrayRef
<uint8_t> &Contents
,
508 const char *ErrorContext
) const {
509 for (const SectionRef
&S
: sections()) {
510 const coff_section
*Section
= getCOFFSection(S
);
511 uint32_t SectionStart
= Section
->VirtualAddress
;
512 // Check if this RVA is within the section bounds. Be careful about integer
514 uint32_t OffsetIntoSection
= RVA
- SectionStart
;
515 if (SectionStart
<= RVA
&& OffsetIntoSection
< Section
->VirtualSize
&&
516 Size
<= Section
->VirtualSize
- OffsetIntoSection
) {
517 uintptr_t Begin
= reinterpret_cast<uintptr_t>(base()) +
518 Section
->PointerToRawData
+ OffsetIntoSection
;
520 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(Begin
), Size
);
521 return Error::success();
525 return createStringError(object_error::parse_failed
,
526 "RVA 0x%" PRIx32
" for %s not found", RVA
,
528 return createStringError(object_error::parse_failed
,
529 "RVA 0x%" PRIx32
" not found", RVA
);
532 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
534 Error
COFFObjectFile::getHintName(uint32_t Rva
, uint16_t &Hint
,
535 StringRef
&Name
) const {
536 uintptr_t IntPtr
= 0;
537 if (Error E
= getRvaPtr(Rva
, IntPtr
))
539 const uint8_t *Ptr
= reinterpret_cast<const uint8_t *>(IntPtr
);
540 Hint
= *reinterpret_cast<const ulittle16_t
*>(Ptr
);
541 Name
= StringRef(reinterpret_cast<const char *>(Ptr
+ 2));
542 return Error::success();
545 Error
COFFObjectFile::getDebugPDBInfo(const debug_directory
*DebugDir
,
546 const codeview::DebugInfo
*&PDBInfo
,
547 StringRef
&PDBFileName
) const {
548 ArrayRef
<uint8_t> InfoBytes
;
550 getRvaAndSizeAsBytes(DebugDir
->AddressOfRawData
, DebugDir
->SizeOfData
,
551 InfoBytes
, "PDB info"))
553 if (InfoBytes
.size() < sizeof(*PDBInfo
) + 1)
554 return createStringError(object_error::parse_failed
, "PDB info too small");
555 PDBInfo
= reinterpret_cast<const codeview::DebugInfo
*>(InfoBytes
.data());
556 InfoBytes
= InfoBytes
.drop_front(sizeof(*PDBInfo
));
557 PDBFileName
= StringRef(reinterpret_cast<const char *>(InfoBytes
.data()),
559 // Truncate the name at the first null byte. Ignore any padding.
560 PDBFileName
= PDBFileName
.split('\0').first
;
561 return Error::success();
564 Error
COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo
*&PDBInfo
,
565 StringRef
&PDBFileName
) const {
566 for (const debug_directory
&D
: debug_directories())
567 if (D
.Type
== COFF::IMAGE_DEBUG_TYPE_CODEVIEW
)
568 return getDebugPDBInfo(&D
, PDBInfo
, PDBFileName
);
569 // If we get here, there is no PDB info to return.
571 PDBFileName
= StringRef();
572 return Error::success();
575 // Find the import table.
576 Error
COFFObjectFile::initImportTablePtr() {
577 // First, we get the RVA of the import table. If the file lacks a pointer to
578 // the import table, do nothing.
579 const data_directory
*DataEntry
= getDataDirectory(COFF::IMPORT_TABLE
);
581 return Error::success();
583 // Do nothing if the pointer to import table is NULL.
584 if (DataEntry
->RelativeVirtualAddress
== 0)
585 return Error::success();
587 uint32_t ImportTableRva
= DataEntry
->RelativeVirtualAddress
;
589 // Find the section that contains the RVA. This is needed because the RVA is
590 // the import table's memory address which is different from its file offset.
591 uintptr_t IntPtr
= 0;
592 if (Error E
= getRvaPtr(ImportTableRva
, IntPtr
, "import table"))
594 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
596 ImportDirectory
= reinterpret_cast<
597 const coff_import_directory_table_entry
*>(IntPtr
);
598 return Error::success();
601 // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
602 Error
COFFObjectFile::initDelayImportTablePtr() {
603 const data_directory
*DataEntry
=
604 getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR
);
606 return Error::success();
607 if (DataEntry
->RelativeVirtualAddress
== 0)
608 return Error::success();
610 uint32_t RVA
= DataEntry
->RelativeVirtualAddress
;
611 NumberOfDelayImportDirectory
= DataEntry
->Size
/
612 sizeof(delay_import_directory_table_entry
) - 1;
614 uintptr_t IntPtr
= 0;
615 if (Error E
= getRvaPtr(RVA
, IntPtr
, "delay import table"))
617 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
620 DelayImportDirectory
= reinterpret_cast<
621 const delay_import_directory_table_entry
*>(IntPtr
);
622 return Error::success();
625 // Find the export table.
626 Error
COFFObjectFile::initExportTablePtr() {
627 // First, we get the RVA of the export table. If the file lacks a pointer to
628 // the export table, do nothing.
629 const data_directory
*DataEntry
= getDataDirectory(COFF::EXPORT_TABLE
);
631 return Error::success();
633 // Do nothing if the pointer to export table is NULL.
634 if (DataEntry
->RelativeVirtualAddress
== 0)
635 return Error::success();
637 uint32_t ExportTableRva
= DataEntry
->RelativeVirtualAddress
;
638 uintptr_t IntPtr
= 0;
639 if (Error E
= getRvaPtr(ExportTableRva
, IntPtr
, "export table"))
641 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
645 reinterpret_cast<const export_directory_table_entry
*>(IntPtr
);
646 return Error::success();
649 Error
COFFObjectFile::initBaseRelocPtr() {
650 const data_directory
*DataEntry
=
651 getDataDirectory(COFF::BASE_RELOCATION_TABLE
);
653 return Error::success();
654 if (DataEntry
->RelativeVirtualAddress
== 0)
655 return Error::success();
657 uintptr_t IntPtr
= 0;
658 if (Error E
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
,
661 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
664 BaseRelocHeader
= reinterpret_cast<const coff_base_reloc_block_header
*>(
666 BaseRelocEnd
= reinterpret_cast<coff_base_reloc_block_header
*>(
667 IntPtr
+ DataEntry
->Size
);
668 // FIXME: Verify the section containing BaseRelocHeader has at least
669 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
670 return Error::success();
673 Error
COFFObjectFile::initDebugDirectoryPtr() {
674 // Get the RVA of the debug directory. Do nothing if it does not exist.
675 const data_directory
*DataEntry
= getDataDirectory(COFF::DEBUG_DIRECTORY
);
677 return Error::success();
679 // Do nothing if the RVA is NULL.
680 if (DataEntry
->RelativeVirtualAddress
== 0)
681 return Error::success();
683 // Check that the size is a multiple of the entry size.
684 if (DataEntry
->Size
% sizeof(debug_directory
) != 0)
685 return createStringError(object_error::parse_failed
,
686 "debug directory has uneven size");
688 uintptr_t IntPtr
= 0;
689 if (Error E
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
,
692 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
695 DebugDirectoryBegin
= reinterpret_cast<const debug_directory
*>(IntPtr
);
696 DebugDirectoryEnd
= reinterpret_cast<const debug_directory
*>(
697 IntPtr
+ DataEntry
->Size
);
698 // FIXME: Verify the section containing DebugDirectoryBegin has at least
699 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
700 return Error::success();
703 Error
COFFObjectFile::initTLSDirectoryPtr() {
704 // Get the RVA of the TLS directory. Do nothing if it does not exist.
705 const data_directory
*DataEntry
= getDataDirectory(COFF::TLS_TABLE
);
707 return Error::success();
709 // Do nothing if the RVA is NULL.
710 if (DataEntry
->RelativeVirtualAddress
== 0)
711 return Error::success();
714 is64() ? sizeof(coff_tls_directory64
) : sizeof(coff_tls_directory32
);
716 // Check that the size is correct.
717 if (DataEntry
->Size
!= DirSize
)
718 return createStringError(
719 object_error::parse_failed
,
720 "TLS Directory size (%u) is not the expected size (%" PRIu64
").",
721 static_cast<uint32_t>(DataEntry
->Size
), DirSize
);
723 uintptr_t IntPtr
= 0;
725 getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
, "TLS directory"))
727 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
731 TLSDirectory64
= reinterpret_cast<const coff_tls_directory64
*>(IntPtr
);
733 TLSDirectory32
= reinterpret_cast<const coff_tls_directory32
*>(IntPtr
);
735 return Error::success();
738 Error
COFFObjectFile::initLoadConfigPtr() {
739 // Get the RVA of the debug directory. Do nothing if it does not exist.
740 const data_directory
*DataEntry
= getDataDirectory(COFF::LOAD_CONFIG_TABLE
);
742 return Error::success();
744 // Do nothing if the RVA is NULL.
745 if (DataEntry
->RelativeVirtualAddress
== 0)
746 return Error::success();
747 uintptr_t IntPtr
= 0;
748 if (Error E
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
,
749 "load config table"))
751 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
754 LoadConfig
= (const void *)IntPtr
;
757 auto Config
= getLoadConfig64();
759 offsetof(coff_load_configuration64
, CHPEMetadataPointer
) +
760 sizeof(Config
->CHPEMetadataPointer
) &&
761 Config
->CHPEMetadataPointer
) {
762 uint64_t ChpeOff
= Config
->CHPEMetadataPointer
;
764 getRvaPtr(ChpeOff
- getImageBase(), IntPtr
, "CHPE metadata"))
766 if (Error E
= checkOffset(Data
, IntPtr
, sizeof(*CHPEMetadata
)))
769 CHPEMetadata
= reinterpret_cast<const chpe_metadata
*>(IntPtr
);
771 // Validate CHPE metadata
772 if (CHPEMetadata
->CodeMapCount
) {
773 if (Error E
= getRvaPtr(CHPEMetadata
->CodeMap
, IntPtr
, "CHPE code map"))
775 if (Error E
= checkOffset(Data
, IntPtr
,
776 CHPEMetadata
->CodeMapCount
*
777 sizeof(chpe_range_entry
)))
781 if (CHPEMetadata
->CodeRangesToEntryPointsCount
) {
782 if (Error E
= getRvaPtr(CHPEMetadata
->CodeRangesToEntryPoints
, IntPtr
,
783 "CHPE entry point ranges"))
785 if (Error E
= checkOffset(Data
, IntPtr
,
786 CHPEMetadata
->CodeRangesToEntryPointsCount
*
787 sizeof(chpe_code_range_entry
)))
791 if (CHPEMetadata
->RedirectionMetadataCount
) {
792 if (Error E
= getRvaPtr(CHPEMetadata
->RedirectionMetadata
, IntPtr
,
793 "CHPE redirection metadata"))
795 if (Error E
= checkOffset(Data
, IntPtr
,
796 CHPEMetadata
->RedirectionMetadataCount
*
797 sizeof(chpe_redirection_entry
)))
803 offsetof(coff_load_configuration64
, DynamicValueRelocTableSection
) +
804 sizeof(Config
->DynamicValueRelocTableSection
))
805 if (Error E
= initDynamicRelocPtr(Config
->DynamicValueRelocTableSection
,
806 Config
->DynamicValueRelocTableOffset
))
809 auto Config
= getLoadConfig32();
811 offsetof(coff_load_configuration32
, DynamicValueRelocTableSection
) +
812 sizeof(Config
->DynamicValueRelocTableSection
)) {
813 if (Error E
= initDynamicRelocPtr(Config
->DynamicValueRelocTableSection
,
814 Config
->DynamicValueRelocTableOffset
))
818 return Error::success();
821 Error
COFFObjectFile::initDynamicRelocPtr(uint32_t SectionIndex
,
822 uint32_t SectionOffset
) {
823 Expected
<const coff_section
*> Section
= getSection(SectionIndex
);
825 return Section
.takeError();
827 return Error::success();
829 // Interpret and validate dynamic relocations.
830 ArrayRef
<uint8_t> Contents
;
831 if (Error E
= getSectionContents(*Section
, Contents
))
834 Contents
= Contents
.drop_front(SectionOffset
);
835 if (Contents
.size() < sizeof(coff_dynamic_reloc_table
))
836 return createStringError(object_error::parse_failed
,
837 "Too large DynamicValueRelocTableOffset (" +
838 Twine(SectionOffset
) + ")");
841 reinterpret_cast<const coff_dynamic_reloc_table
*>(Contents
.data());
843 if (DynamicRelocTable
->Version
!= 1 && DynamicRelocTable
->Version
!= 2)
844 return createStringError(object_error::parse_failed
,
845 "Unsupported dynamic relocations table version (" +
846 Twine(DynamicRelocTable
->Version
) + ")");
847 if (DynamicRelocTable
->Size
> Contents
.size() - sizeof(*DynamicRelocTable
))
848 return createStringError(object_error::parse_failed
,
849 "Indvalid dynamic relocations directory size (" +
850 Twine(DynamicRelocTable
->Size
) + ")");
852 for (auto DynReloc
: dynamic_relocs()) {
853 if (Error e
= DynReloc
.validate())
857 return Error::success();
860 Expected
<std::unique_ptr
<COFFObjectFile
>>
861 COFFObjectFile::create(MemoryBufferRef Object
) {
862 std::unique_ptr
<COFFObjectFile
> Obj(new COFFObjectFile(std::move(Object
)));
863 if (Error E
= Obj
->initialize())
865 return std::move(Obj
);
868 COFFObjectFile::COFFObjectFile(MemoryBufferRef Object
)
869 : ObjectFile(Binary::ID_COFF
, Object
), COFFHeader(nullptr),
870 COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
871 DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
872 SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
873 ImportDirectory(nullptr), DelayImportDirectory(nullptr),
874 NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
875 BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
876 DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
877 TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
879 static Error
ignoreStrippedErrors(Error E
) {
880 if (E
.isA
<SectionStrippedError
>()) {
881 consumeError(std::move(E
));
882 return Error::success();
887 Error
COFFObjectFile::initialize() {
888 // Check that we at least have enough room for a header.
890 if (!checkSize(Data
, EC
, sizeof(coff_file_header
)))
891 return errorCodeToError(EC
);
893 // The current location in the file where we are looking at.
896 // PE header is optional and is present only in executables. If it exists,
897 // it is placed right after COFF header.
898 bool HasPEHeader
= false;
900 // Check if this is a PE/COFF file.
901 if (checkSize(Data
, EC
, sizeof(dos_header
) + sizeof(COFF::PEMagic
))) {
902 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
903 // PE signature to find 'normal' COFF header.
904 const auto *DH
= reinterpret_cast<const dos_header
*>(base());
905 if (DH
->Magic
[0] == 'M' && DH
->Magic
[1] == 'Z') {
906 CurPtr
= DH
->AddressOfNewExeHeader
;
907 // Check the PE magic bytes. ("PE\0\0")
908 if (memcmp(base() + CurPtr
, COFF::PEMagic
, sizeof(COFF::PEMagic
)) != 0) {
909 return createStringError(object_error::parse_failed
,
910 "incorrect PE magic");
912 CurPtr
+= sizeof(COFF::PEMagic
); // Skip the PE magic bytes.
917 if (Error E
= getObject(COFFHeader
, Data
, base() + CurPtr
))
920 // It might be a bigobj file, let's check. Note that COFF bigobj and COFF
921 // import libraries share a common prefix but bigobj is more restrictive.
922 if (!HasPEHeader
&& COFFHeader
->Machine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
&&
923 COFFHeader
->NumberOfSections
== uint16_t(0xffff) &&
924 checkSize(Data
, EC
, sizeof(coff_bigobj_file_header
))) {
925 if (Error E
= getObject(COFFBigObjHeader
, Data
, base() + CurPtr
))
928 // Verify that we are dealing with bigobj.
929 if (COFFBigObjHeader
->Version
>= COFF::BigObjHeader::MinBigObjectVersion
&&
930 std::memcmp(COFFBigObjHeader
->UUID
, COFF::BigObjMagic
,
931 sizeof(COFF::BigObjMagic
)) == 0) {
932 COFFHeader
= nullptr;
933 CurPtr
+= sizeof(coff_bigobj_file_header
);
935 // It's not a bigobj.
936 COFFBigObjHeader
= nullptr;
940 // The prior checkSize call may have failed. This isn't a hard error
941 // because we were just trying to sniff out bigobj.
942 EC
= std::error_code();
943 CurPtr
+= sizeof(coff_file_header
);
945 if (COFFHeader
->isImportLibrary())
946 return errorCodeToError(EC
);
950 const pe32_header
*Header
;
951 if (Error E
= getObject(Header
, Data
, base() + CurPtr
))
954 const uint8_t *DataDirAddr
;
955 uint64_t DataDirSize
;
956 if (Header
->Magic
== COFF::PE32Header::PE32
) {
958 DataDirAddr
= base() + CurPtr
+ sizeof(pe32_header
);
959 DataDirSize
= sizeof(data_directory
) * PE32Header
->NumberOfRvaAndSize
;
960 } else if (Header
->Magic
== COFF::PE32Header::PE32_PLUS
) {
961 PE32PlusHeader
= reinterpret_cast<const pe32plus_header
*>(Header
);
962 DataDirAddr
= base() + CurPtr
+ sizeof(pe32plus_header
);
963 DataDirSize
= sizeof(data_directory
) * PE32PlusHeader
->NumberOfRvaAndSize
;
965 // It's neither PE32 nor PE32+.
966 return createStringError(object_error::parse_failed
,
967 "incorrect PE magic");
969 if (Error E
= getObject(DataDirectory
, Data
, DataDirAddr
, DataDirSize
))
974 CurPtr
+= COFFHeader
->SizeOfOptionalHeader
;
976 assert(COFFHeader
|| COFFBigObjHeader
);
979 getObject(SectionTable
, Data
, base() + CurPtr
,
980 (uint64_t)getNumberOfSections() * sizeof(coff_section
)))
983 // Initialize the pointer to the symbol table.
984 if (getPointerToSymbolTable() != 0) {
985 if (Error E
= initSymbolTablePtr()) {
986 // Recover from errors reading the symbol table.
987 consumeError(std::move(E
));
988 SymbolTable16
= nullptr;
989 SymbolTable32
= nullptr;
990 StringTable
= nullptr;
994 // We had better not have any symbols if we don't have a symbol table.
995 if (getNumberOfSymbols() != 0) {
996 return createStringError(object_error::parse_failed
,
997 "symbol table missing");
1001 // Initialize the pointer to the beginning of the import table.
1002 if (Error E
= ignoreStrippedErrors(initImportTablePtr()))
1004 if (Error E
= ignoreStrippedErrors(initDelayImportTablePtr()))
1007 // Initialize the pointer to the export table.
1008 if (Error E
= ignoreStrippedErrors(initExportTablePtr()))
1011 // Initialize the pointer to the base relocation table.
1012 if (Error E
= ignoreStrippedErrors(initBaseRelocPtr()))
1015 // Initialize the pointer to the debug directory.
1016 if (Error E
= ignoreStrippedErrors(initDebugDirectoryPtr()))
1019 // Initialize the pointer to the TLS directory.
1020 if (Error E
= ignoreStrippedErrors(initTLSDirectoryPtr()))
1023 if (Error E
= ignoreStrippedErrors(initLoadConfigPtr()))
1026 return Error::success();
1029 basic_symbol_iterator
COFFObjectFile::symbol_begin() const {
1031 Ret
.p
= getSymbolTable();
1032 return basic_symbol_iterator(SymbolRef(Ret
, this));
1035 basic_symbol_iterator
COFFObjectFile::symbol_end() const {
1036 // The symbol table ends where the string table begins.
1038 Ret
.p
= reinterpret_cast<uintptr_t>(StringTable
);
1039 return basic_symbol_iterator(SymbolRef(Ret
, this));
1042 import_directory_iterator
COFFObjectFile::import_directory_begin() const {
1043 if (!ImportDirectory
)
1044 return import_directory_end();
1045 if (ImportDirectory
->isNull())
1046 return import_directory_end();
1047 return import_directory_iterator(
1048 ImportDirectoryEntryRef(ImportDirectory
, 0, this));
1051 import_directory_iterator
COFFObjectFile::import_directory_end() const {
1052 return import_directory_iterator(
1053 ImportDirectoryEntryRef(nullptr, -1, this));
1056 delay_import_directory_iterator
1057 COFFObjectFile::delay_import_directory_begin() const {
1058 return delay_import_directory_iterator(
1059 DelayImportDirectoryEntryRef(DelayImportDirectory
, 0, this));
1062 delay_import_directory_iterator
1063 COFFObjectFile::delay_import_directory_end() const {
1064 return delay_import_directory_iterator(
1065 DelayImportDirectoryEntryRef(
1066 DelayImportDirectory
, NumberOfDelayImportDirectory
, this));
1069 export_directory_iterator
COFFObjectFile::export_directory_begin() const {
1070 return export_directory_iterator(
1071 ExportDirectoryEntryRef(ExportDirectory
, 0, this));
1074 export_directory_iterator
COFFObjectFile::export_directory_end() const {
1075 if (!ExportDirectory
)
1076 return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
1077 ExportDirectoryEntryRef
Ref(ExportDirectory
,
1078 ExportDirectory
->AddressTableEntries
, this);
1079 return export_directory_iterator(Ref
);
1082 section_iterator
COFFObjectFile::section_begin() const {
1084 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
);
1085 return section_iterator(SectionRef(Ret
, this));
1088 section_iterator
COFFObjectFile::section_end() const {
1091 COFFHeader
&& COFFHeader
->isImportLibrary() ? 0 : getNumberOfSections();
1092 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
+ NumSections
);
1093 return section_iterator(SectionRef(Ret
, this));
1096 base_reloc_iterator
COFFObjectFile::base_reloc_begin() const {
1097 return base_reloc_iterator(BaseRelocRef(BaseRelocHeader
, this));
1100 base_reloc_iterator
COFFObjectFile::base_reloc_end() const {
1101 return base_reloc_iterator(BaseRelocRef(BaseRelocEnd
, this));
1104 dynamic_reloc_iterator
COFFObjectFile::dynamic_reloc_begin() const {
1105 const void *Header
= DynamicRelocTable
? DynamicRelocTable
+ 1 : nullptr;
1106 return dynamic_reloc_iterator(DynamicRelocRef(Header
, this));
1109 dynamic_reloc_iterator
COFFObjectFile::dynamic_reloc_end() const {
1110 const void *Header
= nullptr;
1111 if (DynamicRelocTable
)
1112 Header
= reinterpret_cast<const uint8_t *>(DynamicRelocTable
+ 1) +
1113 DynamicRelocTable
->Size
;
1114 return dynamic_reloc_iterator(DynamicRelocRef(Header
, this));
1117 uint8_t COFFObjectFile::getBytesInAddress() const {
1118 return getArch() == Triple::x86_64
|| getArch() == Triple::aarch64
? 8 : 4;
1121 StringRef
COFFObjectFile::getFileFormatName() const {
1122 switch(getMachine()) {
1123 case COFF::IMAGE_FILE_MACHINE_I386
:
1125 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1126 return "COFF-x86-64";
1127 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1129 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1130 return "COFF-ARM64";
1131 case COFF::IMAGE_FILE_MACHINE_ARM64EC
:
1132 return "COFF-ARM64EC";
1133 case COFF::IMAGE_FILE_MACHINE_ARM64X
:
1134 return "COFF-ARM64X";
1135 case COFF::IMAGE_FILE_MACHINE_R4000
:
1138 return "COFF-<unknown arch>";
1142 Triple::ArchType
COFFObjectFile::getArch() const {
1143 return getMachineArchType(getMachine());
1146 Expected
<uint64_t> COFFObjectFile::getStartAddress() const {
1148 return PE32Header
->AddressOfEntryPoint
;
1152 iterator_range
<import_directory_iterator
>
1153 COFFObjectFile::import_directories() const {
1154 return make_range(import_directory_begin(), import_directory_end());
1157 iterator_range
<delay_import_directory_iterator
>
1158 COFFObjectFile::delay_import_directories() const {
1159 return make_range(delay_import_directory_begin(),
1160 delay_import_directory_end());
1163 iterator_range
<export_directory_iterator
>
1164 COFFObjectFile::export_directories() const {
1165 return make_range(export_directory_begin(), export_directory_end());
1168 iterator_range
<base_reloc_iterator
> COFFObjectFile::base_relocs() const {
1169 return make_range(base_reloc_begin(), base_reloc_end());
1172 iterator_range
<dynamic_reloc_iterator
> COFFObjectFile::dynamic_relocs() const {
1173 return make_range(dynamic_reloc_begin(), dynamic_reloc_end());
1176 const data_directory
*COFFObjectFile::getDataDirectory(uint32_t Index
) const {
1179 assert(PE32Header
|| PE32PlusHeader
);
1180 uint32_t NumEnt
= PE32Header
? PE32Header
->NumberOfRvaAndSize
1181 : PE32PlusHeader
->NumberOfRvaAndSize
;
1182 if (Index
>= NumEnt
)
1184 return &DataDirectory
[Index
];
1187 Expected
<const coff_section
*> COFFObjectFile::getSection(int32_t Index
) const {
1188 // Perhaps getting the section of a reserved section index should be an error,
1189 // but callers rely on this to return null.
1190 if (COFF::isReservedSectionNumber(Index
))
1191 return (const coff_section
*)nullptr;
1192 if (static_cast<uint32_t>(Index
) <= getNumberOfSections()) {
1193 // We already verified the section table data, so no need to check again.
1194 return SectionTable
+ (Index
- 1);
1196 return createStringError(object_error::parse_failed
,
1197 "section index out of bounds");
1200 Expected
<StringRef
> COFFObjectFile::getString(uint32_t Offset
) const {
1201 if (StringTableSize
<= 4)
1202 // Tried to get a string from an empty string table.
1203 return createStringError(object_error::parse_failed
, "string table empty");
1204 if (Offset
>= StringTableSize
)
1205 return errorCodeToError(object_error::unexpected_eof
);
1206 return StringRef(StringTable
+ Offset
);
1209 Expected
<StringRef
> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol
) const {
1210 return getSymbolName(Symbol
.getGeneric());
1214 COFFObjectFile::getSymbolName(const coff_symbol_generic
*Symbol
) const {
1215 // Check for string table entry. First 4 bytes are 0.
1216 if (Symbol
->Name
.Offset
.Zeroes
== 0)
1217 return getString(Symbol
->Name
.Offset
.Offset
);
1219 // Null terminated, let ::strlen figure out the length.
1220 if (Symbol
->Name
.ShortName
[COFF::NameSize
- 1] == 0)
1221 return StringRef(Symbol
->Name
.ShortName
);
1223 // Not null terminated, use all 8 bytes.
1224 return StringRef(Symbol
->Name
.ShortName
, COFF::NameSize
);
1228 COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol
) const {
1229 const uint8_t *Aux
= nullptr;
1231 size_t SymbolSize
= getSymbolTableEntrySize();
1232 if (Symbol
.getNumberOfAuxSymbols() > 0) {
1233 // AUX data comes immediately after the symbol in COFF
1234 Aux
= reinterpret_cast<const uint8_t *>(Symbol
.getRawPtr()) + SymbolSize
;
1236 // Verify that the Aux symbol points to a valid entry in the symbol table.
1237 uintptr_t Offset
= uintptr_t(Aux
) - uintptr_t(base());
1238 if (Offset
< getPointerToSymbolTable() ||
1240 getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize
))
1241 report_fatal_error("Aux Symbol data was outside of symbol table.");
1243 assert((Offset
- getPointerToSymbolTable()) % SymbolSize
== 0 &&
1244 "Aux Symbol data did not point to the beginning of a symbol");
1247 return ArrayRef(Aux
, Symbol
.getNumberOfAuxSymbols() * SymbolSize
);
1250 uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol
) const {
1252 reinterpret_cast<uintptr_t>(Symbol
.getRawPtr()) - getSymbolTable();
1253 assert(Offset
% getSymbolTableEntrySize() == 0 &&
1254 "Symbol did not point to the beginning of a symbol");
1255 size_t Index
= Offset
/ getSymbolTableEntrySize();
1256 assert(Index
< getNumberOfSymbols());
1261 COFFObjectFile::getSectionName(const coff_section
*Sec
) const {
1262 StringRef Name
= StringRef(Sec
->Name
, COFF::NameSize
).split('\0').first
;
1264 // Check for string table entry. First byte is '/'.
1265 if (Name
.starts_with("/")) {
1267 if (Name
.starts_with("//")) {
1268 if (decodeBase64StringEntry(Name
.substr(2), Offset
))
1269 return createStringError(object_error::parse_failed
,
1270 "invalid section name");
1272 if (Name
.substr(1).getAsInteger(10, Offset
))
1273 return createStringError(object_error::parse_failed
,
1274 "invalid section name");
1276 return getString(Offset
);
1282 uint64_t COFFObjectFile::getSectionSize(const coff_section
*Sec
) const {
1283 // SizeOfRawData and VirtualSize change what they represent depending on
1284 // whether or not we have an executable image.
1286 // For object files, SizeOfRawData contains the size of section's data;
1287 // VirtualSize should be zero but isn't due to buggy COFF writers.
1289 // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1290 // actual section size is in VirtualSize. It is possible for VirtualSize to
1291 // be greater than SizeOfRawData; the contents past that point should be
1292 // considered to be zero.
1294 return std::min(Sec
->VirtualSize
, Sec
->SizeOfRawData
);
1295 return Sec
->SizeOfRawData
;
1298 Error
COFFObjectFile::getSectionContents(const coff_section
*Sec
,
1299 ArrayRef
<uint8_t> &Res
) const {
1300 // In COFF, a virtual section won't have any in-file
1301 // content, so the file pointer to the content will be zero.
1302 if (Sec
->PointerToRawData
== 0)
1303 return Error::success();
1304 // The only thing that we need to verify is that the contents is contained
1305 // within the file bounds. We don't need to make sure it doesn't cover other
1306 // data, as there's nothing that says that is not allowed.
1307 uintptr_t ConStart
=
1308 reinterpret_cast<uintptr_t>(base()) + Sec
->PointerToRawData
;
1309 uint32_t SectionSize
= getSectionSize(Sec
);
1310 if (Error E
= checkOffset(Data
, ConStart
, SectionSize
))
1312 Res
= ArrayRef(reinterpret_cast<const uint8_t *>(ConStart
), SectionSize
);
1313 return Error::success();
1316 const coff_relocation
*COFFObjectFile::toRel(DataRefImpl Rel
) const {
1317 return reinterpret_cast<const coff_relocation
*>(Rel
.p
);
1320 void COFFObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
1321 Rel
.p
= reinterpret_cast<uintptr_t>(
1322 reinterpret_cast<const coff_relocation
*>(Rel
.p
) + 1);
1325 uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
1326 const coff_relocation
*R
= toRel(Rel
);
1327 return R
->VirtualAddress
;
1330 symbol_iterator
COFFObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
1331 const coff_relocation
*R
= toRel(Rel
);
1333 if (R
->SymbolTableIndex
>= getNumberOfSymbols())
1334 return symbol_end();
1336 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable16
+ R
->SymbolTableIndex
);
1337 else if (SymbolTable32
)
1338 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable32
+ R
->SymbolTableIndex
);
1340 llvm_unreachable("no symbol table pointer!");
1341 return symbol_iterator(SymbolRef(Ref
, this));
1344 uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel
) const {
1345 const coff_relocation
* R
= toRel(Rel
);
1349 const coff_section
*
1350 COFFObjectFile::getCOFFSection(const SectionRef
&Section
) const {
1351 return toSec(Section
.getRawDataRefImpl());
1354 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const DataRefImpl
&Ref
) const {
1356 return toSymb
<coff_symbol16
>(Ref
);
1358 return toSymb
<coff_symbol32
>(Ref
);
1359 llvm_unreachable("no symbol table pointer!");
1362 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const SymbolRef
&Symbol
) const {
1363 return getCOFFSymbol(Symbol
.getRawDataRefImpl());
1366 const coff_relocation
*
1367 COFFObjectFile::getCOFFRelocation(const RelocationRef
&Reloc
) const {
1368 return toRel(Reloc
.getRawDataRefImpl());
1371 ArrayRef
<coff_relocation
>
1372 COFFObjectFile::getRelocations(const coff_section
*Sec
) const {
1373 return {getFirstReloc(Sec
, Data
, base()),
1374 getNumberOfRelocations(Sec
, Data
, base())};
1377 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1378 case COFF::reloc_type: \
1381 StringRef
COFFObjectFile::getRelocationTypeName(uint16_t Type
) const {
1382 switch (getArch()) {
1383 case Triple::x86_64
:
1385 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE
);
1386 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64
);
1387 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32
);
1388 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB
);
1389 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32
);
1390 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1
);
1391 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2
);
1392 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3
);
1393 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4
);
1394 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5
);
1395 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION
);
1396 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL
);
1397 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7
);
1398 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN
);
1399 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32
);
1400 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR
);
1401 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32
);
1408 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE
);
1409 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32
);
1410 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB
);
1411 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24
);
1412 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11
);
1413 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN
);
1414 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24
);
1415 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11
);
1416 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32
);
1417 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION
);
1418 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL
);
1419 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A
);
1420 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T
);
1421 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T
);
1422 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T
);
1423 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T
);
1424 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR
);
1429 case Triple::aarch64
:
1431 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE
);
1432 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32
);
1433 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB
);
1434 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26
);
1435 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21
);
1436 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21
);
1437 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A
);
1438 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L
);
1439 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL
);
1440 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A
);
1441 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A
);
1442 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L
);
1443 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN
);
1444 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION
);
1445 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64
);
1446 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19
);
1447 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14
);
1448 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32
);
1455 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE
);
1456 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16
);
1457 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16
);
1458 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32
);
1459 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB
);
1460 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12
);
1461 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION
);
1462 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL
);
1463 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN
);
1464 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7
);
1465 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32
);
1470 case Triple::mipsel
:
1472 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_ABSOLUTE
);
1473 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFHALF
);
1474 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFWORD
);
1475 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_JMPADDR
);
1476 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFHI
);
1477 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFLO
);
1478 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_GPREL
);
1479 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_LITERAL
);
1480 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECTION
);
1481 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECREL
);
1482 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECRELLO
);
1483 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECRELHI
);
1484 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_JMPADDR16
);
1485 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFWORDNB
);
1486 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_PAIR
);
1496 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1498 void COFFObjectFile::getRelocationTypeName(
1499 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
1500 const coff_relocation
*Reloc
= toRel(Rel
);
1501 StringRef Res
= getRelocationTypeName(Reloc
->Type
);
1502 Result
.append(Res
.begin(), Res
.end());
1505 bool COFFObjectFile::isRelocatableObject() const {
1506 return !DataDirectory
;
1509 StringRef
COFFObjectFile::mapDebugSectionName(StringRef Name
) const {
1510 return StringSwitch
<StringRef
>(Name
)
1511 .Case("eh_fram", "eh_frame")
1515 std::unique_ptr
<MemoryBuffer
> COFFObjectFile::getHybridObjectView() const {
1516 if (getMachine() != COFF::IMAGE_FILE_MACHINE_ARM64X
)
1519 std::unique_ptr
<WritableMemoryBuffer
> HybridView
;
1521 for (auto DynReloc
: dynamic_relocs()) {
1522 if (DynReloc
.getType() != COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X
)
1525 for (auto reloc
: DynReloc
.arm64x_relocs()) {
1528 WritableMemoryBuffer::getNewUninitMemBuffer(Data
.getBufferSize());
1529 memcpy(HybridView
->getBufferStart(), Data
.getBufferStart(),
1530 Data
.getBufferSize());
1533 uint32_t RVA
= reloc
.getRVA();
1537 cantFail(getRvaPtr(RVA
, IntPtr
));
1538 Ptr
= HybridView
->getBufferStart() + IntPtr
-
1539 reinterpret_cast<uintptr_t>(base());
1541 // PE header relocation.
1542 Ptr
= HybridView
->getBufferStart() + RVA
;
1545 switch (reloc
.getType()) {
1546 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL
:
1547 memset(Ptr
, 0, reloc
.getSize());
1549 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE
: {
1550 auto Value
= static_cast<ulittle64_t
>(reloc
.getValue());
1551 memcpy(Ptr
, &Value
, reloc
.getSize());
1554 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA
:
1555 *reinterpret_cast<ulittle32_t
*>(Ptr
) += reloc
.getValue();
1563 bool ImportDirectoryEntryRef::
1564 operator==(const ImportDirectoryEntryRef
&Other
) const {
1565 return ImportTable
== Other
.ImportTable
&& Index
== Other
.Index
;
1568 void ImportDirectoryEntryRef::moveNext() {
1570 if (ImportTable
[Index
].isNull()) {
1572 ImportTable
= nullptr;
1576 Error
ImportDirectoryEntryRef::getImportTableEntry(
1577 const coff_import_directory_table_entry
*&Result
) const {
1578 return getObject(Result
, OwningObject
->Data
, ImportTable
+ Index
);
1581 static imported_symbol_iterator
1582 makeImportedSymbolIterator(const COFFObjectFile
*Object
,
1583 uintptr_t Ptr
, int Index
) {
1584 if (Object
->getBytesInAddress() == 4) {
1585 auto *P
= reinterpret_cast<const import_lookup_table_entry32
*>(Ptr
);
1586 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1588 auto *P
= reinterpret_cast<const import_lookup_table_entry64
*>(Ptr
);
1589 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1592 static imported_symbol_iterator
1593 importedSymbolBegin(uint32_t RVA
, const COFFObjectFile
*Object
) {
1594 uintptr_t IntPtr
= 0;
1595 // FIXME: Handle errors.
1596 cantFail(Object
->getRvaPtr(RVA
, IntPtr
));
1597 return makeImportedSymbolIterator(Object
, IntPtr
, 0);
1600 static imported_symbol_iterator
1601 importedSymbolEnd(uint32_t RVA
, const COFFObjectFile
*Object
) {
1602 uintptr_t IntPtr
= 0;
1603 // FIXME: Handle errors.
1604 cantFail(Object
->getRvaPtr(RVA
, IntPtr
));
1605 // Forward the pointer to the last entry which is null.
1607 if (Object
->getBytesInAddress() == 4) {
1608 auto *Entry
= reinterpret_cast<ulittle32_t
*>(IntPtr
);
1612 auto *Entry
= reinterpret_cast<ulittle64_t
*>(IntPtr
);
1616 return makeImportedSymbolIterator(Object
, IntPtr
, Index
);
1619 imported_symbol_iterator
1620 ImportDirectoryEntryRef::imported_symbol_begin() const {
1621 return importedSymbolBegin(ImportTable
[Index
].ImportAddressTableRVA
,
1625 imported_symbol_iterator
1626 ImportDirectoryEntryRef::imported_symbol_end() const {
1627 return importedSymbolEnd(ImportTable
[Index
].ImportAddressTableRVA
,
1631 iterator_range
<imported_symbol_iterator
>
1632 ImportDirectoryEntryRef::imported_symbols() const {
1633 return make_range(imported_symbol_begin(), imported_symbol_end());
1636 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_begin() const {
1637 return importedSymbolBegin(ImportTable
[Index
].ImportLookupTableRVA
,
1641 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_end() const {
1642 return importedSymbolEnd(ImportTable
[Index
].ImportLookupTableRVA
,
1646 iterator_range
<imported_symbol_iterator
>
1647 ImportDirectoryEntryRef::lookup_table_symbols() const {
1648 return make_range(lookup_table_begin(), lookup_table_end());
1651 Error
ImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1652 uintptr_t IntPtr
= 0;
1653 if (Error E
= OwningObject
->getRvaPtr(ImportTable
[Index
].NameRVA
, IntPtr
,
1654 "import directory name"))
1656 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1657 return Error::success();
1661 ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result
) const {
1662 Result
= ImportTable
[Index
].ImportLookupTableRVA
;
1663 return Error::success();
1666 Error
ImportDirectoryEntryRef::getImportAddressTableRVA(
1667 uint32_t &Result
) const {
1668 Result
= ImportTable
[Index
].ImportAddressTableRVA
;
1669 return Error::success();
1672 bool DelayImportDirectoryEntryRef::
1673 operator==(const DelayImportDirectoryEntryRef
&Other
) const {
1674 return Table
== Other
.Table
&& Index
== Other
.Index
;
1677 void DelayImportDirectoryEntryRef::moveNext() {
1681 imported_symbol_iterator
1682 DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1683 return importedSymbolBegin(Table
[Index
].DelayImportNameTable
,
1687 imported_symbol_iterator
1688 DelayImportDirectoryEntryRef::imported_symbol_end() const {
1689 return importedSymbolEnd(Table
[Index
].DelayImportNameTable
,
1693 iterator_range
<imported_symbol_iterator
>
1694 DelayImportDirectoryEntryRef::imported_symbols() const {
1695 return make_range(imported_symbol_begin(), imported_symbol_end());
1698 Error
DelayImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1699 uintptr_t IntPtr
= 0;
1700 if (Error E
= OwningObject
->getRvaPtr(Table
[Index
].Name
, IntPtr
,
1701 "delay import directory name"))
1703 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1704 return Error::success();
1707 Error
DelayImportDirectoryEntryRef::getDelayImportTable(
1708 const delay_import_directory_table_entry
*&Result
) const {
1709 Result
= &Table
[Index
];
1710 return Error::success();
1713 Error
DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex
,
1714 uint64_t &Result
) const {
1715 uint32_t RVA
= Table
[Index
].DelayImportAddressTable
+
1716 AddrIndex
* (OwningObject
->is64() ? 8 : 4);
1717 uintptr_t IntPtr
= 0;
1718 if (Error E
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "import address"))
1720 if (OwningObject
->is64())
1721 Result
= *reinterpret_cast<const ulittle64_t
*>(IntPtr
);
1723 Result
= *reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1724 return Error::success();
1727 bool ExportDirectoryEntryRef::
1728 operator==(const ExportDirectoryEntryRef
&Other
) const {
1729 return ExportTable
== Other
.ExportTable
&& Index
== Other
.Index
;
1732 void ExportDirectoryEntryRef::moveNext() {
1736 // Returns the name of the current export symbol. If the symbol is exported only
1737 // by ordinal, the empty string is set as a result.
1738 Error
ExportDirectoryEntryRef::getDllName(StringRef
&Result
) const {
1739 uintptr_t IntPtr
= 0;
1741 OwningObject
->getRvaPtr(ExportTable
->NameRVA
, IntPtr
, "dll name"))
1743 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1744 return Error::success();
1747 // Returns the starting ordinal number.
1748 Error
ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result
) const {
1749 Result
= ExportTable
->OrdinalBase
;
1750 return Error::success();
1753 // Returns the export ordinal of the current export symbol.
1754 Error
ExportDirectoryEntryRef::getOrdinal(uint32_t &Result
) const {
1755 Result
= ExportTable
->OrdinalBase
+ Index
;
1756 return Error::success();
1759 // Returns the address of the current export symbol.
1760 Error
ExportDirectoryEntryRef::getExportRVA(uint32_t &Result
) const {
1761 uintptr_t IntPtr
= 0;
1762 if (Error EC
= OwningObject
->getRvaPtr(ExportTable
->ExportAddressTableRVA
,
1763 IntPtr
, "export address"))
1765 const export_address_table_entry
*entry
=
1766 reinterpret_cast<const export_address_table_entry
*>(IntPtr
);
1767 Result
= entry
[Index
].ExportRVA
;
1768 return Error::success();
1771 // Returns the name of the current export symbol. If the symbol is exported only
1772 // by ordinal, the empty string is set as a result.
1774 ExportDirectoryEntryRef::getSymbolName(StringRef
&Result
) const {
1775 uintptr_t IntPtr
= 0;
1776 if (Error EC
= OwningObject
->getRvaPtr(ExportTable
->OrdinalTableRVA
, IntPtr
,
1777 "export ordinal table"))
1779 const ulittle16_t
*Start
= reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1781 uint32_t NumEntries
= ExportTable
->NumberOfNamePointers
;
1783 for (const ulittle16_t
*I
= Start
, *E
= Start
+ NumEntries
;
1784 I
< E
; ++I
, ++Offset
) {
1787 if (Error EC
= OwningObject
->getRvaPtr(ExportTable
->NamePointerRVA
, IntPtr
,
1788 "export table entry"))
1790 const ulittle32_t
*NamePtr
= reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1791 if (Error EC
= OwningObject
->getRvaPtr(NamePtr
[Offset
], IntPtr
,
1792 "export symbol name"))
1794 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1795 return Error::success();
1798 return Error::success();
1801 Error
ExportDirectoryEntryRef::isForwarder(bool &Result
) const {
1802 const data_directory
*DataEntry
=
1803 OwningObject
->getDataDirectory(COFF::EXPORT_TABLE
);
1805 return createStringError(object_error::parse_failed
,
1806 "export table missing");
1808 if (auto EC
= getExportRVA(RVA
))
1810 uint32_t Begin
= DataEntry
->RelativeVirtualAddress
;
1811 uint32_t End
= DataEntry
->RelativeVirtualAddress
+ DataEntry
->Size
;
1812 Result
= (Begin
<= RVA
&& RVA
< End
);
1813 return Error::success();
1816 Error
ExportDirectoryEntryRef::getForwardTo(StringRef
&Result
) const {
1818 if (auto EC
= getExportRVA(RVA
))
1820 uintptr_t IntPtr
= 0;
1821 if (auto EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "export forward target"))
1823 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1824 return Error::success();
1827 bool ImportedSymbolRef::
1828 operator==(const ImportedSymbolRef
&Other
) const {
1829 return Entry32
== Other
.Entry32
&& Entry64
== Other
.Entry64
1830 && Index
== Other
.Index
;
1833 void ImportedSymbolRef::moveNext() {
1837 Error
ImportedSymbolRef::getSymbolName(StringRef
&Result
) const {
1840 // If a symbol is imported only by ordinal, it has no name.
1841 if (Entry32
[Index
].isOrdinal())
1842 return Error::success();
1843 RVA
= Entry32
[Index
].getHintNameRVA();
1845 if (Entry64
[Index
].isOrdinal())
1846 return Error::success();
1847 RVA
= Entry64
[Index
].getHintNameRVA();
1849 uintptr_t IntPtr
= 0;
1850 if (Error EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "import symbol name"))
1852 // +2 because the first two bytes is hint.
1853 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
+ 2));
1854 return Error::success();
1857 Error
ImportedSymbolRef::isOrdinal(bool &Result
) const {
1859 Result
= Entry32
[Index
].isOrdinal();
1861 Result
= Entry64
[Index
].isOrdinal();
1862 return Error::success();
1865 Error
ImportedSymbolRef::getHintNameRVA(uint32_t &Result
) const {
1867 Result
= Entry32
[Index
].getHintNameRVA();
1869 Result
= Entry64
[Index
].getHintNameRVA();
1870 return Error::success();
1873 Error
ImportedSymbolRef::getOrdinal(uint16_t &Result
) const {
1876 if (Entry32
[Index
].isOrdinal()) {
1877 Result
= Entry32
[Index
].getOrdinal();
1878 return Error::success();
1880 RVA
= Entry32
[Index
].getHintNameRVA();
1882 if (Entry64
[Index
].isOrdinal()) {
1883 Result
= Entry64
[Index
].getOrdinal();
1884 return Error::success();
1886 RVA
= Entry64
[Index
].getHintNameRVA();
1888 uintptr_t IntPtr
= 0;
1889 if (Error EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "import symbol ordinal"))
1891 Result
= *reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1892 return Error::success();
1895 Expected
<std::unique_ptr
<COFFObjectFile
>>
1896 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object
) {
1897 return COFFObjectFile::create(Object
);
1900 bool BaseRelocRef::operator==(const BaseRelocRef
&Other
) const {
1901 return Header
== Other
.Header
&& Index
== Other
.Index
;
1904 void BaseRelocRef::moveNext() {
1905 // Header->BlockSize is the size of the current block, including the
1906 // size of the header itself.
1907 uint32_t Size
= sizeof(*Header
) +
1908 sizeof(coff_base_reloc_block_entry
) * (Index
+ 1);
1909 if (Size
== Header
->BlockSize
) {
1910 // .reloc contains a list of base relocation blocks. Each block
1911 // consists of the header followed by entries. The header contains
1912 // how many entories will follow. When we reach the end of the
1913 // current block, proceed to the next block.
1914 Header
= reinterpret_cast<const coff_base_reloc_block_header
*>(
1915 reinterpret_cast<const uint8_t *>(Header
) + Size
);
1922 Error
BaseRelocRef::getType(uint8_t &Type
) const {
1923 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1924 Type
= Entry
[Index
].getType();
1925 return Error::success();
1928 Error
BaseRelocRef::getRVA(uint32_t &Result
) const {
1929 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1930 Result
= Header
->PageRVA
+ Entry
[Index
].getOffset();
1931 return Error::success();
1934 bool DynamicRelocRef::operator==(const DynamicRelocRef
&Other
) const {
1935 return Header
== Other
.Header
;
1938 void DynamicRelocRef::moveNext() {
1939 switch (Obj
->getDynamicRelocTable()->Version
) {
1942 auto H
= reinterpret_cast<const coff_dynamic_relocation64
*>(Header
);
1943 Header
+= sizeof(*H
) + H
->BaseRelocSize
;
1945 auto H
= reinterpret_cast<const coff_dynamic_relocation32
*>(Header
);
1946 Header
+= sizeof(*H
) + H
->BaseRelocSize
;
1951 auto H
= reinterpret_cast<const coff_dynamic_relocation64_v2
*>(Header
);
1952 Header
+= H
->HeaderSize
+ H
->FixupInfoSize
;
1954 auto H
= reinterpret_cast<const coff_dynamic_relocation32_v2
*>(Header
);
1955 Header
+= H
->HeaderSize
+ H
->FixupInfoSize
;
1961 uint32_t DynamicRelocRef::getType() const {
1962 switch (Obj
->getDynamicRelocTable()->Version
) {
1965 auto H
= reinterpret_cast<const coff_dynamic_relocation64
*>(Header
);
1968 auto H
= reinterpret_cast<const coff_dynamic_relocation32
*>(Header
);
1974 auto H
= reinterpret_cast<const coff_dynamic_relocation64_v2
*>(Header
);
1977 auto H
= reinterpret_cast<const coff_dynamic_relocation32_v2
*>(Header
);
1982 llvm_unreachable("invalid version");
1986 void DynamicRelocRef::getContents(ArrayRef
<uint8_t> &Ref
) const {
1987 switch (Obj
->getDynamicRelocTable()->Version
) {
1990 auto H
= reinterpret_cast<const coff_dynamic_relocation64
*>(Header
);
1991 Ref
= ArrayRef(Header
+ sizeof(*H
), H
->BaseRelocSize
);
1993 auto H
= reinterpret_cast<const coff_dynamic_relocation32
*>(Header
);
1994 Ref
= ArrayRef(Header
+ sizeof(*H
), H
->BaseRelocSize
);
1999 auto H
= reinterpret_cast<const coff_dynamic_relocation64_v2
*>(Header
);
2000 Ref
= ArrayRef(Header
+ H
->HeaderSize
, H
->FixupInfoSize
);
2002 auto H
= reinterpret_cast<const coff_dynamic_relocation32_v2
*>(Header
);
2003 Ref
= ArrayRef(Header
+ H
->HeaderSize
, H
->FixupInfoSize
);
2009 Error
DynamicRelocRef::validate() const {
2010 const coff_dynamic_reloc_table
*Table
= Obj
->getDynamicRelocTable();
2011 size_t ContentsSize
=
2012 reinterpret_cast<const uint8_t *>(Table
+ 1) + Table
->Size
- Header
;
2014 if (Table
->Version
== 1)
2015 HeaderSize
= Obj
->is64() ? sizeof(coff_dynamic_relocation64
)
2016 : sizeof(coff_dynamic_relocation32
);
2018 HeaderSize
= Obj
->is64() ? sizeof(coff_dynamic_relocation64_v2
)
2019 : sizeof(coff_dynamic_relocation32_v2
);
2020 if (HeaderSize
> ContentsSize
)
2021 return createStringError(object_error::parse_failed
,
2022 "Unexpected end of dynamic relocations data");
2024 if (Table
->Version
== 2) {
2027 ? reinterpret_cast<const coff_dynamic_relocation64_v2
*>(Header
)
2029 : reinterpret_cast<const coff_dynamic_relocation32_v2
*>(Header
)
2031 if (Size
< HeaderSize
|| Size
> ContentsSize
)
2032 return createStringError(object_error::parse_failed
,
2033 "Invalid dynamic relocation header size (" +
2038 ArrayRef
<uint8_t> Contents
;
2039 getContents(Contents
);
2040 if (Contents
.size() > ContentsSize
- HeaderSize
)
2041 return createStringError(object_error::parse_failed
,
2042 "Too large dynamic relocation size (" +
2043 Twine(Contents
.size()) + ")");
2045 switch (getType()) {
2046 case COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X
:
2047 for (auto Reloc
: arm64x_relocs()) {
2048 if (Error E
= Reloc
.validate(Obj
))
2054 return Error::success();
2057 arm64x_reloc_iterator
DynamicRelocRef::arm64x_reloc_begin() const {
2058 assert(getType() == COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X
);
2059 ArrayRef
<uint8_t> Content
;
2060 getContents(Content
);
2062 reinterpret_cast<const coff_base_reloc_block_header
*>(Content
.begin());
2063 return arm64x_reloc_iterator(Arm64XRelocRef(Header
));
2066 arm64x_reloc_iterator
DynamicRelocRef::arm64x_reloc_end() const {
2067 assert(getType() == COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X
);
2068 ArrayRef
<uint8_t> Content
;
2069 getContents(Content
);
2071 reinterpret_cast<const coff_base_reloc_block_header
*>(Content
.end());
2072 return arm64x_reloc_iterator(Arm64XRelocRef(Header
, 0));
2075 iterator_range
<arm64x_reloc_iterator
> DynamicRelocRef::arm64x_relocs() const {
2076 return make_range(arm64x_reloc_begin(), arm64x_reloc_end());
2079 bool Arm64XRelocRef::operator==(const Arm64XRelocRef
&Other
) const {
2080 return Header
== Other
.Header
&& Index
== Other
.Index
;
2083 uint8_t Arm64XRelocRef::getEntrySize() const {
2084 switch (getType()) {
2085 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE
:
2086 return (1ull << getArg()) / sizeof(uint16_t) + 1;
2087 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA
:
2094 void Arm64XRelocRef::moveNext() {
2095 Index
+= getEntrySize();
2096 if (sizeof(*Header
) + Index
* sizeof(uint16_t) < Header
->BlockSize
&&
2098 ++Index
; // Skip padding
2099 if (sizeof(*Header
) + Index
* sizeof(uint16_t) == Header
->BlockSize
) {
2100 // The end of the block, move to the next one.
2102 reinterpret_cast<const coff_base_reloc_block_header
*>(&getReloc());
2107 uint8_t Arm64XRelocRef::getSize() const {
2108 switch (getType()) {
2109 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL
:
2110 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE
:
2111 return 1 << getArg();
2112 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA
:
2113 return sizeof(uint32_t);
2115 llvm_unreachable("Unknown Arm64XFixupType enum");
2118 uint64_t Arm64XRelocRef::getValue() const {
2119 auto Ptr
= reinterpret_cast<const ulittle16_t
*>(Header
+ 1) + Index
+ 1;
2121 switch (getType()) {
2122 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE
: {
2123 ulittle64_t
Value(0);
2124 memcpy(&Value
, Ptr
, getSize());
2127 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA
: {
2128 uint16_t arg
= getArg();
2133 delta
*= (arg
& 2) ? 8 : 4;
2141 Error
Arm64XRelocRef::validate(const COFFObjectFile
*Obj
) const {
2143 const coff_dynamic_reloc_table
*Table
= Obj
->getDynamicRelocTable();
2144 size_t ContentsSize
= reinterpret_cast<const uint8_t *>(Table
+ 1) +
2146 reinterpret_cast<const uint8_t *>(Header
);
2147 if (ContentsSize
< sizeof(coff_base_reloc_block_header
))
2148 return createStringError(object_error::parse_failed
,
2149 "Unexpected end of ARM64X relocations data");
2150 if (Header
->BlockSize
<= sizeof(*Header
))
2151 return createStringError(object_error::parse_failed
,
2152 "ARM64X relocations block size (" +
2153 Twine(Header
->BlockSize
) + ") is too small");
2154 if (Header
->BlockSize
% sizeof(uint32_t))
2155 return createStringError(object_error::parse_failed
,
2156 "Unaligned ARM64X relocations block size (" +
2157 Twine(Header
->BlockSize
) + ")");
2158 if (Header
->BlockSize
> ContentsSize
)
2159 return createStringError(object_error::parse_failed
,
2160 "ARM64X relocations block size (" +
2161 Twine(Header
->BlockSize
) + ") is too large");
2162 if (Header
->PageRVA
& 0xfff)
2163 return createStringError(object_error::parse_failed
,
2164 "Unaligned ARM64X relocations page RVA (" +
2165 Twine(Header
->PageRVA
) + ")");
2168 switch ((getReloc() >> 12) & 3) {
2169 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL
:
2170 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA
:
2172 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE
:
2174 return createStringError(object_error::parse_failed
,
2175 "Invalid ARM64X relocation value size (0)");
2178 return createStringError(object_error::parse_failed
,
2179 "Invalid relocation type");
2182 uint32_t RelocsSize
=
2183 (Header
->BlockSize
- sizeof(*Header
)) / sizeof(uint16_t);
2184 uint16_t EntrySize
= getEntrySize();
2186 (Index
+ EntrySize
+ 1 < RelocsSize
&& !getReloc(EntrySize
)))
2187 return createStringError(object_error::parse_failed
,
2188 "Unexpected ARM64X relocations terminator");
2189 if (Index
+ EntrySize
> RelocsSize
)
2190 return createStringError(object_error::parse_failed
,
2191 "Unexpected end of ARM64X relocations");
2192 if (getRVA() % getSize())
2193 return createStringError(object_error::parse_failed
,
2194 "Unaligned ARM64X relocation RVA (" +
2195 Twine(getRVA()) + ")");
2196 if (Header
->PageRVA
) {
2198 return Obj
->getRvaPtr(getRVA() + getSize(), IntPtr
, "ARM64X reloc");
2200 return Error::success();
2203 #define RETURN_IF_ERROR(Expr) \
2207 return std::move(E); \
2210 Expected
<ArrayRef
<UTF16
>>
2211 ResourceSectionRef::getDirStringAtOffset(uint32_t Offset
) {
2212 BinaryStreamReader Reader
= BinaryStreamReader(BBS
);
2213 Reader
.setOffset(Offset
);
2215 RETURN_IF_ERROR(Reader
.readInteger(Length
));
2216 ArrayRef
<UTF16
> RawDirString
;
2217 RETURN_IF_ERROR(Reader
.readArray(RawDirString
, Length
));
2218 return RawDirString
;
2221 Expected
<ArrayRef
<UTF16
>>
2222 ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry
&Entry
) {
2223 return getDirStringAtOffset(Entry
.Identifier
.getNameOffset());
2226 Expected
<const coff_resource_dir_table
&>
2227 ResourceSectionRef::getTableAtOffset(uint32_t Offset
) {
2228 const coff_resource_dir_table
*Table
= nullptr;
2230 BinaryStreamReader
Reader(BBS
);
2231 Reader
.setOffset(Offset
);
2232 RETURN_IF_ERROR(Reader
.readObject(Table
));
2233 assert(Table
!= nullptr);
2237 Expected
<const coff_resource_dir_entry
&>
2238 ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset
) {
2239 const coff_resource_dir_entry
*Entry
= nullptr;
2241 BinaryStreamReader
Reader(BBS
);
2242 Reader
.setOffset(Offset
);
2243 RETURN_IF_ERROR(Reader
.readObject(Entry
));
2244 assert(Entry
!= nullptr);
2248 Expected
<const coff_resource_data_entry
&>
2249 ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset
) {
2250 const coff_resource_data_entry
*Entry
= nullptr;
2252 BinaryStreamReader
Reader(BBS
);
2253 Reader
.setOffset(Offset
);
2254 RETURN_IF_ERROR(Reader
.readObject(Entry
));
2255 assert(Entry
!= nullptr);
2259 Expected
<const coff_resource_dir_table
&>
2260 ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry
&Entry
) {
2261 assert(Entry
.Offset
.isSubDir());
2262 return getTableAtOffset(Entry
.Offset
.value());
2265 Expected
<const coff_resource_data_entry
&>
2266 ResourceSectionRef::getEntryData(const coff_resource_dir_entry
&Entry
) {
2267 assert(!Entry
.Offset
.isSubDir());
2268 return getDataEntryAtOffset(Entry
.Offset
.value());
2271 Expected
<const coff_resource_dir_table
&> ResourceSectionRef::getBaseTable() {
2272 return getTableAtOffset(0);
2275 Expected
<const coff_resource_dir_entry
&>
2276 ResourceSectionRef::getTableEntry(const coff_resource_dir_table
&Table
,
2278 if (Index
>= (uint32_t)(Table
.NumberOfNameEntries
+ Table
.NumberOfIDEntries
))
2279 return createStringError(object_error::parse_failed
, "index out of range");
2280 const uint8_t *TablePtr
= reinterpret_cast<const uint8_t *>(&Table
);
2281 ptrdiff_t TableOffset
= TablePtr
- BBS
.data().data();
2282 return getTableEntryAtOffset(TableOffset
+ sizeof(Table
) +
2283 Index
* sizeof(coff_resource_dir_entry
));
2286 Error
ResourceSectionRef::load(const COFFObjectFile
*O
) {
2287 for (const SectionRef
&S
: O
->sections()) {
2288 Expected
<StringRef
> Name
= S
.getName();
2290 return Name
.takeError();
2292 if (*Name
== ".rsrc" || *Name
== ".rsrc$01")
2295 return createStringError(object_error::parse_failed
,
2296 "no resource section found");
2299 Error
ResourceSectionRef::load(const COFFObjectFile
*O
, const SectionRef
&S
) {
2302 Expected
<StringRef
> Contents
= Section
.getContents();
2304 return Contents
.takeError();
2305 BBS
= BinaryByteStream(*Contents
, llvm::endianness::little
);
2306 const coff_section
*COFFSect
= Obj
->getCOFFSection(Section
);
2307 ArrayRef
<coff_relocation
> OrigRelocs
= Obj
->getRelocations(COFFSect
);
2308 Relocs
.reserve(OrigRelocs
.size());
2309 for (const coff_relocation
&R
: OrigRelocs
)
2310 Relocs
.push_back(&R
);
2311 llvm::sort(Relocs
, [](const coff_relocation
*A
, const coff_relocation
*B
) {
2312 return A
->VirtualAddress
< B
->VirtualAddress
;
2314 return Error::success();
2318 ResourceSectionRef::getContents(const coff_resource_data_entry
&Entry
) {
2320 return createStringError(object_error::parse_failed
, "no object provided");
2322 // Find a potential relocation at the DataRVA field (first member of
2323 // the coff_resource_data_entry struct).
2324 const uint8_t *EntryPtr
= reinterpret_cast<const uint8_t *>(&Entry
);
2325 ptrdiff_t EntryOffset
= EntryPtr
- BBS
.data().data();
2326 coff_relocation RelocTarget
{ulittle32_t(EntryOffset
), ulittle32_t(0),
2328 auto RelocsForOffset
=
2329 std::equal_range(Relocs
.begin(), Relocs
.end(), &RelocTarget
,
2330 [](const coff_relocation
*A
, const coff_relocation
*B
) {
2331 return A
->VirtualAddress
< B
->VirtualAddress
;
2334 if (RelocsForOffset
.first
!= RelocsForOffset
.second
) {
2335 // We found a relocation with the right offset. Check that it does have
2336 // the expected type.
2337 const coff_relocation
&R
= **RelocsForOffset
.first
;
2339 switch (Obj
->getArch()) {
2341 RVAReloc
= COFF::IMAGE_REL_I386_DIR32NB
;
2343 case Triple::x86_64
:
2344 RVAReloc
= COFF::IMAGE_REL_AMD64_ADDR32NB
;
2347 RVAReloc
= COFF::IMAGE_REL_ARM_ADDR32NB
;
2349 case Triple::aarch64
:
2350 RVAReloc
= COFF::IMAGE_REL_ARM64_ADDR32NB
;
2353 return createStringError(object_error::parse_failed
,
2354 "unsupported architecture");
2356 if (R
.Type
!= RVAReloc
)
2357 return createStringError(object_error::parse_failed
,
2358 "unexpected relocation type");
2359 // Get the relocation's symbol
2360 Expected
<COFFSymbolRef
> Sym
= Obj
->getSymbol(R
.SymbolTableIndex
);
2362 return Sym
.takeError();
2363 // And the symbol's section
2364 Expected
<const coff_section
*> Section
=
2365 Obj
->getSection(Sym
->getSectionNumber());
2367 return Section
.takeError();
2368 // Add the initial value of DataRVA to the symbol's offset to find the
2369 // data it points at.
2370 uint64_t Offset
= Entry
.DataRVA
+ Sym
->getValue();
2371 ArrayRef
<uint8_t> Contents
;
2372 if (Error E
= Obj
->getSectionContents(*Section
, Contents
))
2374 if (Offset
+ Entry
.DataSize
> Contents
.size())
2375 return createStringError(object_error::parse_failed
,
2376 "data outside of section");
2377 // Return a reference to the data inside the section.
2378 return StringRef(reinterpret_cast<const char *>(Contents
.data()) + Offset
,
2381 // Relocatable objects need a relocation for the DataRVA field.
2382 if (Obj
->isRelocatableObject())
2383 return createStringError(object_error::parse_failed
,
2384 "no relocation found for DataRVA");
2386 // Locate the section that contains the address that DataRVA points at.
2387 uint64_t VA
= Entry
.DataRVA
+ Obj
->getImageBase();
2388 for (const SectionRef
&S
: Obj
->sections()) {
2389 if (VA
>= S
.getAddress() &&
2390 VA
+ Entry
.DataSize
<= S
.getAddress() + S
.getSize()) {
2391 uint64_t Offset
= VA
- S
.getAddress();
2392 Expected
<StringRef
> Contents
= S
.getContents();
2394 return Contents
.takeError();
2395 return Contents
->substr(Offset
, Entry
.DataSize
);
2398 return createStringError(object_error::parse_failed
,
2399 "address not found in image");