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 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 isImportLibrarycoff_file_header84 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 isOrdinalimport_lookup_table_entry192 bool isOrdinal() const { return Data < 0; } 193 getOrdinalimport_lookup_table_entry194 uint16_t getOrdinal() const { 195 assert(isOrdinal() && "ILT entry is not an ordinal!"); 196 return Data & 0xFFFF; 197 } 198 getHintNameRVAimport_lookup_table_entry199 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; COFFSymbolRef(const coff_symbol16 * CS)283 COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {} COFFSymbolRef(const coff_symbol32 * CS)284 COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {} 285 getRawPtr()286 const void *getRawPtr() const { 287 return CS16 ? static_cast<const void *>(CS16) : CS32; 288 } 289 getGeneric()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 isBigObj()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 getShortName()308 const char *getShortName() const { 309 return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; 310 } 311 getStringTableOffset()312 const StringTableOffset &getStringTableOffset() const { 313 assert(isSet() && "COFFSymbolRef points to nothing!"); 314 return CS16 ? CS16->Name.Offset : CS32->Name.Offset; 315 } 316 getValue()317 uint32_t getValue() const { 318 assert(isSet() && "COFFSymbolRef points to nothing!"); 319 return CS16 ? CS16->Value : CS32->Value; 320 } 321 getSectionNumber()322 int32_t getSectionNumber() const { 323 assert(isSet() && "COFFSymbolRef points to nothing!"); 324 if (CS16) { 325 // Reserved sections are returned as negative numbers. 326 if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) 327 return CS16->SectionNumber; 328 return static_cast<int16_t>(CS16->SectionNumber); 329 } 330 return static_cast<int32_t>(CS32->SectionNumber); 331 } 332 getType()333 uint16_t getType() const { 334 assert(isSet() && "COFFSymbolRef points to nothing!"); 335 return CS16 ? CS16->Type : CS32->Type; 336 } 337 getStorageClass()338 uint8_t getStorageClass() const { 339 assert(isSet() && "COFFSymbolRef points to nothing!"); 340 return CS16 ? CS16->StorageClass : CS32->StorageClass; 341 } 342 getNumberOfAuxSymbols()343 uint8_t getNumberOfAuxSymbols() const { 344 assert(isSet() && "COFFSymbolRef points to nothing!"); 345 return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; 346 } 347 getBaseType()348 uint8_t getBaseType() const { return getType() & 0x0F; } 349 getComplexType()350 uint8_t getComplexType() const { 351 return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; 352 } 353 getAux()354 template <typename T> const T *getAux() const { 355 return CS16 ? reinterpret_cast<const T *>(CS16 + 1) 356 : reinterpret_cast<const T *>(CS32 + 1); 357 } 358 getSectionDefinition()359 const coff_aux_section_definition *getSectionDefinition() const { 360 if (!getNumberOfAuxSymbols() || 361 getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC) 362 return nullptr; 363 return getAux<coff_aux_section_definition>(); 364 } 365 getWeakExternal()366 const coff_aux_weak_external *getWeakExternal() const { 367 if (!getNumberOfAuxSymbols() || 368 getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 369 return nullptr; 370 return getAux<coff_aux_weak_external>(); 371 } 372 isAbsolute()373 bool isAbsolute() const { 374 return getSectionNumber() == -1; 375 } 376 isExternal()377 bool isExternal() const { 378 return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; 379 } 380 isCommon()381 bool isCommon() const { 382 return (isExternal() || isSection()) && 383 getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && getValue() != 0; 384 } 385 isUndefined()386 bool isUndefined() const { 387 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 388 getValue() == 0; 389 } 390 isWeakExternal()391 bool isWeakExternal() const { 392 return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; 393 } 394 isFunctionDefinition()395 bool isFunctionDefinition() const { 396 return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && 397 getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && 398 !COFF::isReservedSectionNumber(getSectionNumber()); 399 } 400 isFunctionLineInfo()401 bool isFunctionLineInfo() const { 402 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; 403 } 404 isAnyUndefined()405 bool isAnyUndefined() const { 406 return isUndefined() || isWeakExternal(); 407 } 408 isFileRecord()409 bool isFileRecord() const { 410 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; 411 } 412 isSection()413 bool isSection() const { 414 return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; 415 } 416 isSectionDefinition()417 bool isSectionDefinition() const { 418 // C++/CLI creates external ABS symbols for non-const appdomain globals. 419 // These are also followed by an auxiliary section definition. 420 bool isAppdomainGlobal = 421 getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && 422 getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; 423 bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; 424 if (!getNumberOfAuxSymbols()) 425 return false; 426 return isAppdomainGlobal || isOrdinarySection; 427 } 428 isCLRToken()429 bool isCLRToken() const { 430 return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; 431 } 432 433 private: isSet()434 bool isSet() const { return CS16 || CS32; } 435 436 const coff_symbol16 *CS16 = nullptr; 437 const coff_symbol32 *CS32 = nullptr; 438 }; 439 440 struct coff_section { 441 char Name[COFF::NameSize]; 442 support::ulittle32_t VirtualSize; 443 support::ulittle32_t VirtualAddress; 444 support::ulittle32_t SizeOfRawData; 445 support::ulittle32_t PointerToRawData; 446 support::ulittle32_t PointerToRelocations; 447 support::ulittle32_t PointerToLinenumbers; 448 support::ulittle16_t NumberOfRelocations; 449 support::ulittle16_t NumberOfLinenumbers; 450 support::ulittle32_t Characteristics; 451 452 // Returns true if the actual number of relocations is stored in 453 // VirtualAddress field of the first relocation table entry. hasExtendedRelocationscoff_section454 bool hasExtendedRelocations() const { 455 return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && 456 NumberOfRelocations == UINT16_MAX; 457 } 458 getAlignmentcoff_section459 uint32_t getAlignment() const { 460 // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to 461 // IMAGE_SCN_ALIGN_1BYTES. 462 if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) 463 return 1; 464 465 // Bit [20:24] contains section alignment. 0 means use a default alignment 466 // of 16. 467 uint32_t Shift = (Characteristics >> 20) & 0xF; 468 if (Shift > 0) 469 return 1U << (Shift - 1); 470 return 16; 471 } 472 }; 473 474 struct coff_relocation { 475 support::ulittle32_t VirtualAddress; 476 support::ulittle32_t SymbolTableIndex; 477 support::ulittle16_t Type; 478 }; 479 480 struct coff_aux_function_definition { 481 support::ulittle32_t TagIndex; 482 support::ulittle32_t TotalSize; 483 support::ulittle32_t PointerToLinenumber; 484 support::ulittle32_t PointerToNextFunction; 485 char Unused1[2]; 486 }; 487 488 static_assert(sizeof(coff_aux_function_definition) == 18, 489 "auxiliary entry must be 18 bytes"); 490 491 struct coff_aux_bf_and_ef_symbol { 492 char Unused1[4]; 493 support::ulittle16_t Linenumber; 494 char Unused2[6]; 495 support::ulittle32_t PointerToNextFunction; 496 char Unused3[2]; 497 }; 498 499 static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, 500 "auxiliary entry must be 18 bytes"); 501 502 struct coff_aux_weak_external { 503 support::ulittle32_t TagIndex; 504 support::ulittle32_t Characteristics; 505 char Unused1[10]; 506 }; 507 508 static_assert(sizeof(coff_aux_weak_external) == 18, 509 "auxiliary entry must be 18 bytes"); 510 511 struct coff_aux_section_definition { 512 support::ulittle32_t Length; 513 support::ulittle16_t NumberOfRelocations; 514 support::ulittle16_t NumberOfLinenumbers; 515 support::ulittle32_t CheckSum; 516 support::ulittle16_t NumberLowPart; 517 uint8_t Selection; 518 uint8_t Unused; 519 support::ulittle16_t NumberHighPart; getNumbercoff_aux_section_definition520 int32_t getNumber(bool IsBigObj) const { 521 uint32_t Number = static_cast<uint32_t>(NumberLowPart); 522 if (IsBigObj) 523 Number |= static_cast<uint32_t>(NumberHighPart) << 16; 524 return static_cast<int32_t>(Number); 525 } 526 }; 527 528 static_assert(sizeof(coff_aux_section_definition) == 18, 529 "auxiliary entry must be 18 bytes"); 530 531 struct coff_aux_clr_token { 532 uint8_t AuxType; 533 uint8_t Reserved; 534 support::ulittle32_t SymbolTableIndex; 535 char MBZ[12]; 536 }; 537 538 static_assert(sizeof(coff_aux_clr_token) == 18, 539 "auxiliary entry must be 18 bytes"); 540 541 struct coff_import_header { 542 support::ulittle16_t Sig1; 543 support::ulittle16_t Sig2; 544 support::ulittle16_t Version; 545 support::ulittle16_t Machine; 546 support::ulittle32_t TimeDateStamp; 547 support::ulittle32_t SizeOfData; 548 support::ulittle16_t OrdinalHint; 549 support::ulittle16_t TypeInfo; 550 getTypecoff_import_header551 int getType() const { return TypeInfo & 0x3; } getNameTypecoff_import_header552 int getNameType() const { return (TypeInfo >> 2) & 0x7; } 553 }; 554 555 struct coff_import_directory_table_entry { 556 support::ulittle32_t ImportLookupTableRVA; 557 support::ulittle32_t TimeDateStamp; 558 support::ulittle32_t ForwarderChain; 559 support::ulittle32_t NameRVA; 560 support::ulittle32_t ImportAddressTableRVA; 561 isNullcoff_import_directory_table_entry562 bool isNull() const { 563 return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && 564 ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0; 565 } 566 }; 567 568 template <typename IntTy> 569 struct coff_tls_directory { 570 IntTy StartAddressOfRawData; 571 IntTy EndAddressOfRawData; 572 IntTy AddressOfIndex; 573 IntTy AddressOfCallBacks; 574 support::ulittle32_t SizeOfZeroFill; 575 support::ulittle32_t Characteristics; 576 getAlignmentcoff_tls_directory577 uint32_t getAlignment() const { 578 // Bit [20:24] contains section alignment. 579 uint32_t Shift = (Characteristics & COFF::IMAGE_SCN_ALIGN_MASK) >> 20; 580 if (Shift > 0) 581 return 1U << (Shift - 1); 582 return 0; 583 } 584 setAlignmentcoff_tls_directory585 void setAlignment(uint32_t Align) { 586 uint32_t AlignBits = 0; 587 if (Align) { 588 assert(llvm::isPowerOf2_32(Align) && "alignment is not a power of 2"); 589 assert(llvm::Log2_32(Align) <= 13 && "alignment requested is too large"); 590 AlignBits = (llvm::Log2_32(Align) + 1) << 20; 591 } 592 Characteristics = 593 (Characteristics & ~COFF::IMAGE_SCN_ALIGN_MASK) | AlignBits; 594 } 595 }; 596 597 using coff_tls_directory32 = coff_tls_directory<support::little32_t>; 598 using coff_tls_directory64 = coff_tls_directory<support::little64_t>; 599 600 enum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 }; 601 602 struct coff_load_config_code_integrity { 603 support::ulittle16_t Flags; 604 support::ulittle16_t Catalog; 605 support::ulittle32_t CatalogOffset; 606 support::ulittle32_t Reserved; 607 }; 608 609 /// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) 610 struct coff_load_configuration32 { 611 support::ulittle32_t Size; 612 support::ulittle32_t TimeDateStamp; 613 support::ulittle16_t MajorVersion; 614 support::ulittle16_t MinorVersion; 615 support::ulittle32_t GlobalFlagsClear; 616 support::ulittle32_t GlobalFlagsSet; 617 support::ulittle32_t CriticalSectionDefaultTimeout; 618 support::ulittle32_t DeCommitFreeBlockThreshold; 619 support::ulittle32_t DeCommitTotalFreeThreshold; 620 support::ulittle32_t LockPrefixTable; 621 support::ulittle32_t MaximumAllocationSize; 622 support::ulittle32_t VirtualMemoryThreshold; 623 support::ulittle32_t ProcessAffinityMask; 624 support::ulittle32_t ProcessHeapFlags; 625 support::ulittle16_t CSDVersion; 626 support::ulittle16_t DependentLoadFlags; 627 support::ulittle32_t EditList; 628 support::ulittle32_t SecurityCookie; 629 support::ulittle32_t SEHandlerTable; 630 support::ulittle32_t SEHandlerCount; 631 632 // Added in MSVC 2015 for /guard:cf. 633 support::ulittle32_t GuardCFCheckFunction; 634 support::ulittle32_t GuardCFCheckDispatch; 635 support::ulittle32_t GuardCFFunctionTable; 636 support::ulittle32_t GuardCFFunctionCount; 637 support::ulittle32_t GuardFlags; // coff_guard_flags 638 639 // Added in MSVC 2017 640 coff_load_config_code_integrity CodeIntegrity; 641 support::ulittle32_t GuardAddressTakenIatEntryTable; 642 support::ulittle32_t GuardAddressTakenIatEntryCount; 643 support::ulittle32_t GuardLongJumpTargetTable; 644 support::ulittle32_t GuardLongJumpTargetCount; 645 support::ulittle32_t DynamicValueRelocTable; 646 support::ulittle32_t CHPEMetadataPointer; 647 support::ulittle32_t GuardRFFailureRoutine; 648 support::ulittle32_t GuardRFFailureRoutineFunctionPointer; 649 support::ulittle32_t DynamicValueRelocTableOffset; 650 support::ulittle16_t DynamicValueRelocTableSection; 651 support::ulittle16_t Reserved2; 652 support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; 653 support::ulittle32_t HotPatchTableOffset; 654 655 // Added in MSVC 2019 656 support::ulittle32_t Reserved3; 657 support::ulittle32_t EnclaveConfigurationPointer; 658 support::ulittle32_t VolatileMetadataPointer; 659 support::ulittle32_t GuardEHContinuationTable; 660 support::ulittle32_t GuardEHContinuationCount; 661 support::ulittle32_t GuardXFGCheckFunctionPointer; 662 support::ulittle32_t GuardXFGDispatchFunctionPointer; 663 support::ulittle32_t GuardXFGTableDispatchFunctionPointer; 664 support::ulittle32_t CastGuardOsDeterminedFailureMode; 665 }; 666 667 /// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) 668 struct coff_load_configuration64 { 669 support::ulittle32_t Size; 670 support::ulittle32_t TimeDateStamp; 671 support::ulittle16_t MajorVersion; 672 support::ulittle16_t MinorVersion; 673 support::ulittle32_t GlobalFlagsClear; 674 support::ulittle32_t GlobalFlagsSet; 675 support::ulittle32_t CriticalSectionDefaultTimeout; 676 support::ulittle64_t DeCommitFreeBlockThreshold; 677 support::ulittle64_t DeCommitTotalFreeThreshold; 678 support::ulittle64_t LockPrefixTable; 679 support::ulittle64_t MaximumAllocationSize; 680 support::ulittle64_t VirtualMemoryThreshold; 681 support::ulittle64_t ProcessAffinityMask; 682 support::ulittle32_t ProcessHeapFlags; 683 support::ulittle16_t CSDVersion; 684 support::ulittle16_t DependentLoadFlags; 685 support::ulittle64_t EditList; 686 support::ulittle64_t SecurityCookie; 687 support::ulittle64_t SEHandlerTable; 688 support::ulittle64_t SEHandlerCount; 689 690 // Added in MSVC 2015 for /guard:cf. 691 support::ulittle64_t GuardCFCheckFunction; 692 support::ulittle64_t GuardCFCheckDispatch; 693 support::ulittle64_t GuardCFFunctionTable; 694 support::ulittle64_t GuardCFFunctionCount; 695 support::ulittle32_t GuardFlags; 696 697 // Added in MSVC 2017 698 coff_load_config_code_integrity CodeIntegrity; 699 support::ulittle64_t GuardAddressTakenIatEntryTable; 700 support::ulittle64_t GuardAddressTakenIatEntryCount; 701 support::ulittle64_t GuardLongJumpTargetTable; 702 support::ulittle64_t GuardLongJumpTargetCount; 703 support::ulittle64_t DynamicValueRelocTable; 704 support::ulittle64_t CHPEMetadataPointer; 705 support::ulittle64_t GuardRFFailureRoutine; 706 support::ulittle64_t GuardRFFailureRoutineFunctionPointer; 707 support::ulittle32_t DynamicValueRelocTableOffset; 708 support::ulittle16_t DynamicValueRelocTableSection; 709 support::ulittle16_t Reserved2; 710 support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; 711 support::ulittle32_t HotPatchTableOffset; 712 713 // Added in MSVC 2019 714 support::ulittle32_t Reserved3; 715 support::ulittle64_t EnclaveConfigurationPointer; 716 support::ulittle64_t VolatileMetadataPointer; 717 support::ulittle64_t GuardEHContinuationTable; 718 support::ulittle64_t GuardEHContinuationCount; 719 support::ulittle64_t GuardXFGCheckFunctionPointer; 720 support::ulittle64_t GuardXFGDispatchFunctionPointer; 721 support::ulittle64_t GuardXFGTableDispatchFunctionPointer; 722 support::ulittle64_t CastGuardOsDeterminedFailureMode; 723 }; 724 725 struct chpe_metadata { 726 support::ulittle32_t Version; 727 support::ulittle32_t CodeMap; 728 support::ulittle32_t CodeMapCount; 729 support::ulittle32_t CodeRangesToEntryPoints; 730 support::ulittle32_t RedirectionMetadata; 731 support::ulittle32_t __os_arm64x_dispatch_call_no_redirect; 732 support::ulittle32_t __os_arm64x_dispatch_ret; 733 support::ulittle32_t __os_arm64x_dispatch_call; 734 support::ulittle32_t __os_arm64x_dispatch_icall; 735 support::ulittle32_t __os_arm64x_dispatch_icall_cfg; 736 support::ulittle32_t AlternateEntryPoint; 737 support::ulittle32_t AuxiliaryIAT; 738 support::ulittle32_t CodeRangesToEntryPointsCount; 739 support::ulittle32_t RedirectionMetadataCount; 740 support::ulittle32_t GetX64InformationFunctionPointer; 741 support::ulittle32_t SetX64InformationFunctionPointer; 742 support::ulittle32_t ExtraRFETable; 743 support::ulittle32_t ExtraRFETableSize; 744 support::ulittle32_t __os_arm64x_dispatch_fptr; 745 support::ulittle32_t AuxiliaryIATCopy; 746 }; 747 748 enum chpe_range_type { Arm64 = 0, Arm64EC = 1, Amd64 = 2 }; 749 750 struct chpe_range_entry { 751 support::ulittle32_t StartOffset; 752 support::ulittle32_t Length; 753 754 // The two low bits of StartOffset contain a range type. 755 static constexpr uint32_t TypeMask = 3; 756 getStartchpe_range_entry757 uint32_t getStart() const { return StartOffset & ~TypeMask; } getTypechpe_range_entry758 uint16_t getType() const { return StartOffset & TypeMask; } 759 }; 760 761 struct chpe_code_range_entry { 762 support::ulittle32_t StartRva; 763 support::ulittle32_t EndRva; 764 support::ulittle32_t EntryPoint; 765 }; 766 767 struct chpe_redirection_entry { 768 support::ulittle32_t Source; 769 support::ulittle32_t Destination; 770 }; 771 772 struct coff_runtime_function_x64 { 773 support::ulittle32_t BeginAddress; 774 support::ulittle32_t EndAddress; 775 support::ulittle32_t UnwindInformation; 776 }; 777 778 struct coff_base_reloc_block_header { 779 support::ulittle32_t PageRVA; 780 support::ulittle32_t BlockSize; 781 }; 782 783 struct coff_base_reloc_block_entry { 784 support::ulittle16_t Data; 785 getTypecoff_base_reloc_block_entry786 int getType() const { return Data >> 12; } getOffsetcoff_base_reloc_block_entry787 int getOffset() const { return Data & ((1 << 12) - 1); } 788 }; 789 790 struct coff_resource_dir_entry { 791 union { 792 support::ulittle32_t NameOffset; 793 support::ulittle32_t ID; getNameOffset()794 uint32_t getNameOffset() const { 795 return maskTrailingOnes<uint32_t>(31) & NameOffset; 796 } 797 // Even though the PE/COFF spec doesn't mention this, the high bit of a name 798 // offset is set. setNameOffset(uint32_t Offset)799 void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); } 800 } Identifier; 801 union { 802 support::ulittle32_t DataEntryOffset; 803 support::ulittle32_t SubdirOffset; 804 isSubDir()805 bool isSubDir() const { return SubdirOffset >> 31; } value()806 uint32_t value() const { 807 return maskTrailingOnes<uint32_t>(31) & SubdirOffset; 808 } 809 810 } Offset; 811 }; 812 813 struct coff_resource_data_entry { 814 support::ulittle32_t DataRVA; 815 support::ulittle32_t DataSize; 816 support::ulittle32_t Codepage; 817 support::ulittle32_t Reserved; 818 }; 819 820 struct coff_resource_dir_table { 821 support::ulittle32_t Characteristics; 822 support::ulittle32_t TimeDateStamp; 823 support::ulittle16_t MajorVersion; 824 support::ulittle16_t MinorVersion; 825 support::ulittle16_t NumberOfNameEntries; 826 support::ulittle16_t NumberOfIDEntries; 827 }; 828 829 struct debug_h_header { 830 support::ulittle32_t Magic; 831 support::ulittle16_t Version; 832 support::ulittle16_t HashAlgorithm; 833 }; 834 835 class COFFObjectFile : public ObjectFile { 836 private: 837 COFFObjectFile(MemoryBufferRef Object); 838 839 friend class ImportDirectoryEntryRef; 840 friend class ExportDirectoryEntryRef; 841 const coff_file_header *COFFHeader; 842 const coff_bigobj_file_header *COFFBigObjHeader; 843 const pe32_header *PE32Header; 844 const pe32plus_header *PE32PlusHeader; 845 const data_directory *DataDirectory; 846 const coff_section *SectionTable; 847 const coff_symbol16 *SymbolTable16; 848 const coff_symbol32 *SymbolTable32; 849 const char *StringTable; 850 uint32_t StringTableSize; 851 const coff_import_directory_table_entry *ImportDirectory; 852 const delay_import_directory_table_entry *DelayImportDirectory; 853 uint32_t NumberOfDelayImportDirectory; 854 const export_directory_table_entry *ExportDirectory; 855 const coff_base_reloc_block_header *BaseRelocHeader; 856 const coff_base_reloc_block_header *BaseRelocEnd; 857 const debug_directory *DebugDirectoryBegin; 858 const debug_directory *DebugDirectoryEnd; 859 const coff_tls_directory32 *TLSDirectory32; 860 const coff_tls_directory64 *TLSDirectory64; 861 // Either coff_load_configuration32 or coff_load_configuration64. 862 const void *LoadConfig = nullptr; 863 const chpe_metadata *CHPEMetadata = nullptr; 864 865 Expected<StringRef> getString(uint32_t offset) const; 866 867 template <typename coff_symbol_type> 868 const coff_symbol_type *toSymb(DataRefImpl Symb) const; 869 const coff_section *toSec(DataRefImpl Sec) const; 870 const coff_relocation *toRel(DataRefImpl Rel) const; 871 872 // Finish initializing the object and return success or an error. 873 Error initialize(); 874 875 Error initSymbolTablePtr(); 876 Error initImportTablePtr(); 877 Error initDelayImportTablePtr(); 878 Error initExportTablePtr(); 879 Error initBaseRelocPtr(); 880 Error initDebugDirectoryPtr(); 881 Error initTLSDirectoryPtr(); 882 Error initLoadConfigPtr(); 883 884 public: 885 static Expected<std::unique_ptr<COFFObjectFile>> 886 create(MemoryBufferRef Object); 887 getSymbolTable()888 uintptr_t getSymbolTable() const { 889 if (SymbolTable16) 890 return reinterpret_cast<uintptr_t>(SymbolTable16); 891 if (SymbolTable32) 892 return reinterpret_cast<uintptr_t>(SymbolTable32); 893 return uintptr_t(0); 894 } 895 getMachine()896 uint16_t getMachine() const { 897 if (COFFHeader) { 898 if (CHPEMetadata) { 899 switch (COFFHeader->Machine) { 900 case COFF::IMAGE_FILE_MACHINE_AMD64: 901 return COFF::IMAGE_FILE_MACHINE_ARM64EC; 902 case COFF::IMAGE_FILE_MACHINE_ARM64: 903 return COFF::IMAGE_FILE_MACHINE_ARM64X; 904 } 905 } 906 return COFFHeader->Machine; 907 } 908 if (COFFBigObjHeader) 909 return COFFBigObjHeader->Machine; 910 llvm_unreachable("no COFF header!"); 911 } 912 getSizeOfOptionalHeader()913 uint16_t getSizeOfOptionalHeader() const { 914 if (COFFHeader) 915 return COFFHeader->isImportLibrary() ? 0 916 : COFFHeader->SizeOfOptionalHeader; 917 // bigobj doesn't have this field. 918 if (COFFBigObjHeader) 919 return 0; 920 llvm_unreachable("no COFF header!"); 921 } 922 getCharacteristics()923 uint16_t getCharacteristics() const { 924 if (COFFHeader) 925 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; 926 // bigobj doesn't have characteristics to speak of, 927 // editbin will silently lie to you if you attempt to set any. 928 if (COFFBigObjHeader) 929 return 0; 930 llvm_unreachable("no COFF header!"); 931 } 932 getTimeDateStamp()933 uint32_t getTimeDateStamp() const { 934 if (COFFHeader) 935 return COFFHeader->TimeDateStamp; 936 if (COFFBigObjHeader) 937 return COFFBigObjHeader->TimeDateStamp; 938 llvm_unreachable("no COFF header!"); 939 } 940 getNumberOfSections()941 uint32_t getNumberOfSections() const { 942 if (COFFHeader) 943 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; 944 if (COFFBigObjHeader) 945 return COFFBigObjHeader->NumberOfSections; 946 llvm_unreachable("no COFF header!"); 947 } 948 getPointerToSymbolTable()949 uint32_t getPointerToSymbolTable() const { 950 if (COFFHeader) 951 return COFFHeader->isImportLibrary() ? 0 952 : COFFHeader->PointerToSymbolTable; 953 if (COFFBigObjHeader) 954 return COFFBigObjHeader->PointerToSymbolTable; 955 llvm_unreachable("no COFF header!"); 956 } 957 getRawNumberOfSymbols()958 uint32_t getRawNumberOfSymbols() const { 959 if (COFFHeader) 960 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; 961 if (COFFBigObjHeader) 962 return COFFBigObjHeader->NumberOfSymbols; 963 llvm_unreachable("no COFF header!"); 964 } 965 getNumberOfSymbols()966 uint32_t getNumberOfSymbols() const { 967 if (!SymbolTable16 && !SymbolTable32) 968 return 0; 969 return getRawNumberOfSymbols(); 970 } 971 getStringTableSize()972 uint32_t getStringTableSize() const { return StringTableSize; } 973 getExportTable()974 const export_directory_table_entry *getExportTable() const { 975 return ExportDirectory; 976 } 977 getLoadConfig32()978 const coff_load_configuration32 *getLoadConfig32() const { 979 assert(!is64()); 980 return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig); 981 } 982 getLoadConfig64()983 const coff_load_configuration64 *getLoadConfig64() const { 984 assert(is64()); 985 return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig); 986 } 987 getCHPEMetadata()988 const chpe_metadata *getCHPEMetadata() const { return CHPEMetadata; } 989 990 StringRef getRelocationTypeName(uint16_t Type) const; 991 992 protected: 993 void moveSymbolNext(DataRefImpl &Symb) const override; 994 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 995 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 996 uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 997 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 998 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 999 Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; 1000 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 1001 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 1002 void moveSectionNext(DataRefImpl &Sec) const override; 1003 Expected<StringRef> getSectionName(DataRefImpl Sec) const override; 1004 uint64_t getSectionAddress(DataRefImpl Sec) const override; 1005 uint64_t getSectionIndex(DataRefImpl Sec) const override; 1006 uint64_t getSectionSize(DataRefImpl Sec) const override; 1007 Expected<ArrayRef<uint8_t>> 1008 getSectionContents(DataRefImpl Sec) const override; 1009 uint64_t getSectionAlignment(DataRefImpl Sec) const override; 1010 bool isSectionCompressed(DataRefImpl Sec) const override; 1011 bool isSectionText(DataRefImpl Sec) const override; 1012 bool isSectionData(DataRefImpl Sec) const override; 1013 bool isSectionBSS(DataRefImpl Sec) const override; 1014 bool isSectionVirtual(DataRefImpl Sec) const override; 1015 bool isDebugSection(DataRefImpl Sec) const override; 1016 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 1017 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 1018 1019 void moveRelocationNext(DataRefImpl &Rel) const override; 1020 uint64_t getRelocationOffset(DataRefImpl Rel) const override; 1021 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 1022 uint64_t getRelocationType(DataRefImpl Rel) const override; 1023 void getRelocationTypeName(DataRefImpl Rel, 1024 SmallVectorImpl<char> &Result) const override; 1025 1026 public: 1027 basic_symbol_iterator symbol_begin() const override; 1028 basic_symbol_iterator symbol_end() const override; 1029 section_iterator section_begin() const override; 1030 section_iterator section_end() const override; 1031 is64Bit()1032 bool is64Bit() const override { return false; } 1033 1034 const coff_section *getCOFFSection(const SectionRef &Section) const; 1035 COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; 1036 COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; 1037 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; 1038 unsigned getSectionID(SectionRef Sec) const; 1039 unsigned getSymbolSectionID(SymbolRef Sym) const; 1040 1041 uint8_t getBytesInAddress() const override; 1042 StringRef getFileFormatName() const override; 1043 Triple::ArchType getArch() const override; 1044 Expected<uint64_t> getStartAddress() const override; getFeatures()1045 Expected<SubtargetFeatures> getFeatures() const override { 1046 return SubtargetFeatures(); 1047 } 1048 1049 import_directory_iterator import_directory_begin() const; 1050 import_directory_iterator import_directory_end() const; 1051 delay_import_directory_iterator delay_import_directory_begin() const; 1052 delay_import_directory_iterator delay_import_directory_end() const; 1053 export_directory_iterator export_directory_begin() const; 1054 export_directory_iterator export_directory_end() const; 1055 base_reloc_iterator base_reloc_begin() const; 1056 base_reloc_iterator base_reloc_end() const; debug_directory_begin()1057 const debug_directory *debug_directory_begin() const { 1058 return DebugDirectoryBegin; 1059 } debug_directory_end()1060 const debug_directory *debug_directory_end() const { 1061 return DebugDirectoryEnd; 1062 } 1063 1064 iterator_range<import_directory_iterator> import_directories() const; 1065 iterator_range<delay_import_directory_iterator> 1066 delay_import_directories() const; 1067 iterator_range<export_directory_iterator> export_directories() const; 1068 iterator_range<base_reloc_iterator> base_relocs() const; debug_directories()1069 iterator_range<const debug_directory *> debug_directories() const { 1070 return make_range(debug_directory_begin(), debug_directory_end()); 1071 } 1072 getTLSDirectory32()1073 const coff_tls_directory32 *getTLSDirectory32() const { 1074 return TLSDirectory32; 1075 } getTLSDirectory64()1076 const coff_tls_directory64 *getTLSDirectory64() const { 1077 return TLSDirectory64; 1078 } 1079 getDOSHeader()1080 const dos_header *getDOSHeader() const { 1081 if (!PE32Header && !PE32PlusHeader) 1082 return nullptr; 1083 return reinterpret_cast<const dos_header *>(base()); 1084 } 1085 getCOFFHeader()1086 const coff_file_header *getCOFFHeader() const { return COFFHeader; } getCOFFBigObjHeader()1087 const coff_bigobj_file_header *getCOFFBigObjHeader() const { 1088 return COFFBigObjHeader; 1089 } getPE32Header()1090 const pe32_header *getPE32Header() const { return PE32Header; } getPE32PlusHeader()1091 const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; } 1092 1093 const data_directory *getDataDirectory(uint32_t index) const; 1094 Expected<const coff_section *> getSection(int32_t index) const; 1095 getSymbol(uint32_t index)1096 Expected<COFFSymbolRef> getSymbol(uint32_t index) const { 1097 if (index >= getNumberOfSymbols()) 1098 return errorCodeToError(object_error::parse_failed); 1099 if (SymbolTable16) 1100 return COFFSymbolRef(SymbolTable16 + index); 1101 if (SymbolTable32) 1102 return COFFSymbolRef(SymbolTable32 + index); 1103 return errorCodeToError(object_error::parse_failed); 1104 } 1105 1106 template <typename T> getAuxSymbol(uint32_t index,const T * & Res)1107 Error getAuxSymbol(uint32_t index, const T *&Res) const { 1108 Expected<COFFSymbolRef> S = getSymbol(index); 1109 if (Error E = S.takeError()) 1110 return E; 1111 Res = reinterpret_cast<const T *>(S->getRawPtr()); 1112 return Error::success(); 1113 } 1114 1115 Expected<StringRef> getSymbolName(COFFSymbolRef Symbol) const; 1116 Expected<StringRef> getSymbolName(const coff_symbol_generic *Symbol) const; 1117 1118 ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; 1119 1120 uint32_t getSymbolIndex(COFFSymbolRef Symbol) const; 1121 getSymbolTableEntrySize()1122 size_t getSymbolTableEntrySize() const { 1123 if (COFFHeader) 1124 return sizeof(coff_symbol16); 1125 if (COFFBigObjHeader) 1126 return sizeof(coff_symbol32); 1127 llvm_unreachable("null symbol table pointer!"); 1128 } 1129 1130 ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; 1131 1132 Expected<StringRef> getSectionName(const coff_section *Sec) const; 1133 uint64_t getSectionSize(const coff_section *Sec) const; 1134 Error getSectionContents(const coff_section *Sec, 1135 ArrayRef<uint8_t> &Res) const; 1136 1137 uint64_t getImageBase() const; 1138 Error getVaPtr(uint64_t VA, uintptr_t &Res) const; 1139 Error getRvaPtr(uint32_t Rva, uintptr_t &Res, 1140 const char *ErrorContext = nullptr) const; 1141 1142 /// Given an RVA base and size, returns a valid array of bytes or an error 1143 /// code if the RVA and size is not contained completely within a valid 1144 /// section. 1145 Error getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 1146 ArrayRef<uint8_t> &Contents, 1147 const char *ErrorContext = nullptr) const; 1148 1149 Error getHintName(uint32_t Rva, uint16_t &Hint, 1150 StringRef &Name) const; 1151 1152 /// Get PDB information out of a codeview debug directory entry. 1153 Error getDebugPDBInfo(const debug_directory *DebugDir, 1154 const codeview::DebugInfo *&Info, 1155 StringRef &PDBFileName) const; 1156 1157 /// Get PDB information from an executable. If the information is not present, 1158 /// Info will be set to nullptr and PDBFileName will be empty. An error is 1159 /// returned only on corrupt object files. Convenience accessor that can be 1160 /// used if the debug directory is not already handy. 1161 Error getDebugPDBInfo(const codeview::DebugInfo *&Info, 1162 StringRef &PDBFileName) const; 1163 1164 bool isRelocatableObject() const override; is64()1165 bool is64() const { return PE32PlusHeader; } 1166 1167 StringRef mapDebugSectionName(StringRef Name) const override; 1168 classof(const Binary * v)1169 static bool classof(const Binary *v) { return v->isCOFF(); } 1170 }; 1171 1172 // The iterator for the import directory table. 1173 class ImportDirectoryEntryRef { 1174 public: 1175 ImportDirectoryEntryRef() = default; ImportDirectoryEntryRef(const coff_import_directory_table_entry * Table,uint32_t I,const COFFObjectFile * Owner)1176 ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, 1177 uint32_t I, const COFFObjectFile *Owner) 1178 : ImportTable(Table), Index(I), OwningObject(Owner) {} 1179 1180 bool operator==(const ImportDirectoryEntryRef &Other) const; 1181 void moveNext(); 1182 1183 imported_symbol_iterator imported_symbol_begin() const; 1184 imported_symbol_iterator imported_symbol_end() const; 1185 iterator_range<imported_symbol_iterator> imported_symbols() const; 1186 1187 imported_symbol_iterator lookup_table_begin() const; 1188 imported_symbol_iterator lookup_table_end() const; 1189 iterator_range<imported_symbol_iterator> lookup_table_symbols() const; 1190 1191 Error getName(StringRef &Result) const; 1192 Error getImportLookupTableRVA(uint32_t &Result) const; 1193 Error getImportAddressTableRVA(uint32_t &Result) const; 1194 1195 Error 1196 getImportTableEntry(const coff_import_directory_table_entry *&Result) const; 1197 1198 private: 1199 const coff_import_directory_table_entry *ImportTable; 1200 uint32_t Index; 1201 const COFFObjectFile *OwningObject = nullptr; 1202 }; 1203 1204 class DelayImportDirectoryEntryRef { 1205 public: 1206 DelayImportDirectoryEntryRef() = default; DelayImportDirectoryEntryRef(const delay_import_directory_table_entry * T,uint32_t I,const COFFObjectFile * Owner)1207 DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, 1208 uint32_t I, const COFFObjectFile *Owner) 1209 : Table(T), Index(I), OwningObject(Owner) {} 1210 1211 bool operator==(const DelayImportDirectoryEntryRef &Other) const; 1212 void moveNext(); 1213 1214 imported_symbol_iterator imported_symbol_begin() const; 1215 imported_symbol_iterator imported_symbol_end() const; 1216 iterator_range<imported_symbol_iterator> imported_symbols() const; 1217 1218 Error getName(StringRef &Result) const; 1219 Error getDelayImportTable( 1220 const delay_import_directory_table_entry *&Result) const; 1221 Error getImportAddress(int AddrIndex, uint64_t &Result) const; 1222 1223 private: 1224 const delay_import_directory_table_entry *Table; 1225 uint32_t Index; 1226 const COFFObjectFile *OwningObject = nullptr; 1227 }; 1228 1229 // The iterator for the export directory table entry. 1230 class ExportDirectoryEntryRef { 1231 public: 1232 ExportDirectoryEntryRef() = default; ExportDirectoryEntryRef(const export_directory_table_entry * Table,uint32_t I,const COFFObjectFile * Owner)1233 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, 1234 const COFFObjectFile *Owner) 1235 : ExportTable(Table), Index(I), OwningObject(Owner) {} 1236 1237 bool operator==(const ExportDirectoryEntryRef &Other) const; 1238 void moveNext(); 1239 1240 Error getDllName(StringRef &Result) const; 1241 Error getOrdinalBase(uint32_t &Result) const; 1242 Error getOrdinal(uint32_t &Result) const; 1243 Error getExportRVA(uint32_t &Result) const; 1244 Error getSymbolName(StringRef &Result) const; 1245 1246 Error isForwarder(bool &Result) const; 1247 Error getForwardTo(StringRef &Result) const; 1248 1249 private: 1250 const export_directory_table_entry *ExportTable; 1251 uint32_t Index; 1252 const COFFObjectFile *OwningObject = nullptr; 1253 }; 1254 1255 class ImportedSymbolRef { 1256 public: 1257 ImportedSymbolRef() = default; ImportedSymbolRef(const import_lookup_table_entry32 * Entry,uint32_t I,const COFFObjectFile * Owner)1258 ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, 1259 const COFFObjectFile *Owner) 1260 : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} ImportedSymbolRef(const import_lookup_table_entry64 * Entry,uint32_t I,const COFFObjectFile * Owner)1261 ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, 1262 const COFFObjectFile *Owner) 1263 : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} 1264 1265 bool operator==(const ImportedSymbolRef &Other) const; 1266 void moveNext(); 1267 1268 Error getSymbolName(StringRef &Result) const; 1269 Error isOrdinal(bool &Result) const; 1270 Error getOrdinal(uint16_t &Result) const; 1271 Error getHintNameRVA(uint32_t &Result) const; 1272 1273 private: 1274 const import_lookup_table_entry32 *Entry32; 1275 const import_lookup_table_entry64 *Entry64; 1276 uint32_t Index; 1277 const COFFObjectFile *OwningObject = nullptr; 1278 }; 1279 1280 class BaseRelocRef { 1281 public: 1282 BaseRelocRef() = default; BaseRelocRef(const coff_base_reloc_block_header * Header,const COFFObjectFile * Owner)1283 BaseRelocRef(const coff_base_reloc_block_header *Header, 1284 const COFFObjectFile *Owner) 1285 : Header(Header), Index(0) {} 1286 1287 bool operator==(const BaseRelocRef &Other) const; 1288 void moveNext(); 1289 1290 Error getType(uint8_t &Type) const; 1291 Error getRVA(uint32_t &Result) const; 1292 1293 private: 1294 const coff_base_reloc_block_header *Header; 1295 uint32_t Index; 1296 }; 1297 1298 class ResourceSectionRef { 1299 public: 1300 ResourceSectionRef() = default; ResourceSectionRef(StringRef Ref)1301 explicit ResourceSectionRef(StringRef Ref) 1302 : BBS(Ref, llvm::endianness::little) {} 1303 1304 Error load(const COFFObjectFile *O); 1305 Error load(const COFFObjectFile *O, const SectionRef &S); 1306 1307 Expected<ArrayRef<UTF16>> 1308 getEntryNameString(const coff_resource_dir_entry &Entry); 1309 Expected<const coff_resource_dir_table &> 1310 getEntrySubDir(const coff_resource_dir_entry &Entry); 1311 Expected<const coff_resource_data_entry &> 1312 getEntryData(const coff_resource_dir_entry &Entry); 1313 Expected<const coff_resource_dir_table &> getBaseTable(); 1314 Expected<const coff_resource_dir_entry &> 1315 getTableEntry(const coff_resource_dir_table &Table, uint32_t Index); 1316 1317 Expected<StringRef> getContents(const coff_resource_data_entry &Entry); 1318 1319 private: 1320 BinaryByteStream BBS; 1321 1322 SectionRef Section; 1323 const COFFObjectFile *Obj = nullptr; 1324 1325 std::vector<const coff_relocation *> Relocs; 1326 1327 Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); 1328 Expected<const coff_resource_dir_entry &> 1329 getTableEntryAtOffset(uint32_t Offset); 1330 Expected<const coff_resource_data_entry &> 1331 getDataEntryAtOffset(uint32_t Offset); 1332 Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); 1333 }; 1334 1335 // Corresponds to `_FPO_DATA` structure in the PE/COFF spec. 1336 struct FpoData { 1337 support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code 1338 support::ulittle32_t Size; // cbProcSize: # bytes in function 1339 support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 1340 support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 1341 support::ulittle16_t Attributes; 1342 1343 // cbProlog: # bytes in prolog getPrologSizeFpoData1344 int getPrologSize() const { return Attributes & 0xF; } 1345 1346 // cbRegs: # regs saved getNumSavedRegsFpoData1347 int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } 1348 1349 // fHasSEH: true if seh is func hasSEHFpoData1350 bool hasSEH() const { return (Attributes >> 9) & 1; } 1351 1352 // fUseBP: true if EBP has been allocated useBPFpoData1353 bool useBP() const { return (Attributes >> 10) & 1; } 1354 1355 // cbFrame: frame pointer getFPFpoData1356 frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); } 1357 }; 1358 1359 class SectionStrippedError 1360 : public ErrorInfo<SectionStrippedError, BinaryError> { 1361 public: SectionStrippedError()1362 SectionStrippedError() { setErrorCode(object_error::section_stripped); } 1363 }; 1364 1365 } // end namespace object 1366 1367 } // end namespace llvm 1368 1369 #endif // LLVM_OBJECT_COFF_H 1370