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/Object/ObjectFile.h" 18 #include "llvm/Support/COFF.h" 19 #include "llvm/Support/Endian.h" 20 21 namespace llvm { 22 template <typename T> class ArrayRef; 23 24 namespace object { 25 class ImportDirectoryEntryRef; 26 class ExportDirectoryEntryRef; 27 typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; 28 typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator; 29 30 /// The DOS compatible header at the front of all PE/COFF executables. 31 struct dos_header { 32 support::ulittle16_t Magic; 33 support::ulittle16_t UsedBytesInTheLastPage; 34 support::ulittle16_t FileSizeInPages; 35 support::ulittle16_t NumberOfRelocationItems; 36 support::ulittle16_t HeaderSizeInParagraphs; 37 support::ulittle16_t MinimumExtraParagraphs; 38 support::ulittle16_t MaximumExtraParagraphs; 39 support::ulittle16_t InitialRelativeSS; 40 support::ulittle16_t InitialSP; 41 support::ulittle16_t Checksum; 42 support::ulittle16_t InitialIP; 43 support::ulittle16_t InitialRelativeCS; 44 support::ulittle16_t AddressOfRelocationTable; 45 support::ulittle16_t OverlayNumber; 46 support::ulittle16_t Reserved[4]; 47 support::ulittle16_t OEMid; 48 support::ulittle16_t OEMinfo; 49 support::ulittle16_t Reserved2[10]; 50 support::ulittle32_t AddressOfNewExeHeader; 51 }; 52 53 struct coff_file_header { 54 support::ulittle16_t Machine; 55 support::ulittle16_t NumberOfSections; 56 support::ulittle32_t TimeDateStamp; 57 support::ulittle32_t PointerToSymbolTable; 58 support::ulittle32_t NumberOfSymbols; 59 support::ulittle16_t SizeOfOptionalHeader; 60 support::ulittle16_t Characteristics; 61 62 bool isImportLibrary() const { return NumberOfSections == 0xffff; } 63 }; 64 65 /// The 32-bit PE header that follows the COFF header. 66 struct pe32_header { 67 support::ulittle16_t Magic; 68 uint8_t MajorLinkerVersion; 69 uint8_t MinorLinkerVersion; 70 support::ulittle32_t SizeOfCode; 71 support::ulittle32_t SizeOfInitializedData; 72 support::ulittle32_t SizeOfUninitializedData; 73 support::ulittle32_t AddressOfEntryPoint; 74 support::ulittle32_t BaseOfCode; 75 support::ulittle32_t BaseOfData; 76 support::ulittle32_t ImageBase; 77 support::ulittle32_t SectionAlignment; 78 support::ulittle32_t FileAlignment; 79 support::ulittle16_t MajorOperatingSystemVersion; 80 support::ulittle16_t MinorOperatingSystemVersion; 81 support::ulittle16_t MajorImageVersion; 82 support::ulittle16_t MinorImageVersion; 83 support::ulittle16_t MajorSubsystemVersion; 84 support::ulittle16_t MinorSubsystemVersion; 85 support::ulittle32_t Win32VersionValue; 86 support::ulittle32_t SizeOfImage; 87 support::ulittle32_t SizeOfHeaders; 88 support::ulittle32_t CheckSum; 89 support::ulittle16_t Subsystem; 90 support::ulittle16_t DLLCharacteristics; 91 support::ulittle32_t SizeOfStackReserve; 92 support::ulittle32_t SizeOfStackCommit; 93 support::ulittle32_t SizeOfHeapReserve; 94 support::ulittle32_t SizeOfHeapCommit; 95 support::ulittle32_t LoaderFlags; 96 support::ulittle32_t NumberOfRvaAndSize; 97 }; 98 99 /// The 64-bit PE header that follows the COFF header. 100 struct pe32plus_header { 101 support::ulittle16_t Magic; 102 uint8_t MajorLinkerVersion; 103 uint8_t MinorLinkerVersion; 104 support::ulittle32_t SizeOfCode; 105 support::ulittle32_t SizeOfInitializedData; 106 support::ulittle32_t SizeOfUninitializedData; 107 support::ulittle32_t AddressOfEntryPoint; 108 support::ulittle32_t BaseOfCode; 109 support::ulittle64_t ImageBase; 110 support::ulittle32_t SectionAlignment; 111 support::ulittle32_t FileAlignment; 112 support::ulittle16_t MajorOperatingSystemVersion; 113 support::ulittle16_t MinorOperatingSystemVersion; 114 support::ulittle16_t MajorImageVersion; 115 support::ulittle16_t MinorImageVersion; 116 support::ulittle16_t MajorSubsystemVersion; 117 support::ulittle16_t MinorSubsystemVersion; 118 support::ulittle32_t Win32VersionValue; 119 support::ulittle32_t SizeOfImage; 120 support::ulittle32_t SizeOfHeaders; 121 support::ulittle32_t CheckSum; 122 support::ulittle16_t Subsystem; 123 support::ulittle16_t DLLCharacteristics; 124 support::ulittle64_t SizeOfStackReserve; 125 support::ulittle64_t SizeOfStackCommit; 126 support::ulittle64_t SizeOfHeapReserve; 127 support::ulittle64_t SizeOfHeapCommit; 128 support::ulittle32_t LoaderFlags; 129 support::ulittle32_t NumberOfRvaAndSize; 130 }; 131 132 struct data_directory { 133 support::ulittle32_t RelativeVirtualAddress; 134 support::ulittle32_t Size; 135 }; 136 137 struct import_directory_table_entry { 138 support::ulittle32_t ImportLookupTableRVA; 139 support::ulittle32_t TimeDateStamp; 140 support::ulittle32_t ForwarderChain; 141 support::ulittle32_t NameRVA; 142 support::ulittle32_t ImportAddressTableRVA; 143 }; 144 145 struct import_lookup_table_entry32 { 146 support::ulittle32_t data; 147 148 bool isOrdinal() const { return data & 0x80000000; } 149 150 uint16_t getOrdinal() const { 151 assert(isOrdinal() && "ILT entry is not an ordinal!"); 152 return data & 0xFFFF; 153 } 154 155 uint32_t getHintNameRVA() const { 156 assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); 157 return data; 158 } 159 }; 160 161 struct export_directory_table_entry { 162 support::ulittle32_t ExportFlags; 163 support::ulittle32_t TimeDateStamp; 164 support::ulittle16_t MajorVersion; 165 support::ulittle16_t MinorVersion; 166 support::ulittle32_t NameRVA; 167 support::ulittle32_t OrdinalBase; 168 support::ulittle32_t AddressTableEntries; 169 support::ulittle32_t NumberOfNamePointers; 170 support::ulittle32_t ExportAddressTableRVA; 171 support::ulittle32_t NamePointerRVA; 172 support::ulittle32_t OrdinalTableRVA; 173 }; 174 175 union export_address_table_entry { 176 support::ulittle32_t ExportRVA; 177 support::ulittle32_t ForwarderRVA; 178 }; 179 180 typedef support::ulittle32_t export_name_pointer_table_entry; 181 typedef support::ulittle16_t export_ordinal_table_entry; 182 183 struct coff_symbol { 184 struct StringTableOffset { 185 support::ulittle32_t Zeroes; 186 support::ulittle32_t Offset; 187 }; 188 189 union { 190 char ShortName[8]; 191 StringTableOffset Offset; 192 } Name; 193 194 support::ulittle32_t Value; 195 support::ulittle16_t SectionNumber; 196 197 support::ulittle16_t Type; 198 199 support::ulittle8_t StorageClass; 200 support::ulittle8_t NumberOfAuxSymbols; 201 202 uint8_t getBaseType() const { return Type & 0x0F; } 203 204 uint8_t getComplexType() const { return (Type & 0xF0) >> 4; } 205 206 bool isFunctionDefinition() const { 207 return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 208 getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && 209 getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && 210 !COFF::isReservedSectionNumber(SectionNumber); 211 } 212 213 bool isFunctionLineInfo() const { 214 return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION; 215 } 216 217 bool isWeakExternal() const { 218 return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || 219 (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 220 SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0); 221 } 222 223 bool isFileRecord() const { 224 return StorageClass == COFF::IMAGE_SYM_CLASS_FILE; 225 } 226 227 bool isSectionDefinition() const { 228 // C++/CLI creates external ABS symbols for non-const appdomain globals. 229 // These are also followed by an auxiliary section definition. 230 bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 231 SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; 232 bool isOrdinarySection = 233 StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0; 234 return isAppdomainGlobal || isOrdinarySection; 235 } 236 237 bool isCLRToken() const { 238 return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; 239 } 240 }; 241 242 struct coff_section { 243 char Name[8]; 244 support::ulittle32_t VirtualSize; 245 support::ulittle32_t VirtualAddress; 246 support::ulittle32_t SizeOfRawData; 247 support::ulittle32_t PointerToRawData; 248 support::ulittle32_t PointerToRelocations; 249 support::ulittle32_t PointerToLinenumbers; 250 support::ulittle16_t NumberOfRelocations; 251 support::ulittle16_t NumberOfLinenumbers; 252 support::ulittle32_t Characteristics; 253 254 // Returns true if the actual number of relocations is stored in 255 // VirtualAddress field of the first relocation table entry. 256 bool hasExtendedRelocations() const { 257 return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL && 258 NumberOfRelocations == UINT16_MAX; 259 }; 260 }; 261 262 struct coff_relocation { 263 support::ulittle32_t VirtualAddress; 264 support::ulittle32_t SymbolTableIndex; 265 support::ulittle16_t Type; 266 }; 267 268 struct coff_aux_function_definition { 269 support::ulittle32_t TagIndex; 270 support::ulittle32_t TotalSize; 271 support::ulittle32_t PointerToLinenumber; 272 support::ulittle32_t PointerToNextFunction; 273 char Unused[2]; 274 }; 275 276 struct coff_aux_bf_and_ef_symbol { 277 char Unused1[4]; 278 support::ulittle16_t Linenumber; 279 char Unused2[6]; 280 support::ulittle32_t PointerToNextFunction; 281 char Unused3[2]; 282 }; 283 284 struct coff_aux_weak_external { 285 support::ulittle32_t TagIndex; 286 support::ulittle32_t Characteristics; 287 char Unused[10]; 288 }; 289 290 struct coff_aux_file { 291 char FileName[18]; 292 }; 293 294 struct coff_aux_section_definition { 295 support::ulittle32_t Length; 296 support::ulittle16_t NumberOfRelocations; 297 support::ulittle16_t NumberOfLinenumbers; 298 support::ulittle32_t CheckSum; 299 support::ulittle16_t Number; 300 support::ulittle8_t Selection; 301 char Unused[3]; 302 }; 303 304 struct coff_aux_clr_token { 305 support::ulittle8_t AuxType; 306 support::ulittle8_t Reserved; 307 support::ulittle32_t SymbolTableIndex; 308 char Unused[12]; 309 }; 310 311 struct coff_load_configuration32 { 312 support::ulittle32_t Characteristics; 313 support::ulittle32_t TimeDateStamp; 314 support::ulittle16_t MajorVersion; 315 support::ulittle16_t MinorVersion; 316 support::ulittle32_t GlobalFlagsClear; 317 support::ulittle32_t GlobalFlagsSet; 318 support::ulittle32_t CriticalSectionDefaultTimeout; 319 support::ulittle32_t DeCommitFreeBlockThreshold; 320 support::ulittle32_t DeCommitTotalFreeThreshold; 321 support::ulittle32_t LockPrefixTable; 322 support::ulittle32_t MaximumAllocationSize; 323 support::ulittle32_t VirtualMemoryThreshold; 324 support::ulittle32_t ProcessAffinityMask; 325 support::ulittle32_t ProcessHeapFlags; 326 support::ulittle16_t CSDVersion; 327 uint16_t Reserved; 328 support::ulittle32_t EditList; 329 support::ulittle32_t SecurityCookie; 330 support::ulittle32_t SEHandlerTable; 331 support::ulittle32_t SEHandlerCount; 332 }; 333 334 struct coff_runtime_function_x64 { 335 support::ulittle32_t BeginAddress; 336 support::ulittle32_t EndAddress; 337 support::ulittle32_t UnwindInformation; 338 }; 339 340 class COFFObjectFile : public ObjectFile { 341 private: 342 friend class ImportDirectoryEntryRef; 343 friend class ExportDirectoryEntryRef; 344 const coff_file_header *COFFHeader; 345 const pe32_header *PE32Header; 346 const pe32plus_header *PE32PlusHeader; 347 const data_directory *DataDirectory; 348 const coff_section *SectionTable; 349 const coff_symbol *SymbolTable; 350 const char *StringTable; 351 uint32_t StringTableSize; 352 const import_directory_table_entry *ImportDirectory; 353 uint32_t NumberOfImportDirectory; 354 const export_directory_table_entry *ExportDirectory; 355 356 std::error_code getString(uint32_t offset, StringRef &Res) const; 357 358 const coff_symbol *toSymb(DataRefImpl Symb) const; 359 const coff_section *toSec(DataRefImpl Sec) const; 360 const coff_relocation *toRel(DataRefImpl Rel) const; 361 362 std::error_code initSymbolTablePtr(); 363 std::error_code initImportTablePtr(); 364 std::error_code initExportTablePtr(); 365 366 protected: 367 void moveSymbolNext(DataRefImpl &Symb) const override; 368 std::error_code getSymbolName(DataRefImpl Symb, 369 StringRef &Res) const override; 370 std::error_code getSymbolAddress(DataRefImpl Symb, 371 uint64_t &Res) const override; 372 std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; 373 uint32_t getSymbolFlags(DataRefImpl Symb) const override; 374 std::error_code getSymbolType(DataRefImpl Symb, 375 SymbolRef::Type &Res) const override; 376 std::error_code getSymbolSection(DataRefImpl Symb, 377 section_iterator &Res) const override; 378 void moveSectionNext(DataRefImpl &Sec) const override; 379 std::error_code getSectionName(DataRefImpl Sec, 380 StringRef &Res) const override; 381 std::error_code getSectionAddress(DataRefImpl Sec, 382 uint64_t &Res) const override; 383 std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; 384 std::error_code getSectionContents(DataRefImpl Sec, 385 StringRef &Res) const override; 386 std::error_code getSectionAlignment(DataRefImpl Sec, 387 uint64_t &Res) const override; 388 std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; 389 std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; 390 std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; 391 std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; 392 std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; 393 std::error_code isSectionReadOnlyData(DataRefImpl Sec, 394 bool &Res) const override; 395 std::error_code isSectionRequiredForExecution(DataRefImpl Sec, 396 bool &Res) const override; 397 std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 398 bool &Result) const override; 399 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 400 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 401 402 void moveRelocationNext(DataRefImpl &Rel) const override; 403 std::error_code getRelocationAddress(DataRefImpl Rel, 404 uint64_t &Res) const override; 405 std::error_code getRelocationOffset(DataRefImpl Rel, 406 uint64_t &Res) const override; 407 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 408 std::error_code getRelocationType(DataRefImpl Rel, 409 uint64_t &Res) const override; 410 std::error_code 411 getRelocationTypeName(DataRefImpl Rel, 412 SmallVectorImpl<char> &Result) const override; 413 std::error_code 414 getRelocationValueString(DataRefImpl Rel, 415 SmallVectorImpl<char> &Result) const override; 416 417 std::error_code getLibraryNext(DataRefImpl LibData, 418 LibraryRef &Result) const override; 419 std::error_code getLibraryPath(DataRefImpl LibData, 420 StringRef &Result) const override; 421 422 public: 423 COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC); 424 basic_symbol_iterator symbol_begin_impl() const override; 425 basic_symbol_iterator symbol_end_impl() const override; 426 library_iterator needed_library_begin() const override; 427 library_iterator needed_library_end() const override; 428 section_iterator section_begin() const override; 429 section_iterator section_end() const override; 430 431 const coff_section *getCOFFSection(const SectionRef &Section) const; 432 const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const; 433 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; 434 435 uint8_t getBytesInAddress() const override; 436 StringRef getFileFormatName() const override; 437 unsigned getArch() const override; 438 StringRef getLoadName() const override; 439 440 import_directory_iterator import_directory_begin() const; 441 import_directory_iterator import_directory_end() const; 442 export_directory_iterator export_directory_begin() const; 443 export_directory_iterator export_directory_end() const; 444 445 std::error_code getHeader(const coff_file_header *&Res) const; 446 std::error_code getCOFFHeader(const coff_file_header *&Res) const; 447 std::error_code getPE32Header(const pe32_header *&Res) const; 448 std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; 449 std::error_code getDataDirectory(uint32_t index, 450 const data_directory *&Res) const; 451 std::error_code getSection(int32_t index, const coff_section *&Res) const; 452 std::error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; 453 template <typename T> 454 std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { 455 const coff_symbol *s; 456 std::error_code ec = getSymbol(index, s); 457 Res = reinterpret_cast<const T *>(s); 458 return ec; 459 } 460 std::error_code getSymbolName(const coff_symbol *symbol, 461 StringRef &Res) const; 462 ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const; 463 464 std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; 465 std::error_code getSectionContents(const coff_section *Sec, 466 ArrayRef<uint8_t> &Res) const; 467 468 std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; 469 std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; 470 std::error_code getHintName(uint32_t Rva, uint16_t &Hint, 471 StringRef &Name) const; 472 473 static inline bool classof(const Binary *v) { return v->isCOFF(); } 474 }; 475 476 // The iterator for the import directory table. 477 class ImportDirectoryEntryRef { 478 public: 479 ImportDirectoryEntryRef() : OwningObject(nullptr) {} 480 ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I, 481 const COFFObjectFile *Owner) 482 : ImportTable(Table), Index(I), OwningObject(Owner) {} 483 484 bool operator==(const ImportDirectoryEntryRef &Other) const; 485 void moveNext(); 486 std::error_code getName(StringRef &Result) const; 487 488 std::error_code 489 getImportTableEntry(const import_directory_table_entry *&Result) const; 490 491 std::error_code 492 getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; 493 494 private: 495 const import_directory_table_entry *ImportTable; 496 uint32_t Index; 497 const COFFObjectFile *OwningObject; 498 }; 499 500 // The iterator for the export directory table entry. 501 class ExportDirectoryEntryRef { 502 public: 503 ExportDirectoryEntryRef() : OwningObject(nullptr) {} 504 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, 505 const COFFObjectFile *Owner) 506 : ExportTable(Table), Index(I), OwningObject(Owner) {} 507 508 bool operator==(const ExportDirectoryEntryRef &Other) const; 509 void moveNext(); 510 511 std::error_code getDllName(StringRef &Result) const; 512 std::error_code getOrdinalBase(uint32_t &Result) const; 513 std::error_code getOrdinal(uint32_t &Result) const; 514 std::error_code getExportRVA(uint32_t &Result) const; 515 std::error_code getSymbolName(StringRef &Result) const; 516 517 private: 518 const export_directory_table_entry *ExportTable; 519 uint32_t Index; 520 const COFFObjectFile *OwningObject; 521 }; 522 } // end namespace object 523 } // end namespace llvm 524 525 #endif 526