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 getSectionIndex(DataRefImpl Sec) const override;
786 uint64_t getSectionSize(DataRefImpl Sec) const override;
787 std::error_code getSectionContents(DataRefImpl Sec,
788 StringRef &Res) const override;
789 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
790 bool isSectionCompressed(DataRefImpl Sec) const override;
791 bool isSectionText(DataRefImpl Sec) const override;
792 bool isSectionData(DataRefImpl Sec) const override;
793 bool isSectionBSS(DataRefImpl Sec) const override;
794 bool isSectionVirtual(DataRefImpl Sec) const override;
795 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
796 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
798 void moveRelocationNext(DataRefImpl &Rel) const override;
799 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
800 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
801 uint64_t getRelocationType(DataRefImpl Rel) const override;
802 void getRelocationTypeName(DataRefImpl Rel,
803 SmallVectorImpl<char> &Result) const override;
806 COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
808 basic_symbol_iterator symbol_begin() const override;
809 basic_symbol_iterator symbol_end() const override;
810 section_iterator section_begin() const override;
811 section_iterator section_end() const override;
813 const coff_section *getCOFFSection(const SectionRef &Section) const;
814 COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
815 COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
816 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
817 unsigned getSectionID(SectionRef Sec) const;
818 unsigned getSymbolSectionID(SymbolRef Sym) const;
820 uint8_t getBytesInAddress() const override;
821 StringRef getFileFormatName() const override;
822 unsigned getArch() const override;
823 SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
825 import_directory_iterator import_directory_begin() const;
826 import_directory_iterator import_directory_end() const;
827 delay_import_directory_iterator delay_import_directory_begin() const;
828 delay_import_directory_iterator delay_import_directory_end() const;
829 export_directory_iterator export_directory_begin() const;
830 export_directory_iterator export_directory_end() const;
831 base_reloc_iterator base_reloc_begin() const;
832 base_reloc_iterator base_reloc_end() const;
833 const debug_directory *debug_directory_begin() const {
834 return DebugDirectoryBegin;
836 const debug_directory *debug_directory_end() const {
837 return DebugDirectoryEnd;
840 iterator_range<import_directory_iterator> import_directories() const;
841 iterator_range<delay_import_directory_iterator>
842 delay_import_directories() const;
843 iterator_range<export_directory_iterator> export_directories() const;
844 iterator_range<base_reloc_iterator> base_relocs() const;
845 iterator_range<const debug_directory *> debug_directories() const {
846 return make_range(debug_directory_begin(), debug_directory_end());
849 const dos_header *getDOSHeader() const {
850 if (!PE32Header && !PE32PlusHeader)
852 return reinterpret_cast<const dos_header *>(base());
854 std::error_code getPE32Header(const pe32_header *&Res) const;
855 std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
856 std::error_code getDataDirectory(uint32_t index,
857 const data_directory *&Res) const;
858 std::error_code getSection(int32_t index, const coff_section *&Res) const;
860 template <typename coff_symbol_type>
861 std::error_code getSymbol(uint32_t Index,
862 const coff_symbol_type *&Res) const {
863 if (Index >= getNumberOfSymbols())
864 return object_error::parse_failed;
866 Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
867 return std::error_code();
869 ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const {
871 const coff_symbol16 *Symb = nullptr;
872 if (std::error_code EC = getSymbol(index, Symb))
874 return COFFSymbolRef(Symb);
877 const coff_symbol32 *Symb = nullptr;
878 if (std::error_code EC = getSymbol(index, Symb))
880 return COFFSymbolRef(Symb);
882 return object_error::parse_failed;
885 template <typename T>
886 std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
887 ErrorOr<COFFSymbolRef> s = getSymbol(index);
888 if (std::error_code EC = s.getError())
890 Res = reinterpret_cast<const T *>(s->getRawPtr());
891 return std::error_code();
894 std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
895 std::error_code getSymbolName(const coff_symbol_generic *Symbol,
896 StringRef &Res) const;
898 ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
900 size_t getSymbolTableEntrySize() const {
902 return sizeof(coff_symbol16);
903 if (COFFBigObjHeader)
904 return sizeof(coff_symbol32);
905 llvm_unreachable("null symbol table pointer!");
908 iterator_range<const coff_relocation *>
909 getRelocations(const coff_section *Sec) const;
911 std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
912 uint64_t getSectionSize(const coff_section *Sec) const;
913 std::error_code getSectionContents(const coff_section *Sec,
914 ArrayRef<uint8_t> &Res) const;
916 uint64_t getImageBase() const;
917 std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
918 std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
920 /// Given an RVA base and size, returns a valid array of bytes or an error
921 /// code if the RVA and size is not contained completely within a valid
923 std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
924 ArrayRef<uint8_t> &Contents) const;
926 std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
927 StringRef &Name) const;
929 /// Get PDB information out of a codeview debug directory entry.
930 std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
931 const codeview::DebugInfo *&Info,
932 StringRef &PDBFileName) const;
934 /// Get PDB information from an executable. If the information is not present,
935 /// Info will be set to nullptr and PDBFileName will be empty. An error is
936 /// returned only on corrupt object files. Convenience accessor that can be
937 /// used if the debug directory is not already handy.
938 std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info,
939 StringRef &PDBFileName) const;
941 bool isRelocatableObject() const override;
942 bool is64() const { return PE32PlusHeader; }
944 static inline bool classof(const Binary *v) { return v->isCOFF(); }
947 // The iterator for the import directory table.
948 class ImportDirectoryEntryRef {
950 ImportDirectoryEntryRef() = default;
951 ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table,
952 uint32_t I, const COFFObjectFile *Owner)
953 : ImportTable(Table), Index(I), OwningObject(Owner) {}
955 bool operator==(const ImportDirectoryEntryRef &Other) const;
958 imported_symbol_iterator imported_symbol_begin() const;
959 imported_symbol_iterator imported_symbol_end() const;
960 iterator_range<imported_symbol_iterator> imported_symbols() const;
962 imported_symbol_iterator lookup_table_begin() const;
963 imported_symbol_iterator lookup_table_end() const;
964 iterator_range<imported_symbol_iterator> lookup_table_symbols() const;
966 std::error_code getName(StringRef &Result) const;
967 std::error_code getImportLookupTableRVA(uint32_t &Result) const;
968 std::error_code getImportAddressTableRVA(uint32_t &Result) const;
971 getImportTableEntry(const coff_import_directory_table_entry *&Result) const;
974 const coff_import_directory_table_entry *ImportTable;
976 const COFFObjectFile *OwningObject = nullptr;
979 class DelayImportDirectoryEntryRef {
981 DelayImportDirectoryEntryRef() = default;
982 DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
983 uint32_t I, const COFFObjectFile *Owner)
984 : Table(T), Index(I), OwningObject(Owner) {}
986 bool operator==(const DelayImportDirectoryEntryRef &Other) const;
989 imported_symbol_iterator imported_symbol_begin() const;
990 imported_symbol_iterator imported_symbol_end() const;
991 iterator_range<imported_symbol_iterator> imported_symbols() const;
993 std::error_code getName(StringRef &Result) const;
994 std::error_code getDelayImportTable(
995 const delay_import_directory_table_entry *&Result) const;
996 std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const;
999 const delay_import_directory_table_entry *Table;
1001 const COFFObjectFile *OwningObject = nullptr;
1004 // The iterator for the export directory table entry.
1005 class ExportDirectoryEntryRef {
1007 ExportDirectoryEntryRef() = default;
1008 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
1009 const COFFObjectFile *Owner)
1010 : ExportTable(Table), Index(I), OwningObject(Owner) {}
1012 bool operator==(const ExportDirectoryEntryRef &Other) const;
1015 std::error_code getDllName(StringRef &Result) const;
1016 std::error_code getOrdinalBase(uint32_t &Result) const;
1017 std::error_code getOrdinal(uint32_t &Result) const;
1018 std::error_code getExportRVA(uint32_t &Result) const;
1019 std::error_code getSymbolName(StringRef &Result) const;
1021 std::error_code isForwarder(bool &Result) const;
1022 std::error_code getForwardTo(StringRef &Result) const;
1025 const export_directory_table_entry *ExportTable;
1027 const COFFObjectFile *OwningObject = nullptr;
1030 class ImportedSymbolRef {
1032 ImportedSymbolRef() = default;
1033 ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
1034 const COFFObjectFile *Owner)
1035 : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
1036 ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
1037 const COFFObjectFile *Owner)
1038 : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}
1040 bool operator==(const ImportedSymbolRef &Other) const;
1043 std::error_code getSymbolName(StringRef &Result) const;
1044 std::error_code isOrdinal(bool &Result) const;
1045 std::error_code getOrdinal(uint16_t &Result) const;
1046 std::error_code getHintNameRVA(uint32_t &Result) const;
1049 const import_lookup_table_entry32 *Entry32;
1050 const import_lookup_table_entry64 *Entry64;
1052 const COFFObjectFile *OwningObject = nullptr;
1055 class BaseRelocRef {
1057 BaseRelocRef() = default;
1058 BaseRelocRef(const coff_base_reloc_block_header *Header,
1059 const COFFObjectFile *Owner)
1060 : Header(Header), Index(0), OwningObject(Owner) {}
1062 bool operator==(const BaseRelocRef &Other) const;
1065 std::error_code getType(uint8_t &Type) const;
1066 std::error_code getRVA(uint32_t &Result) const;
1069 const coff_base_reloc_block_header *Header;
1071 const COFFObjectFile *OwningObject = nullptr;
1074 class ResourceSectionRef {
1076 ResourceSectionRef() = default;
1077 explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
1079 ErrorOr<ArrayRef<UTF16>> getEntryNameString(const coff_resource_dir_entry &Entry);
1080 ErrorOr<const coff_resource_dir_table &>
1081 getEntrySubDir(const coff_resource_dir_entry &Entry);
1082 ErrorOr<const coff_resource_dir_table &> getBaseTable();
1085 BinaryByteStream BBS;
1087 ErrorOr<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
1088 ErrorOr<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
1091 // Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
1093 support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
1094 support::ulittle32_t Size; // cbProcSize: # bytes in function
1095 support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
1096 support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
1097 support::ulittle16_t Attributes;
1099 // cbProlog: # bytes in prolog
1100 int getPrologSize() const { return Attributes & 0xF; }
1102 // cbRegs: # regs saved
1103 int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
1105 // fHasSEH: true if seh is func
1106 bool hasSEH() const { return (Attributes >> 9) & 1; }
1108 // fUseBP: true if EBP has been allocated
1109 bool useBP() const { return (Attributes >> 10) & 1; }
1111 // cbFrame: frame pointer
1112 int getFP() const { return Attributes >> 14; }
1115 } // end namespace object
1117 } // end namespace llvm
1119 #endif // LLVM_OBJECT_COFF_H