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