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