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