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 template <typename IntTy> 173 struct import_lookup_table_entry { 174 IntTy Data; 175 isOrdinalimport_lookup_table_entry176 bool isOrdinal() const { return Data < 0; } 177 getOrdinalimport_lookup_table_entry178 uint16_t getOrdinal() const { 179 assert(isOrdinal() && "ILT entry is not an ordinal!"); 180 return Data & 0xFFFF; 181 } 182 getHintNameRVAimport_lookup_table_entry183 uint32_t getHintNameRVA() const { 184 assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); 185 return Data & 0xFFFFFFFF; 186 } 187 }; 188 189 typedef import_lookup_table_entry<support::little32_t> 190 import_lookup_table_entry32; 191 typedef import_lookup_table_entry<support::little64_t> 192 import_lookup_table_entry64; 193 194 struct delay_import_directory_table_entry { 195 // dumpbin reports this field as "Characteristics" instead of "Attributes". 196 support::ulittle32_t Attributes; 197 support::ulittle32_t Name; 198 support::ulittle32_t ModuleHandle; 199 support::ulittle32_t DelayImportAddressTable; 200 support::ulittle32_t DelayImportNameTable; 201 support::ulittle32_t BoundDelayImportTable; 202 support::ulittle32_t UnloadDelayImportTable; 203 support::ulittle32_t TimeStamp; 204 }; 205 206 struct export_directory_table_entry { 207 support::ulittle32_t ExportFlags; 208 support::ulittle32_t TimeDateStamp; 209 support::ulittle16_t MajorVersion; 210 support::ulittle16_t MinorVersion; 211 support::ulittle32_t NameRVA; 212 support::ulittle32_t OrdinalBase; 213 support::ulittle32_t AddressTableEntries; 214 support::ulittle32_t NumberOfNamePointers; 215 support::ulittle32_t ExportAddressTableRVA; 216 support::ulittle32_t NamePointerRVA; 217 support::ulittle32_t OrdinalTableRVA; 218 }; 219 220 union export_address_table_entry { 221 support::ulittle32_t ExportRVA; 222 support::ulittle32_t ForwarderRVA; 223 }; 224 225 typedef support::ulittle32_t export_name_pointer_table_entry; 226 typedef support::ulittle16_t export_ordinal_table_entry; 227 228 struct StringTableOffset { 229 support::ulittle32_t Zeroes; 230 support::ulittle32_t Offset; 231 }; 232 233 template <typename SectionNumberType> 234 struct coff_symbol { 235 union { 236 char ShortName[COFF::NameSize]; 237 StringTableOffset Offset; 238 } Name; 239 240 support::ulittle32_t Value; 241 SectionNumberType SectionNumber; 242 243 support::ulittle16_t Type; 244 245 uint8_t StorageClass; 246 uint8_t NumberOfAuxSymbols; 247 }; 248 249 typedef coff_symbol<support::ulittle16_t> coff_symbol16; 250 typedef coff_symbol<support::ulittle32_t> coff_symbol32; 251 252 // Contains only common parts of coff_symbol16 and coff_symbol32. 253 struct coff_symbol_generic { 254 union { 255 char ShortName[COFF::NameSize]; 256 StringTableOffset Offset; 257 } Name; 258 support::ulittle32_t Value; 259 }; 260 261 class COFFSymbolRef { 262 public: COFFSymbolRef(const coff_symbol16 * CS)263 COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {} COFFSymbolRef(const coff_symbol32 * CS)264 COFFSymbolRef(const coff_symbol32 *CS) : CS16(nullptr), CS32(CS) {} COFFSymbolRef()265 COFFSymbolRef() : CS16(nullptr), CS32(nullptr) {} 266 getRawPtr()267 const void *getRawPtr() const { 268 return CS16 ? static_cast<const void *>(CS16) : CS32; 269 } 270 getGeneric()271 const coff_symbol_generic *getGeneric() const { 272 if (CS16) 273 return reinterpret_cast<const coff_symbol_generic *>(CS16); 274 return reinterpret_cast<const coff_symbol_generic *>(CS32); 275 } 276 277 friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { 278 return A.getRawPtr() < B.getRawPtr(); 279 } 280 isBigObj()281 bool isBigObj() const { 282 if (CS16) 283 return false; 284 if (CS32) 285 return true; 286 llvm_unreachable("COFFSymbolRef points to nothing!"); 287 } 288 getShortName()289 const char *getShortName() const { 290 return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; 291 } 292 getStringTableOffset()293 const StringTableOffset &getStringTableOffset() const { 294 assert(isSet() && "COFFSymbolRef points to nothing!"); 295 return CS16 ? CS16->Name.Offset : CS32->Name.Offset; 296 } 297 getValue()298 uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } 299 getSectionNumber()300 int32_t getSectionNumber() const { 301 assert(isSet() && "COFFSymbolRef points to nothing!"); 302 if (CS16) { 303 // Reserved sections are returned as negative numbers. 304 if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) 305 return CS16->SectionNumber; 306 return static_cast<int16_t>(CS16->SectionNumber); 307 } 308 return static_cast<int32_t>(CS32->SectionNumber); 309 } 310 getType()311 uint16_t getType() const { 312 assert(isSet() && "COFFSymbolRef points to nothing!"); 313 return CS16 ? CS16->Type : CS32->Type; 314 } 315 getStorageClass()316 uint8_t getStorageClass() const { 317 assert(isSet() && "COFFSymbolRef points to nothing!"); 318 return CS16 ? CS16->StorageClass : CS32->StorageClass; 319 } 320 getNumberOfAuxSymbols()321 uint8_t getNumberOfAuxSymbols() const { 322 assert(isSet() && "COFFSymbolRef points to nothing!"); 323 return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; 324 } 325 getBaseType()326 uint8_t getBaseType() const { return getType() & 0x0F; } 327 getComplexType()328 uint8_t getComplexType() const { 329 return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; 330 } 331 isAbsolute()332 bool isAbsolute() const { 333 return getSectionNumber() == -1; 334 } 335 isExternal()336 bool isExternal() const { 337 return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; 338 } 339 isCommon()340 bool isCommon() const { 341 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 342 getValue() != 0; 343 } 344 isUndefined()345 bool isUndefined() const { 346 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 347 getValue() == 0; 348 } 349 isWeakExternal()350 bool isWeakExternal() const { 351 return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; 352 } 353 isFunctionDefinition()354 bool isFunctionDefinition() const { 355 return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && 356 getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && 357 !COFF::isReservedSectionNumber(getSectionNumber()); 358 } 359 isFunctionLineInfo()360 bool isFunctionLineInfo() const { 361 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; 362 } 363 isAnyUndefined()364 bool isAnyUndefined() const { 365 return isUndefined() || isWeakExternal(); 366 } 367 isFileRecord()368 bool isFileRecord() const { 369 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; 370 } 371 isSection()372 bool isSection() const { 373 return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; 374 } 375 isSectionDefinition()376 bool isSectionDefinition() const { 377 // C++/CLI creates external ABS symbols for non-const appdomain globals. 378 // These are also followed by an auxiliary section definition. 379 bool isAppdomainGlobal = 380 getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && 381 getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; 382 bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; 383 if (!getNumberOfAuxSymbols()) 384 return false; 385 return isAppdomainGlobal || isOrdinarySection; 386 } 387 isCLRToken()388 bool isCLRToken() const { 389 return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; 390 } 391 392 private: isSet()393 bool isSet() const { return CS16 || CS32; } 394 395 const coff_symbol16 *CS16; 396 const coff_symbol32 *CS32; 397 }; 398 399 struct coff_section { 400 char Name[COFF::NameSize]; 401 support::ulittle32_t VirtualSize; 402 support::ulittle32_t VirtualAddress; 403 support::ulittle32_t SizeOfRawData; 404 support::ulittle32_t PointerToRawData; 405 support::ulittle32_t PointerToRelocations; 406 support::ulittle32_t PointerToLinenumbers; 407 support::ulittle16_t NumberOfRelocations; 408 support::ulittle16_t NumberOfLinenumbers; 409 support::ulittle32_t Characteristics; 410 411 // Returns true if the actual number of relocations is stored in 412 // VirtualAddress field of the first relocation table entry. hasExtendedRelocationscoff_section413 bool hasExtendedRelocations() const { 414 return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && 415 NumberOfRelocations == UINT16_MAX; 416 } 417 }; 418 419 struct coff_relocation { 420 support::ulittle32_t VirtualAddress; 421 support::ulittle32_t SymbolTableIndex; 422 support::ulittle16_t Type; 423 }; 424 425 struct coff_aux_function_definition { 426 support::ulittle32_t TagIndex; 427 support::ulittle32_t TotalSize; 428 support::ulittle32_t PointerToLinenumber; 429 support::ulittle32_t PointerToNextFunction; 430 }; 431 432 struct coff_aux_bf_and_ef_symbol { 433 char Unused1[4]; 434 support::ulittle16_t Linenumber; 435 char Unused2[6]; 436 support::ulittle32_t PointerToNextFunction; 437 }; 438 439 struct coff_aux_weak_external { 440 support::ulittle32_t TagIndex; 441 support::ulittle32_t Characteristics; 442 }; 443 444 struct coff_aux_section_definition { 445 support::ulittle32_t Length; 446 support::ulittle16_t NumberOfRelocations; 447 support::ulittle16_t NumberOfLinenumbers; 448 support::ulittle32_t CheckSum; 449 support::ulittle16_t NumberLowPart; 450 uint8_t Selection; 451 uint8_t Unused; 452 support::ulittle16_t NumberHighPart; getNumbercoff_aux_section_definition453 int32_t getNumber(bool IsBigObj) const { 454 uint32_t Number = static_cast<uint32_t>(NumberLowPart); 455 if (IsBigObj) 456 Number |= static_cast<uint32_t>(NumberHighPart) << 16; 457 return static_cast<int32_t>(Number); 458 } 459 }; 460 461 struct coff_aux_clr_token { 462 uint8_t AuxType; 463 uint8_t Reserved; 464 support::ulittle32_t SymbolTableIndex; 465 }; 466 467 struct coff_import_header { 468 support::ulittle16_t Sig1; 469 support::ulittle16_t Sig2; 470 support::ulittle16_t Version; 471 support::ulittle16_t Machine; 472 support::ulittle32_t TimeDateStamp; 473 support::ulittle32_t SizeOfData; 474 support::ulittle16_t OrdinalHint; 475 support::ulittle16_t TypeInfo; getTypecoff_import_header476 int getType() const { return TypeInfo & 0x3; } getNameTypecoff_import_header477 int getNameType() const { return (TypeInfo >> 2) & 0x7; } 478 }; 479 480 struct coff_import_directory_table_entry { 481 support::ulittle32_t ImportLookupTableRVA; 482 support::ulittle32_t TimeDateStamp; 483 support::ulittle32_t ForwarderChain; 484 support::ulittle32_t NameRVA; 485 support::ulittle32_t ImportAddressTableRVA; 486 }; 487 488 struct coff_load_configuration32 { 489 support::ulittle32_t Characteristics; 490 support::ulittle32_t TimeDateStamp; 491 support::ulittle16_t MajorVersion; 492 support::ulittle16_t MinorVersion; 493 support::ulittle32_t GlobalFlagsClear; 494 support::ulittle32_t GlobalFlagsSet; 495 support::ulittle32_t CriticalSectionDefaultTimeout; 496 support::ulittle32_t DeCommitFreeBlockThreshold; 497 support::ulittle32_t DeCommitTotalFreeThreshold; 498 support::ulittle32_t LockPrefixTable; 499 support::ulittle32_t MaximumAllocationSize; 500 support::ulittle32_t VirtualMemoryThreshold; 501 support::ulittle32_t ProcessAffinityMask; 502 support::ulittle32_t ProcessHeapFlags; 503 support::ulittle16_t CSDVersion; 504 support::ulittle16_t Reserved; 505 support::ulittle32_t EditList; 506 support::ulittle32_t SecurityCookie; 507 support::ulittle32_t SEHandlerTable; 508 support::ulittle32_t SEHandlerCount; 509 }; 510 511 struct coff_load_configuration64 { 512 support::ulittle32_t Characteristics; 513 support::ulittle32_t TimeDateStamp; 514 support::ulittle16_t MajorVersion; 515 support::ulittle16_t MinorVersion; 516 support::ulittle32_t GlobalFlagsClear; 517 support::ulittle32_t GlobalFlagsSet; 518 support::ulittle32_t CriticalSectionDefaultTimeout; 519 support::ulittle32_t DeCommitFreeBlockThreshold; 520 support::ulittle32_t DeCommitTotalFreeThreshold; 521 support::ulittle32_t LockPrefixTable; 522 support::ulittle32_t MaximumAllocationSize; 523 support::ulittle32_t VirtualMemoryThreshold; 524 support::ulittle32_t ProcessAffinityMask; 525 support::ulittle32_t ProcessHeapFlags; 526 support::ulittle16_t CSDVersion; 527 support::ulittle16_t Reserved; 528 support::ulittle32_t EditList; 529 support::ulittle64_t SecurityCookie; 530 support::ulittle64_t SEHandlerTable; 531 support::ulittle64_t SEHandlerCount; 532 }; 533 534 struct coff_runtime_function_x64 { 535 support::ulittle32_t BeginAddress; 536 support::ulittle32_t EndAddress; 537 support::ulittle32_t UnwindInformation; 538 }; 539 540 struct coff_base_reloc_block_header { 541 support::ulittle32_t PageRVA; 542 support::ulittle32_t BlockSize; 543 }; 544 545 struct coff_base_reloc_block_entry { 546 support::ulittle16_t Data; getTypecoff_base_reloc_block_entry547 int getType() const { return Data >> 12; } getOffsetcoff_base_reloc_block_entry548 int getOffset() const { return Data & ((1 << 12) - 1); } 549 }; 550 551 class COFFObjectFile : public ObjectFile { 552 private: 553 friend class ImportDirectoryEntryRef; 554 friend class ExportDirectoryEntryRef; 555 const coff_file_header *COFFHeader; 556 const coff_bigobj_file_header *COFFBigObjHeader; 557 const pe32_header *PE32Header; 558 const pe32plus_header *PE32PlusHeader; 559 const data_directory *DataDirectory; 560 const coff_section *SectionTable; 561 const coff_symbol16 *SymbolTable16; 562 const coff_symbol32 *SymbolTable32; 563 const char *StringTable; 564 uint32_t StringTableSize; 565 const import_directory_table_entry *ImportDirectory; 566 uint32_t NumberOfImportDirectory; 567 const delay_import_directory_table_entry *DelayImportDirectory; 568 uint32_t NumberOfDelayImportDirectory; 569 const export_directory_table_entry *ExportDirectory; 570 const coff_base_reloc_block_header *BaseRelocHeader; 571 const coff_base_reloc_block_header *BaseRelocEnd; 572 573 std::error_code getString(uint32_t offset, StringRef &Res) const; 574 575 template <typename coff_symbol_type> 576 const coff_symbol_type *toSymb(DataRefImpl Symb) const; 577 const coff_section *toSec(DataRefImpl Sec) const; 578 const coff_relocation *toRel(DataRefImpl Rel) const; 579 580 std::error_code initSymbolTablePtr(); 581 std::error_code initImportTablePtr(); 582 std::error_code initDelayImportTablePtr(); 583 std::error_code initExportTablePtr(); 584 std::error_code initBaseRelocPtr(); 585 586 public: getSymbolTable()587 uintptr_t getSymbolTable() const { 588 if (SymbolTable16) 589 return reinterpret_cast<uintptr_t>(SymbolTable16); 590 if (SymbolTable32) 591 return reinterpret_cast<uintptr_t>(SymbolTable32); 592 return uintptr_t(0); 593 } getMachine()594 uint16_t getMachine() const { 595 if (COFFHeader) 596 return COFFHeader->Machine; 597 if (COFFBigObjHeader) 598 return COFFBigObjHeader->Machine; 599 llvm_unreachable("no COFF header!"); 600 } getSizeOfOptionalHeader()601 uint16_t getSizeOfOptionalHeader() const { 602 if (COFFHeader) 603 return COFFHeader->isImportLibrary() ? 0 604 : COFFHeader->SizeOfOptionalHeader; 605 // bigobj doesn't have this field. 606 if (COFFBigObjHeader) 607 return 0; 608 llvm_unreachable("no COFF header!"); 609 } getCharacteristics()610 uint16_t getCharacteristics() const { 611 if (COFFHeader) 612 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; 613 // bigobj doesn't have characteristics to speak of, 614 // editbin will silently lie to you if you attempt to set any. 615 if (COFFBigObjHeader) 616 return 0; 617 llvm_unreachable("no COFF header!"); 618 } getTimeDateStamp()619 uint32_t getTimeDateStamp() const { 620 if (COFFHeader) 621 return COFFHeader->TimeDateStamp; 622 if (COFFBigObjHeader) 623 return COFFBigObjHeader->TimeDateStamp; 624 llvm_unreachable("no COFF header!"); 625 } getNumberOfSections()626 uint32_t getNumberOfSections() const { 627 if (COFFHeader) 628 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; 629 if (COFFBigObjHeader) 630 return COFFBigObjHeader->NumberOfSections; 631 llvm_unreachable("no COFF header!"); 632 } getPointerToSymbolTable()633 uint32_t getPointerToSymbolTable() const { 634 if (COFFHeader) 635 return COFFHeader->isImportLibrary() ? 0 636 : COFFHeader->PointerToSymbolTable; 637 if (COFFBigObjHeader) 638 return COFFBigObjHeader->PointerToSymbolTable; 639 llvm_unreachable("no COFF header!"); 640 } getNumberOfSymbols()641 uint32_t getNumberOfSymbols() const { 642 if (COFFHeader) 643 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; 644 if (COFFBigObjHeader) 645 return COFFBigObjHeader->NumberOfSymbols; 646 llvm_unreachable("no COFF header!"); 647 } 648 protected: 649 void moveSymbolNext(DataRefImpl &Symb) const override; 650 ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; 651 ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 652 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 653 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 654 uint32_t getSymbolFlags(DataRefImpl Symb) const override; 655 SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; 656 ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 657 void moveSectionNext(DataRefImpl &Sec) const override; 658 std::error_code getSectionName(DataRefImpl Sec, 659 StringRef &Res) const override; 660 uint64_t getSectionAddress(DataRefImpl Sec) const override; 661 uint64_t getSectionSize(DataRefImpl Sec) const override; 662 std::error_code getSectionContents(DataRefImpl Sec, 663 StringRef &Res) const override; 664 uint64_t getSectionAlignment(DataRefImpl Sec) const override; 665 bool isSectionText(DataRefImpl Sec) const override; 666 bool isSectionData(DataRefImpl Sec) const override; 667 bool isSectionBSS(DataRefImpl Sec) const override; 668 bool isSectionVirtual(DataRefImpl Sec) const override; 669 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 670 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 671 672 void moveRelocationNext(DataRefImpl &Rel) const override; 673 uint64_t getRelocationOffset(DataRefImpl Rel) const override; 674 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 675 uint64_t getRelocationType(DataRefImpl Rel) const override; 676 void getRelocationTypeName(DataRefImpl Rel, 677 SmallVectorImpl<char> &Result) const override; 678 679 public: 680 COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); 681 basic_symbol_iterator symbol_begin_impl() const override; 682 basic_symbol_iterator symbol_end_impl() const override; 683 section_iterator section_begin() const override; 684 section_iterator section_end() const override; 685 686 const coff_section *getCOFFSection(const SectionRef &Section) const; 687 COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; 688 COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; 689 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; 690 unsigned getSectionID(SectionRef Sec) const; 691 unsigned getSymbolSectionID(SymbolRef Sym) const; 692 693 uint8_t getBytesInAddress() const override; 694 StringRef getFileFormatName() const override; 695 unsigned getArch() const override; 696 697 import_directory_iterator import_directory_begin() const; 698 import_directory_iterator import_directory_end() const; 699 delay_import_directory_iterator delay_import_directory_begin() const; 700 delay_import_directory_iterator delay_import_directory_end() const; 701 export_directory_iterator export_directory_begin() const; 702 export_directory_iterator export_directory_end() const; 703 base_reloc_iterator base_reloc_begin() const; 704 base_reloc_iterator base_reloc_end() const; 705 706 iterator_range<import_directory_iterator> import_directories() const; 707 iterator_range<delay_import_directory_iterator> 708 delay_import_directories() const; 709 iterator_range<export_directory_iterator> export_directories() const; 710 iterator_range<base_reloc_iterator> base_relocs() const; 711 getDOSHeader()712 const dos_header *getDOSHeader() const { 713 if (!PE32Header && !PE32PlusHeader) 714 return nullptr; 715 return reinterpret_cast<const dos_header *>(base()); 716 } 717 std::error_code getPE32Header(const pe32_header *&Res) const; 718 std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; 719 std::error_code getDataDirectory(uint32_t index, 720 const data_directory *&Res) const; 721 std::error_code getSection(int32_t index, const coff_section *&Res) const; 722 template <typename coff_symbol_type> getSymbol(uint32_t Index,const coff_symbol_type * & Res)723 std::error_code getSymbol(uint32_t Index, 724 const coff_symbol_type *&Res) const { 725 if (Index >= getNumberOfSymbols()) 726 return object_error::parse_failed; 727 728 Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; 729 return std::error_code(); 730 } getSymbol(uint32_t index)731 ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const { 732 if (SymbolTable16) { 733 const coff_symbol16 *Symb = nullptr; 734 if (std::error_code EC = getSymbol(index, Symb)) 735 return EC; 736 return COFFSymbolRef(Symb); 737 } 738 if (SymbolTable32) { 739 const coff_symbol32 *Symb = nullptr; 740 if (std::error_code EC = getSymbol(index, Symb)) 741 return EC; 742 return COFFSymbolRef(Symb); 743 } 744 return object_error::parse_failed; 745 } 746 template <typename T> getAuxSymbol(uint32_t index,const T * & Res)747 std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { 748 ErrorOr<COFFSymbolRef> s = getSymbol(index); 749 if (std::error_code EC = s.getError()) 750 return EC; 751 Res = reinterpret_cast<const T *>(s->getRawPtr()); 752 return std::error_code(); 753 } 754 std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; 755 std::error_code getSymbolName(const coff_symbol_generic *Symbol, 756 StringRef &Res) const; 757 758 ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; 759 getSymbolTableEntrySize()760 size_t getSymbolTableEntrySize() const { 761 if (COFFHeader) 762 return sizeof(coff_symbol16); 763 if (COFFBigObjHeader) 764 return sizeof(coff_symbol32); 765 llvm_unreachable("null symbol table pointer!"); 766 } 767 768 iterator_range<const coff_relocation *> 769 getRelocations(const coff_section *Sec) const; 770 771 std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; 772 uint64_t getSectionSize(const coff_section *Sec) const; 773 std::error_code getSectionContents(const coff_section *Sec, 774 ArrayRef<uint8_t> &Res) const; 775 776 uint64_t getImageBase() const; 777 std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; 778 std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; 779 std::error_code getHintName(uint32_t Rva, uint16_t &Hint, 780 StringRef &Name) const; 781 782 bool isRelocatableObject() const override; is64()783 bool is64() const { return PE32PlusHeader; } 784 classof(const Binary * v)785 static inline bool classof(const Binary *v) { return v->isCOFF(); } 786 }; 787 788 // The iterator for the import directory table. 789 class ImportDirectoryEntryRef { 790 public: ImportDirectoryEntryRef()791 ImportDirectoryEntryRef() : OwningObject(nullptr) {} ImportDirectoryEntryRef(const import_directory_table_entry * Table,uint32_t I,const COFFObjectFile * Owner)792 ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I, 793 const COFFObjectFile *Owner) 794 : ImportTable(Table), Index(I), OwningObject(Owner) {} 795 796 bool operator==(const ImportDirectoryEntryRef &Other) const; 797 void moveNext(); 798 799 imported_symbol_iterator imported_symbol_begin() const; 800 imported_symbol_iterator imported_symbol_end() const; 801 iterator_range<imported_symbol_iterator> imported_symbols() const; 802 803 std::error_code getName(StringRef &Result) const; 804 std::error_code getImportLookupTableRVA(uint32_t &Result) const; 805 std::error_code getImportAddressTableRVA(uint32_t &Result) const; 806 807 std::error_code 808 getImportTableEntry(const import_directory_table_entry *&Result) const; 809 810 std::error_code 811 getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; 812 813 private: 814 const import_directory_table_entry *ImportTable; 815 uint32_t Index; 816 const COFFObjectFile *OwningObject; 817 }; 818 819 class DelayImportDirectoryEntryRef { 820 public: DelayImportDirectoryEntryRef()821 DelayImportDirectoryEntryRef() : OwningObject(nullptr) {} DelayImportDirectoryEntryRef(const delay_import_directory_table_entry * T,uint32_t I,const COFFObjectFile * Owner)822 DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, 823 uint32_t I, const COFFObjectFile *Owner) 824 : Table(T), Index(I), OwningObject(Owner) {} 825 826 bool operator==(const DelayImportDirectoryEntryRef &Other) const; 827 void moveNext(); 828 829 imported_symbol_iterator imported_symbol_begin() const; 830 imported_symbol_iterator imported_symbol_end() const; 831 iterator_range<imported_symbol_iterator> imported_symbols() const; 832 833 std::error_code getName(StringRef &Result) const; 834 std::error_code getDelayImportTable( 835 const delay_import_directory_table_entry *&Result) const; 836 std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; 837 838 private: 839 const delay_import_directory_table_entry *Table; 840 uint32_t Index; 841 const COFFObjectFile *OwningObject; 842 }; 843 844 // The iterator for the export directory table entry. 845 class ExportDirectoryEntryRef { 846 public: ExportDirectoryEntryRef()847 ExportDirectoryEntryRef() : OwningObject(nullptr) {} ExportDirectoryEntryRef(const export_directory_table_entry * Table,uint32_t I,const COFFObjectFile * Owner)848 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, 849 const COFFObjectFile *Owner) 850 : ExportTable(Table), Index(I), OwningObject(Owner) {} 851 852 bool operator==(const ExportDirectoryEntryRef &Other) const; 853 void moveNext(); 854 855 std::error_code getDllName(StringRef &Result) const; 856 std::error_code getOrdinalBase(uint32_t &Result) const; 857 std::error_code getOrdinal(uint32_t &Result) const; 858 std::error_code getExportRVA(uint32_t &Result) const; 859 std::error_code getSymbolName(StringRef &Result) const; 860 861 private: 862 const export_directory_table_entry *ExportTable; 863 uint32_t Index; 864 const COFFObjectFile *OwningObject; 865 }; 866 867 class ImportedSymbolRef { 868 public: ImportedSymbolRef()869 ImportedSymbolRef() : OwningObject(nullptr) {} ImportedSymbolRef(const import_lookup_table_entry32 * Entry,uint32_t I,const COFFObjectFile * Owner)870 ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, 871 const COFFObjectFile *Owner) 872 : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} ImportedSymbolRef(const import_lookup_table_entry64 * Entry,uint32_t I,const COFFObjectFile * Owner)873 ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, 874 const COFFObjectFile *Owner) 875 : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} 876 877 bool operator==(const ImportedSymbolRef &Other) const; 878 void moveNext(); 879 880 std::error_code getSymbolName(StringRef &Result) const; 881 std::error_code getOrdinal(uint16_t &Result) const; 882 883 private: 884 const import_lookup_table_entry32 *Entry32; 885 const import_lookup_table_entry64 *Entry64; 886 uint32_t Index; 887 const COFFObjectFile *OwningObject; 888 }; 889 890 class BaseRelocRef { 891 public: BaseRelocRef()892 BaseRelocRef() : OwningObject(nullptr) {} BaseRelocRef(const coff_base_reloc_block_header * Header,const COFFObjectFile * Owner)893 BaseRelocRef(const coff_base_reloc_block_header *Header, 894 const COFFObjectFile *Owner) 895 : Header(Header), Index(0), OwningObject(Owner) {} 896 897 bool operator==(const BaseRelocRef &Other) const; 898 void moveNext(); 899 900 std::error_code getType(uint8_t &Type) const; 901 std::error_code getRVA(uint32_t &Result) const; 902 903 private: 904 const coff_base_reloc_block_header *Header; 905 uint32_t Index; 906 const COFFObjectFile *OwningObject; 907 }; 908 909 } // end namespace object 910 } // end namespace llvm 911 912 #endif 913