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