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