1 //===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares the COFFObjectFile class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_OBJECT_COFF_H 15 #define LLVM_OBJECT_COFF_H 16 17 #include "llvm/ADT/iterator_range.h" 18 #include "llvm/BinaryFormat/COFF.h" 19 #include "llvm/MC/SubtargetFeature.h" 20 #include "llvm/Object/Binary.h" 21 #include "llvm/Object/CVDebugRecord.h" 22 #include "llvm/Object/Error.h" 23 #include "llvm/Object/ObjectFile.h" 24 #include "llvm/Support/BinaryByteStream.h" 25 #include "llvm/Support/ConvertUTF.h" 26 #include "llvm/Support/Endian.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include <cassert> 29 #include <cstddef> 30 #include <cstdint> 31 #include <system_error> 32 33 namespace llvm { 34 35 template <typename T> class ArrayRef; 36 37 namespace object { 38 39 class BaseRelocRef; 40 class DelayImportDirectoryEntryRef; 41 class ExportDirectoryEntryRef; 42 class ImportDirectoryEntryRef; 43 class ImportedSymbolRef; 44 class ResourceSectionRef; 45 46 using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>; 47 using delay_import_directory_iterator = 48 content_iterator<DelayImportDirectoryEntryRef>; 49 using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>; 50 using imported_symbol_iterator = content_iterator<ImportedSymbolRef>; 51 using base_reloc_iterator = content_iterator<BaseRelocRef>; 52 53 /// The DOS compatible header at the front of all PE/COFF executables. 54 struct dos_header { 55 char Magic[2]; 56 support::ulittle16_t UsedBytesInTheLastPage; 57 support::ulittle16_t FileSizeInPages; 58 support::ulittle16_t NumberOfRelocationItems; 59 support::ulittle16_t HeaderSizeInParagraphs; 60 support::ulittle16_t MinimumExtraParagraphs; 61 support::ulittle16_t MaximumExtraParagraphs; 62 support::ulittle16_t InitialRelativeSS; 63 support::ulittle16_t InitialSP; 64 support::ulittle16_t Checksum; 65 support::ulittle16_t InitialIP; 66 support::ulittle16_t InitialRelativeCS; 67 support::ulittle16_t AddressOfRelocationTable; 68 support::ulittle16_t OverlayNumber; 69 support::ulittle16_t Reserved[4]; 70 support::ulittle16_t OEMid; 71 support::ulittle16_t OEMinfo; 72 support::ulittle16_t Reserved2[10]; 73 support::ulittle32_t AddressOfNewExeHeader; 74 }; 75 76 struct coff_file_header { 77 support::ulittle16_t Machine; 78 support::ulittle16_t NumberOfSections; 79 support::ulittle32_t TimeDateStamp; 80 support::ulittle32_t PointerToSymbolTable; 81 support::ulittle32_t NumberOfSymbols; 82 support::ulittle16_t SizeOfOptionalHeader; 83 support::ulittle16_t Characteristics; 84 isImportLibrarycoff_file_header85 bool isImportLibrary() const { return NumberOfSections == 0xffff; } 86 }; 87 88 struct coff_bigobj_file_header { 89 support::ulittle16_t Sig1; 90 support::ulittle16_t Sig2; 91 support::ulittle16_t Version; 92 support::ulittle16_t Machine; 93 support::ulittle32_t TimeDateStamp; 94 uint8_t UUID[16]; 95 support::ulittle32_t unused1; 96 support::ulittle32_t unused2; 97 support::ulittle32_t unused3; 98 support::ulittle32_t unused4; 99 support::ulittle32_t NumberOfSections; 100 support::ulittle32_t PointerToSymbolTable; 101 support::ulittle32_t NumberOfSymbols; 102 }; 103 104 /// The 32-bit PE header that follows the COFF header. 105 struct pe32_header { 106 support::ulittle16_t Magic; 107 uint8_t MajorLinkerVersion; 108 uint8_t MinorLinkerVersion; 109 support::ulittle32_t SizeOfCode; 110 support::ulittle32_t SizeOfInitializedData; 111 support::ulittle32_t SizeOfUninitializedData; 112 support::ulittle32_t AddressOfEntryPoint; 113 support::ulittle32_t BaseOfCode; 114 support::ulittle32_t BaseOfData; 115 support::ulittle32_t ImageBase; 116 support::ulittle32_t SectionAlignment; 117 support::ulittle32_t FileAlignment; 118 support::ulittle16_t MajorOperatingSystemVersion; 119 support::ulittle16_t MinorOperatingSystemVersion; 120 support::ulittle16_t MajorImageVersion; 121 support::ulittle16_t MinorImageVersion; 122 support::ulittle16_t MajorSubsystemVersion; 123 support::ulittle16_t MinorSubsystemVersion; 124 support::ulittle32_t Win32VersionValue; 125 support::ulittle32_t SizeOfImage; 126 support::ulittle32_t SizeOfHeaders; 127 support::ulittle32_t CheckSum; 128 support::ulittle16_t Subsystem; 129 // FIXME: This should be DllCharacteristics. 130 support::ulittle16_t DLLCharacteristics; 131 support::ulittle32_t SizeOfStackReserve; 132 support::ulittle32_t SizeOfStackCommit; 133 support::ulittle32_t SizeOfHeapReserve; 134 support::ulittle32_t SizeOfHeapCommit; 135 support::ulittle32_t LoaderFlags; 136 // FIXME: This should be NumberOfRvaAndSizes. 137 support::ulittle32_t NumberOfRvaAndSize; 138 }; 139 140 /// The 64-bit PE header that follows the COFF header. 141 struct pe32plus_header { 142 support::ulittle16_t Magic; 143 uint8_t MajorLinkerVersion; 144 uint8_t MinorLinkerVersion; 145 support::ulittle32_t SizeOfCode; 146 support::ulittle32_t SizeOfInitializedData; 147 support::ulittle32_t SizeOfUninitializedData; 148 support::ulittle32_t AddressOfEntryPoint; 149 support::ulittle32_t BaseOfCode; 150 support::ulittle64_t ImageBase; 151 support::ulittle32_t SectionAlignment; 152 support::ulittle32_t FileAlignment; 153 support::ulittle16_t MajorOperatingSystemVersion; 154 support::ulittle16_t MinorOperatingSystemVersion; 155 support::ulittle16_t MajorImageVersion; 156 support::ulittle16_t MinorImageVersion; 157 support::ulittle16_t MajorSubsystemVersion; 158 support::ulittle16_t MinorSubsystemVersion; 159 support::ulittle32_t Win32VersionValue; 160 support::ulittle32_t SizeOfImage; 161 support::ulittle32_t SizeOfHeaders; 162 support::ulittle32_t CheckSum; 163 support::ulittle16_t Subsystem; 164 support::ulittle16_t DLLCharacteristics; 165 support::ulittle64_t SizeOfStackReserve; 166 support::ulittle64_t SizeOfStackCommit; 167 support::ulittle64_t SizeOfHeapReserve; 168 support::ulittle64_t SizeOfHeapCommit; 169 support::ulittle32_t LoaderFlags; 170 support::ulittle32_t NumberOfRvaAndSize; 171 }; 172 173 struct data_directory { 174 support::ulittle32_t RelativeVirtualAddress; 175 support::ulittle32_t Size; 176 }; 177 178 struct debug_directory { 179 support::ulittle32_t Characteristics; 180 support::ulittle32_t TimeDateStamp; 181 support::ulittle16_t MajorVersion; 182 support::ulittle16_t MinorVersion; 183 support::ulittle32_t Type; 184 support::ulittle32_t SizeOfData; 185 support::ulittle32_t AddressOfRawData; 186 support::ulittle32_t PointerToRawData; 187 }; 188 189 template <typename IntTy> 190 struct import_lookup_table_entry { 191 IntTy Data; 192 isOrdinalimport_lookup_table_entry193 bool isOrdinal() const { return Data < 0; } 194 getOrdinalimport_lookup_table_entry195 uint16_t getOrdinal() const { 196 assert(isOrdinal() && "ILT entry is not an ordinal!"); 197 return Data & 0xFFFF; 198 } 199 getHintNameRVAimport_lookup_table_entry200 uint32_t getHintNameRVA() const { 201 assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); 202 return Data & 0xFFFFFFFF; 203 } 204 }; 205 206 using import_lookup_table_entry32 = 207 import_lookup_table_entry<support::little32_t>; 208 using import_lookup_table_entry64 = 209 import_lookup_table_entry<support::little64_t>; 210 211 struct delay_import_directory_table_entry { 212 // dumpbin reports this field as "Characteristics" instead of "Attributes". 213 support::ulittle32_t Attributes; 214 support::ulittle32_t Name; 215 support::ulittle32_t ModuleHandle; 216 support::ulittle32_t DelayImportAddressTable; 217 support::ulittle32_t DelayImportNameTable; 218 support::ulittle32_t BoundDelayImportTable; 219 support::ulittle32_t UnloadDelayImportTable; 220 support::ulittle32_t TimeStamp; 221 }; 222 223 struct export_directory_table_entry { 224 support::ulittle32_t ExportFlags; 225 support::ulittle32_t TimeDateStamp; 226 support::ulittle16_t MajorVersion; 227 support::ulittle16_t MinorVersion; 228 support::ulittle32_t NameRVA; 229 support::ulittle32_t OrdinalBase; 230 support::ulittle32_t AddressTableEntries; 231 support::ulittle32_t NumberOfNamePointers; 232 support::ulittle32_t ExportAddressTableRVA; 233 support::ulittle32_t NamePointerRVA; 234 support::ulittle32_t OrdinalTableRVA; 235 }; 236 237 union export_address_table_entry { 238 support::ulittle32_t ExportRVA; 239 support::ulittle32_t ForwarderRVA; 240 }; 241 242 using export_name_pointer_table_entry = support::ulittle32_t; 243 using export_ordinal_table_entry = support::ulittle16_t; 244 245 struct StringTableOffset { 246 support::ulittle32_t Zeroes; 247 support::ulittle32_t Offset; 248 }; 249 250 template <typename SectionNumberType> 251 struct coff_symbol { 252 union { 253 char ShortName[COFF::NameSize]; 254 StringTableOffset Offset; 255 } Name; 256 257 support::ulittle32_t Value; 258 SectionNumberType SectionNumber; 259 260 support::ulittle16_t Type; 261 262 uint8_t StorageClass; 263 uint8_t NumberOfAuxSymbols; 264 }; 265 266 using coff_symbol16 = coff_symbol<support::ulittle16_t>; 267 using coff_symbol32 = coff_symbol<support::ulittle32_t>; 268 269 // Contains only common parts of coff_symbol16 and coff_symbol32. 270 struct coff_symbol_generic { 271 union { 272 char ShortName[COFF::NameSize]; 273 StringTableOffset Offset; 274 } Name; 275 support::ulittle32_t Value; 276 }; 277 278 struct coff_aux_section_definition; 279 struct coff_aux_weak_external; 280 281 class COFFSymbolRef { 282 public: 283 COFFSymbolRef() = default; COFFSymbolRef(const coff_symbol16 * CS)284 COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {} COFFSymbolRef(const coff_symbol32 * CS)285 COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {} 286 getRawPtr()287 const void *getRawPtr() const { 288 return CS16 ? static_cast<const void *>(CS16) : CS32; 289 } 290 getGeneric()291 const coff_symbol_generic *getGeneric() const { 292 if (CS16) 293 return reinterpret_cast<const coff_symbol_generic *>(CS16); 294 return reinterpret_cast<const coff_symbol_generic *>(CS32); 295 } 296 297 friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { 298 return A.getRawPtr() < B.getRawPtr(); 299 } 300 isBigObj()301 bool isBigObj() const { 302 if (CS16) 303 return false; 304 if (CS32) 305 return true; 306 llvm_unreachable("COFFSymbolRef points to nothing!"); 307 } 308 getShortName()309 const char *getShortName() const { 310 return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; 311 } 312 getStringTableOffset()313 const StringTableOffset &getStringTableOffset() const { 314 assert(isSet() && "COFFSymbolRef points to nothing!"); 315 return CS16 ? CS16->Name.Offset : CS32->Name.Offset; 316 } 317 getValue()318 uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } 319 getSectionNumber()320 int32_t getSectionNumber() const { 321 assert(isSet() && "COFFSymbolRef points to nothing!"); 322 if (CS16) { 323 // Reserved sections are returned as negative numbers. 324 if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) 325 return CS16->SectionNumber; 326 return static_cast<int16_t>(CS16->SectionNumber); 327 } 328 return static_cast<int32_t>(CS32->SectionNumber); 329 } 330 getType()331 uint16_t getType() const { 332 assert(isSet() && "COFFSymbolRef points to nothing!"); 333 return CS16 ? CS16->Type : CS32->Type; 334 } 335 getStorageClass()336 uint8_t getStorageClass() const { 337 assert(isSet() && "COFFSymbolRef points to nothing!"); 338 return CS16 ? CS16->StorageClass : CS32->StorageClass; 339 } 340 getNumberOfAuxSymbols()341 uint8_t getNumberOfAuxSymbols() const { 342 assert(isSet() && "COFFSymbolRef points to nothing!"); 343 return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; 344 } 345 getBaseType()346 uint8_t getBaseType() const { return getType() & 0x0F; } 347 getComplexType()348 uint8_t getComplexType() const { 349 return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; 350 } 351 getAux()352 template <typename T> const T *getAux() const { 353 return CS16 ? reinterpret_cast<const T *>(CS16 + 1) 354 : reinterpret_cast<const T *>(CS32 + 1); 355 } 356 getSectionDefinition()357 const coff_aux_section_definition *getSectionDefinition() const { 358 if (!getNumberOfAuxSymbols() || 359 getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC) 360 return nullptr; 361 return getAux<coff_aux_section_definition>(); 362 } 363 getWeakExternal()364 const coff_aux_weak_external *getWeakExternal() const { 365 if (!getNumberOfAuxSymbols() || 366 getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 367 return nullptr; 368 return getAux<coff_aux_weak_external>(); 369 } 370 isAbsolute()371 bool isAbsolute() const { 372 return getSectionNumber() == -1; 373 } 374 isExternal()375 bool isExternal() const { 376 return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; 377 } 378 isCommon()379 bool isCommon() const { 380 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 381 getValue() != 0; 382 } 383 isUndefined()384 bool isUndefined() const { 385 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 386 getValue() == 0; 387 } 388 isWeakExternal()389 bool isWeakExternal() const { 390 return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; 391 } 392 isFunctionDefinition()393 bool isFunctionDefinition() const { 394 return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && 395 getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && 396 !COFF::isReservedSectionNumber(getSectionNumber()); 397 } 398 isFunctionLineInfo()399 bool isFunctionLineInfo() const { 400 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; 401 } 402 isAnyUndefined()403 bool isAnyUndefined() const { 404 return isUndefined() || isWeakExternal(); 405 } 406 isFileRecord()407 bool isFileRecord() const { 408 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; 409 } 410 isSection()411 bool isSection() const { 412 return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; 413 } 414 isSectionDefinition()415 bool isSectionDefinition() const { 416 // C++/CLI creates external ABS symbols for non-const appdomain globals. 417 // These are also followed by an auxiliary section definition. 418 bool isAppdomainGlobal = 419 getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && 420 getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; 421 bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; 422 if (!getNumberOfAuxSymbols()) 423 return false; 424 return isAppdomainGlobal || isOrdinarySection; 425 } 426 isCLRToken()427 bool isCLRToken() const { 428 return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; 429 } 430 431 private: isSet()432 bool isSet() const { return CS16 || CS32; } 433 434 const coff_symbol16 *CS16 = nullptr; 435 const coff_symbol32 *CS32 = nullptr; 436 }; 437 438 struct coff_section { 439 char Name[COFF::NameSize]; 440 support::ulittle32_t VirtualSize; 441 support::ulittle32_t VirtualAddress; 442 support::ulittle32_t SizeOfRawData; 443 support::ulittle32_t PointerToRawData; 444 support::ulittle32_t PointerToRelocations; 445 support::ulittle32_t PointerToLinenumbers; 446 support::ulittle16_t NumberOfRelocations; 447 support::ulittle16_t NumberOfLinenumbers; 448 support::ulittle32_t Characteristics; 449 450 // Returns true if the actual number of relocations is stored in 451 // VirtualAddress field of the first relocation table entry. hasExtendedRelocationscoff_section452 bool hasExtendedRelocations() const { 453 return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && 454 NumberOfRelocations == UINT16_MAX; 455 } 456 getAlignmentcoff_section457 uint32_t getAlignment() const { 458 // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to 459 // IMAGE_SCN_ALIGN_1BYTES. 460 if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) 461 return 1; 462 463 // Bit [20:24] contains section alignment. 0 means use a default alignment 464 // of 16. 465 uint32_t Shift = (Characteristics >> 20) & 0xF; 466 if (Shift > 0) 467 return 1U << (Shift - 1); 468 return 16; 469 } 470 }; 471 472 struct coff_relocation { 473 support::ulittle32_t VirtualAddress; 474 support::ulittle32_t SymbolTableIndex; 475 support::ulittle16_t Type; 476 }; 477 478 struct coff_aux_function_definition { 479 support::ulittle32_t TagIndex; 480 support::ulittle32_t TotalSize; 481 support::ulittle32_t PointerToLinenumber; 482 support::ulittle32_t PointerToNextFunction; 483 char Unused1[2]; 484 }; 485 486 static_assert(sizeof(coff_aux_function_definition) == 18, 487 "auxiliary entry must be 18 bytes"); 488 489 struct coff_aux_bf_and_ef_symbol { 490 char Unused1[4]; 491 support::ulittle16_t Linenumber; 492 char Unused2[6]; 493 support::ulittle32_t PointerToNextFunction; 494 char Unused3[2]; 495 }; 496 497 static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, 498 "auxiliary entry must be 18 bytes"); 499 500 struct coff_aux_weak_external { 501 support::ulittle32_t TagIndex; 502 support::ulittle32_t Characteristics; 503 char Unused1[10]; 504 }; 505 506 static_assert(sizeof(coff_aux_weak_external) == 18, 507 "auxiliary entry must be 18 bytes"); 508 509 struct coff_aux_section_definition { 510 support::ulittle32_t Length; 511 support::ulittle16_t NumberOfRelocations; 512 support::ulittle16_t NumberOfLinenumbers; 513 support::ulittle32_t CheckSum; 514 support::ulittle16_t NumberLowPart; 515 uint8_t Selection; 516 uint8_t Unused; 517 support::ulittle16_t NumberHighPart; getNumbercoff_aux_section_definition518 int32_t getNumber(bool IsBigObj) const { 519 uint32_t Number = static_cast<uint32_t>(NumberLowPart); 520 if (IsBigObj) 521 Number |= static_cast<uint32_t>(NumberHighPart) << 16; 522 return static_cast<int32_t>(Number); 523 } 524 }; 525 526 static_assert(sizeof(coff_aux_section_definition) == 18, 527 "auxiliary entry must be 18 bytes"); 528 529 struct coff_aux_clr_token { 530 uint8_t AuxType; 531 uint8_t Reserved; 532 support::ulittle32_t SymbolTableIndex; 533 char MBZ[12]; 534 }; 535 536 static_assert(sizeof(coff_aux_clr_token) == 18, 537 "auxiliary entry must be 18 bytes"); 538 539 struct coff_import_header { 540 support::ulittle16_t Sig1; 541 support::ulittle16_t Sig2; 542 support::ulittle16_t Version; 543 support::ulittle16_t Machine; 544 support::ulittle32_t TimeDateStamp; 545 support::ulittle32_t SizeOfData; 546 support::ulittle16_t OrdinalHint; 547 support::ulittle16_t TypeInfo; 548 getTypecoff_import_header549 int getType() const { return TypeInfo & 0x3; } getNameTypecoff_import_header550 int getNameType() const { return (TypeInfo >> 2) & 0x7; } 551 }; 552 553 struct coff_import_directory_table_entry { 554 support::ulittle32_t ImportLookupTableRVA; 555 support::ulittle32_t TimeDateStamp; 556 support::ulittle32_t ForwarderChain; 557 support::ulittle32_t NameRVA; 558 support::ulittle32_t ImportAddressTableRVA; 559 isNullcoff_import_directory_table_entry560 bool isNull() const { 561 return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && 562 ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0; 563 } 564 }; 565 566 template <typename IntTy> 567 struct coff_tls_directory { 568 IntTy StartAddressOfRawData; 569 IntTy EndAddressOfRawData; 570 IntTy AddressOfIndex; 571 IntTy AddressOfCallBacks; 572 support::ulittle32_t SizeOfZeroFill; 573 support::ulittle32_t Characteristics; 574 getAlignmentcoff_tls_directory575 uint32_t getAlignment() const { 576 // Bit [20:24] contains section alignment. 577 uint32_t Shift = (Characteristics & 0x00F00000) >> 20; 578 if (Shift > 0) 579 return 1U << (Shift - 1); 580 return 0; 581 } 582 }; 583 584 using coff_tls_directory32 = coff_tls_directory<support::little32_t>; 585 using coff_tls_directory64 = coff_tls_directory<support::little64_t>; 586 587 /// Bits in control flow guard flags as we understand them. 588 enum class coff_guard_flags : uint32_t { 589 CFInstrumented = 0x00000100, 590 HasFidTable = 0x00000400, 591 ProtectDelayLoadIAT = 0x00001000, 592 DelayLoadIATSection = 0x00002000, // Delay load in separate section 593 HasLongJmpTable = 0x00010000, 594 FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes 595 }; 596 597 enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 }; 598 599 struct coff_load_config_code_integrity { 600 support::ulittle16_t Flags; 601 support::ulittle16_t Catalog; 602 support::ulittle32_t CatalogOffset; 603 support::ulittle32_t Reserved; 604 }; 605 606 /// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) 607 struct coff_load_configuration32 { 608 support::ulittle32_t Size; 609 support::ulittle32_t TimeDateStamp; 610 support::ulittle16_t MajorVersion; 611 support::ulittle16_t MinorVersion; 612 support::ulittle32_t GlobalFlagsClear; 613 support::ulittle32_t GlobalFlagsSet; 614 support::ulittle32_t CriticalSectionDefaultTimeout; 615 support::ulittle32_t DeCommitFreeBlockThreshold; 616 support::ulittle32_t DeCommitTotalFreeThreshold; 617 support::ulittle32_t LockPrefixTable; 618 support::ulittle32_t MaximumAllocationSize; 619 support::ulittle32_t VirtualMemoryThreshold; 620 support::ulittle32_t ProcessAffinityMask; 621 support::ulittle32_t ProcessHeapFlags; 622 support::ulittle16_t CSDVersion; 623 support::ulittle16_t DependentLoadFlags; 624 support::ulittle32_t EditList; 625 support::ulittle32_t SecurityCookie; 626 support::ulittle32_t SEHandlerTable; 627 support::ulittle32_t SEHandlerCount; 628 629 // Added in MSVC 2015 for /guard:cf. 630 support::ulittle32_t GuardCFCheckFunction; 631 support::ulittle32_t GuardCFCheckDispatch; 632 support::ulittle32_t GuardCFFunctionTable; 633 support::ulittle32_t GuardCFFunctionCount; 634 support::ulittle32_t GuardFlags; // coff_guard_flags 635 636 // Added in MSVC 2017 637 coff_load_config_code_integrity CodeIntegrity; 638 support::ulittle32_t GuardAddressTakenIatEntryTable; 639 support::ulittle32_t GuardAddressTakenIatEntryCount; 640 support::ulittle32_t GuardLongJumpTargetTable; 641 support::ulittle32_t GuardLongJumpTargetCount; 642 support::ulittle32_t DynamicValueRelocTable; 643 support::ulittle32_t CHPEMetadataPointer; 644 support::ulittle32_t GuardRFFailureRoutine; 645 support::ulittle32_t GuardRFFailureRoutineFunctionPointer; 646 support::ulittle32_t DynamicValueRelocTableOffset; 647 support::ulittle16_t DynamicValueRelocTableSection; 648 support::ulittle16_t Reserved2; 649 support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; 650 support::ulittle32_t HotPatchTableOffset; 651 }; 652 653 /// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) 654 struct coff_load_configuration64 { 655 support::ulittle32_t Size; 656 support::ulittle32_t TimeDateStamp; 657 support::ulittle16_t MajorVersion; 658 support::ulittle16_t MinorVersion; 659 support::ulittle32_t GlobalFlagsClear; 660 support::ulittle32_t GlobalFlagsSet; 661 support::ulittle32_t CriticalSectionDefaultTimeout; 662 support::ulittle64_t DeCommitFreeBlockThreshold; 663 support::ulittle64_t DeCommitTotalFreeThreshold; 664 support::ulittle64_t LockPrefixTable; 665 support::ulittle64_t MaximumAllocationSize; 666 support::ulittle64_t VirtualMemoryThreshold; 667 support::ulittle64_t ProcessAffinityMask; 668 support::ulittle32_t ProcessHeapFlags; 669 support::ulittle16_t CSDVersion; 670 support::ulittle16_t DependentLoadFlags; 671 support::ulittle64_t EditList; 672 support::ulittle64_t SecurityCookie; 673 support::ulittle64_t SEHandlerTable; 674 support::ulittle64_t SEHandlerCount; 675 676 // Added in MSVC 2015 for /guard:cf. 677 support::ulittle64_t GuardCFCheckFunction; 678 support::ulittle64_t GuardCFCheckDispatch; 679 support::ulittle64_t GuardCFFunctionTable; 680 support::ulittle64_t GuardCFFunctionCount; 681 support::ulittle32_t GuardFlags; 682 683 // Added in MSVC 2017 684 coff_load_config_code_integrity CodeIntegrity; 685 support::ulittle64_t GuardAddressTakenIatEntryTable; 686 support::ulittle64_t GuardAddressTakenIatEntryCount; 687 support::ulittle64_t GuardLongJumpTargetTable; 688 support::ulittle64_t GuardLongJumpTargetCount; 689 support::ulittle64_t DynamicValueRelocTable; 690 support::ulittle64_t CHPEMetadataPointer; 691 support::ulittle64_t GuardRFFailureRoutine; 692 support::ulittle64_t GuardRFFailureRoutineFunctionPointer; 693 support::ulittle32_t DynamicValueRelocTableOffset; 694 support::ulittle16_t DynamicValueRelocTableSection; 695 support::ulittle16_t Reserved2; 696 support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; 697 support::ulittle32_t HotPatchTableOffset; 698 }; 699 700 struct coff_runtime_function_x64 { 701 support::ulittle32_t BeginAddress; 702 support::ulittle32_t EndAddress; 703 support::ulittle32_t UnwindInformation; 704 }; 705 706 struct coff_base_reloc_block_header { 707 support::ulittle32_t PageRVA; 708 support::ulittle32_t BlockSize; 709 }; 710 711 struct coff_base_reloc_block_entry { 712 support::ulittle16_t Data; 713 getTypecoff_base_reloc_block_entry714 int getType() const { return Data >> 12; } getOffsetcoff_base_reloc_block_entry715 int getOffset() const { return Data & ((1 << 12) - 1); } 716 }; 717 718 struct coff_resource_dir_entry { 719 union { 720 support::ulittle32_t NameOffset; 721 support::ulittle32_t ID; getNameOffset()722 uint32_t getNameOffset() const { 723 return maskTrailingOnes<uint32_t>(31) & NameOffset; 724 } 725 // Even though the PE/COFF spec doesn't mention this, the high bit of a name 726 // offset is set. setNameOffset(uint32_t Offset)727 void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); } 728 } Identifier; 729 union { 730 support::ulittle32_t DataEntryOffset; 731 support::ulittle32_t SubdirOffset; 732 isSubDir()733 bool isSubDir() const { return SubdirOffset >> 31; } value()734 uint32_t value() const { 735 return maskTrailingOnes<uint32_t>(31) & SubdirOffset; 736 } 737 738 } Offset; 739 }; 740 741 struct coff_resource_data_entry { 742 support::ulittle32_t DataRVA; 743 support::ulittle32_t DataSize; 744 support::ulittle32_t Codepage; 745 support::ulittle32_t Reserved; 746 }; 747 748 struct coff_resource_dir_table { 749 support::ulittle32_t Characteristics; 750 support::ulittle32_t TimeDateStamp; 751 support::ulittle16_t MajorVersion; 752 support::ulittle16_t MinorVersion; 753 support::ulittle16_t NumberOfNameEntries; 754 support::ulittle16_t NumberOfIDEntries; 755 }; 756 757 struct debug_h_header { 758 support::ulittle32_t Magic; 759 support::ulittle16_t Version; 760 support::ulittle16_t HashAlgorithm; 761 }; 762 763 class COFFObjectFile : public ObjectFile { 764 private: 765 friend class ImportDirectoryEntryRef; 766 friend class ExportDirectoryEntryRef; 767 const coff_file_header *COFFHeader; 768 const coff_bigobj_file_header *COFFBigObjHeader; 769 const pe32_header *PE32Header; 770 const pe32plus_header *PE32PlusHeader; 771 const data_directory *DataDirectory; 772 const coff_section *SectionTable; 773 const coff_symbol16 *SymbolTable16; 774 const coff_symbol32 *SymbolTable32; 775 const char *StringTable; 776 uint32_t StringTableSize; 777 const coff_import_directory_table_entry *ImportDirectory; 778 const delay_import_directory_table_entry *DelayImportDirectory; 779 uint32_t NumberOfDelayImportDirectory; 780 const export_directory_table_entry *ExportDirectory; 781 const coff_base_reloc_block_header *BaseRelocHeader; 782 const coff_base_reloc_block_header *BaseRelocEnd; 783 const debug_directory *DebugDirectoryBegin; 784 const debug_directory *DebugDirectoryEnd; 785 // Either coff_load_configuration32 or coff_load_configuration64. 786 const void *LoadConfig = nullptr; 787 788 std::error_code getString(uint32_t offset, StringRef &Res) const; 789 790 template <typename coff_symbol_type> 791 const coff_symbol_type *toSymb(DataRefImpl Symb) const; 792 const coff_section *toSec(DataRefImpl Sec) const; 793 const coff_relocation *toRel(DataRefImpl Rel) const; 794 795 std::error_code initSymbolTablePtr(); 796 std::error_code initImportTablePtr(); 797 std::error_code initDelayImportTablePtr(); 798 std::error_code initExportTablePtr(); 799 std::error_code initBaseRelocPtr(); 800 std::error_code initDebugDirectoryPtr(); 801 std::error_code initLoadConfigPtr(); 802 803 public: getSymbolTable()804 uintptr_t getSymbolTable() const { 805 if (SymbolTable16) 806 return reinterpret_cast<uintptr_t>(SymbolTable16); 807 if (SymbolTable32) 808 return reinterpret_cast<uintptr_t>(SymbolTable32); 809 return uintptr_t(0); 810 } 811 getMachine()812 uint16_t getMachine() const { 813 if (COFFHeader) 814 return COFFHeader->Machine; 815 if (COFFBigObjHeader) 816 return COFFBigObjHeader->Machine; 817 llvm_unreachable("no COFF header!"); 818 } 819 getSizeOfOptionalHeader()820 uint16_t getSizeOfOptionalHeader() const { 821 if (COFFHeader) 822 return COFFHeader->isImportLibrary() ? 0 823 : COFFHeader->SizeOfOptionalHeader; 824 // bigobj doesn't have this field. 825 if (COFFBigObjHeader) 826 return 0; 827 llvm_unreachable("no COFF header!"); 828 } 829 getCharacteristics()830 uint16_t getCharacteristics() const { 831 if (COFFHeader) 832 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; 833 // bigobj doesn't have characteristics to speak of, 834 // editbin will silently lie to you if you attempt to set any. 835 if (COFFBigObjHeader) 836 return 0; 837 llvm_unreachable("no COFF header!"); 838 } 839 getTimeDateStamp()840 uint32_t getTimeDateStamp() const { 841 if (COFFHeader) 842 return COFFHeader->TimeDateStamp; 843 if (COFFBigObjHeader) 844 return COFFBigObjHeader->TimeDateStamp; 845 llvm_unreachable("no COFF header!"); 846 } 847 getNumberOfSections()848 uint32_t getNumberOfSections() const { 849 if (COFFHeader) 850 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; 851 if (COFFBigObjHeader) 852 return COFFBigObjHeader->NumberOfSections; 853 llvm_unreachable("no COFF header!"); 854 } 855 getPointerToSymbolTable()856 uint32_t getPointerToSymbolTable() const { 857 if (COFFHeader) 858 return COFFHeader->isImportLibrary() ? 0 859 : COFFHeader->PointerToSymbolTable; 860 if (COFFBigObjHeader) 861 return COFFBigObjHeader->PointerToSymbolTable; 862 llvm_unreachable("no COFF header!"); 863 } 864 getRawNumberOfSymbols()865 uint32_t getRawNumberOfSymbols() const { 866 if (COFFHeader) 867 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; 868 if (COFFBigObjHeader) 869 return COFFBigObjHeader->NumberOfSymbols; 870 llvm_unreachable("no COFF header!"); 871 } 872 getNumberOfSymbols()873 uint32_t getNumberOfSymbols() const { 874 if (!SymbolTable16 && !SymbolTable32) 875 return 0; 876 return getRawNumberOfSymbols(); 877 } 878 getLoadConfig32()879 const coff_load_configuration32 *getLoadConfig32() const { 880 assert(!is64()); 881 return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig); 882 } 883 getLoadConfig64()884 const coff_load_configuration64 *getLoadConfig64() const { 885 assert(is64()); 886 return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig); 887 } 888 StringRef getRelocationTypeName(uint16_t Type) const; 889 890 protected: 891 void moveSymbolNext(DataRefImpl &Symb) const override; 892 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 893 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 894 uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 895 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 896 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 897 uint32_t getSymbolFlags(DataRefImpl Symb) const override; 898 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 899 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 900 void moveSectionNext(DataRefImpl &Sec) const override; 901 std::error_code getSectionName(DataRefImpl Sec, 902 StringRef &Res) const override; 903 uint64_t getSectionAddress(DataRefImpl Sec) const override; 904 uint64_t getSectionIndex(DataRefImpl Sec) const override; 905 uint64_t getSectionSize(DataRefImpl Sec) const override; 906 std::error_code getSectionContents(DataRefImpl Sec, 907 StringRef &Res) const override; 908 uint64_t getSectionAlignment(DataRefImpl Sec) const override; 909 bool isSectionCompressed(DataRefImpl Sec) const override; 910 bool isSectionText(DataRefImpl Sec) const override; 911 bool isSectionData(DataRefImpl Sec) const override; 912 bool isSectionBSS(DataRefImpl Sec) const override; 913 bool isSectionVirtual(DataRefImpl Sec) const override; 914 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 915 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 916 917 void moveRelocationNext(DataRefImpl &Rel) const override; 918 uint64_t getRelocationOffset(DataRefImpl Rel) const override; 919 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 920 uint64_t getRelocationType(DataRefImpl Rel) const override; 921 void getRelocationTypeName(DataRefImpl Rel, 922 SmallVectorImpl<char> &Result) const override; 923 924 public: 925 COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); 926 927 basic_symbol_iterator symbol_begin() const override; 928 basic_symbol_iterator symbol_end() const override; 929 section_iterator section_begin() const override; 930 section_iterator section_end() const override; 931 932 const coff_section *getCOFFSection(const SectionRef &Section) const; 933 COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; 934 COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; 935 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; 936 unsigned getSectionID(SectionRef Sec) const; 937 unsigned getSymbolSectionID(SymbolRef Sym) const; 938 939 uint8_t getBytesInAddress() const override; 940 StringRef getFileFormatName() const override; 941 Triple::ArchType getArch() const override; 942 Expected<uint64_t> getStartAddress() const override; getFeatures()943 SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } 944 945 import_directory_iterator import_directory_begin() const; 946 import_directory_iterator import_directory_end() const; 947 delay_import_directory_iterator delay_import_directory_begin() const; 948 delay_import_directory_iterator delay_import_directory_end() const; 949 export_directory_iterator export_directory_begin() const; 950 export_directory_iterator export_directory_end() const; 951 base_reloc_iterator base_reloc_begin() const; 952 base_reloc_iterator base_reloc_end() const; debug_directory_begin()953 const debug_directory *debug_directory_begin() const { 954 return DebugDirectoryBegin; 955 } debug_directory_end()956 const debug_directory *debug_directory_end() const { 957 return DebugDirectoryEnd; 958 } 959 960 iterator_range<import_directory_iterator> import_directories() const; 961 iterator_range<delay_import_directory_iterator> 962 delay_import_directories() const; 963 iterator_range<export_directory_iterator> export_directories() const; 964 iterator_range<base_reloc_iterator> base_relocs() const; debug_directories()965 iterator_range<const debug_directory *> debug_directories() const { 966 return make_range(debug_directory_begin(), debug_directory_end()); 967 } 968 getDOSHeader()969 const dos_header *getDOSHeader() const { 970 if (!PE32Header && !PE32PlusHeader) 971 return nullptr; 972 return reinterpret_cast<const dos_header *>(base()); 973 } 974 std::error_code getCOFFHeader(const coff_file_header *&Res) const; 975 std::error_code 976 getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const; 977 std::error_code getPE32Header(const pe32_header *&Res) const; 978 std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; 979 std::error_code getDataDirectory(uint32_t index, 980 const data_directory *&Res) const; 981 std::error_code getSection(int32_t index, const coff_section *&Res) const; 982 std::error_code getSection(StringRef SectionName, 983 const coff_section *&Res) const; 984 985 template <typename coff_symbol_type> getSymbol(uint32_t Index,const coff_symbol_type * & Res)986 std::error_code getSymbol(uint32_t Index, 987 const coff_symbol_type *&Res) const { 988 if (Index >= getNumberOfSymbols()) 989 return object_error::parse_failed; 990 991 Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; 992 return std::error_code(); 993 } getSymbol(uint32_t index)994 Expected<COFFSymbolRef> getSymbol(uint32_t index) const { 995 if (SymbolTable16) { 996 const coff_symbol16 *Symb = nullptr; 997 if (std::error_code EC = getSymbol(index, Symb)) 998 return errorCodeToError(EC); 999 return COFFSymbolRef(Symb); 1000 } 1001 if (SymbolTable32) { 1002 const coff_symbol32 *Symb = nullptr; 1003 if (std::error_code EC = getSymbol(index, Symb)) 1004 return errorCodeToError(EC); 1005 return COFFSymbolRef(Symb); 1006 } 1007 return errorCodeToError(object_error::parse_failed); 1008 } 1009 1010 template <typename T> getAuxSymbol(uint32_t index,const T * & Res)1011 std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { 1012 Expected<COFFSymbolRef> S = getSymbol(index); 1013 if (Error E = S.takeError()) 1014 return errorToErrorCode(std::move(E)); 1015 Res = reinterpret_cast<const T *>(S->getRawPtr()); 1016 return std::error_code(); 1017 } 1018 1019 std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; 1020 std::error_code getSymbolName(const coff_symbol_generic *Symbol, 1021 StringRef &Res) const; 1022 1023 ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; 1024 1025 uint32_t getSymbolIndex(COFFSymbolRef Symbol) const; 1026 getSymbolTableEntrySize()1027 size_t getSymbolTableEntrySize() const { 1028 if (COFFHeader) 1029 return sizeof(coff_symbol16); 1030 if (COFFBigObjHeader) 1031 return sizeof(coff_symbol32); 1032 llvm_unreachable("null symbol table pointer!"); 1033 } 1034 1035 ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; 1036 1037 std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; 1038 uint64_t getSectionSize(const coff_section *Sec) const; 1039 std::error_code getSectionContents(const coff_section *Sec, 1040 ArrayRef<uint8_t> &Res) const; 1041 1042 uint64_t getImageBase() const; 1043 std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; 1044 std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; 1045 1046 /// Given an RVA base and size, returns a valid array of bytes or an error 1047 /// code if the RVA and size is not contained completely within a valid 1048 /// section. 1049 std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 1050 ArrayRef<uint8_t> &Contents) const; 1051 1052 std::error_code getHintName(uint32_t Rva, uint16_t &Hint, 1053 StringRef &Name) const; 1054 1055 /// Get PDB information out of a codeview debug directory entry. 1056 std::error_code getDebugPDBInfo(const debug_directory *DebugDir, 1057 const codeview::DebugInfo *&Info, 1058 StringRef &PDBFileName) const; 1059 1060 /// Get PDB information from an executable. If the information is not present, 1061 /// Info will be set to nullptr and PDBFileName will be empty. An error is 1062 /// returned only on corrupt object files. Convenience accessor that can be 1063 /// used if the debug directory is not already handy. 1064 std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info, 1065 StringRef &PDBFileName) const; 1066 1067 bool isRelocatableObject() const override; is64()1068 bool is64() const { return PE32PlusHeader; } 1069 1070 StringRef mapDebugSectionName(StringRef Name) const override; 1071 classof(const Binary * v)1072 static bool classof(const Binary *v) { return v->isCOFF(); } 1073 }; 1074 1075 // The iterator for the import directory table. 1076 class ImportDirectoryEntryRef { 1077 public: 1078 ImportDirectoryEntryRef() = default; ImportDirectoryEntryRef(const coff_import_directory_table_entry * Table,uint32_t I,const COFFObjectFile * Owner)1079 ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, 1080 uint32_t I, const COFFObjectFile *Owner) 1081 : ImportTable(Table), Index(I), OwningObject(Owner) {} 1082 1083 bool operator==(const ImportDirectoryEntryRef &Other) const; 1084 void moveNext(); 1085 1086 imported_symbol_iterator imported_symbol_begin() const; 1087 imported_symbol_iterator imported_symbol_end() const; 1088 iterator_range<imported_symbol_iterator> imported_symbols() const; 1089 1090 imported_symbol_iterator lookup_table_begin() const; 1091 imported_symbol_iterator lookup_table_end() const; 1092 iterator_range<imported_symbol_iterator> lookup_table_symbols() const; 1093 1094 std::error_code getName(StringRef &Result) const; 1095 std::error_code getImportLookupTableRVA(uint32_t &Result) const; 1096 std::error_code getImportAddressTableRVA(uint32_t &Result) const; 1097 1098 std::error_code 1099 getImportTableEntry(const coff_import_directory_table_entry *&Result) const; 1100 1101 private: 1102 const coff_import_directory_table_entry *ImportTable; 1103 uint32_t Index; 1104 const COFFObjectFile *OwningObject = nullptr; 1105 }; 1106 1107 class DelayImportDirectoryEntryRef { 1108 public: 1109 DelayImportDirectoryEntryRef() = default; DelayImportDirectoryEntryRef(const delay_import_directory_table_entry * T,uint32_t I,const COFFObjectFile * Owner)1110 DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, 1111 uint32_t I, const COFFObjectFile *Owner) 1112 : Table(T), Index(I), OwningObject(Owner) {} 1113 1114 bool operator==(const DelayImportDirectoryEntryRef &Other) const; 1115 void moveNext(); 1116 1117 imported_symbol_iterator imported_symbol_begin() const; 1118 imported_symbol_iterator imported_symbol_end() const; 1119 iterator_range<imported_symbol_iterator> imported_symbols() const; 1120 1121 std::error_code getName(StringRef &Result) const; 1122 std::error_code getDelayImportTable( 1123 const delay_import_directory_table_entry *&Result) const; 1124 std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; 1125 1126 private: 1127 const delay_import_directory_table_entry *Table; 1128 uint32_t Index; 1129 const COFFObjectFile *OwningObject = nullptr; 1130 }; 1131 1132 // The iterator for the export directory table entry. 1133 class ExportDirectoryEntryRef { 1134 public: 1135 ExportDirectoryEntryRef() = default; ExportDirectoryEntryRef(const export_directory_table_entry * Table,uint32_t I,const COFFObjectFile * Owner)1136 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, 1137 const COFFObjectFile *Owner) 1138 : ExportTable(Table), Index(I), OwningObject(Owner) {} 1139 1140 bool operator==(const ExportDirectoryEntryRef &Other) const; 1141 void moveNext(); 1142 1143 std::error_code getDllName(StringRef &Result) const; 1144 std::error_code getOrdinalBase(uint32_t &Result) const; 1145 std::error_code getOrdinal(uint32_t &Result) const; 1146 std::error_code getExportRVA(uint32_t &Result) const; 1147 std::error_code getSymbolName(StringRef &Result) const; 1148 1149 std::error_code isForwarder(bool &Result) const; 1150 std::error_code getForwardTo(StringRef &Result) const; 1151 1152 private: 1153 const export_directory_table_entry *ExportTable; 1154 uint32_t Index; 1155 const COFFObjectFile *OwningObject = nullptr; 1156 }; 1157 1158 class ImportedSymbolRef { 1159 public: 1160 ImportedSymbolRef() = default; ImportedSymbolRef(const import_lookup_table_entry32 * Entry,uint32_t I,const COFFObjectFile * Owner)1161 ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, 1162 const COFFObjectFile *Owner) 1163 : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} ImportedSymbolRef(const import_lookup_table_entry64 * Entry,uint32_t I,const COFFObjectFile * Owner)1164 ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, 1165 const COFFObjectFile *Owner) 1166 : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} 1167 1168 bool operator==(const ImportedSymbolRef &Other) const; 1169 void moveNext(); 1170 1171 std::error_code getSymbolName(StringRef &Result) const; 1172 std::error_code isOrdinal(bool &Result) const; 1173 std::error_code getOrdinal(uint16_t &Result) const; 1174 std::error_code getHintNameRVA(uint32_t &Result) const; 1175 1176 private: 1177 const import_lookup_table_entry32 *Entry32; 1178 const import_lookup_table_entry64 *Entry64; 1179 uint32_t Index; 1180 const COFFObjectFile *OwningObject = nullptr; 1181 }; 1182 1183 class BaseRelocRef { 1184 public: 1185 BaseRelocRef() = default; BaseRelocRef(const coff_base_reloc_block_header * Header,const COFFObjectFile * Owner)1186 BaseRelocRef(const coff_base_reloc_block_header *Header, 1187 const COFFObjectFile *Owner) 1188 : Header(Header), Index(0) {} 1189 1190 bool operator==(const BaseRelocRef &Other) const; 1191 void moveNext(); 1192 1193 std::error_code getType(uint8_t &Type) const; 1194 std::error_code getRVA(uint32_t &Result) const; 1195 1196 private: 1197 const coff_base_reloc_block_header *Header; 1198 uint32_t Index; 1199 }; 1200 1201 class ResourceSectionRef { 1202 public: 1203 ResourceSectionRef() = default; ResourceSectionRef(StringRef Ref)1204 explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} 1205 1206 Expected<ArrayRef<UTF16>> 1207 getEntryNameString(const coff_resource_dir_entry &Entry); 1208 Expected<const coff_resource_dir_table &> 1209 getEntrySubDir(const coff_resource_dir_entry &Entry); 1210 Expected<const coff_resource_dir_table &> getBaseTable(); 1211 1212 private: 1213 BinaryByteStream BBS; 1214 1215 Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); 1216 Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); 1217 }; 1218 1219 // Corresponds to `_FPO_DATA` structure in the PE/COFF spec. 1220 struct FpoData { 1221 support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code 1222 support::ulittle32_t Size; // cbProcSize: # bytes in function 1223 support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 1224 support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 1225 support::ulittle16_t Attributes; 1226 1227 // cbProlog: # bytes in prolog getPrologSizeFpoData1228 int getPrologSize() const { return Attributes & 0xF; } 1229 1230 // cbRegs: # regs saved getNumSavedRegsFpoData1231 int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } 1232 1233 // fHasSEH: true if seh is func hasSEHFpoData1234 bool hasSEH() const { return (Attributes >> 9) & 1; } 1235 1236 // fUseBP: true if EBP has been allocated useBPFpoData1237 bool useBP() const { return (Attributes >> 10) & 1; } 1238 1239 // cbFrame: frame pointer getFPFpoData1240 frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); } 1241 }; 1242 1243 } // end namespace object 1244 1245 } // end namespace llvm 1246 1247 #endif // LLVM_OBJECT_COFF_H 1248