1 //===- COFF.h - COFF object file implementation -----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file declares the COFFObjectFile class.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_OBJECT_COFF_H
15 #define LLVM_OBJECT_COFF_H
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
19 #include "llvm/MC/SubtargetFeature.h"
20 #include "llvm/Object/Binary.h"
21 #include "llvm/Object/Error.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/BinaryByteStream.h"
24 #include "llvm/Support/COFF.h"
25 #include "llvm/Support/ConvertUTF.h"
26 #include "llvm/Support/Endian.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/ErrorOr.h"
32 #include <system_error>
36 template <typename T> class ArrayRef;
41 class DelayImportDirectoryEntryRef;
42 class ExportDirectoryEntryRef;
43 class ImportDirectoryEntryRef;
44 class ImportedSymbolRef;
45 class ResourceSectionRef;
47 using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>;
48 using delay_import_directory_iterator =
49 content_iterator<DelayImportDirectoryEntryRef>;
50 using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>;
51 using imported_symbol_iterator = content_iterator<ImportedSymbolRef>;
52 using base_reloc_iterator = content_iterator<BaseRelocRef>;
54 /// The DOS compatible header at the front of all PE/COFF executables.
57 support::ulittle16_t UsedBytesInTheLastPage;
58 support::ulittle16_t FileSizeInPages;
59 support::ulittle16_t NumberOfRelocationItems;
60 support::ulittle16_t HeaderSizeInParagraphs;
61 support::ulittle16_t MinimumExtraParagraphs;
62 support::ulittle16_t MaximumExtraParagraphs;
63 support::ulittle16_t InitialRelativeSS;
64 support::ulittle16_t InitialSP;
65 support::ulittle16_t Checksum;
66 support::ulittle16_t InitialIP;
67 support::ulittle16_t InitialRelativeCS;
68 support::ulittle16_t AddressOfRelocationTable;
69 support::ulittle16_t OverlayNumber;
70 support::ulittle16_t Reserved[4];
71 support::ulittle16_t OEMid;
72 support::ulittle16_t OEMinfo;
73 support::ulittle16_t Reserved2[10];
74 support::ulittle32_t AddressOfNewExeHeader;
77 struct coff_file_header {
78 support::ulittle16_t Machine;
79 support::ulittle16_t NumberOfSections;
80 support::ulittle32_t TimeDateStamp;
81 support::ulittle32_t PointerToSymbolTable;
82 support::ulittle32_t NumberOfSymbols;
83 support::ulittle16_t SizeOfOptionalHeader;
84 support::ulittle16_t Characteristics;
86 bool isImportLibrary() const { return NumberOfSections == 0xffff; }
89 struct coff_bigobj_file_header {
90 support::ulittle16_t Sig1;
91 support::ulittle16_t Sig2;
92 support::ulittle16_t Version;
93 support::ulittle16_t Machine;
94 support::ulittle32_t TimeDateStamp;
96 support::ulittle32_t unused1;
97 support::ulittle32_t unused2;
98 support::ulittle32_t unused3;
99 support::ulittle32_t unused4;
100 support::ulittle32_t NumberOfSections;
101 support::ulittle32_t PointerToSymbolTable;
102 support::ulittle32_t NumberOfSymbols;
105 /// The 32-bit PE header that follows the COFF header.
107 support::ulittle16_t Magic;
108 uint8_t MajorLinkerVersion;
109 uint8_t MinorLinkerVersion;
110 support::ulittle32_t SizeOfCode;
111 support::ulittle32_t SizeOfInitializedData;
112 support::ulittle32_t SizeOfUninitializedData;
113 support::ulittle32_t AddressOfEntryPoint;
114 support::ulittle32_t BaseOfCode;
115 support::ulittle32_t BaseOfData;
116 support::ulittle32_t ImageBase;
117 support::ulittle32_t SectionAlignment;
118 support::ulittle32_t FileAlignment;
119 support::ulittle16_t MajorOperatingSystemVersion;
120 support::ulittle16_t MinorOperatingSystemVersion;
121 support::ulittle16_t MajorImageVersion;
122 support::ulittle16_t MinorImageVersion;
123 support::ulittle16_t MajorSubsystemVersion;
124 support::ulittle16_t MinorSubsystemVersion;
125 support::ulittle32_t Win32VersionValue;
126 support::ulittle32_t SizeOfImage;
127 support::ulittle32_t SizeOfHeaders;
128 support::ulittle32_t CheckSum;
129 support::ulittle16_t Subsystem;
130 // FIXME: This should be DllCharacteristics.
131 support::ulittle16_t DLLCharacteristics;
132 support::ulittle32_t SizeOfStackReserve;
133 support::ulittle32_t SizeOfStackCommit;
134 support::ulittle32_t SizeOfHeapReserve;
135 support::ulittle32_t SizeOfHeapCommit;
136 support::ulittle32_t LoaderFlags;
137 // FIXME: This should be NumberOfRvaAndSizes.
138 support::ulittle32_t NumberOfRvaAndSize;
141 /// The 64-bit PE header that follows the COFF header.
142 struct pe32plus_header {
143 support::ulittle16_t Magic;
144 uint8_t MajorLinkerVersion;
145 uint8_t MinorLinkerVersion;
146 support::ulittle32_t SizeOfCode;
147 support::ulittle32_t SizeOfInitializedData;
148 support::ulittle32_t SizeOfUninitializedData;
149 support::ulittle32_t AddressOfEntryPoint;
150 support::ulittle32_t BaseOfCode;
151 support::ulittle64_t ImageBase;
152 support::ulittle32_t SectionAlignment;
153 support::ulittle32_t FileAlignment;
154 support::ulittle16_t MajorOperatingSystemVersion;
155 support::ulittle16_t MinorOperatingSystemVersion;
156 support::ulittle16_t MajorImageVersion;
157 support::ulittle16_t MinorImageVersion;
158 support::ulittle16_t MajorSubsystemVersion;
159 support::ulittle16_t MinorSubsystemVersion;
160 support::ulittle32_t Win32VersionValue;
161 support::ulittle32_t SizeOfImage;
162 support::ulittle32_t SizeOfHeaders;
163 support::ulittle32_t CheckSum;
164 support::ulittle16_t Subsystem;
165 support::ulittle16_t DLLCharacteristics;
166 support::ulittle64_t SizeOfStackReserve;
167 support::ulittle64_t SizeOfStackCommit;
168 support::ulittle64_t SizeOfHeapReserve;
169 support::ulittle64_t SizeOfHeapCommit;
170 support::ulittle32_t LoaderFlags;
171 support::ulittle32_t NumberOfRvaAndSize;
174 struct data_directory {
175 support::ulittle32_t RelativeVirtualAddress;
176 support::ulittle32_t Size;
179 struct debug_directory {
180 support::ulittle32_t Characteristics;
181 support::ulittle32_t TimeDateStamp;
182 support::ulittle16_t MajorVersion;
183 support::ulittle16_t MinorVersion;
184 support::ulittle32_t Type;
185 support::ulittle32_t SizeOfData;
186 support::ulittle32_t AddressOfRawData;
187 support::ulittle32_t PointerToRawData;
190 template <typename IntTy>
191 struct import_lookup_table_entry {
194 bool isOrdinal() const { return Data < 0; }
196 uint16_t getOrdinal() const {
197 assert(isOrdinal() && "ILT entry is not an ordinal!");
198 return Data & 0xFFFF;
201 uint32_t getHintNameRVA() const {
202 assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
203 return Data & 0xFFFFFFFF;
207 using import_lookup_table_entry32 =
208 import_lookup_table_entry<support::little32_t>;
209 using import_lookup_table_entry64 =
210 import_lookup_table_entry<support::little64_t>;
212 struct delay_import_directory_table_entry {
213 // dumpbin reports this field as "Characteristics" instead of "Attributes".
214 support::ulittle32_t Attributes;
215 support::ulittle32_t Name;
216 support::ulittle32_t ModuleHandle;
217 support::ulittle32_t DelayImportAddressTable;
218 support::ulittle32_t DelayImportNameTable;
219 support::ulittle32_t BoundDelayImportTable;
220 support::ulittle32_t UnloadDelayImportTable;
221 support::ulittle32_t TimeStamp;
224 struct export_directory_table_entry {
225 support::ulittle32_t ExportFlags;
226 support::ulittle32_t TimeDateStamp;
227 support::ulittle16_t MajorVersion;
228 support::ulittle16_t MinorVersion;
229 support::ulittle32_t NameRVA;
230 support::ulittle32_t OrdinalBase;
231 support::ulittle32_t AddressTableEntries;
232 support::ulittle32_t NumberOfNamePointers;
233 support::ulittle32_t ExportAddressTableRVA;
234 support::ulittle32_t NamePointerRVA;
235 support::ulittle32_t OrdinalTableRVA;
238 union export_address_table_entry {
239 support::ulittle32_t ExportRVA;
240 support::ulittle32_t ForwarderRVA;
243 using export_name_pointer_table_entry = support::ulittle32_t;
244 using export_ordinal_table_entry = support::ulittle16_t;
246 struct StringTableOffset {
247 support::ulittle32_t Zeroes;
248 support::ulittle32_t Offset;
251 template <typename SectionNumberType>
254 char ShortName[COFF::NameSize];
255 StringTableOffset Offset;
258 support::ulittle32_t Value;
259 SectionNumberType SectionNumber;
261 support::ulittle16_t Type;
263 uint8_t StorageClass;
264 uint8_t NumberOfAuxSymbols;
267 using coff_symbol16 = coff_symbol<support::ulittle16_t>;
268 using coff_symbol32 = coff_symbol<support::ulittle32_t>;
270 // Contains only common parts of coff_symbol16 and coff_symbol32.
271 struct coff_symbol_generic {
273 char ShortName[COFF::NameSize];
274 StringTableOffset Offset;
276 support::ulittle32_t Value;
279 class COFFSymbolRef {
281 COFFSymbolRef() = default;
282 COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {}
283 COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {}
285 const void *getRawPtr() const {
286 return CS16 ? static_cast<const void *>(CS16) : CS32;
289 const coff_symbol_generic *getGeneric() const {
291 return reinterpret_cast<const coff_symbol_generic *>(CS16);
292 return reinterpret_cast<const coff_symbol_generic *>(CS32);
295 friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) {
296 return A.getRawPtr() < B.getRawPtr();
299 bool isBigObj() const {
304 llvm_unreachable("COFFSymbolRef points to nothing!");
307 const char *getShortName() const {
308 return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName;
311 const StringTableOffset &getStringTableOffset() const {
312 assert(isSet() && "COFFSymbolRef points to nothing!");
313 return CS16 ? CS16->Name.Offset : CS32->Name.Offset;
316 uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; }
318 int32_t getSectionNumber() const {
319 assert(isSet() && "COFFSymbolRef points to nothing!");
321 // Reserved sections are returned as negative numbers.
322 if (CS16->SectionNumber <= COFF::MaxNumberOfSections16)
323 return CS16->SectionNumber;
324 return static_cast<int16_t>(CS16->SectionNumber);
326 return static_cast<int32_t>(CS32->SectionNumber);
329 uint16_t getType() const {
330 assert(isSet() && "COFFSymbolRef points to nothing!");
331 return CS16 ? CS16->Type : CS32->Type;
334 uint8_t getStorageClass() const {
335 assert(isSet() && "COFFSymbolRef points to nothing!");
336 return CS16 ? CS16->StorageClass : CS32->StorageClass;
339 uint8_t getNumberOfAuxSymbols() const {
340 assert(isSet() && "COFFSymbolRef points to nothing!");
341 return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols;
344 uint8_t getBaseType() const { return getType() & 0x0F; }
346 uint8_t getComplexType() const {
347 return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
350 bool isAbsolute() const {
351 return getSectionNumber() == -1;
354 bool isExternal() const {
355 return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
358 bool isCommon() const {
359 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
363 bool isUndefined() const {
364 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
368 bool isWeakExternal() const {
369 return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
372 bool isFunctionDefinition() const {
373 return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
374 getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
375 !COFF::isReservedSectionNumber(getSectionNumber());
378 bool isFunctionLineInfo() const {
379 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
382 bool isAnyUndefined() const {
383 return isUndefined() || isWeakExternal();
386 bool isFileRecord() const {
387 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
390 bool isSection() const {
391 return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
394 bool isSectionDefinition() const {
395 // C++/CLI creates external ABS symbols for non-const appdomain globals.
396 // These are also followed by an auxiliary section definition.
397 bool isAppdomainGlobal =
398 getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
399 getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
400 bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
401 if (!getNumberOfAuxSymbols())
403 return isAppdomainGlobal || isOrdinarySection;
406 bool isCLRToken() const {
407 return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
411 bool isSet() const { return CS16 || CS32; }
413 const coff_symbol16 *CS16 = nullptr;
414 const coff_symbol32 *CS32 = nullptr;
417 struct coff_section {
418 char Name[COFF::NameSize];
419 support::ulittle32_t VirtualSize;
420 support::ulittle32_t VirtualAddress;
421 support::ulittle32_t SizeOfRawData;
422 support::ulittle32_t PointerToRawData;
423 support::ulittle32_t PointerToRelocations;
424 support::ulittle32_t PointerToLinenumbers;
425 support::ulittle16_t NumberOfRelocations;
426 support::ulittle16_t NumberOfLinenumbers;
427 support::ulittle32_t Characteristics;
429 // Returns true if the actual number of relocations is stored in
430 // VirtualAddress field of the first relocation table entry.
431 bool hasExtendedRelocations() const {
432 return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
433 NumberOfRelocations == UINT16_MAX;
436 uint32_t getAlignment() const {
437 // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to
438 // IMAGE_SCN_ALIGN_1BYTES.
439 if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
442 // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
443 uint32_t Shift = (Characteristics >> 20) & 0xF;
445 return 1U << (Shift - 1);
450 struct coff_relocation {
451 support::ulittle32_t VirtualAddress;
452 support::ulittle32_t SymbolTableIndex;
453 support::ulittle16_t Type;
456 struct coff_aux_function_definition {
457 support::ulittle32_t TagIndex;
458 support::ulittle32_t TotalSize;
459 support::ulittle32_t PointerToLinenumber;
460 support::ulittle32_t PointerToNextFunction;
464 static_assert(sizeof(coff_aux_function_definition) == 18,
465 "auxiliary entry must be 18 bytes");
467 struct coff_aux_bf_and_ef_symbol {
469 support::ulittle16_t Linenumber;
471 support::ulittle32_t PointerToNextFunction;
475 static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18,
476 "auxiliary entry must be 18 bytes");
478 struct coff_aux_weak_external {
479 support::ulittle32_t TagIndex;
480 support::ulittle32_t Characteristics;
484 static_assert(sizeof(coff_aux_weak_external) == 18,
485 "auxiliary entry must be 18 bytes");
487 struct coff_aux_section_definition {
488 support::ulittle32_t Length;
489 support::ulittle16_t NumberOfRelocations;
490 support::ulittle16_t NumberOfLinenumbers;
491 support::ulittle32_t CheckSum;
492 support::ulittle16_t NumberLowPart;
495 support::ulittle16_t NumberHighPart;
496 int32_t getNumber(bool IsBigObj) const {
497 uint32_t Number = static_cast<uint32_t>(NumberLowPart);
499 Number |= static_cast<uint32_t>(NumberHighPart) << 16;
500 return static_cast<int32_t>(Number);
504 static_assert(sizeof(coff_aux_section_definition) == 18,
505 "auxiliary entry must be 18 bytes");
507 struct coff_aux_clr_token {
510 support::ulittle32_t SymbolTableIndex;
514 static_assert(sizeof(coff_aux_clr_token) == 18,
515 "auxiliary entry must be 18 bytes");
517 struct coff_import_header {
518 support::ulittle16_t Sig1;
519 support::ulittle16_t Sig2;
520 support::ulittle16_t Version;
521 support::ulittle16_t Machine;
522 support::ulittle32_t TimeDateStamp;
523 support::ulittle32_t SizeOfData;
524 support::ulittle16_t OrdinalHint;
525 support::ulittle16_t TypeInfo;
527 int getType() const { return TypeInfo & 0x3; }
528 int getNameType() const { return (TypeInfo >> 2) & 0x7; }
531 struct coff_import_directory_table_entry {
532 support::ulittle32_t ImportLookupTableRVA;
533 support::ulittle32_t TimeDateStamp;
534 support::ulittle32_t ForwarderChain;
535 support::ulittle32_t NameRVA;
536 support::ulittle32_t ImportAddressTableRVA;
538 bool isNull() const {
539 return ImportLookupTableRVA == 0 && TimeDateStamp == 0 &&
540 ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0;
544 template <typename IntTy>
545 struct coff_tls_directory {
546 IntTy StartAddressOfRawData;
547 IntTy EndAddressOfRawData;
548 IntTy AddressOfIndex;
549 IntTy AddressOfCallBacks;
550 support::ulittle32_t SizeOfZeroFill;
551 support::ulittle32_t Characteristics;
553 uint32_t getAlignment() const {
554 // Bit [20:24] contains section alignment.
555 uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
557 return 1U << (Shift - 1);
562 using coff_tls_directory32 = coff_tls_directory<support::little32_t>;
563 using coff_tls_directory64 = coff_tls_directory<support::little64_t>;
565 struct coff_load_configuration32 {
566 support::ulittle32_t Characteristics;
567 support::ulittle32_t TimeDateStamp;
568 support::ulittle16_t MajorVersion;
569 support::ulittle16_t MinorVersion;
570 support::ulittle32_t GlobalFlagsClear;
571 support::ulittle32_t GlobalFlagsSet;
572 support::ulittle32_t CriticalSectionDefaultTimeout;
573 support::ulittle32_t DeCommitFreeBlockThreshold;
574 support::ulittle32_t DeCommitTotalFreeThreshold;
575 support::ulittle32_t LockPrefixTable;
576 support::ulittle32_t MaximumAllocationSize;
577 support::ulittle32_t VirtualMemoryThreshold;
578 support::ulittle32_t ProcessAffinityMask;
579 support::ulittle32_t ProcessHeapFlags;
580 support::ulittle16_t CSDVersion;
581 support::ulittle16_t Reserved;
582 support::ulittle32_t EditList;
583 support::ulittle32_t SecurityCookie;
584 support::ulittle32_t SEHandlerTable;
585 support::ulittle32_t SEHandlerCount;
588 struct coff_load_configuration64 {
589 support::ulittle32_t Characteristics;
590 support::ulittle32_t TimeDateStamp;
591 support::ulittle16_t MajorVersion;
592 support::ulittle16_t MinorVersion;
593 support::ulittle32_t GlobalFlagsClear;
594 support::ulittle32_t GlobalFlagsSet;
595 support::ulittle32_t CriticalSectionDefaultTimeout;
596 support::ulittle32_t DeCommitFreeBlockThreshold;
597 support::ulittle32_t DeCommitTotalFreeThreshold;
598 support::ulittle32_t LockPrefixTable;
599 support::ulittle32_t MaximumAllocationSize;
600 support::ulittle32_t VirtualMemoryThreshold;
601 support::ulittle32_t ProcessAffinityMask;
602 support::ulittle32_t ProcessHeapFlags;
603 support::ulittle16_t CSDVersion;
604 support::ulittle16_t Reserved;
605 support::ulittle32_t EditList;
606 support::ulittle64_t SecurityCookie;
607 support::ulittle64_t SEHandlerTable;
608 support::ulittle64_t SEHandlerCount;
611 struct coff_runtime_function_x64 {
612 support::ulittle32_t BeginAddress;
613 support::ulittle32_t EndAddress;
614 support::ulittle32_t UnwindInformation;
617 struct coff_base_reloc_block_header {
618 support::ulittle32_t PageRVA;
619 support::ulittle32_t BlockSize;
622 struct coff_base_reloc_block_entry {
623 support::ulittle16_t Data;
625 int getType() const { return Data >> 12; }
626 int getOffset() const { return Data & ((1 << 12) - 1); }
629 struct coff_resource_dir_entry {
631 support::ulittle32_t NameOffset;
632 support::ulittle32_t ID;
633 uint32_t getNameOffset() const {
634 return maskTrailingOnes<uint32_t>(31) & NameOffset;
638 support::ulittle32_t DataEntryOffset;
639 support::ulittle32_t SubdirOffset;
641 bool isSubDir() const { return SubdirOffset >> 31; }
642 uint32_t value() const {
643 return maskTrailingOnes<uint32_t>(31) & SubdirOffset;
649 struct coff_resource_dir_table {
650 support::ulittle32_t Characteristics;
651 support::ulittle32_t TimeDateStamp;
652 support::ulittle16_t MajorVersion;
653 support::ulittle16_t MinorVersion;
654 support::ulittle16_t NumberOfNameEntries;
655 support::ulittle16_t NumberOfIDEntries;
658 class COFFObjectFile : public ObjectFile {
660 friend class ImportDirectoryEntryRef;
661 friend class ExportDirectoryEntryRef;
662 const coff_file_header *COFFHeader;
663 const coff_bigobj_file_header *COFFBigObjHeader;
664 const pe32_header *PE32Header;
665 const pe32plus_header *PE32PlusHeader;
666 const data_directory *DataDirectory;
667 const coff_section *SectionTable;
668 const coff_symbol16 *SymbolTable16;
669 const coff_symbol32 *SymbolTable32;
670 const char *StringTable;
671 uint32_t StringTableSize;
672 const coff_import_directory_table_entry *ImportDirectory;
673 const delay_import_directory_table_entry *DelayImportDirectory;
674 uint32_t NumberOfDelayImportDirectory;
675 const export_directory_table_entry *ExportDirectory;
676 const coff_base_reloc_block_header *BaseRelocHeader;
677 const coff_base_reloc_block_header *BaseRelocEnd;
678 const debug_directory *DebugDirectoryBegin;
679 const debug_directory *DebugDirectoryEnd;
681 std::error_code getString(uint32_t offset, StringRef &Res) const;
683 template <typename coff_symbol_type>
684 const coff_symbol_type *toSymb(DataRefImpl Symb) const;
685 const coff_section *toSec(DataRefImpl Sec) const;
686 const coff_relocation *toRel(DataRefImpl Rel) const;
688 std::error_code initSymbolTablePtr();
689 std::error_code initImportTablePtr();
690 std::error_code initDelayImportTablePtr();
691 std::error_code initExportTablePtr();
692 std::error_code initBaseRelocPtr();
693 std::error_code initDebugDirectoryPtr();
696 uintptr_t getSymbolTable() const {
698 return reinterpret_cast<uintptr_t>(SymbolTable16);
700 return reinterpret_cast<uintptr_t>(SymbolTable32);
704 uint16_t getMachine() const {
706 return COFFHeader->Machine;
707 if (COFFBigObjHeader)
708 return COFFBigObjHeader->Machine;
709 llvm_unreachable("no COFF header!");
712 uint16_t getSizeOfOptionalHeader() const {
714 return COFFHeader->isImportLibrary() ? 0
715 : COFFHeader->SizeOfOptionalHeader;
716 // bigobj doesn't have this field.
717 if (COFFBigObjHeader)
719 llvm_unreachable("no COFF header!");
722 uint16_t getCharacteristics() const {
724 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics;
725 // bigobj doesn't have characteristics to speak of,
726 // editbin will silently lie to you if you attempt to set any.
727 if (COFFBigObjHeader)
729 llvm_unreachable("no COFF header!");
732 uint32_t getTimeDateStamp() const {
734 return COFFHeader->TimeDateStamp;
735 if (COFFBigObjHeader)
736 return COFFBigObjHeader->TimeDateStamp;
737 llvm_unreachable("no COFF header!");
740 uint32_t getNumberOfSections() const {
742 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections;
743 if (COFFBigObjHeader)
744 return COFFBigObjHeader->NumberOfSections;
745 llvm_unreachable("no COFF header!");
748 uint32_t getPointerToSymbolTable() const {
750 return COFFHeader->isImportLibrary() ? 0
751 : COFFHeader->PointerToSymbolTable;
752 if (COFFBigObjHeader)
753 return COFFBigObjHeader->PointerToSymbolTable;
754 llvm_unreachable("no COFF header!");
757 uint32_t getRawNumberOfSymbols() const {
759 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols;
760 if (COFFBigObjHeader)
761 return COFFBigObjHeader->NumberOfSymbols;
762 llvm_unreachable("no COFF header!");
765 uint32_t getNumberOfSymbols() const {
766 if (!SymbolTable16 && !SymbolTable32)
768 return getRawNumberOfSymbols();
772 void moveSymbolNext(DataRefImpl &Symb) const override;
773 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
774 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
775 uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
776 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
777 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
778 uint32_t getSymbolFlags(DataRefImpl Symb) const override;
779 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
780 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
781 void moveSectionNext(DataRefImpl &Sec) const override;
782 std::error_code getSectionName(DataRefImpl Sec,
783 StringRef &Res) const override;
784 uint64_t getSectionAddress(DataRefImpl Sec) const override;
785 uint64_t getSectionSize(DataRefImpl Sec) const override;
786 std::error_code getSectionContents(DataRefImpl Sec,
787 StringRef &Res) const override;
788 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
789 bool isSectionCompressed(DataRefImpl Sec) const override;
790 bool isSectionText(DataRefImpl Sec) const override;
791 bool isSectionData(DataRefImpl Sec) const override;
792 bool isSectionBSS(DataRefImpl Sec) const override;
793 bool isSectionVirtual(DataRefImpl Sec) const override;
794 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
795 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
797 void moveRelocationNext(DataRefImpl &Rel) const override;
798 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
799 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
800 uint64_t getRelocationType(DataRefImpl Rel) const override;
801 void getRelocationTypeName(DataRefImpl Rel,
802 SmallVectorImpl<char> &Result) const override;
805 COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
807 basic_symbol_iterator symbol_begin() const override;
808 basic_symbol_iterator symbol_end() const override;
809 section_iterator section_begin() const override;
810 section_iterator section_end() const override;
812 const coff_section *getCOFFSection(const SectionRef &Section) const;
813 COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
814 COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
815 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
816 unsigned getSectionID(SectionRef Sec) const;
817 unsigned getSymbolSectionID(SymbolRef Sym) const;
819 uint8_t getBytesInAddress() const override;
820 StringRef getFileFormatName() const override;
821 unsigned getArch() const override;
822 SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
824 import_directory_iterator import_directory_begin() const;
825 import_directory_iterator import_directory_end() const;
826 delay_import_directory_iterator delay_import_directory_begin() const;
827 delay_import_directory_iterator delay_import_directory_end() const;
828 export_directory_iterator export_directory_begin() const;
829 export_directory_iterator export_directory_end() const;
830 base_reloc_iterator base_reloc_begin() const;
831 base_reloc_iterator base_reloc_end() const;
832 const debug_directory *debug_directory_begin() const {
833 return DebugDirectoryBegin;
835 const debug_directory *debug_directory_end() const {
836 return DebugDirectoryEnd;
839 iterator_range<import_directory_iterator> import_directories() const;
840 iterator_range<delay_import_directory_iterator>
841 delay_import_directories() const;
842 iterator_range<export_directory_iterator> export_directories() const;
843 iterator_range<base_reloc_iterator> base_relocs() const;
844 iterator_range<const debug_directory *> debug_directories() const {
845 return make_range(debug_directory_begin(), debug_directory_end());
848 const dos_header *getDOSHeader() const {
849 if (!PE32Header && !PE32PlusHeader)
851 return reinterpret_cast<const dos_header *>(base());
853 std::error_code getPE32Header(const pe32_header *&Res) const;
854 std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
855 std::error_code getDataDirectory(uint32_t index,
856 const data_directory *&Res) const;
857 std::error_code getSection(int32_t index, const coff_section *&Res) const;
859 template <typename coff_symbol_type>
860 std::error_code getSymbol(uint32_t Index,
861 const coff_symbol_type *&Res) const {
862 if (Index >= getNumberOfSymbols())
863 return object_error::parse_failed;
865 Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
866 return std::error_code();
868 ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const {
870 const coff_symbol16 *Symb = nullptr;
871 if (std::error_code EC = getSymbol(index, Symb))
873 return COFFSymbolRef(Symb);
876 const coff_symbol32 *Symb = nullptr;
877 if (std::error_code EC = getSymbol(index, Symb))
879 return COFFSymbolRef(Symb);
881 return object_error::parse_failed;
884 template <typename T>
885 std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
886 ErrorOr<COFFSymbolRef> s = getSymbol(index);
887 if (std::error_code EC = s.getError())
889 Res = reinterpret_cast<const T *>(s->getRawPtr());
890 return std::error_code();
893 std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
894 std::error_code getSymbolName(const coff_symbol_generic *Symbol,
895 StringRef &Res) const;
897 ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
899 size_t getSymbolTableEntrySize() const {
901 return sizeof(coff_symbol16);
902 if (COFFBigObjHeader)
903 return sizeof(coff_symbol32);
904 llvm_unreachable("null symbol table pointer!");
907 iterator_range<const coff_relocation *>
908 getRelocations(const coff_section *Sec) const;
910 std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
911 uint64_t getSectionSize(const coff_section *Sec) const;
912 std::error_code getSectionContents(const coff_section *Sec,
913 ArrayRef<uint8_t> &Res) const;
915 uint64_t getImageBase() const;
916 std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
917 std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
919 /// Given an RVA base and size, returns a valid array of bytes or an error
920 /// code if the RVA and size is not contained completely within a valid
922 std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
923 ArrayRef<uint8_t> &Contents) const;
925 std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
926 StringRef &Name) const;
928 /// Get PDB information out of a codeview debug directory entry.
929 std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
930 const codeview::DebugInfo *&Info,
931 StringRef &PDBFileName) const;
933 /// Get PDB information from an executable. If the information is not present,
934 /// Info will be set to nullptr and PDBFileName will be empty. An error is
935 /// returned only on corrupt object files. Convenience accessor that can be
936 /// used if the debug directory is not already handy.
937 std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info,
938 StringRef &PDBFileName) const;
940 bool isRelocatableObject() const override;
941 bool is64() const { return PE32PlusHeader; }
943 static inline bool classof(const Binary *v) { return v->isCOFF(); }
946 // The iterator for the import directory table.
947 class ImportDirectoryEntryRef {
949 ImportDirectoryEntryRef() = default;
950 ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table,
951 uint32_t I, const COFFObjectFile *Owner)
952 : ImportTable(Table), Index(I), OwningObject(Owner) {}
954 bool operator==(const ImportDirectoryEntryRef &Other) const;
957 imported_symbol_iterator imported_symbol_begin() const;
958 imported_symbol_iterator imported_symbol_end() const;
959 iterator_range<imported_symbol_iterator> imported_symbols() const;
961 imported_symbol_iterator lookup_table_begin() const;
962 imported_symbol_iterator lookup_table_end() const;
963 iterator_range<imported_symbol_iterator> lookup_table_symbols() const;
965 std::error_code getName(StringRef &Result) const;
966 std::error_code getImportLookupTableRVA(uint32_t &Result) const;
967 std::error_code getImportAddressTableRVA(uint32_t &Result) const;
970 getImportTableEntry(const coff_import_directory_table_entry *&Result) const;
973 const coff_import_directory_table_entry *ImportTable;
975 const COFFObjectFile *OwningObject = nullptr;
978 class DelayImportDirectoryEntryRef {
980 DelayImportDirectoryEntryRef() = default;
981 DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
982 uint32_t I, const COFFObjectFile *Owner)
983 : Table(T), Index(I), OwningObject(Owner) {}
985 bool operator==(const DelayImportDirectoryEntryRef &Other) const;
988 imported_symbol_iterator imported_symbol_begin() const;
989 imported_symbol_iterator imported_symbol_end() const;
990 iterator_range<imported_symbol_iterator> imported_symbols() const;
992 std::error_code getName(StringRef &Result) const;
993 std::error_code getDelayImportTable(
994 const delay_import_directory_table_entry *&Result) const;
995 std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const;
998 const delay_import_directory_table_entry *Table;
1000 const COFFObjectFile *OwningObject = nullptr;
1003 // The iterator for the export directory table entry.
1004 class ExportDirectoryEntryRef {
1006 ExportDirectoryEntryRef() = default;
1007 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
1008 const COFFObjectFile *Owner)
1009 : ExportTable(Table), Index(I), OwningObject(Owner) {}
1011 bool operator==(const ExportDirectoryEntryRef &Other) const;
1014 std::error_code getDllName(StringRef &Result) const;
1015 std::error_code getOrdinalBase(uint32_t &Result) const;
1016 std::error_code getOrdinal(uint32_t &Result) const;
1017 std::error_code getExportRVA(uint32_t &Result) const;
1018 std::error_code getSymbolName(StringRef &Result) const;
1020 std::error_code isForwarder(bool &Result) const;
1021 std::error_code getForwardTo(StringRef &Result) const;
1024 const export_directory_table_entry *ExportTable;
1026 const COFFObjectFile *OwningObject = nullptr;
1029 class ImportedSymbolRef {
1031 ImportedSymbolRef() = default;
1032 ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
1033 const COFFObjectFile *Owner)
1034 : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
1035 ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
1036 const COFFObjectFile *Owner)
1037 : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}
1039 bool operator==(const ImportedSymbolRef &Other) const;
1042 std::error_code getSymbolName(StringRef &Result) const;
1043 std::error_code isOrdinal(bool &Result) const;
1044 std::error_code getOrdinal(uint16_t &Result) const;
1045 std::error_code getHintNameRVA(uint32_t &Result) const;
1048 const import_lookup_table_entry32 *Entry32;
1049 const import_lookup_table_entry64 *Entry64;
1051 const COFFObjectFile *OwningObject = nullptr;
1054 class BaseRelocRef {
1056 BaseRelocRef() = default;
1057 BaseRelocRef(const coff_base_reloc_block_header *Header,
1058 const COFFObjectFile *Owner)
1059 : Header(Header), Index(0), OwningObject(Owner) {}
1061 bool operator==(const BaseRelocRef &Other) const;
1064 std::error_code getType(uint8_t &Type) const;
1065 std::error_code getRVA(uint32_t &Result) const;
1068 const coff_base_reloc_block_header *Header;
1070 const COFFObjectFile *OwningObject = nullptr;
1073 class ResourceSectionRef {
1075 ResourceSectionRef() = default;
1076 explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
1078 ErrorOr<ArrayRef<UTF16>> getEntryNameString(const coff_resource_dir_entry &Entry);
1079 ErrorOr<const coff_resource_dir_table &>
1080 getEntrySubDir(const coff_resource_dir_entry &Entry);
1081 ErrorOr<const coff_resource_dir_table &> getBaseTable();
1084 BinaryByteStream BBS;
1086 ErrorOr<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
1087 ErrorOr<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
1090 // Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
1092 support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
1093 support::ulittle32_t Size; // cbProcSize: # bytes in function
1094 support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
1095 support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
1096 support::ulittle16_t Attributes;
1098 // cbProlog: # bytes in prolog
1099 int getPrologSize() const { return Attributes & 0xF; }
1101 // cbRegs: # regs saved
1102 int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
1104 // fHasSEH: true if seh is func
1105 bool hasSEH() const { return (Attributes >> 9) & 1; }
1107 // fUseBP: true if EBP has been allocated
1108 bool useBP() const { return (Attributes >> 10) & 1; }
1110 // cbFrame: frame pointer
1111 int getFP() const { return Attributes >> 14; }
1114 } // end namespace object
1116 } // end namespace llvm
1118 #endif // LLVM_OBJECT_COFF_H