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