1224133Sdim//===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// 2224133Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6224133Sdim// 7224133Sdim//===----------------------------------------------------------------------===// 8224133Sdim// 9224133Sdim// This file declares the COFFObjectFile class. 10224133Sdim// 11224133Sdim//===----------------------------------------------------------------------===// 12224133Sdim 13224133Sdim#ifndef LLVM_OBJECT_COFF_H 14224133Sdim#define LLVM_OBJECT_COFF_H 15224133Sdim 16321369Sdim#include "llvm/ADT/iterator_range.h" 17321369Sdim#include "llvm/BinaryFormat/COFF.h" 18321369Sdim#include "llvm/MC/SubtargetFeature.h" 19321369Sdim#include "llvm/Object/Binary.h" 20341825Sdim#include "llvm/Object/CVDebugRecord.h" 21321369Sdim#include "llvm/Object/Error.h" 22224133Sdim#include "llvm/Object/ObjectFile.h" 23321369Sdim#include "llvm/Support/BinaryByteStream.h" 24321369Sdim#include "llvm/Support/ConvertUTF.h" 25224133Sdim#include "llvm/Support/Endian.h" 26321369Sdim#include "llvm/Support/ErrorHandling.h" 27321369Sdim#include <cassert> 28321369Sdim#include <cstddef> 29321369Sdim#include <cstdint> 30321369Sdim#include <system_error> 31224133Sdim 32224133Sdimnamespace llvm { 33321369Sdim 34276479Sdimtemplate <typename T> class ArrayRef; 35234353Sdim 36224133Sdimnamespace object { 37321369Sdim 38321369Sdimclass BaseRelocRef; 39280031Sdimclass DelayImportDirectoryEntryRef; 40276479Sdimclass ExportDirectoryEntryRef; 41321369Sdimclass ImportDirectoryEntryRef; 42280031Sdimclass ImportedSymbolRef; 43321369Sdimclass ResourceSectionRef; 44224133Sdim 45321369Sdimusing import_directory_iterator = content_iterator<ImportDirectoryEntryRef>; 46321369Sdimusing delay_import_directory_iterator = 47321369Sdim content_iterator<DelayImportDirectoryEntryRef>; 48321369Sdimusing export_directory_iterator = content_iterator<ExportDirectoryEntryRef>; 49321369Sdimusing imported_symbol_iterator = content_iterator<ImportedSymbolRef>; 50321369Sdimusing base_reloc_iterator = content_iterator<BaseRelocRef>; 51321369Sdim 52261991Sdim/// The DOS compatible header at the front of all PE/COFF executables. 53261991Sdimstruct dos_header { 54280031Sdim char Magic[2]; 55261991Sdim support::ulittle16_t UsedBytesInTheLastPage; 56261991Sdim support::ulittle16_t FileSizeInPages; 57261991Sdim support::ulittle16_t NumberOfRelocationItems; 58261991Sdim support::ulittle16_t HeaderSizeInParagraphs; 59261991Sdim support::ulittle16_t MinimumExtraParagraphs; 60261991Sdim support::ulittle16_t MaximumExtraParagraphs; 61261991Sdim support::ulittle16_t InitialRelativeSS; 62261991Sdim support::ulittle16_t InitialSP; 63261991Sdim support::ulittle16_t Checksum; 64261991Sdim support::ulittle16_t InitialIP; 65261991Sdim support::ulittle16_t InitialRelativeCS; 66261991Sdim support::ulittle16_t AddressOfRelocationTable; 67261991Sdim support::ulittle16_t OverlayNumber; 68261991Sdim support::ulittle16_t Reserved[4]; 69261991Sdim support::ulittle16_t OEMid; 70261991Sdim support::ulittle16_t OEMinfo; 71261991Sdim support::ulittle16_t Reserved2[10]; 72261991Sdim support::ulittle32_t AddressOfNewExeHeader; 73261991Sdim}; 74261991Sdim 75224133Sdimstruct coff_file_header { 76224133Sdim support::ulittle16_t Machine; 77224133Sdim support::ulittle16_t NumberOfSections; 78224133Sdim support::ulittle32_t TimeDateStamp; 79224133Sdim support::ulittle32_t PointerToSymbolTable; 80224133Sdim support::ulittle32_t NumberOfSymbols; 81224133Sdim support::ulittle16_t SizeOfOptionalHeader; 82224133Sdim support::ulittle16_t Characteristics; 83261991Sdim 84261991Sdim bool isImportLibrary() const { return NumberOfSections == 0xffff; } 85224133Sdim}; 86224133Sdim 87280031Sdimstruct coff_bigobj_file_header { 88280031Sdim support::ulittle16_t Sig1; 89280031Sdim support::ulittle16_t Sig2; 90280031Sdim support::ulittle16_t Version; 91280031Sdim support::ulittle16_t Machine; 92280031Sdim support::ulittle32_t TimeDateStamp; 93280031Sdim uint8_t UUID[16]; 94280031Sdim support::ulittle32_t unused1; 95280031Sdim support::ulittle32_t unused2; 96280031Sdim support::ulittle32_t unused3; 97280031Sdim support::ulittle32_t unused4; 98280031Sdim support::ulittle32_t NumberOfSections; 99280031Sdim support::ulittle32_t PointerToSymbolTable; 100280031Sdim support::ulittle32_t NumberOfSymbols; 101280031Sdim}; 102280031Sdim 103261991Sdim/// The 32-bit PE header that follows the COFF header. 104261991Sdimstruct pe32_header { 105261991Sdim support::ulittle16_t Magic; 106276479Sdim uint8_t MajorLinkerVersion; 107276479Sdim uint8_t MinorLinkerVersion; 108261991Sdim support::ulittle32_t SizeOfCode; 109261991Sdim support::ulittle32_t SizeOfInitializedData; 110261991Sdim support::ulittle32_t SizeOfUninitializedData; 111261991Sdim support::ulittle32_t AddressOfEntryPoint; 112261991Sdim support::ulittle32_t BaseOfCode; 113261991Sdim support::ulittle32_t BaseOfData; 114261991Sdim support::ulittle32_t ImageBase; 115261991Sdim support::ulittle32_t SectionAlignment; 116261991Sdim support::ulittle32_t FileAlignment; 117261991Sdim support::ulittle16_t MajorOperatingSystemVersion; 118261991Sdim support::ulittle16_t MinorOperatingSystemVersion; 119261991Sdim support::ulittle16_t MajorImageVersion; 120261991Sdim support::ulittle16_t MinorImageVersion; 121261991Sdim support::ulittle16_t MajorSubsystemVersion; 122261991Sdim support::ulittle16_t MinorSubsystemVersion; 123261991Sdim support::ulittle32_t Win32VersionValue; 124261991Sdim support::ulittle32_t SizeOfImage; 125261991Sdim support::ulittle32_t SizeOfHeaders; 126261991Sdim support::ulittle32_t CheckSum; 127261991Sdim support::ulittle16_t Subsystem; 128280031Sdim // FIXME: This should be DllCharacteristics. 129261991Sdim support::ulittle16_t DLLCharacteristics; 130261991Sdim support::ulittle32_t SizeOfStackReserve; 131261991Sdim support::ulittle32_t SizeOfStackCommit; 132261991Sdim support::ulittle32_t SizeOfHeapReserve; 133261991Sdim support::ulittle32_t SizeOfHeapCommit; 134261991Sdim support::ulittle32_t LoaderFlags; 135280031Sdim // FIXME: This should be NumberOfRvaAndSizes. 136261991Sdim support::ulittle32_t NumberOfRvaAndSize; 137261991Sdim}; 138261991Sdim 139261991Sdim/// The 64-bit PE header that follows the COFF header. 140261991Sdimstruct pe32plus_header { 141261991Sdim support::ulittle16_t Magic; 142276479Sdim uint8_t MajorLinkerVersion; 143276479Sdim uint8_t MinorLinkerVersion; 144261991Sdim support::ulittle32_t SizeOfCode; 145261991Sdim support::ulittle32_t SizeOfInitializedData; 146261991Sdim support::ulittle32_t SizeOfUninitializedData; 147261991Sdim support::ulittle32_t AddressOfEntryPoint; 148261991Sdim support::ulittle32_t BaseOfCode; 149261991Sdim support::ulittle64_t ImageBase; 150261991Sdim support::ulittle32_t SectionAlignment; 151261991Sdim support::ulittle32_t FileAlignment; 152261991Sdim support::ulittle16_t MajorOperatingSystemVersion; 153261991Sdim support::ulittle16_t MinorOperatingSystemVersion; 154261991Sdim support::ulittle16_t MajorImageVersion; 155261991Sdim support::ulittle16_t MinorImageVersion; 156261991Sdim support::ulittle16_t MajorSubsystemVersion; 157261991Sdim support::ulittle16_t MinorSubsystemVersion; 158261991Sdim support::ulittle32_t Win32VersionValue; 159261991Sdim support::ulittle32_t SizeOfImage; 160261991Sdim support::ulittle32_t SizeOfHeaders; 161261991Sdim support::ulittle32_t CheckSum; 162261991Sdim support::ulittle16_t Subsystem; 163261991Sdim support::ulittle16_t DLLCharacteristics; 164261991Sdim support::ulittle64_t SizeOfStackReserve; 165261991Sdim support::ulittle64_t SizeOfStackCommit; 166261991Sdim support::ulittle64_t SizeOfHeapReserve; 167261991Sdim support::ulittle64_t SizeOfHeapCommit; 168261991Sdim support::ulittle32_t LoaderFlags; 169261991Sdim support::ulittle32_t NumberOfRvaAndSize; 170261991Sdim}; 171261991Sdim 172261991Sdimstruct data_directory { 173261991Sdim support::ulittle32_t RelativeVirtualAddress; 174261991Sdim support::ulittle32_t Size; 175261991Sdim}; 176261991Sdim 177309124Sdimstruct debug_directory { 178309124Sdim support::ulittle32_t Characteristics; 179309124Sdim support::ulittle32_t TimeDateStamp; 180309124Sdim support::ulittle16_t MajorVersion; 181309124Sdim support::ulittle16_t MinorVersion; 182309124Sdim support::ulittle32_t Type; 183309124Sdim support::ulittle32_t SizeOfData; 184309124Sdim support::ulittle32_t AddressOfRawData; 185309124Sdim support::ulittle32_t PointerToRawData; 186309124Sdim}; 187309124Sdim 188280031Sdimtemplate <typename IntTy> 189280031Sdimstruct import_lookup_table_entry { 190280031Sdim IntTy Data; 191261991Sdim 192280031Sdim bool isOrdinal() const { return Data < 0; } 193261991Sdim 194261991Sdim uint16_t getOrdinal() const { 195261991Sdim assert(isOrdinal() && "ILT entry is not an ordinal!"); 196280031Sdim return Data & 0xFFFF; 197261991Sdim } 198261991Sdim 199261991Sdim uint32_t getHintNameRVA() const { 200261991Sdim assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); 201280031Sdim return Data & 0xFFFFFFFF; 202261991Sdim } 203261991Sdim}; 204261991Sdim 205321369Sdimusing import_lookup_table_entry32 = 206321369Sdim import_lookup_table_entry<support::little32_t>; 207321369Sdimusing import_lookup_table_entry64 = 208321369Sdim import_lookup_table_entry<support::little64_t>; 209280031Sdim 210280031Sdimstruct delay_import_directory_table_entry { 211280031Sdim // dumpbin reports this field as "Characteristics" instead of "Attributes". 212280031Sdim support::ulittle32_t Attributes; 213280031Sdim support::ulittle32_t Name; 214280031Sdim support::ulittle32_t ModuleHandle; 215280031Sdim support::ulittle32_t DelayImportAddressTable; 216280031Sdim support::ulittle32_t DelayImportNameTable; 217280031Sdim support::ulittle32_t BoundDelayImportTable; 218280031Sdim support::ulittle32_t UnloadDelayImportTable; 219280031Sdim support::ulittle32_t TimeStamp; 220280031Sdim}; 221280031Sdim 222276479Sdimstruct export_directory_table_entry { 223276479Sdim support::ulittle32_t ExportFlags; 224276479Sdim support::ulittle32_t TimeDateStamp; 225276479Sdim support::ulittle16_t MajorVersion; 226276479Sdim support::ulittle16_t MinorVersion; 227276479Sdim support::ulittle32_t NameRVA; 228276479Sdim support::ulittle32_t OrdinalBase; 229276479Sdim support::ulittle32_t AddressTableEntries; 230276479Sdim support::ulittle32_t NumberOfNamePointers; 231276479Sdim support::ulittle32_t ExportAddressTableRVA; 232276479Sdim support::ulittle32_t NamePointerRVA; 233276479Sdim support::ulittle32_t OrdinalTableRVA; 234276479Sdim}; 235276479Sdim 236276479Sdimunion export_address_table_entry { 237276479Sdim support::ulittle32_t ExportRVA; 238276479Sdim support::ulittle32_t ForwarderRVA; 239276479Sdim}; 240276479Sdim 241321369Sdimusing export_name_pointer_table_entry = support::ulittle32_t; 242321369Sdimusing export_ordinal_table_entry = support::ulittle16_t; 243276479Sdim 244280031Sdimstruct StringTableOffset { 245280031Sdim support::ulittle32_t Zeroes; 246280031Sdim support::ulittle32_t Offset; 247280031Sdim}; 248280031Sdim 249280031Sdimtemplate <typename SectionNumberType> 250224133Sdimstruct coff_symbol { 251224133Sdim union { 252280031Sdim char ShortName[COFF::NameSize]; 253224133Sdim StringTableOffset Offset; 254224133Sdim } Name; 255224133Sdim 256224133Sdim support::ulittle32_t Value; 257280031Sdim SectionNumberType SectionNumber; 258224133Sdim 259234353Sdim support::ulittle16_t Type; 260224133Sdim 261280031Sdim uint8_t StorageClass; 262280031Sdim uint8_t NumberOfAuxSymbols; 263280031Sdim}; 264234353Sdim 265321369Sdimusing coff_symbol16 = coff_symbol<support::ulittle16_t>; 266321369Sdimusing coff_symbol32 = coff_symbol<support::ulittle32_t>; 267276479Sdim 268288943Sdim// Contains only common parts of coff_symbol16 and coff_symbol32. 269288943Sdimstruct coff_symbol_generic { 270288943Sdim union { 271288943Sdim char ShortName[COFF::NameSize]; 272288943Sdim StringTableOffset Offset; 273288943Sdim } Name; 274288943Sdim support::ulittle32_t Value; 275288943Sdim}; 276288943Sdim 277327952Sdimstruct coff_aux_section_definition; 278341825Sdimstruct coff_aux_weak_external; 279327952Sdim 280280031Sdimclass COFFSymbolRef { 281280031Sdimpublic: 282321369Sdim COFFSymbolRef() = default; 283321369Sdim COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {} 284321369Sdim COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {} 285276479Sdim 286280031Sdim const void *getRawPtr() const { 287280031Sdim return CS16 ? static_cast<const void *>(CS16) : CS32; 288280031Sdim } 289280031Sdim 290288943Sdim const coff_symbol_generic *getGeneric() const { 291288943Sdim if (CS16) 292288943Sdim return reinterpret_cast<const coff_symbol_generic *>(CS16); 293288943Sdim return reinterpret_cast<const coff_symbol_generic *>(CS32); 294288943Sdim } 295288943Sdim 296280031Sdim friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { 297280031Sdim return A.getRawPtr() < B.getRawPtr(); 298280031Sdim } 299280031Sdim 300280031Sdim bool isBigObj() const { 301280031Sdim if (CS16) 302280031Sdim return false; 303280031Sdim if (CS32) 304280031Sdim return true; 305280031Sdim llvm_unreachable("COFFSymbolRef points to nothing!"); 306280031Sdim } 307280031Sdim 308280031Sdim const char *getShortName() const { 309280031Sdim return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; 310280031Sdim } 311280031Sdim 312280031Sdim const StringTableOffset &getStringTableOffset() const { 313280031Sdim assert(isSet() && "COFFSymbolRef points to nothing!"); 314280031Sdim return CS16 ? CS16->Name.Offset : CS32->Name.Offset; 315280031Sdim } 316280031Sdim 317360784Sdim uint32_t getValue() const { 318360784Sdim assert(isSet() && "COFFSymbolRef points to nothing!"); 319360784Sdim return CS16 ? CS16->Value : CS32->Value; 320360784Sdim } 321280031Sdim 322280031Sdim int32_t getSectionNumber() const { 323280031Sdim assert(isSet() && "COFFSymbolRef points to nothing!"); 324280031Sdim if (CS16) { 325280031Sdim // Reserved sections are returned as negative numbers. 326280031Sdim if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) 327280031Sdim return CS16->SectionNumber; 328280031Sdim return static_cast<int16_t>(CS16->SectionNumber); 329280031Sdim } 330280031Sdim return static_cast<int32_t>(CS32->SectionNumber); 331280031Sdim } 332280031Sdim 333280031Sdim uint16_t getType() const { 334280031Sdim assert(isSet() && "COFFSymbolRef points to nothing!"); 335280031Sdim return CS16 ? CS16->Type : CS32->Type; 336280031Sdim } 337280031Sdim 338280031Sdim uint8_t getStorageClass() const { 339280031Sdim assert(isSet() && "COFFSymbolRef points to nothing!"); 340280031Sdim return CS16 ? CS16->StorageClass : CS32->StorageClass; 341280031Sdim } 342280031Sdim 343280031Sdim uint8_t getNumberOfAuxSymbols() const { 344280031Sdim assert(isSet() && "COFFSymbolRef points to nothing!"); 345280031Sdim return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; 346280031Sdim } 347280031Sdim 348280031Sdim uint8_t getBaseType() const { return getType() & 0x0F; } 349280031Sdim 350280031Sdim uint8_t getComplexType() const { 351280031Sdim return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; 352280031Sdim } 353280031Sdim 354327952Sdim template <typename T> const T *getAux() const { 355327952Sdim return CS16 ? reinterpret_cast<const T *>(CS16 + 1) 356327952Sdim : reinterpret_cast<const T *>(CS32 + 1); 357327952Sdim } 358327952Sdim 359327952Sdim const coff_aux_section_definition *getSectionDefinition() const { 360327952Sdim if (!getNumberOfAuxSymbols() || 361327952Sdim getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC) 362327952Sdim return nullptr; 363327952Sdim return getAux<coff_aux_section_definition>(); 364327952Sdim } 365327952Sdim 366341825Sdim const coff_aux_weak_external *getWeakExternal() const { 367341825Sdim if (!getNumberOfAuxSymbols() || 368341825Sdim getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 369341825Sdim return nullptr; 370341825Sdim return getAux<coff_aux_weak_external>(); 371341825Sdim } 372341825Sdim 373288943Sdim bool isAbsolute() const { 374288943Sdim return getSectionNumber() == -1; 375288943Sdim } 376288943Sdim 377280031Sdim bool isExternal() const { 378280031Sdim return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; 379280031Sdim } 380280031Sdim 381280031Sdim bool isCommon() const { 382280031Sdim return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 383280031Sdim getValue() != 0; 384280031Sdim } 385280031Sdim 386280031Sdim bool isUndefined() const { 387280031Sdim return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && 388280031Sdim getValue() == 0; 389280031Sdim } 390280031Sdim 391280031Sdim bool isWeakExternal() const { 392280031Sdim return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; 393280031Sdim } 394280031Sdim 395276479Sdim bool isFunctionDefinition() const { 396280031Sdim return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && 397276479Sdim getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && 398280031Sdim !COFF::isReservedSectionNumber(getSectionNumber()); 399234353Sdim } 400234353Sdim 401276479Sdim bool isFunctionLineInfo() const { 402280031Sdim return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; 403234353Sdim } 404276479Sdim 405280031Sdim bool isAnyUndefined() const { 406280031Sdim return isUndefined() || isWeakExternal(); 407276479Sdim } 408276479Sdim 409276479Sdim bool isFileRecord() const { 410280031Sdim return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; 411276479Sdim } 412276479Sdim 413288943Sdim bool isSection() const { 414288943Sdim return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; 415288943Sdim } 416288943Sdim 417276479Sdim bool isSectionDefinition() const { 418276479Sdim // C++/CLI creates external ABS symbols for non-const appdomain globals. 419276479Sdim // These are also followed by an auxiliary section definition. 420280031Sdim bool isAppdomainGlobal = 421280031Sdim getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && 422280031Sdim getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; 423280031Sdim bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; 424280031Sdim if (!getNumberOfAuxSymbols()) 425280031Sdim return false; 426276479Sdim return isAppdomainGlobal || isOrdinarySection; 427276479Sdim } 428276479Sdim 429276479Sdim bool isCLRToken() const { 430280031Sdim return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; 431276479Sdim } 432280031Sdim 433280031Sdimprivate: 434280031Sdim bool isSet() const { return CS16 || CS32; } 435280031Sdim 436321369Sdim const coff_symbol16 *CS16 = nullptr; 437321369Sdim const coff_symbol32 *CS32 = nullptr; 438224133Sdim}; 439224133Sdim 440224133Sdimstruct coff_section { 441280031Sdim char Name[COFF::NameSize]; 442224133Sdim support::ulittle32_t VirtualSize; 443224133Sdim support::ulittle32_t VirtualAddress; 444224133Sdim support::ulittle32_t SizeOfRawData; 445224133Sdim support::ulittle32_t PointerToRawData; 446224133Sdim support::ulittle32_t PointerToRelocations; 447224133Sdim support::ulittle32_t PointerToLinenumbers; 448224133Sdim support::ulittle16_t NumberOfRelocations; 449224133Sdim support::ulittle16_t NumberOfLinenumbers; 450224133Sdim support::ulittle32_t Characteristics; 451276479Sdim 452276479Sdim // Returns true if the actual number of relocations is stored in 453276479Sdim // VirtualAddress field of the first relocation table entry. 454276479Sdim bool hasExtendedRelocations() const { 455280031Sdim return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && 456280031Sdim NumberOfRelocations == UINT16_MAX; 457280031Sdim } 458321369Sdim 459309124Sdim uint32_t getAlignment() const { 460309124Sdim // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to 461309124Sdim // IMAGE_SCN_ALIGN_1BYTES. 462309124Sdim if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) 463309124Sdim return 1; 464309124Sdim 465341825Sdim // Bit [20:24] contains section alignment. 0 means use a default alignment 466341825Sdim // of 16. 467309124Sdim uint32_t Shift = (Characteristics >> 20) & 0xF; 468309124Sdim if (Shift > 0) 469309124Sdim return 1U << (Shift - 1); 470341825Sdim return 16; 471309124Sdim } 472224133Sdim}; 473224133Sdim 474226633Sdimstruct coff_relocation { 475226633Sdim support::ulittle32_t VirtualAddress; 476226633Sdim support::ulittle32_t SymbolTableIndex; 477226633Sdim support::ulittle16_t Type; 478226633Sdim}; 479226633Sdim 480276479Sdimstruct coff_aux_function_definition { 481276479Sdim support::ulittle32_t TagIndex; 482276479Sdim support::ulittle32_t TotalSize; 483276479Sdim support::ulittle32_t PointerToLinenumber; 484276479Sdim support::ulittle32_t PointerToNextFunction; 485309124Sdim char Unused1[2]; 486276479Sdim}; 487276479Sdim 488309124Sdimstatic_assert(sizeof(coff_aux_function_definition) == 18, 489309124Sdim "auxiliary entry must be 18 bytes"); 490309124Sdim 491276479Sdimstruct coff_aux_bf_and_ef_symbol { 492276479Sdim char Unused1[4]; 493276479Sdim support::ulittle16_t Linenumber; 494276479Sdim char Unused2[6]; 495276479Sdim support::ulittle32_t PointerToNextFunction; 496309124Sdim char Unused3[2]; 497276479Sdim}; 498276479Sdim 499309124Sdimstatic_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18, 500309124Sdim "auxiliary entry must be 18 bytes"); 501309124Sdim 502261991Sdimstruct coff_aux_weak_external { 503261991Sdim support::ulittle32_t TagIndex; 504261991Sdim support::ulittle32_t Characteristics; 505309124Sdim char Unused1[10]; 506261991Sdim}; 507261991Sdim 508309124Sdimstatic_assert(sizeof(coff_aux_weak_external) == 18, 509309124Sdim "auxiliary entry must be 18 bytes"); 510309124Sdim 511234353Sdimstruct coff_aux_section_definition { 512234353Sdim support::ulittle32_t Length; 513234353Sdim support::ulittle16_t NumberOfRelocations; 514234353Sdim support::ulittle16_t NumberOfLinenumbers; 515234353Sdim support::ulittle32_t CheckSum; 516280031Sdim support::ulittle16_t NumberLowPart; 517280031Sdim uint8_t Selection; 518280031Sdim uint8_t Unused; 519280031Sdim support::ulittle16_t NumberHighPart; 520280031Sdim int32_t getNumber(bool IsBigObj) const { 521280031Sdim uint32_t Number = static_cast<uint32_t>(NumberLowPart); 522280031Sdim if (IsBigObj) 523280031Sdim Number |= static_cast<uint32_t>(NumberHighPart) << 16; 524280031Sdim return static_cast<int32_t>(Number); 525280031Sdim } 526234353Sdim}; 527234353Sdim 528309124Sdimstatic_assert(sizeof(coff_aux_section_definition) == 18, 529309124Sdim "auxiliary entry must be 18 bytes"); 530309124Sdim 531276479Sdimstruct coff_aux_clr_token { 532280031Sdim uint8_t AuxType; 533280031Sdim uint8_t Reserved; 534276479Sdim support::ulittle32_t SymbolTableIndex; 535309124Sdim char MBZ[12]; 536276479Sdim}; 537276479Sdim 538309124Sdimstatic_assert(sizeof(coff_aux_clr_token) == 18, 539309124Sdim "auxiliary entry must be 18 bytes"); 540309124Sdim 541288943Sdimstruct coff_import_header { 542288943Sdim support::ulittle16_t Sig1; 543288943Sdim support::ulittle16_t Sig2; 544288943Sdim support::ulittle16_t Version; 545288943Sdim support::ulittle16_t Machine; 546288943Sdim support::ulittle32_t TimeDateStamp; 547288943Sdim support::ulittle32_t SizeOfData; 548288943Sdim support::ulittle16_t OrdinalHint; 549288943Sdim support::ulittle16_t TypeInfo; 550321369Sdim 551288943Sdim int getType() const { return TypeInfo & 0x3; } 552288943Sdim int getNameType() const { return (TypeInfo >> 2) & 0x7; } 553288943Sdim}; 554288943Sdim 555288943Sdimstruct coff_import_directory_table_entry { 556288943Sdim support::ulittle32_t ImportLookupTableRVA; 557288943Sdim support::ulittle32_t TimeDateStamp; 558288943Sdim support::ulittle32_t ForwarderChain; 559288943Sdim support::ulittle32_t NameRVA; 560288943Sdim support::ulittle32_t ImportAddressTableRVA; 561321369Sdim 562314564Sdim bool isNull() const { 563314564Sdim return ImportLookupTableRVA == 0 && TimeDateStamp == 0 && 564314564Sdim ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0; 565314564Sdim } 566288943Sdim}; 567288943Sdim 568309124Sdimtemplate <typename IntTy> 569309124Sdimstruct coff_tls_directory { 570309124Sdim IntTy StartAddressOfRawData; 571309124Sdim IntTy EndAddressOfRawData; 572309124Sdim IntTy AddressOfIndex; 573309124Sdim IntTy AddressOfCallBacks; 574309124Sdim support::ulittle32_t SizeOfZeroFill; 575309124Sdim support::ulittle32_t Characteristics; 576321369Sdim 577309124Sdim uint32_t getAlignment() const { 578309124Sdim // Bit [20:24] contains section alignment. 579309124Sdim uint32_t Shift = (Characteristics & 0x00F00000) >> 20; 580309124Sdim if (Shift > 0) 581309124Sdim return 1U << (Shift - 1); 582309124Sdim return 0; 583309124Sdim } 584309124Sdim}; 585309124Sdim 586321369Sdimusing coff_tls_directory32 = coff_tls_directory<support::little32_t>; 587321369Sdimusing coff_tls_directory64 = coff_tls_directory<support::little64_t>; 588309124Sdim 589321369Sdim/// Bits in control flow guard flags as we understand them. 590321369Sdimenum class coff_guard_flags : uint32_t { 591321369Sdim CFInstrumented = 0x00000100, 592321369Sdim HasFidTable = 0x00000400, 593321369Sdim ProtectDelayLoadIAT = 0x00001000, 594321369Sdim DelayLoadIATSection = 0x00002000, // Delay load in separate section 595321369Sdim HasLongJmpTable = 0x00010000, 596321369Sdim FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes 597321369Sdim}; 598321369Sdim 599344779Sdimenum class frame_type : uint16_t { Fpo = 0, Trap = 1, Tss = 2, NonFpo = 3 }; 600344779Sdim 601321369Sdimstruct coff_load_config_code_integrity { 602321369Sdim support::ulittle16_t Flags; 603321369Sdim support::ulittle16_t Catalog; 604321369Sdim support::ulittle32_t CatalogOffset; 605321369Sdim support::ulittle32_t Reserved; 606321369Sdim}; 607321369Sdim 608321369Sdim/// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32) 609276479Sdimstruct coff_load_configuration32 { 610321369Sdim support::ulittle32_t Size; 611276479Sdim support::ulittle32_t TimeDateStamp; 612276479Sdim support::ulittle16_t MajorVersion; 613276479Sdim support::ulittle16_t MinorVersion; 614276479Sdim support::ulittle32_t GlobalFlagsClear; 615276479Sdim support::ulittle32_t GlobalFlagsSet; 616276479Sdim support::ulittle32_t CriticalSectionDefaultTimeout; 617276479Sdim support::ulittle32_t DeCommitFreeBlockThreshold; 618276479Sdim support::ulittle32_t DeCommitTotalFreeThreshold; 619276479Sdim support::ulittle32_t LockPrefixTable; 620276479Sdim support::ulittle32_t MaximumAllocationSize; 621276479Sdim support::ulittle32_t VirtualMemoryThreshold; 622276479Sdim support::ulittle32_t ProcessAffinityMask; 623276479Sdim support::ulittle32_t ProcessHeapFlags; 624276479Sdim support::ulittle16_t CSDVersion; 625321369Sdim support::ulittle16_t DependentLoadFlags; 626276479Sdim support::ulittle32_t EditList; 627276479Sdim support::ulittle32_t SecurityCookie; 628276479Sdim support::ulittle32_t SEHandlerTable; 629276479Sdim support::ulittle32_t SEHandlerCount; 630321369Sdim 631321369Sdim // Added in MSVC 2015 for /guard:cf. 632321369Sdim support::ulittle32_t GuardCFCheckFunction; 633321369Sdim support::ulittle32_t GuardCFCheckDispatch; 634321369Sdim support::ulittle32_t GuardCFFunctionTable; 635321369Sdim support::ulittle32_t GuardCFFunctionCount; 636321369Sdim support::ulittle32_t GuardFlags; // coff_guard_flags 637321369Sdim 638321369Sdim // Added in MSVC 2017 639321369Sdim coff_load_config_code_integrity CodeIntegrity; 640321369Sdim support::ulittle32_t GuardAddressTakenIatEntryTable; 641321369Sdim support::ulittle32_t GuardAddressTakenIatEntryCount; 642321369Sdim support::ulittle32_t GuardLongJumpTargetTable; 643321369Sdim support::ulittle32_t GuardLongJumpTargetCount; 644321369Sdim support::ulittle32_t DynamicValueRelocTable; 645321369Sdim support::ulittle32_t CHPEMetadataPointer; 646321369Sdim support::ulittle32_t GuardRFFailureRoutine; 647321369Sdim support::ulittle32_t GuardRFFailureRoutineFunctionPointer; 648321369Sdim support::ulittle32_t DynamicValueRelocTableOffset; 649321369Sdim support::ulittle16_t DynamicValueRelocTableSection; 650321369Sdim support::ulittle16_t Reserved2; 651321369Sdim support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer; 652321369Sdim support::ulittle32_t HotPatchTableOffset; 653276479Sdim}; 654276479Sdim 655321369Sdim/// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64) 656288943Sdimstruct coff_load_configuration64 { 657321369Sdim support::ulittle32_t Size; 658288943Sdim support::ulittle32_t TimeDateStamp; 659288943Sdim support::ulittle16_t MajorVersion; 660288943Sdim support::ulittle16_t MinorVersion; 661288943Sdim support::ulittle32_t GlobalFlagsClear; 662288943Sdim support::ulittle32_t GlobalFlagsSet; 663288943Sdim support::ulittle32_t CriticalSectionDefaultTimeout; 664321369Sdim support::ulittle64_t DeCommitFreeBlockThreshold; 665321369Sdim support::ulittle64_t DeCommitTotalFreeThreshold; 666321369Sdim support::ulittle64_t LockPrefixTable; 667321369Sdim support::ulittle64_t MaximumAllocationSize; 668321369Sdim support::ulittle64_t VirtualMemoryThreshold; 669321369Sdim support::ulittle64_t ProcessAffinityMask; 670288943Sdim support::ulittle32_t ProcessHeapFlags; 671288943Sdim support::ulittle16_t CSDVersion; 672321369Sdim support::ulittle16_t DependentLoadFlags; 673321369Sdim support::ulittle64_t EditList; 674288943Sdim support::ulittle64_t SecurityCookie; 675288943Sdim support::ulittle64_t SEHandlerTable; 676288943Sdim support::ulittle64_t SEHandlerCount; 677321369Sdim 678321369Sdim // Added in MSVC 2015 for /guard:cf. 679321369Sdim support::ulittle64_t GuardCFCheckFunction; 680321369Sdim support::ulittle64_t GuardCFCheckDispatch; 681321369Sdim support::ulittle64_t GuardCFFunctionTable; 682321369Sdim support::ulittle64_t GuardCFFunctionCount; 683321369Sdim support::ulittle32_t GuardFlags; 684321369Sdim 685321369Sdim // Added in MSVC 2017 686321369Sdim coff_load_config_code_integrity CodeIntegrity; 687321369Sdim support::ulittle64_t GuardAddressTakenIatEntryTable; 688321369Sdim support::ulittle64_t GuardAddressTakenIatEntryCount; 689321369Sdim support::ulittle64_t GuardLongJumpTargetTable; 690321369Sdim support::ulittle64_t GuardLongJumpTargetCount; 691321369Sdim support::ulittle64_t DynamicValueRelocTable; 692321369Sdim support::ulittle64_t CHPEMetadataPointer; 693321369Sdim support::ulittle64_t GuardRFFailureRoutine; 694321369Sdim support::ulittle64_t GuardRFFailureRoutineFunctionPointer; 695321369Sdim support::ulittle32_t DynamicValueRelocTableOffset; 696321369Sdim support::ulittle16_t DynamicValueRelocTableSection; 697321369Sdim support::ulittle16_t Reserved2; 698321369Sdim support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer; 699321369Sdim support::ulittle32_t HotPatchTableOffset; 700288943Sdim}; 701288943Sdim 702276479Sdimstruct coff_runtime_function_x64 { 703276479Sdim support::ulittle32_t BeginAddress; 704276479Sdim support::ulittle32_t EndAddress; 705276479Sdim support::ulittle32_t UnwindInformation; 706276479Sdim}; 707276479Sdim 708280031Sdimstruct coff_base_reloc_block_header { 709280031Sdim support::ulittle32_t PageRVA; 710280031Sdim support::ulittle32_t BlockSize; 711280031Sdim}; 712280031Sdim 713280031Sdimstruct coff_base_reloc_block_entry { 714280031Sdim support::ulittle16_t Data; 715321369Sdim 716280031Sdim int getType() const { return Data >> 12; } 717280031Sdim int getOffset() const { return Data & ((1 << 12) - 1); } 718280031Sdim}; 719280031Sdim 720321369Sdimstruct coff_resource_dir_entry { 721321369Sdim union { 722321369Sdim support::ulittle32_t NameOffset; 723321369Sdim support::ulittle32_t ID; 724321369Sdim uint32_t getNameOffset() const { 725321369Sdim return maskTrailingOnes<uint32_t>(31) & NameOffset; 726321369Sdim } 727321369Sdim // Even though the PE/COFF spec doesn't mention this, the high bit of a name 728321369Sdim // offset is set. 729321369Sdim void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); } 730321369Sdim } Identifier; 731321369Sdim union { 732321369Sdim support::ulittle32_t DataEntryOffset; 733321369Sdim support::ulittle32_t SubdirOffset; 734321369Sdim 735321369Sdim bool isSubDir() const { return SubdirOffset >> 31; } 736321369Sdim uint32_t value() const { 737321369Sdim return maskTrailingOnes<uint32_t>(31) & SubdirOffset; 738321369Sdim } 739321369Sdim 740321369Sdim } Offset; 741321369Sdim}; 742321369Sdim 743321369Sdimstruct coff_resource_data_entry { 744321369Sdim support::ulittle32_t DataRVA; 745321369Sdim support::ulittle32_t DataSize; 746321369Sdim support::ulittle32_t Codepage; 747321369Sdim support::ulittle32_t Reserved; 748321369Sdim}; 749321369Sdim 750321369Sdimstruct coff_resource_dir_table { 751321369Sdim support::ulittle32_t Characteristics; 752321369Sdim support::ulittle32_t TimeDateStamp; 753321369Sdim support::ulittle16_t MajorVersion; 754321369Sdim support::ulittle16_t MinorVersion; 755321369Sdim support::ulittle16_t NumberOfNameEntries; 756321369Sdim support::ulittle16_t NumberOfIDEntries; 757321369Sdim}; 758321369Sdim 759327952Sdimstruct debug_h_header { 760327952Sdim support::ulittle32_t Magic; 761327952Sdim support::ulittle16_t Version; 762327952Sdim support::ulittle16_t HashAlgorithm; 763327952Sdim}; 764327952Sdim 765224133Sdimclass COFFObjectFile : public ObjectFile { 766224133Sdimprivate: 767261991Sdim friend class ImportDirectoryEntryRef; 768276479Sdim friend class ExportDirectoryEntryRef; 769261991Sdim const coff_file_header *COFFHeader; 770280031Sdim const coff_bigobj_file_header *COFFBigObjHeader; 771276479Sdim const pe32_header *PE32Header; 772276479Sdim const pe32plus_header *PE32PlusHeader; 773276479Sdim const data_directory *DataDirectory; 774276479Sdim const coff_section *SectionTable; 775280031Sdim const coff_symbol16 *SymbolTable16; 776280031Sdim const coff_symbol32 *SymbolTable32; 777276479Sdim const char *StringTable; 778276479Sdim uint32_t StringTableSize; 779314564Sdim const coff_import_directory_table_entry *ImportDirectory; 780280031Sdim const delay_import_directory_table_entry *DelayImportDirectory; 781280031Sdim uint32_t NumberOfDelayImportDirectory; 782276479Sdim const export_directory_table_entry *ExportDirectory; 783280031Sdim const coff_base_reloc_block_header *BaseRelocHeader; 784280031Sdim const coff_base_reloc_block_header *BaseRelocEnd; 785309124Sdim const debug_directory *DebugDirectoryBegin; 786309124Sdim const debug_directory *DebugDirectoryEnd; 787321369Sdim // Either coff_load_configuration32 or coff_load_configuration64. 788327952Sdim const void *LoadConfig = nullptr; 789224133Sdim 790276479Sdim std::error_code getString(uint32_t offset, StringRef &Res) const; 791224133Sdim 792280031Sdim template <typename coff_symbol_type> 793280031Sdim const coff_symbol_type *toSymb(DataRefImpl Symb) const; 794276479Sdim const coff_section *toSec(DataRefImpl Sec) const; 795276479Sdim const coff_relocation *toRel(DataRefImpl Rel) const; 796224133Sdim 797276479Sdim std::error_code initSymbolTablePtr(); 798276479Sdim std::error_code initImportTablePtr(); 799280031Sdim std::error_code initDelayImportTablePtr(); 800276479Sdim std::error_code initExportTablePtr(); 801280031Sdim std::error_code initBaseRelocPtr(); 802309124Sdim std::error_code initDebugDirectoryPtr(); 803321369Sdim std::error_code initLoadConfigPtr(); 804261991Sdim 805280031Sdimpublic: 806280031Sdim uintptr_t getSymbolTable() const { 807280031Sdim if (SymbolTable16) 808280031Sdim return reinterpret_cast<uintptr_t>(SymbolTable16); 809280031Sdim if (SymbolTable32) 810280031Sdim return reinterpret_cast<uintptr_t>(SymbolTable32); 811280031Sdim return uintptr_t(0); 812280031Sdim } 813321369Sdim 814280031Sdim uint16_t getMachine() const { 815280031Sdim if (COFFHeader) 816280031Sdim return COFFHeader->Machine; 817280031Sdim if (COFFBigObjHeader) 818280031Sdim return COFFBigObjHeader->Machine; 819280031Sdim llvm_unreachable("no COFF header!"); 820280031Sdim } 821321369Sdim 822280031Sdim uint16_t getSizeOfOptionalHeader() const { 823280031Sdim if (COFFHeader) 824280031Sdim return COFFHeader->isImportLibrary() ? 0 825280031Sdim : COFFHeader->SizeOfOptionalHeader; 826280031Sdim // bigobj doesn't have this field. 827280031Sdim if (COFFBigObjHeader) 828280031Sdim return 0; 829280031Sdim llvm_unreachable("no COFF header!"); 830280031Sdim } 831321369Sdim 832280031Sdim uint16_t getCharacteristics() const { 833280031Sdim if (COFFHeader) 834280031Sdim return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; 835280031Sdim // bigobj doesn't have characteristics to speak of, 836280031Sdim // editbin will silently lie to you if you attempt to set any. 837280031Sdim if (COFFBigObjHeader) 838280031Sdim return 0; 839280031Sdim llvm_unreachable("no COFF header!"); 840280031Sdim } 841321369Sdim 842280031Sdim uint32_t getTimeDateStamp() const { 843280031Sdim if (COFFHeader) 844280031Sdim return COFFHeader->TimeDateStamp; 845280031Sdim if (COFFBigObjHeader) 846280031Sdim return COFFBigObjHeader->TimeDateStamp; 847280031Sdim llvm_unreachable("no COFF header!"); 848280031Sdim } 849321369Sdim 850280031Sdim uint32_t getNumberOfSections() const { 851280031Sdim if (COFFHeader) 852280031Sdim return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; 853280031Sdim if (COFFBigObjHeader) 854280031Sdim return COFFBigObjHeader->NumberOfSections; 855280031Sdim llvm_unreachable("no COFF header!"); 856280031Sdim } 857321369Sdim 858280031Sdim uint32_t getPointerToSymbolTable() const { 859280031Sdim if (COFFHeader) 860280031Sdim return COFFHeader->isImportLibrary() ? 0 861280031Sdim : COFFHeader->PointerToSymbolTable; 862280031Sdim if (COFFBigObjHeader) 863280031Sdim return COFFBigObjHeader->PointerToSymbolTable; 864280031Sdim llvm_unreachable("no COFF header!"); 865280031Sdim } 866321369Sdim 867314564Sdim uint32_t getRawNumberOfSymbols() const { 868280031Sdim if (COFFHeader) 869280031Sdim return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; 870280031Sdim if (COFFBigObjHeader) 871280031Sdim return COFFBigObjHeader->NumberOfSymbols; 872280031Sdim llvm_unreachable("no COFF header!"); 873280031Sdim } 874321369Sdim 875314564Sdim uint32_t getNumberOfSymbols() const { 876314564Sdim if (!SymbolTable16 && !SymbolTable32) 877314564Sdim return 0; 878314564Sdim return getRawNumberOfSymbols(); 879314564Sdim } 880321369Sdim 881321369Sdim const coff_load_configuration32 *getLoadConfig32() const { 882321369Sdim assert(!is64()); 883321369Sdim return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig); 884321369Sdim } 885321369Sdim 886321369Sdim const coff_load_configuration64 *getLoadConfig64() const { 887321369Sdim assert(is64()); 888321369Sdim return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig); 889321369Sdim } 890344779Sdim StringRef getRelocationTypeName(uint16_t Type) const; 891321369Sdim 892224133Sdimprotected: 893276479Sdim void moveSymbolNext(DataRefImpl &Symb) const override; 894309124Sdim Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 895309124Sdim Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 896314564Sdim uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 897288943Sdim uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 898288943Sdim uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 899276479Sdim uint32_t getSymbolFlags(DataRefImpl Symb) const override; 900309124Sdim Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 901309124Sdim Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 902276479Sdim void moveSectionNext(DataRefImpl &Sec) const override; 903353358Sdim Expected<StringRef> getSectionName(DataRefImpl Sec) const override; 904280031Sdim uint64_t getSectionAddress(DataRefImpl Sec) const override; 905321369Sdim uint64_t getSectionIndex(DataRefImpl Sec) const override; 906280031Sdim uint64_t getSectionSize(DataRefImpl Sec) const override; 907353358Sdim Expected<ArrayRef<uint8_t>> 908353358Sdim getSectionContents(DataRefImpl Sec) const override; 909280031Sdim uint64_t getSectionAlignment(DataRefImpl Sec) const override; 910309124Sdim bool isSectionCompressed(DataRefImpl Sec) const override; 911280031Sdim bool isSectionText(DataRefImpl Sec) const override; 912280031Sdim bool isSectionData(DataRefImpl Sec) const override; 913280031Sdim bool isSectionBSS(DataRefImpl Sec) const override; 914280031Sdim bool isSectionVirtual(DataRefImpl Sec) const override; 915276479Sdim relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 916276479Sdim relocation_iterator section_rel_end(DataRefImpl Sec) const override; 917224133Sdim 918276479Sdim void moveRelocationNext(DataRefImpl &Rel) const override; 919288943Sdim uint64_t getRelocationOffset(DataRefImpl Rel) const override; 920276479Sdim symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 921288943Sdim uint64_t getRelocationType(DataRefImpl Rel) const override; 922288943Sdim void getRelocationTypeName(DataRefImpl Rel, 923288943Sdim SmallVectorImpl<char> &Result) const override; 924224133Sdim 925224133Sdimpublic: 926280031Sdim COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); 927321369Sdim 928314564Sdim basic_symbol_iterator symbol_begin() const override; 929314564Sdim basic_symbol_iterator symbol_end() const override; 930276479Sdim section_iterator section_begin() const override; 931276479Sdim section_iterator section_end() const override; 932224133Sdim 933276479Sdim const coff_section *getCOFFSection(const SectionRef &Section) const; 934280031Sdim COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; 935280031Sdim COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; 936276479Sdim const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; 937288943Sdim unsigned getSectionID(SectionRef Sec) const; 938288943Sdim unsigned getSymbolSectionID(SymbolRef Sym) const; 939261991Sdim 940276479Sdim uint8_t getBytesInAddress() const override; 941276479Sdim StringRef getFileFormatName() const override; 942327952Sdim Triple::ArchType getArch() const override; 943341825Sdim Expected<uint64_t> getStartAddress() const override; 944309124Sdim SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } 945234353Sdim 946261991Sdim import_directory_iterator import_directory_begin() const; 947261991Sdim import_directory_iterator import_directory_end() const; 948280031Sdim delay_import_directory_iterator delay_import_directory_begin() const; 949280031Sdim delay_import_directory_iterator delay_import_directory_end() const; 950276479Sdim export_directory_iterator export_directory_begin() const; 951276479Sdim export_directory_iterator export_directory_end() const; 952280031Sdim base_reloc_iterator base_reloc_begin() const; 953280031Sdim base_reloc_iterator base_reloc_end() const; 954309124Sdim const debug_directory *debug_directory_begin() const { 955309124Sdim return DebugDirectoryBegin; 956309124Sdim } 957309124Sdim const debug_directory *debug_directory_end() const { 958309124Sdim return DebugDirectoryEnd; 959309124Sdim } 960261991Sdim 961280031Sdim iterator_range<import_directory_iterator> import_directories() const; 962280031Sdim iterator_range<delay_import_directory_iterator> 963280031Sdim delay_import_directories() const; 964280031Sdim iterator_range<export_directory_iterator> export_directories() const; 965280031Sdim iterator_range<base_reloc_iterator> base_relocs() const; 966309124Sdim iterator_range<const debug_directory *> debug_directories() const { 967309124Sdim return make_range(debug_directory_begin(), debug_directory_end()); 968309124Sdim } 969280031Sdim 970280031Sdim const dos_header *getDOSHeader() const { 971280031Sdim if (!PE32Header && !PE32PlusHeader) 972280031Sdim return nullptr; 973280031Sdim return reinterpret_cast<const dos_header *>(base()); 974280031Sdim } 975360784Sdim 976360784Sdim const coff_file_header *getCOFFHeader() const { return COFFHeader; } 977360784Sdim const coff_bigobj_file_header *getCOFFBigObjHeader() const { 978360784Sdim return COFFBigObjHeader; 979360784Sdim } 980360784Sdim const pe32_header *getPE32Header() const { return PE32Header; } 981360784Sdim const pe32plus_header *getPE32PlusHeader() const { return PE32PlusHeader; } 982360784Sdim 983276479Sdim std::error_code getDataDirectory(uint32_t index, 984276479Sdim const data_directory *&Res) const; 985276479Sdim std::error_code getSection(int32_t index, const coff_section *&Res) const; 986341825Sdim std::error_code getSection(StringRef SectionName, 987341825Sdim const coff_section *&Res) const; 988321369Sdim 989280031Sdim template <typename coff_symbol_type> 990280031Sdim std::error_code getSymbol(uint32_t Index, 991280031Sdim const coff_symbol_type *&Res) const { 992280031Sdim if (Index >= getNumberOfSymbols()) 993280031Sdim return object_error::parse_failed; 994280031Sdim 995280031Sdim Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index; 996288943Sdim return std::error_code(); 997280031Sdim } 998327952Sdim Expected<COFFSymbolRef> getSymbol(uint32_t index) const { 999280031Sdim if (SymbolTable16) { 1000280031Sdim const coff_symbol16 *Symb = nullptr; 1001280031Sdim if (std::error_code EC = getSymbol(index, Symb)) 1002327952Sdim return errorCodeToError(EC); 1003280031Sdim return COFFSymbolRef(Symb); 1004280031Sdim } 1005280031Sdim if (SymbolTable32) { 1006280031Sdim const coff_symbol32 *Symb = nullptr; 1007280031Sdim if (std::error_code EC = getSymbol(index, Symb)) 1008327952Sdim return errorCodeToError(EC); 1009280031Sdim return COFFSymbolRef(Symb); 1010280031Sdim } 1011327952Sdim return errorCodeToError(object_error::parse_failed); 1012280031Sdim } 1013321369Sdim 1014234353Sdim template <typename T> 1015276479Sdim std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { 1016327952Sdim Expected<COFFSymbolRef> S = getSymbol(index); 1017327952Sdim if (Error E = S.takeError()) 1018327952Sdim return errorToErrorCode(std::move(E)); 1019327952Sdim Res = reinterpret_cast<const T *>(S->getRawPtr()); 1020288943Sdim return std::error_code(); 1021234353Sdim } 1022321369Sdim 1023280031Sdim std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; 1024288943Sdim std::error_code getSymbolName(const coff_symbol_generic *Symbol, 1025288943Sdim StringRef &Res) const; 1026239462Sdim 1027280031Sdim ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const; 1028280031Sdim 1029344779Sdim uint32_t getSymbolIndex(COFFSymbolRef Symbol) const; 1030344779Sdim 1031280031Sdim size_t getSymbolTableEntrySize() const { 1032280031Sdim if (COFFHeader) 1033280031Sdim return sizeof(coff_symbol16); 1034280031Sdim if (COFFBigObjHeader) 1035280031Sdim return sizeof(coff_symbol32); 1036280031Sdim llvm_unreachable("null symbol table pointer!"); 1037280031Sdim } 1038280031Sdim 1039341825Sdim ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; 1040288943Sdim 1041353358Sdim Expected<StringRef> getSectionName(const coff_section *Sec) const; 1042280031Sdim uint64_t getSectionSize(const coff_section *Sec) const; 1043353358Sdim Error getSectionContents(const coff_section *Sec, 1044353358Sdim ArrayRef<uint8_t> &Res) const; 1045234353Sdim 1046296417Sdim uint64_t getImageBase() const; 1047276479Sdim std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; 1048276479Sdim std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; 1049309124Sdim 1050309124Sdim /// Given an RVA base and size, returns a valid array of bytes or an error 1051309124Sdim /// code if the RVA and size is not contained completely within a valid 1052309124Sdim /// section. 1053309124Sdim std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 1054309124Sdim ArrayRef<uint8_t> &Contents) const; 1055309124Sdim 1056276479Sdim std::error_code getHintName(uint32_t Rva, uint16_t &Hint, 1057276479Sdim StringRef &Name) const; 1058261991Sdim 1059309124Sdim /// Get PDB information out of a codeview debug directory entry. 1060309124Sdim std::error_code getDebugPDBInfo(const debug_directory *DebugDir, 1061314564Sdim const codeview::DebugInfo *&Info, 1062309124Sdim StringRef &PDBFileName) const; 1063309124Sdim 1064309124Sdim /// Get PDB information from an executable. If the information is not present, 1065309124Sdim /// Info will be set to nullptr and PDBFileName will be empty. An error is 1066309124Sdim /// returned only on corrupt object files. Convenience accessor that can be 1067309124Sdim /// used if the debug directory is not already handy. 1068314564Sdim std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info, 1069309124Sdim StringRef &PDBFileName) const; 1070309124Sdim 1071280031Sdim bool isRelocatableObject() const override; 1072280031Sdim bool is64() const { return PE32PlusHeader; } 1073280031Sdim 1074344779Sdim StringRef mapDebugSectionName(StringRef Name) const override; 1075344779Sdim 1076321369Sdim static bool classof(const Binary *v) { return v->isCOFF(); } 1077224133Sdim}; 1078224133Sdim 1079261991Sdim// The iterator for the import directory table. 1080261991Sdimclass ImportDirectoryEntryRef { 1081261991Sdimpublic: 1082321369Sdim ImportDirectoryEntryRef() = default; 1083314564Sdim ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table, 1084314564Sdim uint32_t I, const COFFObjectFile *Owner) 1085276479Sdim : ImportTable(Table), Index(I), OwningObject(Owner) {} 1086224133Sdim 1087261991Sdim bool operator==(const ImportDirectoryEntryRef &Other) const; 1088276479Sdim void moveNext(); 1089280031Sdim 1090280031Sdim imported_symbol_iterator imported_symbol_begin() const; 1091280031Sdim imported_symbol_iterator imported_symbol_end() const; 1092280031Sdim iterator_range<imported_symbol_iterator> imported_symbols() const; 1093280031Sdim 1094314564Sdim imported_symbol_iterator lookup_table_begin() const; 1095314564Sdim imported_symbol_iterator lookup_table_end() const; 1096314564Sdim iterator_range<imported_symbol_iterator> lookup_table_symbols() const; 1097314564Sdim 1098276479Sdim std::error_code getName(StringRef &Result) const; 1099280031Sdim std::error_code getImportLookupTableRVA(uint32_t &Result) const; 1100280031Sdim std::error_code getImportAddressTableRVA(uint32_t &Result) const; 1101261991Sdim 1102276479Sdim std::error_code 1103314564Sdim getImportTableEntry(const coff_import_directory_table_entry *&Result) const; 1104261991Sdim 1105261991Sdimprivate: 1106314564Sdim const coff_import_directory_table_entry *ImportTable; 1107276479Sdim uint32_t Index; 1108321369Sdim const COFFObjectFile *OwningObject = nullptr; 1109261991Sdim}; 1110276479Sdim 1111280031Sdimclass DelayImportDirectoryEntryRef { 1112280031Sdimpublic: 1113321369Sdim DelayImportDirectoryEntryRef() = default; 1114280031Sdim DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, 1115280031Sdim uint32_t I, const COFFObjectFile *Owner) 1116280031Sdim : Table(T), Index(I), OwningObject(Owner) {} 1117280031Sdim 1118280031Sdim bool operator==(const DelayImportDirectoryEntryRef &Other) const; 1119280031Sdim void moveNext(); 1120280031Sdim 1121280031Sdim imported_symbol_iterator imported_symbol_begin() const; 1122280031Sdim imported_symbol_iterator imported_symbol_end() const; 1123280031Sdim iterator_range<imported_symbol_iterator> imported_symbols() const; 1124280031Sdim 1125280031Sdim std::error_code getName(StringRef &Result) const; 1126280031Sdim std::error_code getDelayImportTable( 1127280031Sdim const delay_import_directory_table_entry *&Result) const; 1128280031Sdim std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; 1129280031Sdim 1130280031Sdimprivate: 1131280031Sdim const delay_import_directory_table_entry *Table; 1132280031Sdim uint32_t Index; 1133321369Sdim const COFFObjectFile *OwningObject = nullptr; 1134280031Sdim}; 1135280031Sdim 1136276479Sdim// The iterator for the export directory table entry. 1137276479Sdimclass ExportDirectoryEntryRef { 1138276479Sdimpublic: 1139321369Sdim ExportDirectoryEntryRef() = default; 1140276479Sdim ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, 1141276479Sdim const COFFObjectFile *Owner) 1142276479Sdim : ExportTable(Table), Index(I), OwningObject(Owner) {} 1143276479Sdim 1144276479Sdim bool operator==(const ExportDirectoryEntryRef &Other) const; 1145276479Sdim void moveNext(); 1146276479Sdim 1147276479Sdim std::error_code getDllName(StringRef &Result) const; 1148276479Sdim std::error_code getOrdinalBase(uint32_t &Result) const; 1149276479Sdim std::error_code getOrdinal(uint32_t &Result) const; 1150276479Sdim std::error_code getExportRVA(uint32_t &Result) const; 1151276479Sdim std::error_code getSymbolName(StringRef &Result) const; 1152276479Sdim 1153296417Sdim std::error_code isForwarder(bool &Result) const; 1154296417Sdim std::error_code getForwardTo(StringRef &Result) const; 1155296417Sdim 1156276479Sdimprivate: 1157276479Sdim const export_directory_table_entry *ExportTable; 1158276479Sdim uint32_t Index; 1159321369Sdim const COFFObjectFile *OwningObject = nullptr; 1160276479Sdim}; 1161280031Sdim 1162280031Sdimclass ImportedSymbolRef { 1163280031Sdimpublic: 1164321369Sdim ImportedSymbolRef() = default; 1165280031Sdim ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, 1166280031Sdim const COFFObjectFile *Owner) 1167280031Sdim : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} 1168280031Sdim ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, 1169280031Sdim const COFFObjectFile *Owner) 1170280031Sdim : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} 1171280031Sdim 1172280031Sdim bool operator==(const ImportedSymbolRef &Other) const; 1173280031Sdim void moveNext(); 1174280031Sdim 1175280031Sdim std::error_code getSymbolName(StringRef &Result) const; 1176309124Sdim std::error_code isOrdinal(bool &Result) const; 1177280031Sdim std::error_code getOrdinal(uint16_t &Result) const; 1178309124Sdim std::error_code getHintNameRVA(uint32_t &Result) const; 1179280031Sdim 1180280031Sdimprivate: 1181280031Sdim const import_lookup_table_entry32 *Entry32; 1182280031Sdim const import_lookup_table_entry64 *Entry64; 1183280031Sdim uint32_t Index; 1184321369Sdim const COFFObjectFile *OwningObject = nullptr; 1185280031Sdim}; 1186280031Sdim 1187280031Sdimclass BaseRelocRef { 1188280031Sdimpublic: 1189321369Sdim BaseRelocRef() = default; 1190280031Sdim BaseRelocRef(const coff_base_reloc_block_header *Header, 1191280031Sdim const COFFObjectFile *Owner) 1192327952Sdim : Header(Header), Index(0) {} 1193280031Sdim 1194280031Sdim bool operator==(const BaseRelocRef &Other) const; 1195280031Sdim void moveNext(); 1196280031Sdim 1197280031Sdim std::error_code getType(uint8_t &Type) const; 1198280031Sdim std::error_code getRVA(uint32_t &Result) const; 1199280031Sdim 1200280031Sdimprivate: 1201280031Sdim const coff_base_reloc_block_header *Header; 1202280031Sdim uint32_t Index; 1203280031Sdim}; 1204280031Sdim 1205321369Sdimclass ResourceSectionRef { 1206321369Sdimpublic: 1207321369Sdim ResourceSectionRef() = default; 1208321369Sdim explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {} 1209321369Sdim 1210360784Sdim Error load(const COFFObjectFile *O); 1211360784Sdim Error load(const COFFObjectFile *O, const SectionRef &S); 1212360784Sdim 1213327952Sdim Expected<ArrayRef<UTF16>> 1214327952Sdim getEntryNameString(const coff_resource_dir_entry &Entry); 1215327952Sdim Expected<const coff_resource_dir_table &> 1216321369Sdim getEntrySubDir(const coff_resource_dir_entry &Entry); 1217360784Sdim Expected<const coff_resource_data_entry &> 1218360784Sdim getEntryData(const coff_resource_dir_entry &Entry); 1219327952Sdim Expected<const coff_resource_dir_table &> getBaseTable(); 1220360784Sdim Expected<const coff_resource_dir_entry &> 1221360784Sdim getTableEntry(const coff_resource_dir_table &Table, uint32_t Index); 1222321369Sdim 1223360784Sdim Expected<StringRef> getContents(const coff_resource_data_entry &Entry); 1224360784Sdim 1225321369Sdimprivate: 1226321369Sdim BinaryByteStream BBS; 1227321369Sdim 1228360784Sdim SectionRef Section; 1229360784Sdim const COFFObjectFile *Obj; 1230360784Sdim 1231360784Sdim std::vector<const coff_relocation *> Relocs; 1232360784Sdim 1233327952Sdim Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset); 1234360784Sdim Expected<const coff_resource_dir_entry &> 1235360784Sdim getTableEntryAtOffset(uint32_t Offset); 1236360784Sdim Expected<const coff_resource_data_entry &> 1237360784Sdim getDataEntryAtOffset(uint32_t Offset); 1238327952Sdim Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset); 1239321369Sdim}; 1240321369Sdim 1241309124Sdim// Corresponds to `_FPO_DATA` structure in the PE/COFF spec. 1242309124Sdimstruct FpoData { 1243309124Sdim support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code 1244309124Sdim support::ulittle32_t Size; // cbProcSize: # bytes in function 1245309124Sdim support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4 1246309124Sdim support::ulittle16_t NumParams; // cdwParams: # bytes in params/4 1247309124Sdim support::ulittle16_t Attributes; 1248309124Sdim 1249309124Sdim // cbProlog: # bytes in prolog 1250309124Sdim int getPrologSize() const { return Attributes & 0xF; } 1251309124Sdim 1252309124Sdim // cbRegs: # regs saved 1253309124Sdim int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; } 1254309124Sdim 1255309124Sdim // fHasSEH: true if seh is func 1256309124Sdim bool hasSEH() const { return (Attributes >> 9) & 1; } 1257309124Sdim 1258309124Sdim // fUseBP: true if EBP has been allocated 1259309124Sdim bool useBP() const { return (Attributes >> 10) & 1; } 1260309124Sdim 1261309124Sdim // cbFrame: frame pointer 1262344779Sdim frame_type getFP() const { return static_cast<frame_type>(Attributes >> 14); } 1263309124Sdim}; 1264309124Sdim 1265261991Sdim} // end namespace object 1266321369Sdim 1267261991Sdim} // end namespace llvm 1268261991Sdim 1269321369Sdim#endif // LLVM_OBJECT_COFF_H 1270