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