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