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/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/MemoryBufferRef.h"
28 #include "llvm/TargetParser/Triple.h"
36 #include <system_error>
39 using namespace object
;
41 using support::ulittle16_t
;
42 using support::ulittle32_t
;
43 using support::ulittle64_t
;
44 using support::little16_t
;
46 // Returns false if size is greater than the buffer size. And sets ec.
47 static bool checkSize(MemoryBufferRef M
, std::error_code
&EC
, uint64_t Size
) {
48 if (M
.getBufferSize() < Size
) {
49 EC
= object_error::unexpected_eof
;
55 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
56 // Returns unexpected_eof if error.
58 static Error
getObject(const T
*&Obj
, MemoryBufferRef M
, const void *Ptr
,
59 const uint64_t Size
= sizeof(T
)) {
60 uintptr_t Addr
= reinterpret_cast<uintptr_t>(Ptr
);
61 if (Error E
= Binary::checkOffset(M
, Addr
, Size
))
63 Obj
= reinterpret_cast<const T
*>(Addr
);
64 return Error::success();
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
, reinterpret_cast<uintptr_t>(Addr
), sizeof(*Addr
)));
108 // Verify that the symbol points to a valid entry in the symbol table.
110 reinterpret_cast<uintptr_t>(Addr
) - reinterpret_cast<uintptr_t>(base());
112 assert((Offset
- getPointerToSymbolTable()) % sizeof(coff_symbol_type
) == 0 &&
113 "Symbol did not point to the beginning of a symbol");
119 const coff_section
*COFFObjectFile::toSec(DataRefImpl Ref
) const {
120 const coff_section
*Addr
= reinterpret_cast<const coff_section
*>(Ref
.p
);
123 // Verify that the section points to a valid entry in the section table.
124 if (Addr
< SectionTable
|| Addr
>= (SectionTable
+ getNumberOfSections()))
125 report_fatal_error("Section was outside of section table.");
127 uintptr_t Offset
= reinterpret_cast<uintptr_t>(Addr
) -
128 reinterpret_cast<uintptr_t>(SectionTable
);
129 assert(Offset
% sizeof(coff_section
) == 0 &&
130 "Section did not point to the beginning of a section");
136 void COFFObjectFile::moveSymbolNext(DataRefImpl
&Ref
) const {
137 auto End
= reinterpret_cast<uintptr_t>(StringTable
);
139 const coff_symbol16
*Symb
= toSymb
<coff_symbol16
>(Ref
);
140 Symb
+= 1 + Symb
->NumberOfAuxSymbols
;
141 Ref
.p
= std::min(reinterpret_cast<uintptr_t>(Symb
), End
);
142 } else if (SymbolTable32
) {
143 const coff_symbol32
*Symb
= toSymb
<coff_symbol32
>(Ref
);
144 Symb
+= 1 + Symb
->NumberOfAuxSymbols
;
145 Ref
.p
= std::min(reinterpret_cast<uintptr_t>(Symb
), End
);
147 llvm_unreachable("no symbol table pointer!");
151 Expected
<StringRef
> COFFObjectFile::getSymbolName(DataRefImpl Ref
) const {
152 return getSymbolName(getCOFFSymbol(Ref
));
155 uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref
) const {
156 return getCOFFSymbol(Ref
).getValue();
159 uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref
) const {
160 // MSVC/link.exe seems to align symbols to the next-power-of-2
162 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
163 return std::min(uint64_t(32), PowerOf2Ceil(Symb
.getValue()));
166 Expected
<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref
) const {
167 uint64_t Result
= cantFail(getSymbolValue(Ref
));
168 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
169 int32_t SectionNumber
= Symb
.getSectionNumber();
171 if (Symb
.isAnyUndefined() || Symb
.isCommon() ||
172 COFF::isReservedSectionNumber(SectionNumber
))
175 Expected
<const coff_section
*> Section
= getSection(SectionNumber
);
177 return Section
.takeError();
178 Result
+= (*Section
)->VirtualAddress
;
180 // The section VirtualAddress does not include ImageBase, and we want to
181 // return virtual addresses.
182 Result
+= getImageBase();
187 Expected
<SymbolRef::Type
> COFFObjectFile::getSymbolType(DataRefImpl Ref
) const {
188 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
189 int32_t SectionNumber
= Symb
.getSectionNumber();
191 if (Symb
.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION
)
192 return SymbolRef::ST_Function
;
193 if (Symb
.isAnyUndefined())
194 return SymbolRef::ST_Unknown
;
196 return SymbolRef::ST_Data
;
197 if (Symb
.isFileRecord())
198 return SymbolRef::ST_File
;
200 // TODO: perhaps we need a new symbol type ST_Section.
201 if (SectionNumber
== COFF::IMAGE_SYM_DEBUG
|| Symb
.isSectionDefinition())
202 return SymbolRef::ST_Debug
;
204 if (!COFF::isReservedSectionNumber(SectionNumber
))
205 return SymbolRef::ST_Data
;
207 return SymbolRef::ST_Other
;
210 Expected
<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref
) const {
211 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
212 uint32_t Result
= SymbolRef::SF_None
;
214 if (Symb
.isExternal() || Symb
.isWeakExternal())
215 Result
|= SymbolRef::SF_Global
;
217 if (const coff_aux_weak_external
*AWE
= Symb
.getWeakExternal()) {
218 Result
|= SymbolRef::SF_Weak
;
219 if (AWE
->Characteristics
!= COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
)
220 Result
|= SymbolRef::SF_Undefined
;
223 if (Symb
.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE
)
224 Result
|= SymbolRef::SF_Absolute
;
226 if (Symb
.isFileRecord())
227 Result
|= SymbolRef::SF_FormatSpecific
;
229 if (Symb
.isSectionDefinition())
230 Result
|= SymbolRef::SF_FormatSpecific
;
233 Result
|= SymbolRef::SF_Common
;
235 if (Symb
.isUndefined())
236 Result
|= SymbolRef::SF_Undefined
;
241 uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref
) const {
242 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
243 return Symb
.getValue();
246 Expected
<section_iterator
>
247 COFFObjectFile::getSymbolSection(DataRefImpl Ref
) const {
248 COFFSymbolRef Symb
= getCOFFSymbol(Ref
);
249 if (COFF::isReservedSectionNumber(Symb
.getSectionNumber()))
250 return section_end();
251 Expected
<const coff_section
*> Sec
= getSection(Symb
.getSectionNumber());
253 return Sec
.takeError();
255 Ret
.p
= reinterpret_cast<uintptr_t>(*Sec
);
256 return section_iterator(SectionRef(Ret
, this));
259 unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym
) const {
260 COFFSymbolRef Symb
= getCOFFSymbol(Sym
.getRawDataRefImpl());
261 return Symb
.getSectionNumber();
264 void COFFObjectFile::moveSectionNext(DataRefImpl
&Ref
) const {
265 const coff_section
*Sec
= toSec(Ref
);
267 Ref
.p
= reinterpret_cast<uintptr_t>(Sec
);
270 Expected
<StringRef
> COFFObjectFile::getSectionName(DataRefImpl Ref
) const {
271 const coff_section
*Sec
= toSec(Ref
);
272 return getSectionName(Sec
);
275 uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref
) const {
276 const coff_section
*Sec
= toSec(Ref
);
277 uint64_t Result
= Sec
->VirtualAddress
;
279 // The section VirtualAddress does not include ImageBase, and we want to
280 // return virtual addresses.
281 Result
+= getImageBase();
285 uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec
) const {
286 return toSec(Sec
) - SectionTable
;
289 uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref
) const {
290 return getSectionSize(toSec(Ref
));
293 Expected
<ArrayRef
<uint8_t>>
294 COFFObjectFile::getSectionContents(DataRefImpl Ref
) const {
295 const coff_section
*Sec
= toSec(Ref
);
296 ArrayRef
<uint8_t> Res
;
297 if (Error E
= getSectionContents(Sec
, Res
))
302 uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref
) const {
303 const coff_section
*Sec
= toSec(Ref
);
304 return Sec
->getAlignment();
307 bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec
) const {
311 bool COFFObjectFile::isSectionText(DataRefImpl Ref
) const {
312 const coff_section
*Sec
= toSec(Ref
);
313 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_CODE
;
316 bool COFFObjectFile::isSectionData(DataRefImpl Ref
) const {
317 const coff_section
*Sec
= toSec(Ref
);
318 return Sec
->Characteristics
& COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
;
321 bool COFFObjectFile::isSectionBSS(DataRefImpl Ref
) const {
322 const coff_section
*Sec
= toSec(Ref
);
323 const uint32_t BssFlags
= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
324 COFF::IMAGE_SCN_MEM_READ
|
325 COFF::IMAGE_SCN_MEM_WRITE
;
326 return (Sec
->Characteristics
& BssFlags
) == BssFlags
;
329 // The .debug sections are the only debug sections for COFF
330 // (\see MCObjectFileInfo.cpp).
331 bool COFFObjectFile::isDebugSection(DataRefImpl Ref
) const {
332 Expected
<StringRef
> SectionNameOrErr
= getSectionName(Ref
);
333 if (!SectionNameOrErr
) {
334 // TODO: Report the error message properly.
335 consumeError(SectionNameOrErr
.takeError());
338 StringRef SectionName
= SectionNameOrErr
.get();
339 return SectionName
.startswith(".debug");
342 unsigned COFFObjectFile::getSectionID(SectionRef Sec
) const {
344 Sec
.getRawDataRefImpl().p
- reinterpret_cast<uintptr_t>(SectionTable
);
345 assert((Offset
% sizeof(coff_section
)) == 0);
346 return (Offset
/ sizeof(coff_section
)) + 1;
349 bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref
) const {
350 const coff_section
*Sec
= toSec(Ref
);
351 // In COFF, a virtual section won't have any in-file
352 // content, so the file pointer to the content will be zero.
353 return Sec
->PointerToRawData
== 0;
356 static uint32_t getNumberOfRelocations(const coff_section
*Sec
,
357 MemoryBufferRef M
, const uint8_t *base
) {
358 // The field for the number of relocations in COFF section table is only
359 // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
360 // NumberOfRelocations field, and the actual relocation count is stored in the
361 // VirtualAddress field in the first relocation entry.
362 if (Sec
->hasExtendedRelocations()) {
363 const coff_relocation
*FirstReloc
;
364 if (Error E
= getObject(FirstReloc
, M
,
365 reinterpret_cast<const coff_relocation
*>(
366 base
+ Sec
->PointerToRelocations
))) {
367 consumeError(std::move(E
));
370 // -1 to exclude this first relocation entry.
371 return FirstReloc
->VirtualAddress
- 1;
373 return Sec
->NumberOfRelocations
;
376 static const coff_relocation
*
377 getFirstReloc(const coff_section
*Sec
, MemoryBufferRef M
, const uint8_t *Base
) {
378 uint64_t NumRelocs
= getNumberOfRelocations(Sec
, M
, Base
);
381 auto begin
= reinterpret_cast<const coff_relocation
*>(
382 Base
+ Sec
->PointerToRelocations
);
383 if (Sec
->hasExtendedRelocations()) {
384 // Skip the first relocation entry repurposed to store the number of
388 if (auto E
= Binary::checkOffset(M
, reinterpret_cast<uintptr_t>(begin
),
389 sizeof(coff_relocation
) * NumRelocs
)) {
390 consumeError(std::move(E
));
396 relocation_iterator
COFFObjectFile::section_rel_begin(DataRefImpl Ref
) const {
397 const coff_section
*Sec
= toSec(Ref
);
398 const coff_relocation
*begin
= getFirstReloc(Sec
, Data
, base());
399 if (begin
&& Sec
->VirtualAddress
!= 0)
400 report_fatal_error("Sections with relocations should have an address of 0");
402 Ret
.p
= reinterpret_cast<uintptr_t>(begin
);
403 return relocation_iterator(RelocationRef(Ret
, this));
406 relocation_iterator
COFFObjectFile::section_rel_end(DataRefImpl Ref
) const {
407 const coff_section
*Sec
= toSec(Ref
);
408 const coff_relocation
*I
= getFirstReloc(Sec
, Data
, base());
410 I
+= getNumberOfRelocations(Sec
, Data
, base());
412 Ret
.p
= reinterpret_cast<uintptr_t>(I
);
413 return relocation_iterator(RelocationRef(Ret
, this));
416 // Initialize the pointer to the symbol table.
417 Error
COFFObjectFile::initSymbolTablePtr() {
419 if (Error E
= getObject(
420 SymbolTable16
, Data
, base() + getPointerToSymbolTable(),
421 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
424 if (COFFBigObjHeader
)
425 if (Error E
= getObject(
426 SymbolTable32
, Data
, base() + getPointerToSymbolTable(),
427 (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
430 // Find string table. The first four byte of the string table contains the
431 // total size of the string table, including the size field itself. If the
432 // string table is empty, the value of the first four byte would be 4.
433 uint32_t StringTableOffset
= getPointerToSymbolTable() +
434 getNumberOfSymbols() * getSymbolTableEntrySize();
435 const uint8_t *StringTableAddr
= base() + StringTableOffset
;
436 const ulittle32_t
*StringTableSizePtr
;
437 if (Error E
= getObject(StringTableSizePtr
, Data
, StringTableAddr
))
439 StringTableSize
= *StringTableSizePtr
;
440 if (Error E
= getObject(StringTable
, Data
, StringTableAddr
, StringTableSize
))
443 // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
444 // tools like cvtres write a size of 0 for an empty table instead of 4.
445 if (StringTableSize
< 4)
448 // Check that the string table is null terminated if has any in it.
449 if (StringTableSize
> 4 && StringTable
[StringTableSize
- 1] != 0)
450 return createStringError(object_error::parse_failed
,
451 "string table missing null terminator");
452 return Error::success();
455 uint64_t COFFObjectFile::getImageBase() const {
457 return PE32Header
->ImageBase
;
458 else if (PE32PlusHeader
)
459 return PE32PlusHeader
->ImageBase
;
460 // This actually comes up in practice.
464 // Returns the file offset for the given VA.
465 Error
COFFObjectFile::getVaPtr(uint64_t Addr
, uintptr_t &Res
) const {
466 uint64_t ImageBase
= getImageBase();
467 uint64_t Rva
= Addr
- ImageBase
;
468 assert(Rva
<= UINT32_MAX
);
469 return getRvaPtr((uint32_t)Rva
, Res
);
472 // Returns the file offset for the given RVA.
473 Error
COFFObjectFile::getRvaPtr(uint32_t Addr
, uintptr_t &Res
,
474 const char *ErrorContext
) const {
475 for (const SectionRef
&S
: sections()) {
476 const coff_section
*Section
= getCOFFSection(S
);
477 uint32_t SectionStart
= Section
->VirtualAddress
;
478 uint32_t SectionEnd
= Section
->VirtualAddress
+ Section
->VirtualSize
;
479 if (SectionStart
<= Addr
&& Addr
< SectionEnd
) {
480 // A table/directory entry can be pointing to somewhere in a stripped
481 // section, in an object that went through `objcopy --only-keep-debug`.
482 // In this case we don't want to cause the parsing of the object file to
483 // fail, otherwise it will be impossible to use this object as debug info
484 // in LLDB. Return SectionStrippedError here so that
485 // COFFObjectFile::initialize can ignore the error.
486 // Somewhat common binaries may have RVAs pointing outside of the
487 // provided raw data. Instead of rejecting the binaries, just
488 // treat the section as stripped for these purposes.
489 if (Section
->SizeOfRawData
< Section
->VirtualSize
&&
490 Addr
>= SectionStart
+ Section
->SizeOfRawData
) {
491 return make_error
<SectionStrippedError
>();
493 uint32_t Offset
= Addr
- SectionStart
;
494 Res
= reinterpret_cast<uintptr_t>(base()) + Section
->PointerToRawData
+
496 return Error::success();
500 return createStringError(object_error::parse_failed
,
501 "RVA 0x%" PRIx32
" for %s not found", Addr
,
503 return createStringError(object_error::parse_failed
,
504 "RVA 0x%" PRIx32
" not found", Addr
);
507 Error
COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA
, uint32_t Size
,
508 ArrayRef
<uint8_t> &Contents
,
509 const char *ErrorContext
) const {
510 for (const SectionRef
&S
: sections()) {
511 const coff_section
*Section
= getCOFFSection(S
);
512 uint32_t SectionStart
= Section
->VirtualAddress
;
513 // Check if this RVA is within the section bounds. Be careful about integer
515 uint32_t OffsetIntoSection
= RVA
- SectionStart
;
516 if (SectionStart
<= RVA
&& OffsetIntoSection
< Section
->VirtualSize
&&
517 Size
<= Section
->VirtualSize
- OffsetIntoSection
) {
518 uintptr_t Begin
= reinterpret_cast<uintptr_t>(base()) +
519 Section
->PointerToRawData
+ OffsetIntoSection
;
521 ArrayRef
<uint8_t>(reinterpret_cast<const uint8_t *>(Begin
), Size
);
522 return Error::success();
526 return createStringError(object_error::parse_failed
,
527 "RVA 0x%" PRIx32
" for %s not found", RVA
,
529 return createStringError(object_error::parse_failed
,
530 "RVA 0x%" PRIx32
" not found", RVA
);
533 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
535 Error
COFFObjectFile::getHintName(uint32_t Rva
, uint16_t &Hint
,
536 StringRef
&Name
) const {
537 uintptr_t IntPtr
= 0;
538 if (Error E
= getRvaPtr(Rva
, IntPtr
))
540 const uint8_t *Ptr
= reinterpret_cast<const uint8_t *>(IntPtr
);
541 Hint
= *reinterpret_cast<const ulittle16_t
*>(Ptr
);
542 Name
= StringRef(reinterpret_cast<const char *>(Ptr
+ 2));
543 return Error::success();
546 Error
COFFObjectFile::getDebugPDBInfo(const debug_directory
*DebugDir
,
547 const codeview::DebugInfo
*&PDBInfo
,
548 StringRef
&PDBFileName
) const {
549 ArrayRef
<uint8_t> InfoBytes
;
551 getRvaAndSizeAsBytes(DebugDir
->AddressOfRawData
, DebugDir
->SizeOfData
,
552 InfoBytes
, "PDB info"))
554 if (InfoBytes
.size() < sizeof(*PDBInfo
) + 1)
555 return createStringError(object_error::parse_failed
, "PDB info too small");
556 PDBInfo
= reinterpret_cast<const codeview::DebugInfo
*>(InfoBytes
.data());
557 InfoBytes
= InfoBytes
.drop_front(sizeof(*PDBInfo
));
558 PDBFileName
= StringRef(reinterpret_cast<const char *>(InfoBytes
.data()),
560 // Truncate the name at the first null byte. Ignore any padding.
561 PDBFileName
= PDBFileName
.split('\0').first
;
562 return Error::success();
565 Error
COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo
*&PDBInfo
,
566 StringRef
&PDBFileName
) const {
567 for (const debug_directory
&D
: debug_directories())
568 if (D
.Type
== COFF::IMAGE_DEBUG_TYPE_CODEVIEW
)
569 return getDebugPDBInfo(&D
, PDBInfo
, PDBFileName
);
570 // If we get here, there is no PDB info to return.
572 PDBFileName
= StringRef();
573 return Error::success();
576 // Find the import table.
577 Error
COFFObjectFile::initImportTablePtr() {
578 // First, we get the RVA of the import table. If the file lacks a pointer to
579 // the import table, do nothing.
580 const data_directory
*DataEntry
= getDataDirectory(COFF::IMPORT_TABLE
);
582 return Error::success();
584 // Do nothing if the pointer to import table is NULL.
585 if (DataEntry
->RelativeVirtualAddress
== 0)
586 return Error::success();
588 uint32_t ImportTableRva
= DataEntry
->RelativeVirtualAddress
;
590 // Find the section that contains the RVA. This is needed because the RVA is
591 // the import table's memory address which is different from its file offset.
592 uintptr_t IntPtr
= 0;
593 if (Error E
= getRvaPtr(ImportTableRva
, IntPtr
, "import table"))
595 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
597 ImportDirectory
= reinterpret_cast<
598 const coff_import_directory_table_entry
*>(IntPtr
);
599 return Error::success();
602 // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
603 Error
COFFObjectFile::initDelayImportTablePtr() {
604 const data_directory
*DataEntry
=
605 getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR
);
607 return Error::success();
608 if (DataEntry
->RelativeVirtualAddress
== 0)
609 return Error::success();
611 uint32_t RVA
= DataEntry
->RelativeVirtualAddress
;
612 NumberOfDelayImportDirectory
= DataEntry
->Size
/
613 sizeof(delay_import_directory_table_entry
) - 1;
615 uintptr_t IntPtr
= 0;
616 if (Error E
= getRvaPtr(RVA
, IntPtr
, "delay import table"))
618 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
621 DelayImportDirectory
= reinterpret_cast<
622 const delay_import_directory_table_entry
*>(IntPtr
);
623 return Error::success();
626 // Find the export table.
627 Error
COFFObjectFile::initExportTablePtr() {
628 // First, we get the RVA of the export table. If the file lacks a pointer to
629 // the export table, do nothing.
630 const data_directory
*DataEntry
= getDataDirectory(COFF::EXPORT_TABLE
);
632 return Error::success();
634 // Do nothing if the pointer to export table is NULL.
635 if (DataEntry
->RelativeVirtualAddress
== 0)
636 return Error::success();
638 uint32_t ExportTableRva
= DataEntry
->RelativeVirtualAddress
;
639 uintptr_t IntPtr
= 0;
640 if (Error E
= getRvaPtr(ExportTableRva
, IntPtr
, "export table"))
642 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
646 reinterpret_cast<const export_directory_table_entry
*>(IntPtr
);
647 return Error::success();
650 Error
COFFObjectFile::initBaseRelocPtr() {
651 const data_directory
*DataEntry
=
652 getDataDirectory(COFF::BASE_RELOCATION_TABLE
);
654 return Error::success();
655 if (DataEntry
->RelativeVirtualAddress
== 0)
656 return Error::success();
658 uintptr_t IntPtr
= 0;
659 if (Error E
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
,
662 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
665 BaseRelocHeader
= reinterpret_cast<const coff_base_reloc_block_header
*>(
667 BaseRelocEnd
= reinterpret_cast<coff_base_reloc_block_header
*>(
668 IntPtr
+ DataEntry
->Size
);
669 // FIXME: Verify the section containing BaseRelocHeader has at least
670 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
671 return Error::success();
674 Error
COFFObjectFile::initDebugDirectoryPtr() {
675 // Get the RVA of the debug directory. Do nothing if it does not exist.
676 const data_directory
*DataEntry
= getDataDirectory(COFF::DEBUG_DIRECTORY
);
678 return Error::success();
680 // Do nothing if the RVA is NULL.
681 if (DataEntry
->RelativeVirtualAddress
== 0)
682 return Error::success();
684 // Check that the size is a multiple of the entry size.
685 if (DataEntry
->Size
% sizeof(debug_directory
) != 0)
686 return createStringError(object_error::parse_failed
,
687 "debug directory has uneven size");
689 uintptr_t IntPtr
= 0;
690 if (Error E
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
,
693 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
696 DebugDirectoryBegin
= reinterpret_cast<const debug_directory
*>(IntPtr
);
697 DebugDirectoryEnd
= reinterpret_cast<const debug_directory
*>(
698 IntPtr
+ DataEntry
->Size
);
699 // FIXME: Verify the section containing DebugDirectoryBegin has at least
700 // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
701 return Error::success();
704 Error
COFFObjectFile::initTLSDirectoryPtr() {
705 // Get the RVA of the TLS directory. Do nothing if it does not exist.
706 const data_directory
*DataEntry
= getDataDirectory(COFF::TLS_TABLE
);
708 return Error::success();
710 // Do nothing if the RVA is NULL.
711 if (DataEntry
->RelativeVirtualAddress
== 0)
712 return Error::success();
715 is64() ? sizeof(coff_tls_directory64
) : sizeof(coff_tls_directory32
);
717 // Check that the size is correct.
718 if (DataEntry
->Size
!= DirSize
)
719 return createStringError(
720 object_error::parse_failed
,
721 "TLS Directory size (%u) is not the expected size (%" PRIu64
").",
722 static_cast<uint32_t>(DataEntry
->Size
), DirSize
);
724 uintptr_t IntPtr
= 0;
726 getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
, "TLS directory"))
728 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
732 TLSDirectory64
= reinterpret_cast<const coff_tls_directory64
*>(IntPtr
);
734 TLSDirectory32
= reinterpret_cast<const coff_tls_directory32
*>(IntPtr
);
736 return Error::success();
739 Error
COFFObjectFile::initLoadConfigPtr() {
740 // Get the RVA of the debug directory. Do nothing if it does not exist.
741 const data_directory
*DataEntry
= getDataDirectory(COFF::LOAD_CONFIG_TABLE
);
743 return Error::success();
745 // Do nothing if the RVA is NULL.
746 if (DataEntry
->RelativeVirtualAddress
== 0)
747 return Error::success();
748 uintptr_t IntPtr
= 0;
749 if (Error E
= getRvaPtr(DataEntry
->RelativeVirtualAddress
, IntPtr
,
750 "load config table"))
752 if (Error E
= checkOffset(Data
, IntPtr
, DataEntry
->Size
))
755 LoadConfig
= (const void *)IntPtr
;
758 auto Config
= getLoadConfig64();
760 offsetof(coff_load_configuration64
, CHPEMetadataPointer
) +
761 sizeof(Config
->CHPEMetadataPointer
) &&
762 Config
->CHPEMetadataPointer
) {
763 uint64_t ChpeOff
= Config
->CHPEMetadataPointer
;
765 getRvaPtr(ChpeOff
- getImageBase(), IntPtr
, "CHPE metadata"))
767 if (Error E
= checkOffset(Data
, IntPtr
, sizeof(CHPEMetadata
)))
770 CHPEMetadata
= reinterpret_cast<const chpe_metadata
*>(IntPtr
);
772 // Validate CHPE metadata
773 if (CHPEMetadata
->CodeMapCount
) {
774 if (Error E
= getRvaPtr(CHPEMetadata
->CodeMap
, IntPtr
, "CHPE code map"))
776 if (Error E
= checkOffset(Data
, IntPtr
,
777 CHPEMetadata
->CodeMapCount
*
778 sizeof(chpe_range_entry
)))
782 if (CHPEMetadata
->CodeRangesToEntryPointsCount
) {
783 if (Error E
= getRvaPtr(CHPEMetadata
->CodeRangesToEntryPoints
, IntPtr
,
784 "CHPE entry point ranges"))
786 if (Error E
= checkOffset(Data
, IntPtr
,
787 CHPEMetadata
->CodeRangesToEntryPointsCount
*
788 sizeof(chpe_code_range_entry
)))
792 if (CHPEMetadata
->RedirectionMetadataCount
) {
793 if (Error E
= getRvaPtr(CHPEMetadata
->RedirectionMetadata
, IntPtr
,
794 "CHPE redirection metadata"))
796 if (Error E
= checkOffset(Data
, IntPtr
,
797 CHPEMetadata
->RedirectionMetadataCount
*
798 sizeof(chpe_redirection_entry
)))
804 return Error::success();
807 Expected
<std::unique_ptr
<COFFObjectFile
>>
808 COFFObjectFile::create(MemoryBufferRef Object
) {
809 std::unique_ptr
<COFFObjectFile
> Obj(new COFFObjectFile(std::move(Object
)));
810 if (Error E
= Obj
->initialize())
812 return std::move(Obj
);
815 COFFObjectFile::COFFObjectFile(MemoryBufferRef Object
)
816 : ObjectFile(Binary::ID_COFF
, Object
), COFFHeader(nullptr),
817 COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
818 DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
819 SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
820 ImportDirectory(nullptr), DelayImportDirectory(nullptr),
821 NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
822 BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
823 DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
824 TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
826 static Error
ignoreStrippedErrors(Error E
) {
827 if (E
.isA
<SectionStrippedError
>()) {
828 consumeError(std::move(E
));
829 return Error::success();
834 Error
COFFObjectFile::initialize() {
835 // Check that we at least have enough room for a header.
837 if (!checkSize(Data
, EC
, sizeof(coff_file_header
)))
838 return errorCodeToError(EC
);
840 // The current location in the file where we are looking at.
843 // PE header is optional and is present only in executables. If it exists,
844 // it is placed right after COFF header.
845 bool HasPEHeader
= false;
847 // Check if this is a PE/COFF file.
848 if (checkSize(Data
, EC
, sizeof(dos_header
) + sizeof(COFF::PEMagic
))) {
849 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
850 // PE signature to find 'normal' COFF header.
851 const auto *DH
= reinterpret_cast<const dos_header
*>(base());
852 if (DH
->Magic
[0] == 'M' && DH
->Magic
[1] == 'Z') {
853 CurPtr
= DH
->AddressOfNewExeHeader
;
854 // Check the PE magic bytes. ("PE\0\0")
855 if (memcmp(base() + CurPtr
, COFF::PEMagic
, sizeof(COFF::PEMagic
)) != 0) {
856 return createStringError(object_error::parse_failed
,
857 "incorrect PE magic");
859 CurPtr
+= sizeof(COFF::PEMagic
); // Skip the PE magic bytes.
864 if (Error E
= getObject(COFFHeader
, Data
, base() + CurPtr
))
867 // It might be a bigobj file, let's check. Note that COFF bigobj and COFF
868 // import libraries share a common prefix but bigobj is more restrictive.
869 if (!HasPEHeader
&& COFFHeader
->Machine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
&&
870 COFFHeader
->NumberOfSections
== uint16_t(0xffff) &&
871 checkSize(Data
, EC
, sizeof(coff_bigobj_file_header
))) {
872 if (Error E
= getObject(COFFBigObjHeader
, Data
, base() + CurPtr
))
875 // Verify that we are dealing with bigobj.
876 if (COFFBigObjHeader
->Version
>= COFF::BigObjHeader::MinBigObjectVersion
&&
877 std::memcmp(COFFBigObjHeader
->UUID
, COFF::BigObjMagic
,
878 sizeof(COFF::BigObjMagic
)) == 0) {
879 COFFHeader
= nullptr;
880 CurPtr
+= sizeof(coff_bigobj_file_header
);
882 // It's not a bigobj.
883 COFFBigObjHeader
= nullptr;
887 // The prior checkSize call may have failed. This isn't a hard error
888 // because we were just trying to sniff out bigobj.
889 EC
= std::error_code();
890 CurPtr
+= sizeof(coff_file_header
);
892 if (COFFHeader
->isImportLibrary())
893 return errorCodeToError(EC
);
897 const pe32_header
*Header
;
898 if (Error E
= getObject(Header
, Data
, base() + CurPtr
))
901 const uint8_t *DataDirAddr
;
902 uint64_t DataDirSize
;
903 if (Header
->Magic
== COFF::PE32Header::PE32
) {
905 DataDirAddr
= base() + CurPtr
+ sizeof(pe32_header
);
906 DataDirSize
= sizeof(data_directory
) * PE32Header
->NumberOfRvaAndSize
;
907 } else if (Header
->Magic
== COFF::PE32Header::PE32_PLUS
) {
908 PE32PlusHeader
= reinterpret_cast<const pe32plus_header
*>(Header
);
909 DataDirAddr
= base() + CurPtr
+ sizeof(pe32plus_header
);
910 DataDirSize
= sizeof(data_directory
) * PE32PlusHeader
->NumberOfRvaAndSize
;
912 // It's neither PE32 nor PE32+.
913 return createStringError(object_error::parse_failed
,
914 "incorrect PE magic");
916 if (Error E
= getObject(DataDirectory
, Data
, DataDirAddr
, DataDirSize
))
921 CurPtr
+= COFFHeader
->SizeOfOptionalHeader
;
923 assert(COFFHeader
|| COFFBigObjHeader
);
926 getObject(SectionTable
, Data
, base() + CurPtr
,
927 (uint64_t)getNumberOfSections() * sizeof(coff_section
)))
930 // Initialize the pointer to the symbol table.
931 if (getPointerToSymbolTable() != 0) {
932 if (Error E
= initSymbolTablePtr()) {
933 // Recover from errors reading the symbol table.
934 consumeError(std::move(E
));
935 SymbolTable16
= nullptr;
936 SymbolTable32
= nullptr;
937 StringTable
= nullptr;
941 // We had better not have any symbols if we don't have a symbol table.
942 if (getNumberOfSymbols() != 0) {
943 return createStringError(object_error::parse_failed
,
944 "symbol table missing");
948 // Initialize the pointer to the beginning of the import table.
949 if (Error E
= ignoreStrippedErrors(initImportTablePtr()))
951 if (Error E
= ignoreStrippedErrors(initDelayImportTablePtr()))
954 // Initialize the pointer to the export table.
955 if (Error E
= ignoreStrippedErrors(initExportTablePtr()))
958 // Initialize the pointer to the base relocation table.
959 if (Error E
= ignoreStrippedErrors(initBaseRelocPtr()))
962 // Initialize the pointer to the debug directory.
963 if (Error E
= ignoreStrippedErrors(initDebugDirectoryPtr()))
966 // Initialize the pointer to the TLS directory.
967 if (Error E
= ignoreStrippedErrors(initTLSDirectoryPtr()))
970 if (Error E
= ignoreStrippedErrors(initLoadConfigPtr()))
973 return Error::success();
976 basic_symbol_iterator
COFFObjectFile::symbol_begin() const {
978 Ret
.p
= getSymbolTable();
979 return basic_symbol_iterator(SymbolRef(Ret
, this));
982 basic_symbol_iterator
COFFObjectFile::symbol_end() const {
983 // The symbol table ends where the string table begins.
985 Ret
.p
= reinterpret_cast<uintptr_t>(StringTable
);
986 return basic_symbol_iterator(SymbolRef(Ret
, this));
989 import_directory_iterator
COFFObjectFile::import_directory_begin() const {
990 if (!ImportDirectory
)
991 return import_directory_end();
992 if (ImportDirectory
->isNull())
993 return import_directory_end();
994 return import_directory_iterator(
995 ImportDirectoryEntryRef(ImportDirectory
, 0, this));
998 import_directory_iterator
COFFObjectFile::import_directory_end() const {
999 return import_directory_iterator(
1000 ImportDirectoryEntryRef(nullptr, -1, this));
1003 delay_import_directory_iterator
1004 COFFObjectFile::delay_import_directory_begin() const {
1005 return delay_import_directory_iterator(
1006 DelayImportDirectoryEntryRef(DelayImportDirectory
, 0, this));
1009 delay_import_directory_iterator
1010 COFFObjectFile::delay_import_directory_end() const {
1011 return delay_import_directory_iterator(
1012 DelayImportDirectoryEntryRef(
1013 DelayImportDirectory
, NumberOfDelayImportDirectory
, this));
1016 export_directory_iterator
COFFObjectFile::export_directory_begin() const {
1017 return export_directory_iterator(
1018 ExportDirectoryEntryRef(ExportDirectory
, 0, this));
1021 export_directory_iterator
COFFObjectFile::export_directory_end() const {
1022 if (!ExportDirectory
)
1023 return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
1024 ExportDirectoryEntryRef
Ref(ExportDirectory
,
1025 ExportDirectory
->AddressTableEntries
, this);
1026 return export_directory_iterator(Ref
);
1029 section_iterator
COFFObjectFile::section_begin() const {
1031 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
);
1032 return section_iterator(SectionRef(Ret
, this));
1035 section_iterator
COFFObjectFile::section_end() const {
1038 COFFHeader
&& COFFHeader
->isImportLibrary() ? 0 : getNumberOfSections();
1039 Ret
.p
= reinterpret_cast<uintptr_t>(SectionTable
+ NumSections
);
1040 return section_iterator(SectionRef(Ret
, this));
1043 base_reloc_iterator
COFFObjectFile::base_reloc_begin() const {
1044 return base_reloc_iterator(BaseRelocRef(BaseRelocHeader
, this));
1047 base_reloc_iterator
COFFObjectFile::base_reloc_end() const {
1048 return base_reloc_iterator(BaseRelocRef(BaseRelocEnd
, this));
1051 uint8_t COFFObjectFile::getBytesInAddress() const {
1052 return getArch() == Triple::x86_64
|| getArch() == Triple::aarch64
? 8 : 4;
1055 StringRef
COFFObjectFile::getFileFormatName() const {
1056 switch(getMachine()) {
1057 case COFF::IMAGE_FILE_MACHINE_I386
:
1059 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1060 return "COFF-x86-64";
1061 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1063 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1064 return "COFF-ARM64";
1065 case COFF::IMAGE_FILE_MACHINE_ARM64EC
:
1066 return "COFF-ARM64EC";
1067 case COFF::IMAGE_FILE_MACHINE_ARM64X
:
1068 return "COFF-ARM64X";
1070 return "COFF-<unknown arch>";
1074 Triple::ArchType
COFFObjectFile::getArch() const {
1075 switch (getMachine()) {
1076 case COFF::IMAGE_FILE_MACHINE_I386
:
1078 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1079 return Triple::x86_64
;
1080 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1081 return Triple::thumb
;
1082 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1083 case COFF::IMAGE_FILE_MACHINE_ARM64EC
:
1084 case COFF::IMAGE_FILE_MACHINE_ARM64X
:
1085 return Triple::aarch64
;
1087 return Triple::UnknownArch
;
1091 Expected
<uint64_t> COFFObjectFile::getStartAddress() const {
1093 return PE32Header
->AddressOfEntryPoint
;
1097 iterator_range
<import_directory_iterator
>
1098 COFFObjectFile::import_directories() const {
1099 return make_range(import_directory_begin(), import_directory_end());
1102 iterator_range
<delay_import_directory_iterator
>
1103 COFFObjectFile::delay_import_directories() const {
1104 return make_range(delay_import_directory_begin(),
1105 delay_import_directory_end());
1108 iterator_range
<export_directory_iterator
>
1109 COFFObjectFile::export_directories() const {
1110 return make_range(export_directory_begin(), export_directory_end());
1113 iterator_range
<base_reloc_iterator
> COFFObjectFile::base_relocs() const {
1114 return make_range(base_reloc_begin(), base_reloc_end());
1117 const data_directory
*COFFObjectFile::getDataDirectory(uint32_t Index
) const {
1120 assert(PE32Header
|| PE32PlusHeader
);
1121 uint32_t NumEnt
= PE32Header
? PE32Header
->NumberOfRvaAndSize
1122 : PE32PlusHeader
->NumberOfRvaAndSize
;
1123 if (Index
>= NumEnt
)
1125 return &DataDirectory
[Index
];
1128 Expected
<const coff_section
*> COFFObjectFile::getSection(int32_t Index
) const {
1129 // Perhaps getting the section of a reserved section index should be an error,
1130 // but callers rely on this to return null.
1131 if (COFF::isReservedSectionNumber(Index
))
1132 return (const coff_section
*)nullptr;
1133 if (static_cast<uint32_t>(Index
) <= getNumberOfSections()) {
1134 // We already verified the section table data, so no need to check again.
1135 return SectionTable
+ (Index
- 1);
1137 return createStringError(object_error::parse_failed
,
1138 "section index out of bounds");
1141 Expected
<StringRef
> COFFObjectFile::getString(uint32_t Offset
) const {
1142 if (StringTableSize
<= 4)
1143 // Tried to get a string from an empty string table.
1144 return createStringError(object_error::parse_failed
, "string table empty");
1145 if (Offset
>= StringTableSize
)
1146 return errorCodeToError(object_error::unexpected_eof
);
1147 return StringRef(StringTable
+ Offset
);
1150 Expected
<StringRef
> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol
) const {
1151 return getSymbolName(Symbol
.getGeneric());
1155 COFFObjectFile::getSymbolName(const coff_symbol_generic
*Symbol
) const {
1156 // Check for string table entry. First 4 bytes are 0.
1157 if (Symbol
->Name
.Offset
.Zeroes
== 0)
1158 return getString(Symbol
->Name
.Offset
.Offset
);
1160 // Null terminated, let ::strlen figure out the length.
1161 if (Symbol
->Name
.ShortName
[COFF::NameSize
- 1] == 0)
1162 return StringRef(Symbol
->Name
.ShortName
);
1164 // Not null terminated, use all 8 bytes.
1165 return StringRef(Symbol
->Name
.ShortName
, COFF::NameSize
);
1169 COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol
) const {
1170 const uint8_t *Aux
= nullptr;
1172 size_t SymbolSize
= getSymbolTableEntrySize();
1173 if (Symbol
.getNumberOfAuxSymbols() > 0) {
1174 // AUX data comes immediately after the symbol in COFF
1175 Aux
= reinterpret_cast<const uint8_t *>(Symbol
.getRawPtr()) + SymbolSize
;
1177 // Verify that the Aux symbol points to a valid entry in the symbol table.
1178 uintptr_t Offset
= uintptr_t(Aux
) - uintptr_t(base());
1179 if (Offset
< getPointerToSymbolTable() ||
1181 getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize
))
1182 report_fatal_error("Aux Symbol data was outside of symbol table.");
1184 assert((Offset
- getPointerToSymbolTable()) % SymbolSize
== 0 &&
1185 "Aux Symbol data did not point to the beginning of a symbol");
1188 return ArrayRef(Aux
, Symbol
.getNumberOfAuxSymbols() * SymbolSize
);
1191 uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol
) const {
1193 reinterpret_cast<uintptr_t>(Symbol
.getRawPtr()) - getSymbolTable();
1194 assert(Offset
% getSymbolTableEntrySize() == 0 &&
1195 "Symbol did not point to the beginning of a symbol");
1196 size_t Index
= Offset
/ getSymbolTableEntrySize();
1197 assert(Index
< getNumberOfSymbols());
1202 COFFObjectFile::getSectionName(const coff_section
*Sec
) const {
1203 StringRef Name
= StringRef(Sec
->Name
, COFF::NameSize
).split('\0').first
;
1205 // Check for string table entry. First byte is '/'.
1206 if (Name
.startswith("/")) {
1208 if (Name
.startswith("//")) {
1209 if (decodeBase64StringEntry(Name
.substr(2), Offset
))
1210 return createStringError(object_error::parse_failed
,
1211 "invalid section name");
1213 if (Name
.substr(1).getAsInteger(10, Offset
))
1214 return createStringError(object_error::parse_failed
,
1215 "invalid section name");
1217 return getString(Offset
);
1223 uint64_t COFFObjectFile::getSectionSize(const coff_section
*Sec
) const {
1224 // SizeOfRawData and VirtualSize change what they represent depending on
1225 // whether or not we have an executable image.
1227 // For object files, SizeOfRawData contains the size of section's data;
1228 // VirtualSize should be zero but isn't due to buggy COFF writers.
1230 // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1231 // actual section size is in VirtualSize. It is possible for VirtualSize to
1232 // be greater than SizeOfRawData; the contents past that point should be
1233 // considered to be zero.
1235 return std::min(Sec
->VirtualSize
, Sec
->SizeOfRawData
);
1236 return Sec
->SizeOfRawData
;
1239 Error
COFFObjectFile::getSectionContents(const coff_section
*Sec
,
1240 ArrayRef
<uint8_t> &Res
) const {
1241 // In COFF, a virtual section won't have any in-file
1242 // content, so the file pointer to the content will be zero.
1243 if (Sec
->PointerToRawData
== 0)
1244 return Error::success();
1245 // The only thing that we need to verify is that the contents is contained
1246 // within the file bounds. We don't need to make sure it doesn't cover other
1247 // data, as there's nothing that says that is not allowed.
1248 uintptr_t ConStart
=
1249 reinterpret_cast<uintptr_t>(base()) + Sec
->PointerToRawData
;
1250 uint32_t SectionSize
= getSectionSize(Sec
);
1251 if (Error E
= checkOffset(Data
, ConStart
, SectionSize
))
1253 Res
= ArrayRef(reinterpret_cast<const uint8_t *>(ConStart
), SectionSize
);
1254 return Error::success();
1257 const coff_relocation
*COFFObjectFile::toRel(DataRefImpl Rel
) const {
1258 return reinterpret_cast<const coff_relocation
*>(Rel
.p
);
1261 void COFFObjectFile::moveRelocationNext(DataRefImpl
&Rel
) const {
1262 Rel
.p
= reinterpret_cast<uintptr_t>(
1263 reinterpret_cast<const coff_relocation
*>(Rel
.p
) + 1);
1266 uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel
) const {
1267 const coff_relocation
*R
= toRel(Rel
);
1268 return R
->VirtualAddress
;
1271 symbol_iterator
COFFObjectFile::getRelocationSymbol(DataRefImpl Rel
) const {
1272 const coff_relocation
*R
= toRel(Rel
);
1274 if (R
->SymbolTableIndex
>= getNumberOfSymbols())
1275 return symbol_end();
1277 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable16
+ R
->SymbolTableIndex
);
1278 else if (SymbolTable32
)
1279 Ref
.p
= reinterpret_cast<uintptr_t>(SymbolTable32
+ R
->SymbolTableIndex
);
1281 llvm_unreachable("no symbol table pointer!");
1282 return symbol_iterator(SymbolRef(Ref
, this));
1285 uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel
) const {
1286 const coff_relocation
* R
= toRel(Rel
);
1290 const coff_section
*
1291 COFFObjectFile::getCOFFSection(const SectionRef
&Section
) const {
1292 return toSec(Section
.getRawDataRefImpl());
1295 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const DataRefImpl
&Ref
) const {
1297 return toSymb
<coff_symbol16
>(Ref
);
1299 return toSymb
<coff_symbol32
>(Ref
);
1300 llvm_unreachable("no symbol table pointer!");
1303 COFFSymbolRef
COFFObjectFile::getCOFFSymbol(const SymbolRef
&Symbol
) const {
1304 return getCOFFSymbol(Symbol
.getRawDataRefImpl());
1307 const coff_relocation
*
1308 COFFObjectFile::getCOFFRelocation(const RelocationRef
&Reloc
) const {
1309 return toRel(Reloc
.getRawDataRefImpl());
1312 ArrayRef
<coff_relocation
>
1313 COFFObjectFile::getRelocations(const coff_section
*Sec
) const {
1314 return {getFirstReloc(Sec
, Data
, base()),
1315 getNumberOfRelocations(Sec
, Data
, base())};
1318 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
1319 case COFF::reloc_type: \
1322 StringRef
COFFObjectFile::getRelocationTypeName(uint16_t Type
) const {
1323 switch (getMachine()) {
1324 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1326 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE
);
1327 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64
);
1328 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32
);
1329 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB
);
1330 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32
);
1331 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1
);
1332 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2
);
1333 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3
);
1334 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4
);
1335 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5
);
1336 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION
);
1337 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL
);
1338 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7
);
1339 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN
);
1340 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32
);
1341 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR
);
1342 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32
);
1347 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1349 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE
);
1350 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32
);
1351 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB
);
1352 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24
);
1353 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11
);
1354 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN
);
1355 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24
);
1356 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11
);
1357 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32
);
1358 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION
);
1359 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL
);
1360 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A
);
1361 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T
);
1362 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T
);
1363 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T
);
1364 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T
);
1365 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR
);
1370 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1371 case COFF::IMAGE_FILE_MACHINE_ARM64EC
:
1372 case COFF::IMAGE_FILE_MACHINE_ARM64X
:
1374 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE
);
1375 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32
);
1376 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB
);
1377 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26
);
1378 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21
);
1379 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21
);
1380 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A
);
1381 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L
);
1382 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL
);
1383 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A
);
1384 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A
);
1385 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L
);
1386 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN
);
1387 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION
);
1388 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64
);
1389 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19
);
1390 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14
);
1391 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32
);
1396 case COFF::IMAGE_FILE_MACHINE_I386
:
1398 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE
);
1399 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16
);
1400 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16
);
1401 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32
);
1402 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB
);
1403 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12
);
1404 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION
);
1405 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL
);
1406 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN
);
1407 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7
);
1408 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32
);
1418 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1420 void COFFObjectFile::getRelocationTypeName(
1421 DataRefImpl Rel
, SmallVectorImpl
<char> &Result
) const {
1422 const coff_relocation
*Reloc
= toRel(Rel
);
1423 StringRef Res
= getRelocationTypeName(Reloc
->Type
);
1424 Result
.append(Res
.begin(), Res
.end());
1427 bool COFFObjectFile::isRelocatableObject() const {
1428 return !DataDirectory
;
1431 StringRef
COFFObjectFile::mapDebugSectionName(StringRef Name
) const {
1432 return StringSwitch
<StringRef
>(Name
)
1433 .Case("eh_fram", "eh_frame")
1437 bool ImportDirectoryEntryRef::
1438 operator==(const ImportDirectoryEntryRef
&Other
) const {
1439 return ImportTable
== Other
.ImportTable
&& Index
== Other
.Index
;
1442 void ImportDirectoryEntryRef::moveNext() {
1444 if (ImportTable
[Index
].isNull()) {
1446 ImportTable
= nullptr;
1450 Error
ImportDirectoryEntryRef::getImportTableEntry(
1451 const coff_import_directory_table_entry
*&Result
) const {
1452 return getObject(Result
, OwningObject
->Data
, ImportTable
+ Index
);
1455 static imported_symbol_iterator
1456 makeImportedSymbolIterator(const COFFObjectFile
*Object
,
1457 uintptr_t Ptr
, int Index
) {
1458 if (Object
->getBytesInAddress() == 4) {
1459 auto *P
= reinterpret_cast<const import_lookup_table_entry32
*>(Ptr
);
1460 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1462 auto *P
= reinterpret_cast<const import_lookup_table_entry64
*>(Ptr
);
1463 return imported_symbol_iterator(ImportedSymbolRef(P
, Index
, Object
));
1466 static imported_symbol_iterator
1467 importedSymbolBegin(uint32_t RVA
, const COFFObjectFile
*Object
) {
1468 uintptr_t IntPtr
= 0;
1469 // FIXME: Handle errors.
1470 cantFail(Object
->getRvaPtr(RVA
, IntPtr
));
1471 return makeImportedSymbolIterator(Object
, IntPtr
, 0);
1474 static imported_symbol_iterator
1475 importedSymbolEnd(uint32_t RVA
, const COFFObjectFile
*Object
) {
1476 uintptr_t IntPtr
= 0;
1477 // FIXME: Handle errors.
1478 cantFail(Object
->getRvaPtr(RVA
, IntPtr
));
1479 // Forward the pointer to the last entry which is null.
1481 if (Object
->getBytesInAddress() == 4) {
1482 auto *Entry
= reinterpret_cast<ulittle32_t
*>(IntPtr
);
1486 auto *Entry
= reinterpret_cast<ulittle64_t
*>(IntPtr
);
1490 return makeImportedSymbolIterator(Object
, IntPtr
, Index
);
1493 imported_symbol_iterator
1494 ImportDirectoryEntryRef::imported_symbol_begin() const {
1495 return importedSymbolBegin(ImportTable
[Index
].ImportAddressTableRVA
,
1499 imported_symbol_iterator
1500 ImportDirectoryEntryRef::imported_symbol_end() const {
1501 return importedSymbolEnd(ImportTable
[Index
].ImportAddressTableRVA
,
1505 iterator_range
<imported_symbol_iterator
>
1506 ImportDirectoryEntryRef::imported_symbols() const {
1507 return make_range(imported_symbol_begin(), imported_symbol_end());
1510 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_begin() const {
1511 return importedSymbolBegin(ImportTable
[Index
].ImportLookupTableRVA
,
1515 imported_symbol_iterator
ImportDirectoryEntryRef::lookup_table_end() const {
1516 return importedSymbolEnd(ImportTable
[Index
].ImportLookupTableRVA
,
1520 iterator_range
<imported_symbol_iterator
>
1521 ImportDirectoryEntryRef::lookup_table_symbols() const {
1522 return make_range(lookup_table_begin(), lookup_table_end());
1525 Error
ImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1526 uintptr_t IntPtr
= 0;
1527 if (Error E
= OwningObject
->getRvaPtr(ImportTable
[Index
].NameRVA
, IntPtr
,
1528 "import directory name"))
1530 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1531 return Error::success();
1535 ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result
) const {
1536 Result
= ImportTable
[Index
].ImportLookupTableRVA
;
1537 return Error::success();
1540 Error
ImportDirectoryEntryRef::getImportAddressTableRVA(
1541 uint32_t &Result
) const {
1542 Result
= ImportTable
[Index
].ImportAddressTableRVA
;
1543 return Error::success();
1546 bool DelayImportDirectoryEntryRef::
1547 operator==(const DelayImportDirectoryEntryRef
&Other
) const {
1548 return Table
== Other
.Table
&& Index
== Other
.Index
;
1551 void DelayImportDirectoryEntryRef::moveNext() {
1555 imported_symbol_iterator
1556 DelayImportDirectoryEntryRef::imported_symbol_begin() const {
1557 return importedSymbolBegin(Table
[Index
].DelayImportNameTable
,
1561 imported_symbol_iterator
1562 DelayImportDirectoryEntryRef::imported_symbol_end() const {
1563 return importedSymbolEnd(Table
[Index
].DelayImportNameTable
,
1567 iterator_range
<imported_symbol_iterator
>
1568 DelayImportDirectoryEntryRef::imported_symbols() const {
1569 return make_range(imported_symbol_begin(), imported_symbol_end());
1572 Error
DelayImportDirectoryEntryRef::getName(StringRef
&Result
) const {
1573 uintptr_t IntPtr
= 0;
1574 if (Error E
= OwningObject
->getRvaPtr(Table
[Index
].Name
, IntPtr
,
1575 "delay import directory name"))
1577 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1578 return Error::success();
1581 Error
DelayImportDirectoryEntryRef::getDelayImportTable(
1582 const delay_import_directory_table_entry
*&Result
) const {
1583 Result
= &Table
[Index
];
1584 return Error::success();
1587 Error
DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex
,
1588 uint64_t &Result
) const {
1589 uint32_t RVA
= Table
[Index
].DelayImportAddressTable
+
1590 AddrIndex
* (OwningObject
->is64() ? 8 : 4);
1591 uintptr_t IntPtr
= 0;
1592 if (Error E
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "import address"))
1594 if (OwningObject
->is64())
1595 Result
= *reinterpret_cast<const ulittle64_t
*>(IntPtr
);
1597 Result
= *reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1598 return Error::success();
1601 bool ExportDirectoryEntryRef::
1602 operator==(const ExportDirectoryEntryRef
&Other
) const {
1603 return ExportTable
== Other
.ExportTable
&& Index
== Other
.Index
;
1606 void ExportDirectoryEntryRef::moveNext() {
1610 // Returns the name of the current export symbol. If the symbol is exported only
1611 // by ordinal, the empty string is set as a result.
1612 Error
ExportDirectoryEntryRef::getDllName(StringRef
&Result
) const {
1613 uintptr_t IntPtr
= 0;
1615 OwningObject
->getRvaPtr(ExportTable
->NameRVA
, IntPtr
, "dll name"))
1617 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1618 return Error::success();
1621 // Returns the starting ordinal number.
1622 Error
ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result
) const {
1623 Result
= ExportTable
->OrdinalBase
;
1624 return Error::success();
1627 // Returns the export ordinal of the current export symbol.
1628 Error
ExportDirectoryEntryRef::getOrdinal(uint32_t &Result
) const {
1629 Result
= ExportTable
->OrdinalBase
+ Index
;
1630 return Error::success();
1633 // Returns the address of the current export symbol.
1634 Error
ExportDirectoryEntryRef::getExportRVA(uint32_t &Result
) const {
1635 uintptr_t IntPtr
= 0;
1636 if (Error EC
= OwningObject
->getRvaPtr(ExportTable
->ExportAddressTableRVA
,
1637 IntPtr
, "export address"))
1639 const export_address_table_entry
*entry
=
1640 reinterpret_cast<const export_address_table_entry
*>(IntPtr
);
1641 Result
= entry
[Index
].ExportRVA
;
1642 return Error::success();
1645 // Returns the name of the current export symbol. If the symbol is exported only
1646 // by ordinal, the empty string is set as a result.
1648 ExportDirectoryEntryRef::getSymbolName(StringRef
&Result
) const {
1649 uintptr_t IntPtr
= 0;
1650 if (Error EC
= OwningObject
->getRvaPtr(ExportTable
->OrdinalTableRVA
, IntPtr
,
1651 "export ordinal table"))
1653 const ulittle16_t
*Start
= reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1655 uint32_t NumEntries
= ExportTable
->NumberOfNamePointers
;
1657 for (const ulittle16_t
*I
= Start
, *E
= Start
+ NumEntries
;
1658 I
< E
; ++I
, ++Offset
) {
1661 if (Error EC
= OwningObject
->getRvaPtr(ExportTable
->NamePointerRVA
, IntPtr
,
1662 "export table entry"))
1664 const ulittle32_t
*NamePtr
= reinterpret_cast<const ulittle32_t
*>(IntPtr
);
1665 if (Error EC
= OwningObject
->getRvaPtr(NamePtr
[Offset
], IntPtr
,
1666 "export symbol name"))
1668 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1669 return Error::success();
1672 return Error::success();
1675 Error
ExportDirectoryEntryRef::isForwarder(bool &Result
) const {
1676 const data_directory
*DataEntry
=
1677 OwningObject
->getDataDirectory(COFF::EXPORT_TABLE
);
1679 return createStringError(object_error::parse_failed
,
1680 "export table missing");
1682 if (auto EC
= getExportRVA(RVA
))
1684 uint32_t Begin
= DataEntry
->RelativeVirtualAddress
;
1685 uint32_t End
= DataEntry
->RelativeVirtualAddress
+ DataEntry
->Size
;
1686 Result
= (Begin
<= RVA
&& RVA
< End
);
1687 return Error::success();
1690 Error
ExportDirectoryEntryRef::getForwardTo(StringRef
&Result
) const {
1692 if (auto EC
= getExportRVA(RVA
))
1694 uintptr_t IntPtr
= 0;
1695 if (auto EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "export forward target"))
1697 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
));
1698 return Error::success();
1701 bool ImportedSymbolRef::
1702 operator==(const ImportedSymbolRef
&Other
) const {
1703 return Entry32
== Other
.Entry32
&& Entry64
== Other
.Entry64
1704 && Index
== Other
.Index
;
1707 void ImportedSymbolRef::moveNext() {
1711 Error
ImportedSymbolRef::getSymbolName(StringRef
&Result
) const {
1714 // If a symbol is imported only by ordinal, it has no name.
1715 if (Entry32
[Index
].isOrdinal())
1716 return Error::success();
1717 RVA
= Entry32
[Index
].getHintNameRVA();
1719 if (Entry64
[Index
].isOrdinal())
1720 return Error::success();
1721 RVA
= Entry64
[Index
].getHintNameRVA();
1723 uintptr_t IntPtr
= 0;
1724 if (Error EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "import symbol name"))
1726 // +2 because the first two bytes is hint.
1727 Result
= StringRef(reinterpret_cast<const char *>(IntPtr
+ 2));
1728 return Error::success();
1731 Error
ImportedSymbolRef::isOrdinal(bool &Result
) const {
1733 Result
= Entry32
[Index
].isOrdinal();
1735 Result
= Entry64
[Index
].isOrdinal();
1736 return Error::success();
1739 Error
ImportedSymbolRef::getHintNameRVA(uint32_t &Result
) const {
1741 Result
= Entry32
[Index
].getHintNameRVA();
1743 Result
= Entry64
[Index
].getHintNameRVA();
1744 return Error::success();
1747 Error
ImportedSymbolRef::getOrdinal(uint16_t &Result
) const {
1750 if (Entry32
[Index
].isOrdinal()) {
1751 Result
= Entry32
[Index
].getOrdinal();
1752 return Error::success();
1754 RVA
= Entry32
[Index
].getHintNameRVA();
1756 if (Entry64
[Index
].isOrdinal()) {
1757 Result
= Entry64
[Index
].getOrdinal();
1758 return Error::success();
1760 RVA
= Entry64
[Index
].getHintNameRVA();
1762 uintptr_t IntPtr
= 0;
1763 if (Error EC
= OwningObject
->getRvaPtr(RVA
, IntPtr
, "import symbol ordinal"))
1765 Result
= *reinterpret_cast<const ulittle16_t
*>(IntPtr
);
1766 return Error::success();
1769 Expected
<std::unique_ptr
<COFFObjectFile
>>
1770 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object
) {
1771 return COFFObjectFile::create(Object
);
1774 bool BaseRelocRef::operator==(const BaseRelocRef
&Other
) const {
1775 return Header
== Other
.Header
&& Index
== Other
.Index
;
1778 void BaseRelocRef::moveNext() {
1779 // Header->BlockSize is the size of the current block, including the
1780 // size of the header itself.
1781 uint32_t Size
= sizeof(*Header
) +
1782 sizeof(coff_base_reloc_block_entry
) * (Index
+ 1);
1783 if (Size
== Header
->BlockSize
) {
1784 // .reloc contains a list of base relocation blocks. Each block
1785 // consists of the header followed by entries. The header contains
1786 // how many entories will follow. When we reach the end of the
1787 // current block, proceed to the next block.
1788 Header
= reinterpret_cast<const coff_base_reloc_block_header
*>(
1789 reinterpret_cast<const uint8_t *>(Header
) + Size
);
1796 Error
BaseRelocRef::getType(uint8_t &Type
) const {
1797 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1798 Type
= Entry
[Index
].getType();
1799 return Error::success();
1802 Error
BaseRelocRef::getRVA(uint32_t &Result
) const {
1803 auto *Entry
= reinterpret_cast<const coff_base_reloc_block_entry
*>(Header
+ 1);
1804 Result
= Header
->PageRVA
+ Entry
[Index
].getOffset();
1805 return Error::success();
1808 #define RETURN_IF_ERROR(Expr) \
1812 return std::move(E); \
1815 Expected
<ArrayRef
<UTF16
>>
1816 ResourceSectionRef::getDirStringAtOffset(uint32_t Offset
) {
1817 BinaryStreamReader Reader
= BinaryStreamReader(BBS
);
1818 Reader
.setOffset(Offset
);
1820 RETURN_IF_ERROR(Reader
.readInteger(Length
));
1821 ArrayRef
<UTF16
> RawDirString
;
1822 RETURN_IF_ERROR(Reader
.readArray(RawDirString
, Length
));
1823 return RawDirString
;
1826 Expected
<ArrayRef
<UTF16
>>
1827 ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry
&Entry
) {
1828 return getDirStringAtOffset(Entry
.Identifier
.getNameOffset());
1831 Expected
<const coff_resource_dir_table
&>
1832 ResourceSectionRef::getTableAtOffset(uint32_t Offset
) {
1833 const coff_resource_dir_table
*Table
= nullptr;
1835 BinaryStreamReader
Reader(BBS
);
1836 Reader
.setOffset(Offset
);
1837 RETURN_IF_ERROR(Reader
.readObject(Table
));
1838 assert(Table
!= nullptr);
1842 Expected
<const coff_resource_dir_entry
&>
1843 ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset
) {
1844 const coff_resource_dir_entry
*Entry
= nullptr;
1846 BinaryStreamReader
Reader(BBS
);
1847 Reader
.setOffset(Offset
);
1848 RETURN_IF_ERROR(Reader
.readObject(Entry
));
1849 assert(Entry
!= nullptr);
1853 Expected
<const coff_resource_data_entry
&>
1854 ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset
) {
1855 const coff_resource_data_entry
*Entry
= nullptr;
1857 BinaryStreamReader
Reader(BBS
);
1858 Reader
.setOffset(Offset
);
1859 RETURN_IF_ERROR(Reader
.readObject(Entry
));
1860 assert(Entry
!= nullptr);
1864 Expected
<const coff_resource_dir_table
&>
1865 ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry
&Entry
) {
1866 assert(Entry
.Offset
.isSubDir());
1867 return getTableAtOffset(Entry
.Offset
.value());
1870 Expected
<const coff_resource_data_entry
&>
1871 ResourceSectionRef::getEntryData(const coff_resource_dir_entry
&Entry
) {
1872 assert(!Entry
.Offset
.isSubDir());
1873 return getDataEntryAtOffset(Entry
.Offset
.value());
1876 Expected
<const coff_resource_dir_table
&> ResourceSectionRef::getBaseTable() {
1877 return getTableAtOffset(0);
1880 Expected
<const coff_resource_dir_entry
&>
1881 ResourceSectionRef::getTableEntry(const coff_resource_dir_table
&Table
,
1883 if (Index
>= (uint32_t)(Table
.NumberOfNameEntries
+ Table
.NumberOfIDEntries
))
1884 return createStringError(object_error::parse_failed
, "index out of range");
1885 const uint8_t *TablePtr
= reinterpret_cast<const uint8_t *>(&Table
);
1886 ptrdiff_t TableOffset
= TablePtr
- BBS
.data().data();
1887 return getTableEntryAtOffset(TableOffset
+ sizeof(Table
) +
1888 Index
* sizeof(coff_resource_dir_entry
));
1891 Error
ResourceSectionRef::load(const COFFObjectFile
*O
) {
1892 for (const SectionRef
&S
: O
->sections()) {
1893 Expected
<StringRef
> Name
= S
.getName();
1895 return Name
.takeError();
1897 if (*Name
== ".rsrc" || *Name
== ".rsrc$01")
1900 return createStringError(object_error::parse_failed
,
1901 "no resource section found");
1904 Error
ResourceSectionRef::load(const COFFObjectFile
*O
, const SectionRef
&S
) {
1907 Expected
<StringRef
> Contents
= Section
.getContents();
1909 return Contents
.takeError();
1910 BBS
= BinaryByteStream(*Contents
, llvm::endianness::little
);
1911 const coff_section
*COFFSect
= Obj
->getCOFFSection(Section
);
1912 ArrayRef
<coff_relocation
> OrigRelocs
= Obj
->getRelocations(COFFSect
);
1913 Relocs
.reserve(OrigRelocs
.size());
1914 for (const coff_relocation
&R
: OrigRelocs
)
1915 Relocs
.push_back(&R
);
1916 llvm::sort(Relocs
, [](const coff_relocation
*A
, const coff_relocation
*B
) {
1917 return A
->VirtualAddress
< B
->VirtualAddress
;
1919 return Error::success();
1923 ResourceSectionRef::getContents(const coff_resource_data_entry
&Entry
) {
1925 return createStringError(object_error::parse_failed
, "no object provided");
1927 // Find a potential relocation at the DataRVA field (first member of
1928 // the coff_resource_data_entry struct).
1929 const uint8_t *EntryPtr
= reinterpret_cast<const uint8_t *>(&Entry
);
1930 ptrdiff_t EntryOffset
= EntryPtr
- BBS
.data().data();
1931 coff_relocation RelocTarget
{ulittle32_t(EntryOffset
), ulittle32_t(0),
1933 auto RelocsForOffset
=
1934 std::equal_range(Relocs
.begin(), Relocs
.end(), &RelocTarget
,
1935 [](const coff_relocation
*A
, const coff_relocation
*B
) {
1936 return A
->VirtualAddress
< B
->VirtualAddress
;
1939 if (RelocsForOffset
.first
!= RelocsForOffset
.second
) {
1940 // We found a relocation with the right offset. Check that it does have
1941 // the expected type.
1942 const coff_relocation
&R
= **RelocsForOffset
.first
;
1944 switch (Obj
->getMachine()) {
1945 case COFF::IMAGE_FILE_MACHINE_I386
:
1946 RVAReloc
= COFF::IMAGE_REL_I386_DIR32NB
;
1948 case COFF::IMAGE_FILE_MACHINE_AMD64
:
1949 RVAReloc
= COFF::IMAGE_REL_AMD64_ADDR32NB
;
1951 case COFF::IMAGE_FILE_MACHINE_ARMNT
:
1952 RVAReloc
= COFF::IMAGE_REL_ARM_ADDR32NB
;
1954 case COFF::IMAGE_FILE_MACHINE_ARM64
:
1955 case COFF::IMAGE_FILE_MACHINE_ARM64EC
:
1956 case COFF::IMAGE_FILE_MACHINE_ARM64X
:
1957 RVAReloc
= COFF::IMAGE_REL_ARM64_ADDR32NB
;
1960 return createStringError(object_error::parse_failed
,
1961 "unsupported architecture");
1963 if (R
.Type
!= RVAReloc
)
1964 return createStringError(object_error::parse_failed
,
1965 "unexpected relocation type");
1966 // Get the relocation's symbol
1967 Expected
<COFFSymbolRef
> Sym
= Obj
->getSymbol(R
.SymbolTableIndex
);
1969 return Sym
.takeError();
1970 // And the symbol's section
1971 Expected
<const coff_section
*> Section
=
1972 Obj
->getSection(Sym
->getSectionNumber());
1974 return Section
.takeError();
1975 // Add the initial value of DataRVA to the symbol's offset to find the
1976 // data it points at.
1977 uint64_t Offset
= Entry
.DataRVA
+ Sym
->getValue();
1978 ArrayRef
<uint8_t> Contents
;
1979 if (Error E
= Obj
->getSectionContents(*Section
, Contents
))
1980 return std::move(E
);
1981 if (Offset
+ Entry
.DataSize
> Contents
.size())
1982 return createStringError(object_error::parse_failed
,
1983 "data outside of section");
1984 // Return a reference to the data inside the section.
1985 return StringRef(reinterpret_cast<const char *>(Contents
.data()) + Offset
,
1988 // Relocatable objects need a relocation for the DataRVA field.
1989 if (Obj
->isRelocatableObject())
1990 return createStringError(object_error::parse_failed
,
1991 "no relocation found for DataRVA");
1993 // Locate the section that contains the address that DataRVA points at.
1994 uint64_t VA
= Entry
.DataRVA
+ Obj
->getImageBase();
1995 for (const SectionRef
&S
: Obj
->sections()) {
1996 if (VA
>= S
.getAddress() &&
1997 VA
+ Entry
.DataSize
<= S
.getAddress() + S
.getSize()) {
1998 uint64_t Offset
= VA
- S
.getAddress();
1999 Expected
<StringRef
> Contents
= S
.getContents();
2001 return Contents
.takeError();
2002 return Contents
->slice(Offset
, Offset
+ Entry
.DataSize
);
2005 return createStringError(object_error::parse_failed
,
2006 "address not found in image");