LCOV - code coverage report
Current view: top level - lib/Object - COFFObjectFile.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 763 841 90.7 %
Date: 2018-07-13 00:08:38 Functions: 144 145 99.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
       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             : #include "llvm/ADT/ArrayRef.h"
      15             : #include "llvm/ADT/StringRef.h"
      16             : #include "llvm/ADT/Triple.h"
      17             : #include "llvm/ADT/iterator_range.h"
      18             : #include "llvm/BinaryFormat/COFF.h"
      19             : #include "llvm/Object/Binary.h"
      20             : #include "llvm/Object/COFF.h"
      21             : #include "llvm/Object/Error.h"
      22             : #include "llvm/Object/ObjectFile.h"
      23             : #include "llvm/Support/BinaryStreamReader.h"
      24             : #include "llvm/Support/Endian.h"
      25             : #include "llvm/Support/Error.h"
      26             : #include "llvm/Support/ErrorHandling.h"
      27             : #include "llvm/Support/MathExtras.h"
      28             : #include "llvm/Support/MemoryBuffer.h"
      29             : #include <algorithm>
      30             : #include <cassert>
      31             : #include <cstddef>
      32             : #include <cstdint>
      33             : #include <cstring>
      34             : #include <limits>
      35             : #include <memory>
      36             : #include <system_error>
      37             : 
      38             : using namespace llvm;
      39             : using namespace object;
      40             : 
      41             : using support::ulittle16_t;
      42             : using support::ulittle32_t;
      43             : using support::ulittle64_t;
      44             : using support::little16_t;
      45             : 
      46             : // Returns false if size is greater than the buffer size. And sets ec.
      47             : static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
      48        1691 :   if (M.getBufferSize() < Size) {
      49             :     EC = object_error::unexpected_eof;
      50             :     return false;
      51             :   }
      52             :   return true;
      53             : }
      54             : 
      55             : // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
      56             : // Returns unexpected_eof if error.
      57             : template <typename T>
      58        8176 : static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
      59             :                                  const void *Ptr,
      60             :                                  const uint64_t Size = sizeof(T)) {
      61        8176 :   uintptr_t Addr = uintptr_t(Ptr);
      62        8176 :   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
      63           0 :     return EC;
      64        8176 :   Obj = reinterpret_cast<const T *>(Addr);
      65        8176 :   return std::error_code();
      66             : }
      67             : 
      68             : // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
      69             : // prefixed slashes.
      70           1 : static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
      71             :   assert(Str.size() <= 6 && "String too long, possible overflow.");
      72           1 :   if (Str.size() > 6)
      73             :     return true;
      74             : 
      75             :   uint64_t Value = 0;
      76          13 :   while (!Str.empty()) {
      77             :     unsigned CharVal;
      78          12 :     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
      79           3 :       CharVal = Str[0] - 'A';
      80           3 :     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
      81           2 :       CharVal = Str[0] - 'a' + 26;
      82           2 :     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
      83           1 :       CharVal = Str[0] - '0' + 52;
      84           0 :     else if (Str[0] == '+') // 62
      85             :       CharVal = 62;
      86           0 :     else if (Str[0] == '/') // 63
      87             :       CharVal = 63;
      88             :     else
      89             :       return true;
      90             : 
      91           6 :     Value = (Value * 64) + CharVal;
      92           6 :     Str = Str.substr(1);
      93             :   }
      94             : 
      95           1 :   if (Value > std::numeric_limits<uint32_t>::max())
      96             :     return true;
      97             : 
      98           1 :   Result = static_cast<uint32_t>(Value);
      99           1 :   return false;
     100             : }
     101             : 
     102             : template <typename coff_symbol_type>
     103             : const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
     104       17056 :   const coff_symbol_type *Addr =
     105             :       reinterpret_cast<const coff_symbol_type *>(Ref.p);
     106             : 
     107             :   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
     108             : #ifndef NDEBUG
     109             :   // Verify that the symbol points to a valid entry in the symbol table.
     110             :   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
     111             : 
     112             :   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
     113             :          "Symbol did not point to the beginning of a symbol");
     114             : #endif
     115             : 
     116             :   return Addr;
     117             : }
     118             : 
     119      177487 : const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
     120      177487 :   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
     121             : 
     122             : #ifndef NDEBUG
     123             :   // Verify that the section points to a valid entry in the section table.
     124             :   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
     125             :     report_fatal_error("Section was outside of section table.");
     126             : 
     127             :   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
     128             :   assert(Offset % sizeof(coff_section) == 0 &&
     129             :          "Section did not point to the beginning of a section");
     130             : #endif
     131             : 
     132      177487 :   return Addr;
     133             : }
     134             : 
     135        3829 : void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
     136        3829 :   auto End = reinterpret_cast<uintptr_t>(StringTable);
     137        3829 :   if (SymbolTable16) {
     138             :     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
     139        3825 :     Symb += 1 + Symb->NumberOfAuxSymbols;
     140        7650 :     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
     141           4 :   } else if (SymbolTable32) {
     142             :     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
     143           4 :     Symb += 1 + Symb->NumberOfAuxSymbols;
     144           8 :     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
     145             :   } else {
     146           0 :     llvm_unreachable("no symbol table pointer!");
     147             :   }
     148        3829 : }
     149             : 
     150        2610 : Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
     151        2610 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     152        2610 :   StringRef Result;
     153        2610 :   if (std::error_code EC = getSymbolName(Symb, Result))
     154           0 :     return errorCodeToError(EC);
     155             :   return Result;
     156             : }
     157             : 
     158         879 : uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
     159        1758 :   return getCOFFSymbol(Ref).getValue();
     160             : }
     161             : 
     162           0 : uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
     163             :   // MSVC/link.exe seems to align symbols to the next-power-of-2
     164             :   // up to 32 bytes.
     165           0 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     166           0 :   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
     167             : }
     168             : 
     169         728 : Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
     170         728 :   uint64_t Result = getSymbolValue(Ref);
     171         728 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     172             :   int32_t SectionNumber = Symb.getSectionNumber();
     173             : 
     174         728 :   if (Symb.isAnyUndefined() || Symb.isCommon() ||
     175             :       COFF::isReservedSectionNumber(SectionNumber))
     176             :     return Result;
     177             : 
     178         610 :   const coff_section *Section = nullptr;
     179         610 :   if (std::error_code EC = getSection(SectionNumber, Section))
     180           0 :     return errorCodeToError(EC);
     181        1220 :   Result += Section->VirtualAddress;
     182             : 
     183             :   // The section VirtualAddress does not include ImageBase, and we want to
     184             :   // return virtual addresses.
     185         610 :   Result += getImageBase();
     186             : 
     187             :   return Result;
     188             : }
     189             : 
     190          73 : Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
     191          73 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     192             :   int32_t SectionNumber = Symb.getSectionNumber();
     193             : 
     194          73 :   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
     195             :     return SymbolRef::ST_Function;
     196          64 :   if (Symb.isAnyUndefined())
     197             :     return SymbolRef::ST_Unknown;
     198          64 :   if (Symb.isCommon())
     199             :     return SymbolRef::ST_Data;
     200          64 :   if (Symb.isFileRecord())
     201             :     return SymbolRef::ST_File;
     202             : 
     203             :   // TODO: perhaps we need a new symbol type ST_Section.
     204          64 :   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
     205             :     return SymbolRef::ST_Debug;
     206             : 
     207          47 :   if (!COFF::isReservedSectionNumber(SectionNumber))
     208             :     return SymbolRef::ST_Data;
     209             : 
     210             :   return SymbolRef::ST_Other;
     211             : }
     212             : 
     213        5979 : uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
     214        5979 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     215             :   uint32_t Result = SymbolRef::SF_None;
     216             : 
     217        5979 :   if (Symb.isExternal() || Symb.isWeakExternal())
     218             :     Result |= SymbolRef::SF_Global;
     219             : 
     220        5979 :   if (Symb.isWeakExternal()) {
     221             :     Result |= SymbolRef::SF_Weak;
     222             :     // We use indirect to allow the archiver to write weak externs
     223          59 :     Result |= SymbolRef::SF_Indirect;
     224             :   }
     225             : 
     226        5979 :   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
     227         170 :     Result |= SymbolRef::SF_Absolute;
     228             : 
     229        5979 :   if (Symb.isFileRecord())
     230           8 :     Result |= SymbolRef::SF_FormatSpecific;
     231             : 
     232        5979 :   if (Symb.isSectionDefinition())
     233        2012 :     Result |= SymbolRef::SF_FormatSpecific;
     234             : 
     235        5979 :   if (Symb.isCommon())
     236           7 :     Result |= SymbolRef::SF_Common;
     237             : 
     238        5979 :   if (Symb.isAnyUndefined())
     239         758 :     Result |= SymbolRef::SF_Undefined;
     240             : 
     241        5979 :   return Result;
     242             : }
     243             : 
     244           4 : uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
     245           4 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     246           4 :   return Symb.getValue();
     247             : }
     248             : 
     249             : Expected<section_iterator>
     250        1925 : COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
     251        1925 :   COFFSymbolRef Symb = getCOFFSymbol(Ref);
     252        1925 :   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
     253         584 :     return section_end();
     254        1633 :   const coff_section *Sec = nullptr;
     255        1633 :   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
     256           0 :     return errorCodeToError(EC);
     257             :   DataRefImpl Ret;
     258        1633 :   Ret.p = reinterpret_cast<uintptr_t>(Sec);
     259        3266 :   return section_iterator(SectionRef(Ret, this));
     260             : }
     261             : 
     262         210 : unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
     263         210 :   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
     264         210 :   return Symb.getSectionNumber();
     265             : }
     266             : 
     267        8549 : void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
     268        8549 :   const coff_section *Sec = toSec(Ref);
     269        8549 :   Sec += 1;
     270        8549 :   Ref.p = reinterpret_cast<uintptr_t>(Sec);
     271        8549 : }
     272             : 
     273        3960 : std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
     274             :                                                StringRef &Result) const {
     275        3960 :   const coff_section *Sec = toSec(Ref);
     276        3960 :   return getSectionName(Sec, Result);
     277             : }
     278             : 
     279         632 : uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
     280         632 :   const coff_section *Sec = toSec(Ref);
     281         632 :   uint64_t Result = Sec->VirtualAddress;
     282             : 
     283             :   // The section VirtualAddress does not include ImageBase, and we want to
     284             :   // return virtual addresses.
     285         632 :   Result += getImageBase();
     286         632 :   return Result;
     287             : }
     288             : 
     289          61 : uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
     290          61 :   return toSec(Sec) - SectionTable;
     291             : }
     292             : 
     293      150494 : uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
     294      150494 :   return getSectionSize(toSec(Ref));
     295             : }
     296             : 
     297         773 : std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
     298             :                                                    StringRef &Result) const {
     299         773 :   const coff_section *Sec = toSec(Ref);
     300         773 :   ArrayRef<uint8_t> Res;
     301         773 :   std::error_code EC = getSectionContents(Sec, Res);
     302         773 :   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
     303         773 :   return EC;
     304             : }
     305             : 
     306          34 : uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
     307          34 :   const coff_section *Sec = toSec(Ref);
     308          34 :   return Sec->getAlignment();
     309             : }
     310             : 
     311         143 : bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
     312         143 :   return false;
     313             : }
     314             : 
     315         292 : bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
     316         292 :   const coff_section *Sec = toSec(Ref);
     317         292 :   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
     318             : }
     319             : 
     320          28 : bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
     321          28 :   const coff_section *Sec = toSec(Ref);
     322          28 :   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
     323             : }
     324             : 
     325         476 : bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
     326         476 :   const coff_section *Sec = toSec(Ref);
     327             :   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
     328             :                             COFF::IMAGE_SCN_MEM_READ |
     329             :                             COFF::IMAGE_SCN_MEM_WRITE;
     330         476 :   return (Sec->Characteristics & BssFlags) == BssFlags;
     331             : }
     332             : 
     333         340 : unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
     334             :   uintptr_t Offset =
     335         340 :       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
     336             :   assert((Offset % sizeof(coff_section)) == 0);
     337         340 :   return (Offset / sizeof(coff_section)) + 1;
     338             : }
     339             : 
     340         715 : bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
     341         715 :   const coff_section *Sec = toSec(Ref);
     342             :   // In COFF, a virtual section won't have any in-file 
     343             :   // content, so the file pointer to the content will be zero.
     344         715 :   return Sec->PointerToRawData == 0;
     345             : }
     346             : 
     347        6208 : static uint32_t getNumberOfRelocations(const coff_section *Sec,
     348             :                                        MemoryBufferRef M, const uint8_t *base) {
     349             :   // The field for the number of relocations in COFF section table is only
     350             :   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
     351             :   // NumberOfRelocations field, and the actual relocation count is stored in the
     352             :   // VirtualAddress field in the first relocation entry.
     353             :   if (Sec->hasExtendedRelocations()) {
     354             :     const coff_relocation *FirstReloc;
     355          12 :     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
     356          12 :         base + Sec->PointerToRelocations)))
     357             :       return 0;
     358             :     // -1 to exclude this first relocation entry.
     359          12 :     return FirstReloc->VirtualAddress - 1;
     360             :   }
     361        6202 :   return Sec->NumberOfRelocations;
     362             : }
     363             : 
     364             : static const coff_relocation *
     365        4056 : getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
     366        4056 :   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
     367        4056 :   if (!NumRelocs)
     368             :     return nullptr;
     369             :   auto begin = reinterpret_cast<const coff_relocation *>(
     370        1639 :       Base + Sec->PointerToRelocations);
     371             :   if (Sec->hasExtendedRelocations()) {
     372             :     // Skip the first relocation entry repurposed to store the number of
     373             :     // relocations.
     374           4 :     begin++;
     375             :   }
     376        3278 :   if (Binary::checkOffset(M, uintptr_t(begin),
     377        3278 :                           sizeof(coff_relocation) * NumRelocs))
     378             :     return nullptr;
     379             :   return begin;
     380             : }
     381             : 
     382        1274 : relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
     383        1274 :   const coff_section *Sec = toSec(Ref);
     384        1274 :   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
     385        1918 :   if (begin && Sec->VirtualAddress != 0)
     386           1 :     report_fatal_error("Sections with relocations should have an address of 0");
     387             :   DataRefImpl Ret;
     388        1273 :   Ret.p = reinterpret_cast<uintptr_t>(begin);
     389        2546 :   return relocation_iterator(RelocationRef(Ret, this));
     390             : }
     391             : 
     392        1274 : relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
     393        1274 :   const coff_section *Sec = toSec(Ref);
     394        1274 :   const coff_relocation *I = getFirstReloc(Sec, Data, base());
     395        1274 :   if (I)
     396         644 :     I += getNumberOfRelocations(Sec, Data, base());
     397             :   DataRefImpl Ret;
     398        1274 :   Ret.p = reinterpret_cast<uintptr_t>(I);
     399        2548 :   return relocation_iterator(RelocationRef(Ret, this));
     400             : }
     401             : 
     402             : // Initialize the pointer to the symbol table.
     403        1377 : std::error_code COFFObjectFile::initSymbolTablePtr() {
     404        1377 :   if (COFFHeader)
     405        1376 :     if (std::error_code EC = getObject(
     406        1376 :             SymbolTable16, Data, base() + getPointerToSymbolTable(),
     407        2752 :             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
     408           0 :       return EC;
     409             : 
     410        1377 :   if (COFFBigObjHeader)
     411           1 :     if (std::error_code EC = getObject(
     412           1 :             SymbolTable32, Data, base() + getPointerToSymbolTable(),
     413           3 :             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
     414           0 :       return EC;
     415             : 
     416             :   // Find string table. The first four byte of the string table contains the
     417             :   // total size of the string table, including the size field itself. If the
     418             :   // string table is empty, the value of the first four byte would be 4.
     419        2754 :   uint32_t StringTableOffset = getPointerToSymbolTable() +
     420        1377 :                                getNumberOfSymbols() * getSymbolTableEntrySize();
     421        1377 :   const uint8_t *StringTableAddr = base() + StringTableOffset;
     422             :   const ulittle32_t *StringTableSizePtr;
     423        1377 :   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
     424           0 :     return EC;
     425        2754 :   StringTableSize = *StringTableSizePtr;
     426        1377 :   if (std::error_code EC =
     427        1377 :           getObject(StringTable, Data, StringTableAddr, StringTableSize))
     428           0 :     return EC;
     429             : 
     430             :   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
     431             :   // tools like cvtres write a size of 0 for an empty table instead of 4.
     432        1377 :   if (StringTableSize < 4)
     433          19 :       StringTableSize = 4;
     434             : 
     435             :   // Check that the string table is null terminated if has any in it.
     436        1377 :   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
     437           0 :     return  object_error::parse_failed;
     438        1377 :   return std::error_code();
     439             : }
     440             : 
     441        1574 : uint64_t COFFObjectFile::getImageBase() const {
     442        1574 :   if (PE32Header)
     443          82 :     return PE32Header->ImageBase;
     444        1492 :   else if (PE32PlusHeader)
     445         421 :     return PE32PlusHeader->ImageBase;
     446             :   // This actually comes up in practice.
     447             :   return 0;
     448             : }
     449             : 
     450             : // Returns the file offset for the given VA.
     451          36 : std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
     452          36 :   uint64_t ImageBase = getImageBase();
     453          36 :   uint64_t Rva = Addr - ImageBase;
     454             :   assert(Rva <= UINT32_MAX);
     455          36 :   return getRvaPtr((uint32_t)Rva, Res);
     456             : }
     457             : 
     458             : // Returns the file offset for the given RVA.
     459        3243 : std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
     460       16383 :   for (const SectionRef &S : sections()) {
     461        6654 :     const coff_section *Section = getCOFFSection(S);
     462             :     uint32_t SectionStart = Section->VirtualAddress;
     463        6654 :     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
     464        6654 :     if (SectionStart <= Addr && Addr < SectionEnd) {
     465        3243 :       uint32_t Offset = Addr - SectionStart;
     466        6486 :       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
     467        3243 :       return std::error_code();
     468             :     }
     469             :   }
     470           0 :   return object_error::parse_failed;
     471             : }
     472             : 
     473             : std::error_code
     474          30 : COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
     475             :                                      ArrayRef<uint8_t> &Contents) const {
     476         149 :   for (const SectionRef &S : sections()) {
     477          59 :     const coff_section *Section = getCOFFSection(S);
     478             :     uint32_t SectionStart = Section->VirtualAddress;
     479             :     // Check if this RVA is within the section bounds. Be careful about integer
     480             :     // overflow.
     481          59 :     uint32_t OffsetIntoSection = RVA - SectionStart;
     482         148 :     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
     483          30 :         Size <= Section->VirtualSize - OffsetIntoSection) {
     484             :       uintptr_t Begin =
     485          60 :           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
     486          30 :       Contents =
     487          30 :           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
     488          30 :       return std::error_code();
     489             :     }
     490             :   }
     491           0 :   return object_error::parse_failed;
     492             : }
     493             : 
     494             : // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
     495             : // table entry.
     496          70 : std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
     497             :                                             StringRef &Name) const {
     498          70 :   uintptr_t IntPtr = 0;
     499          70 :   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
     500           0 :     return EC;
     501          70 :   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
     502          70 :   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
     503         140 :   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
     504          70 :   return std::error_code();
     505             : }
     506             : 
     507             : std::error_code
     508          29 : COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
     509             :                                 const codeview::DebugInfo *&PDBInfo,
     510             :                                 StringRef &PDBFileName) const {
     511          29 :   ArrayRef<uint8_t> InfoBytes;
     512          29 :   if (std::error_code EC = getRvaAndSizeAsBytes(
     513          29 :           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
     514           0 :     return EC;
     515          29 :   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
     516           0 :     return object_error::parse_failed;
     517          29 :   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
     518          29 :   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
     519          29 :   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
     520             :                           InfoBytes.size());
     521             :   // Truncate the name at the first null byte. Ignore any padding.
     522          29 :   PDBFileName = PDBFileName.split('\0').first;
     523          29 :   return std::error_code();
     524             : }
     525             : 
     526             : std::error_code
     527          21 : COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
     528             :                                 StringRef &PDBFileName) const {
     529          21 :   for (const debug_directory &D : debug_directories())
     530          21 :     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
     531          21 :       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
     532             :   // If we get here, there is no PDB info to return.
     533           0 :   PDBInfo = nullptr;
     534           0 :   PDBFileName = StringRef();
     535           0 :   return std::error_code();
     536             : }
     537             : 
     538             : // Find the import table.
     539        1690 : std::error_code COFFObjectFile::initImportTablePtr() {
     540             :   // First, we get the RVA of the import table. If the file lacks a pointer to
     541             :   // the import table, do nothing.
     542             :   const data_directory *DataEntry;
     543        1690 :   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
     544        1363 :     return std::error_code();
     545             : 
     546             :   // Do nothing if the pointer to import table is NULL.
     547         654 :   if (DataEntry->RelativeVirtualAddress == 0)
     548         282 :     return std::error_code();
     549             : 
     550             :   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
     551             : 
     552             :   // Find the section that contains the RVA. This is needed because the RVA is
     553             :   // the import table's memory address which is different from its file offset.
     554          45 :   uintptr_t IntPtr = 0;
     555          45 :   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
     556           0 :     return EC;
     557          90 :   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
     558           0 :     return EC;
     559          45 :   ImportDirectory = reinterpret_cast<
     560             :       const coff_import_directory_table_entry *>(IntPtr);
     561          45 :   return std::error_code();
     562             : }
     563             : 
     564             : // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
     565        1690 : std::error_code COFFObjectFile::initDelayImportTablePtr() {
     566             :   const data_directory *DataEntry;
     567        1690 :   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
     568        1363 :     return std::error_code();
     569         654 :   if (DataEntry->RelativeVirtualAddress == 0)
     570         317 :     return std::error_code();
     571             : 
     572             :   uint32_t RVA = DataEntry->RelativeVirtualAddress;
     573          20 :   NumberOfDelayImportDirectory = DataEntry->Size /
     574          10 :       sizeof(delay_import_directory_table_entry) - 1;
     575             : 
     576          10 :   uintptr_t IntPtr = 0;
     577          10 :   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
     578           0 :     return EC;
     579          10 :   DelayImportDirectory = reinterpret_cast<
     580             :       const delay_import_directory_table_entry *>(IntPtr);
     581          10 :   return std::error_code();
     582             : }
     583             : 
     584             : // Find the export table.
     585        1690 : std::error_code COFFObjectFile::initExportTablePtr() {
     586             :   // First, we get the RVA of the export table. If the file lacks a pointer to
     587             :   // the export table, do nothing.
     588             :   const data_directory *DataEntry;
     589        1690 :   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
     590        1363 :     return std::error_code();
     591             : 
     592             :   // Do nothing if the pointer to export table is NULL.
     593         654 :   if (DataEntry->RelativeVirtualAddress == 0)
     594         266 :     return std::error_code();
     595             : 
     596             :   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
     597          61 :   uintptr_t IntPtr = 0;
     598          61 :   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
     599           0 :     return EC;
     600          61 :   ExportDirectory =
     601             :       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
     602          61 :   return std::error_code();
     603             : }
     604             : 
     605        1690 : std::error_code COFFObjectFile::initBaseRelocPtr() {
     606             :   const data_directory *DataEntry;
     607        1690 :   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
     608        1363 :     return std::error_code();
     609         654 :   if (DataEntry->RelativeVirtualAddress == 0)
     610         243 :     return std::error_code();
     611             : 
     612          84 :   uintptr_t IntPtr = 0;
     613          84 :   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
     614           0 :     return EC;
     615          84 :   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
     616             :       IntPtr);
     617          84 :   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
     618         168 :       IntPtr + DataEntry->Size);
     619          84 :   return std::error_code();
     620             : }
     621             : 
     622        1690 : std::error_code COFFObjectFile::initDebugDirectoryPtr() {
     623             :   // Get the RVA of the debug directory. Do nothing if it does not exist.
     624             :   const data_directory *DataEntry;
     625        1690 :   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
     626        1363 :     return std::error_code();
     627             : 
     628             :   // Do nothing if the RVA is NULL.
     629         654 :   if (DataEntry->RelativeVirtualAddress == 0)
     630         256 :     return std::error_code();
     631             : 
     632             :   // Check that the size is a multiple of the entry size.
     633          71 :   if (DataEntry->Size % sizeof(debug_directory) != 0)
     634           0 :     return object_error::parse_failed;
     635             : 
     636          71 :   uintptr_t IntPtr = 0;
     637          71 :   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
     638           0 :     return EC;
     639          71 :   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
     640          71 :   if (std::error_code EC = getRvaPtr(
     641         142 :           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
     642           0 :     return EC;
     643          71 :   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
     644          71 :   return std::error_code();
     645             : }
     646             : 
     647        1690 : std::error_code COFFObjectFile::initLoadConfigPtr() {
     648             :   // Get the RVA of the debug directory. Do nothing if it does not exist.
     649             :   const data_directory *DataEntry;
     650        1690 :   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
     651        1363 :     return std::error_code();
     652             : 
     653             :   // Do nothing if the RVA is NULL.
     654         654 :   if (DataEntry->RelativeVirtualAddress == 0)
     655         295 :     return std::error_code();
     656          32 :   uintptr_t IntPtr = 0;
     657          32 :   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
     658           0 :     return EC;
     659             : 
     660          32 :   LoadConfig = (const void *)IntPtr;
     661          32 :   return std::error_code();
     662             : }
     663             : 
     664        1690 : COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
     665             :     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
     666             :       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
     667             :       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
     668             :       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
     669             :       ImportDirectory(nullptr),
     670             :       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
     671             :       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
     672        1690 :       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
     673             :   // Check that we at least have enough room for a header.
     674        1690 :   if (!checkSize(Data, EC, sizeof(coff_file_header)))
     675             :     return;
     676             : 
     677             :   // The current location in the file where we are looking at.
     678             :   uint64_t CurPtr = 0;
     679             : 
     680             :   // PE header is optional and is present only in executables. If it exists,
     681             :   // it is placed right after COFF header.
     682             :   bool HasPEHeader = false;
     683             : 
     684             :   // Check if this is a PE/COFF file.
     685             :   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
     686             :     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
     687             :     // PE signature to find 'normal' COFF header.
     688             :     const auto *DH = reinterpret_cast<const dos_header *>(base());
     689        1687 :     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
     690         327 :       CurPtr = DH->AddressOfNewExeHeader;
     691             :       // Check the PE magic bytes. ("PE\0\0")
     692         327 :       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
     693             :         EC = object_error::parse_failed;
     694             :         return;
     695             :       }
     696         327 :       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
     697             :       HasPEHeader = true;
     698             :     }
     699             :   }
     700             : 
     701        1690 :   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
     702             :     return;
     703             : 
     704             :   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
     705             :   // import libraries share a common prefix but bigobj is more restrictive.
     706        2744 :   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
     707        1690 :       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
     708           1 :       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
     709           1 :     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
     710             :       return;
     711             : 
     712             :     // Verify that we are dealing with bigobj.
     713           3 :     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
     714           1 :         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
     715             :                     sizeof(COFF::BigObjMagic)) == 0) {
     716           1 :       COFFHeader = nullptr;
     717           1 :       CurPtr += sizeof(coff_bigobj_file_header);
     718             :     } else {
     719             :       // It's not a bigobj.
     720           0 :       COFFBigObjHeader = nullptr;
     721             :     }
     722             :   }
     723        1690 :   if (COFFHeader) {
     724             :     // The prior checkSize call may have failed.  This isn't a hard error
     725             :     // because we were just trying to sniff out bigobj.
     726        1689 :     EC = std::error_code();
     727        1689 :     CurPtr += sizeof(coff_file_header);
     728             : 
     729        1689 :     if (COFFHeader->isImportLibrary())
     730             :       return;
     731             :   }
     732             : 
     733        1690 :   if (HasPEHeader) {
     734             :     const pe32_header *Header;
     735         327 :     if ((EC = getObject(Header, Data, base() + CurPtr)))
     736           0 :       return;
     737             : 
     738             :     const uint8_t *DataDirAddr;
     739             :     uint64_t DataDirSize;
     740         654 :     if (Header->Magic == COFF::PE32Header::PE32) {
     741          89 :       PE32Header = Header;
     742          89 :       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
     743          89 :       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
     744         238 :     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
     745         238 :       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
     746         238 :       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
     747         238 :       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
     748             :     } else {
     749             :       // It's neither PE32 nor PE32+.
     750             :       EC = object_error::parse_failed;
     751             :       return;
     752             :     }
     753         327 :     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
     754             :       return;
     755             :   }
     756             : 
     757        1690 :   if (COFFHeader)
     758        1689 :     CurPtr += COFFHeader->SizeOfOptionalHeader;
     759             : 
     760        5070 :   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
     761        5070 :                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
     762             :     return;
     763             : 
     764             :   // Initialize the pointer to the symbol table.
     765        3380 :   if (getPointerToSymbolTable() != 0) {
     766        1377 :     if ((EC = initSymbolTablePtr())) {
     767           0 :       SymbolTable16 = nullptr;
     768           0 :       SymbolTable32 = nullptr;
     769           0 :       StringTable = nullptr;
     770           0 :       StringTableSize = 0;
     771             :     }
     772             :   } else {
     773             :     // We had better not have any symbols if we don't have a symbol table.
     774           0 :     if (getNumberOfSymbols() != 0) {
     775             :       EC = object_error::parse_failed;
     776             :       return;
     777             :     }
     778             :   }
     779             : 
     780             :   // Initialize the pointer to the beginning of the import table.
     781        1690 :   if ((EC = initImportTablePtr()))
     782             :     return;
     783        1690 :   if ((EC = initDelayImportTablePtr()))
     784             :     return;
     785             : 
     786             :   // Initialize the pointer to the export table.
     787        1690 :   if ((EC = initExportTablePtr()))
     788             :     return;
     789             : 
     790             :   // Initialize the pointer to the base relocation table.
     791        1690 :   if ((EC = initBaseRelocPtr()))
     792             :     return;
     793             : 
     794             :   // Initialize the pointer to the export table.
     795        1690 :   if ((EC = initDebugDirectoryPtr()))
     796             :     return;
     797             : 
     798        1690 :   if ((EC = initLoadConfigPtr()))
     799             :     return;
     800             : 
     801        1690 :   EC = std::error_code();
     802             : }
     803             : 
     804         719 : basic_symbol_iterator COFFObjectFile::symbol_begin() const {
     805             :   DataRefImpl Ret;
     806        1438 :   Ret.p = getSymbolTable();
     807        1438 :   return basic_symbol_iterator(SymbolRef(Ret, this));
     808             : }
     809             : 
     810        3355 : basic_symbol_iterator COFFObjectFile::symbol_end() const {
     811             :   // The symbol table ends where the string table begins.
     812             :   DataRefImpl Ret;
     813        3355 :   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
     814        6710 :   return basic_symbol_iterator(SymbolRef(Ret, this));
     815             : }
     816             : 
     817          44 : import_directory_iterator COFFObjectFile::import_directory_begin() const {
     818          44 :   if (!ImportDirectory)
     819          28 :     return import_directory_end();
     820             :   if (ImportDirectory->isNull())
     821           0 :     return import_directory_end();
     822             :   return import_directory_iterator(
     823             :       ImportDirectoryEntryRef(ImportDirectory, 0, this));
     824             : }
     825             : 
     826          72 : import_directory_iterator COFFObjectFile::import_directory_end() const {
     827             :   return import_directory_iterator(
     828          72 :       ImportDirectoryEntryRef(nullptr, -1, this));
     829             : }
     830             : 
     831             : delay_import_directory_iterator
     832          16 : COFFObjectFile::delay_import_directory_begin() const {
     833             :   return delay_import_directory_iterator(
     834          32 :       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
     835             : }
     836             : 
     837             : delay_import_directory_iterator
     838          16 : COFFObjectFile::delay_import_directory_end() const {
     839             :   return delay_import_directory_iterator(
     840             :       DelayImportDirectoryEntryRef(
     841          32 :           DelayImportDirectory, NumberOfDelayImportDirectory, this));
     842             : }
     843             : 
     844         106 : export_directory_iterator COFFObjectFile::export_directory_begin() const {
     845             :   return export_directory_iterator(
     846         212 :       ExportDirectoryEntryRef(ExportDirectory, 0, this));
     847             : }
     848             : 
     849         106 : export_directory_iterator COFFObjectFile::export_directory_end() const {
     850         106 :   if (!ExportDirectory)
     851             :     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
     852             :   ExportDirectoryEntryRef Ref(ExportDirectory,
     853             :                               ExportDirectory->AddressTableEntries, this);
     854             :   return export_directory_iterator(Ref);
     855             : }
     856             : 
     857        4483 : section_iterator COFFObjectFile::section_begin() const {
     858             :   DataRefImpl Ret;
     859        4483 :   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
     860        8966 :   return section_iterator(SectionRef(Ret, this));
     861             : }
     862             : 
     863        6100 : section_iterator COFFObjectFile::section_end() const {
     864             :   DataRefImpl Ret;
     865             :   int NumSections =
     866       18298 :       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
     867        6100 :   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
     868       12200 :   return section_iterator(SectionRef(Ret, this));
     869             : }
     870             : 
     871          13 : base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
     872          13 :   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
     873             : }
     874             : 
     875          13 : base_reloc_iterator COFFObjectFile::base_reloc_end() const {
     876          13 :   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
     877             : }
     878             : 
     879         614 : uint8_t COFFObjectFile::getBytesInAddress() const {
     880         614 :   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
     881             : }
     882             : 
     883         597 : StringRef COFFObjectFile::getFileFormatName() const {
     884        1194 :   switch(getMachine()) {
     885             :   case COFF::IMAGE_FILE_MACHINE_I386:
     886         228 :     return "COFF-i386";
     887             :   case COFF::IMAGE_FILE_MACHINE_AMD64:
     888         306 :     return "COFF-x86-64";
     889             :   case COFF::IMAGE_FILE_MACHINE_ARMNT:
     890          37 :     return "COFF-ARM";
     891             :   case COFF::IMAGE_FILE_MACHINE_ARM64:
     892          23 :     return "COFF-ARM64";
     893             :   default:
     894           3 :     return "COFF-<unknown arch>";
     895             :   }
     896             : }
     897             : 
     898      152589 : Triple::ArchType COFFObjectFile::getArch() const {
     899      305178 :   switch (getMachine()) {
     900             :   case COFF::IMAGE_FILE_MACHINE_I386:
     901             :     return Triple::x86;
     902      151247 :   case COFF::IMAGE_FILE_MACHINE_AMD64:
     903      151247 :     return Triple::x86_64;
     904         305 :   case COFF::IMAGE_FILE_MACHINE_ARMNT:
     905         305 :     return Triple::thumb;
     906         193 :   case COFF::IMAGE_FILE_MACHINE_ARM64:
     907         193 :     return Triple::aarch64;
     908           9 :   default:
     909           9 :     return Triple::UnknownArch;
     910             :   }
     911             : }
     912             : 
     913           5 : Expected<uint64_t> COFFObjectFile::getStartAddress() const {
     914           5 :   if (PE32Header)
     915             :     return PE32Header->AddressOfEntryPoint;
     916             :   return 0;
     917             : }
     918             : 
     919             : iterator_range<import_directory_iterator>
     920          19 : COFFObjectFile::import_directories() const {
     921          38 :   return make_range(import_directory_begin(), import_directory_end());
     922             : }
     923             : 
     924             : iterator_range<delay_import_directory_iterator>
     925          16 : COFFObjectFile::delay_import_directories() const {
     926             :   return make_range(delay_import_directory_begin(),
     927          32 :                     delay_import_directory_end());
     928             : }
     929             : 
     930             : iterator_range<export_directory_iterator>
     931          81 : COFFObjectFile::export_directories() const {
     932         162 :   return make_range(export_directory_begin(), export_directory_end());
     933             : }
     934             : 
     935          13 : iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
     936          26 :   return make_range(base_reloc_begin(), base_reloc_end());
     937             : }
     938             : 
     939         180 : std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
     940         180 :   Res = PE32Header;
     941         180 :   return std::error_code();
     942             : }
     943             : 
     944             : std::error_code
     945         153 : COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
     946         153 :   Res = PE32PlusHeader;
     947         153 :   return std::error_code();
     948             : }
     949             : 
     950             : std::error_code
     951       11830 : COFFObjectFile::getDataDirectory(uint32_t Index,
     952             :                                  const data_directory *&Res) const {
     953             :   // Error if there's no data directory or the index is out of range.
     954       11830 :   if (!DataDirectory) {
     955        8178 :     Res = nullptr;
     956        8178 :     return object_error::parse_failed;
     957             :   }
     958             :   assert(PE32Header || PE32PlusHeader);
     959        3652 :   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
     960        3652 :                                : PE32PlusHeader->NumberOfRvaAndSize;
     961        3652 :   if (Index >= NumEnt) {
     962           0 :     Res = nullptr;
     963           0 :     return object_error::parse_failed;
     964             :   }
     965        3652 :   Res = &DataDirectory[Index];
     966        3652 :   return std::error_code();
     967             : }
     968             : 
     969        6115 : std::error_code COFFObjectFile::getSection(int32_t Index,
     970             :                                            const coff_section *&Result) const {
     971        6115 :   Result = nullptr;
     972        6115 :   if (COFF::isReservedSectionNumber(Index))
     973          59 :     return std::error_code();
     974       12112 :   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
     975             :     // We already verified the section table data, so no need to check again.
     976        6056 :     Result = SectionTable + (Index - 1);
     977        6056 :     return std::error_code();
     978             :   }
     979           0 :   return object_error::parse_failed;
     980             : }
     981             : 
     982        2487 : std::error_code COFFObjectFile::getString(uint32_t Offset,
     983             :                                           StringRef &Result) const {
     984        2487 :   if (StringTableSize <= 4)
     985             :     // Tried to get a string from an empty string table.
     986           0 :     return object_error::parse_failed;
     987        2487 :   if (Offset >= StringTableSize)
     988           0 :     return object_error::unexpected_eof;
     989        4974 :   Result = StringRef(StringTable + Offset);
     990        2487 :   return std::error_code();
     991             : }
     992             : 
     993        4621 : std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
     994             :                                               StringRef &Res) const {
     995        4621 :   return getSymbolName(Symbol.getGeneric(), Res);
     996             : }
     997             : 
     998        4882 : std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
     999             :                                               StringRef &Res) const {
    1000             :   // Check for string table entry. First 4 bytes are 0.
    1001        4882 :   if (Symbol->Name.Offset.Zeroes == 0) {
    1002        1994 :     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
    1003           0 :       return EC;
    1004        1994 :     return std::error_code();
    1005             :   }
    1006             : 
    1007        2888 :   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
    1008             :     // Null terminated, let ::strlen figure out the length.
    1009        4556 :     Res = StringRef(Symbol->Name.ShortName);
    1010             :   else
    1011             :     // Not null terminated, use all 8 bytes.
    1012         610 :     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
    1013        2888 :   return std::error_code();
    1014             : }
    1015             : 
    1016             : ArrayRef<uint8_t>
    1017         347 : COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
    1018             :   const uint8_t *Aux = nullptr;
    1019             : 
    1020         347 :   size_t SymbolSize = getSymbolTableEntrySize();
    1021         347 :   if (Symbol.getNumberOfAuxSymbols() > 0) {
    1022             :     // AUX data comes immediately after the symbol in COFF
    1023         347 :     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
    1024             : #ifndef NDEBUG
    1025             :     // Verify that the Aux symbol points to a valid entry in the symbol table.
    1026             :     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
    1027             :     if (Offset < getPointerToSymbolTable() ||
    1028             :         Offset >=
    1029             :             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
    1030             :       report_fatal_error("Aux Symbol data was outside of symbol table.");
    1031             : 
    1032             :     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
    1033             :            "Aux Symbol data did not point to the beginning of a symbol");
    1034             : #endif
    1035             :   }
    1036         347 :   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
    1037             : }
    1038             : 
    1039        7794 : std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
    1040             :                                                StringRef &Res) const {
    1041        7794 :   StringRef Name;
    1042        7794 :   if (Sec->Name[COFF::NameSize - 1] == 0)
    1043             :     // Null terminated, let ::strlen figure out the length.
    1044       10366 :     Name = Sec->Name;
    1045             :   else
    1046             :     // Not null terminated, use all 8 bytes.
    1047        2611 :     Name = StringRef(Sec->Name, COFF::NameSize);
    1048             : 
    1049             :   // Check for string table entry. First byte is '/'.
    1050             :   if (Name.startswith("/")) {
    1051             :     uint32_t Offset;
    1052             :     if (Name.startswith("//")) {
    1053           1 :       if (decodeBase64StringEntry(Name.substr(2), Offset))
    1054           0 :         return object_error::parse_failed;
    1055             :     } else {
    1056         984 :       if (Name.substr(1).getAsInteger(10, Offset))
    1057           0 :         return object_error::parse_failed;
    1058             :     }
    1059         493 :     if (std::error_code EC = getString(Offset, Name))
    1060           0 :       return EC;
    1061             :   }
    1062             : 
    1063        7794 :   Res = Name;
    1064        7794 :   return std::error_code();
    1065             : }
    1066             : 
    1067      152993 : uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
    1068             :   // SizeOfRawData and VirtualSize change what they represent depending on
    1069             :   // whether or not we have an executable image.
    1070             :   //
    1071             :   // For object files, SizeOfRawData contains the size of section's data;
    1072             :   // VirtualSize should be zero but isn't due to buggy COFF writers.
    1073             :   //
    1074             :   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
    1075             :   // actual section size is in VirtualSize.  It is possible for VirtualSize to
    1076             :   // be greater than SizeOfRawData; the contents past that point should be
    1077             :   // considered to be zero.
    1078      150225 :   if (getDOSHeader())
    1079      300450 :     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
    1080        2768 :   return Sec->SizeOfRawData;
    1081             : }
    1082             : 
    1083             : std::error_code
    1084        2511 : COFFObjectFile::getSectionContents(const coff_section *Sec,
    1085             :                                    ArrayRef<uint8_t> &Res) const {
    1086             :   // In COFF, a virtual section won't have any in-file
    1087             :   // content, so the file pointer to the content will be zero.
    1088        2511 :   if (Sec->PointerToRawData == 0)
    1089          12 :     return std::error_code();
    1090             :   // The only thing that we need to verify is that the contents is contained
    1091             :   // within the file bounds. We don't need to make sure it doesn't cover other
    1092             :   // data, as there's nothing that says that is not allowed.
    1093        2499 :   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
    1094        2499 :   uint32_t SectionSize = getSectionSize(Sec);
    1095        2499 :   if (checkOffset(Data, ConStart, SectionSize))
    1096           0 :     return object_error::parse_failed;
    1097        2499 :   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
    1098        2499 :   return std::error_code();
    1099             : }
    1100             : 
    1101       16843 : const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
    1102       16843 :   return reinterpret_cast<const coff_relocation*>(Rel.p);
    1103             : }
    1104             : 
    1105        2634 : void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
    1106        2634 :   Rel.p = reinterpret_cast<uintptr_t>(
    1107        2634 :             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
    1108        2634 : }
    1109             : 
    1110       14500 : uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
    1111       14500 :   const coff_relocation *R = toRel(Rel);
    1112       14500 :   return R->VirtualAddress;
    1113             : }
    1114             : 
    1115        1396 : symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
    1116        1396 :   const coff_relocation *R = toRel(Rel);
    1117             :   DataRefImpl Ref;
    1118        1396 :   if (R->SymbolTableIndex >= getNumberOfSymbols())
    1119           2 :     return symbol_end();
    1120        1394 :   if (SymbolTable16)
    1121        1394 :     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
    1122           0 :   else if (SymbolTable32)
    1123           0 :     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
    1124             :   else
    1125           0 :     llvm_unreachable("no symbol table pointer!");
    1126        2788 :   return symbol_iterator(SymbolRef(Ref, this));
    1127             : }
    1128             : 
    1129         512 : uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
    1130         512 :   const coff_relocation* R = toRel(Rel);
    1131         512 :   return R->Type;
    1132             : }
    1133             : 
    1134             : const coff_section *
    1135        8925 : COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
    1136        8925 :   return toSec(Section.getRawDataRefImpl());
    1137             : }
    1138             : 
    1139       13227 : COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
    1140       13227 :   if (SymbolTable16)
    1141       13223 :     return toSymb<coff_symbol16>(Ref);
    1142           4 :   if (SymbolTable32)
    1143           4 :     return toSymb<coff_symbol32>(Ref);
    1144           0 :   llvm_unreachable("no symbol table pointer!");
    1145             : }
    1146             : 
    1147         819 : COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
    1148         819 :   return getCOFFSymbol(Symbol.getRawDataRefImpl());
    1149             : }
    1150             : 
    1151             : const coff_relocation *
    1152          60 : COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
    1153          60 :   return toRel(Reloc.getRawDataRefImpl());
    1154             : }
    1155             : 
    1156             : ArrayRef<coff_relocation>
    1157        1508 : COFFObjectFile::getRelocations(const coff_section *Sec) const {
    1158             :   return {getFirstReloc(Sec, Data, base()),
    1159        3016 :           getNumberOfRelocations(Sec, Data, base())};
    1160             : }
    1161             : 
    1162             : #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
    1163             :   case COFF::reloc_type:                                                       \
    1164             :     Res = #reloc_type;                                                         \
    1165             :     break;
    1166             : 
    1167         375 : void COFFObjectFile::getRelocationTypeName(
    1168             :     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
    1169         375 :   const coff_relocation *Reloc = toRel(Rel);
    1170             :   StringRef Res;
    1171         750 :   switch (getMachine()) {
    1172         145 :   case COFF::IMAGE_FILE_MACHINE_AMD64:
    1173         145 :     switch (Reloc->Type) {
    1174             :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
    1175           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
    1176           6 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
    1177          53 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
    1178          28 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
    1179           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
    1180           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
    1181           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
    1182           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
    1183           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
    1184          21 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
    1185          24 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
    1186           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
    1187           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
    1188           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
    1189           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
    1190           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
    1191             :     default:
    1192             :       Res = "Unknown";
    1193             :     }
    1194             :     break;
    1195          32 :   case COFF::IMAGE_FILE_MACHINE_ARMNT:
    1196          32 :     switch (Reloc->Type) {
    1197             :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
    1198           5 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
    1199           9 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
    1200           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
    1201           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
    1202           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
    1203           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
    1204           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
    1205           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
    1206          11 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
    1207           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
    1208           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
    1209           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
    1210           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
    1211           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
    1212             :     default:
    1213             :       Res = "Unknown";
    1214             :     }
    1215             :     break;
    1216          31 :   case COFF::IMAGE_FILE_MACHINE_ARM64:
    1217          31 :     switch (Reloc->Type) {
    1218             :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
    1219           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
    1220          12 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
    1221           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
    1222           3 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
    1223           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
    1224           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
    1225           3 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
    1226           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
    1227           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
    1228           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
    1229           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
    1230           0 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
    1231           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
    1232           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
    1233           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
    1234           1 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
    1235             :     default:
    1236             :       Res = "Unknown";
    1237             :     }
    1238             :     break;
    1239         167 :   case COFF::IMAGE_FILE_MACHINE_I386:
    1240         167 :     switch (Reloc->Type) {
    1241             :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
    1242           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
    1243           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
    1244          37 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
    1245          21 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
    1246           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
    1247          27 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
    1248          35 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
    1249           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
    1250           2 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
    1251          34 :     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
    1252             :     default:
    1253             :       Res = "Unknown";
    1254             :     }
    1255             :     break;
    1256             :   default:
    1257             :     Res = "Unknown";
    1258             :   }
    1259         375 :   Result.append(Res.begin(), Res.end());
    1260         375 : }
    1261             : 
    1262             : #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
    1263             : 
    1264       27891 : bool COFFObjectFile::isRelocatableObject() const {
    1265       27891 :   return !DataDirectory;
    1266             : }
    1267             : 
    1268          65 : bool ImportDirectoryEntryRef::
    1269             : operator==(const ImportDirectoryEntryRef &Other) const {
    1270          65 :   return ImportTable == Other.ImportTable && Index == Other.Index;
    1271             : }
    1272             : 
    1273          21 : void ImportDirectoryEntryRef::moveNext() {
    1274          21 :   ++Index;
    1275          21 :   if (ImportTable[Index].isNull()) {
    1276          14 :     Index = -1;
    1277          14 :     ImportTable = nullptr;
    1278             :   }
    1279          21 : }
    1280             : 
    1281           4 : std::error_code ImportDirectoryEntryRef::getImportTableEntry(
    1282             :     const coff_import_directory_table_entry *&Result) const {
    1283           4 :   return getObject(Result, OwningObject->Data, ImportTable + Index);
    1284             : }
    1285             : 
    1286             : static imported_symbol_iterator
    1287             : makeImportedSymbolIterator(const COFFObjectFile *Object,
    1288             :                            uintptr_t Ptr, int Index) {
    1289          50 :   if (Object->getBytesInAddress() == 4) {
    1290          24 :     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
    1291          12 :     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
    1292             :   }
    1293          26 :   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
    1294          13 :   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
    1295             : }
    1296             : 
    1297             : static imported_symbol_iterator
    1298          25 : importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
    1299          25 :   uintptr_t IntPtr = 0;
    1300          25 :   Object->getRvaPtr(RVA, IntPtr);
    1301          50 :   return makeImportedSymbolIterator(Object, IntPtr, 0);
    1302             : }
    1303             : 
    1304             : static imported_symbol_iterator
    1305          25 : importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
    1306          25 :   uintptr_t IntPtr = 0;
    1307          25 :   Object->getRvaPtr(RVA, IntPtr);
    1308             :   // Forward the pointer to the last entry which is null.
    1309             :   int Index = 0;
    1310          25 :   if (Object->getBytesInAddress() == 4) {
    1311          12 :     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
    1312         288 :     while (*Entry++)
    1313          88 :       ++Index;
    1314             :   } else {
    1315          13 :     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
    1316         122 :     while (*Entry++)
    1317          32 :       ++Index;
    1318             :   }
    1319          50 :   return makeImportedSymbolIterator(Object, IntPtr, Index);
    1320             : }
    1321             : 
    1322             : imported_symbol_iterator
    1323           4 : ImportDirectoryEntryRef::imported_symbol_begin() const {
    1324           4 :   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
    1325           8 :                              OwningObject);
    1326             : }
    1327             : 
    1328             : imported_symbol_iterator
    1329           4 : ImportDirectoryEntryRef::imported_symbol_end() const {
    1330           4 :   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
    1331           8 :                            OwningObject);
    1332             : }
    1333             : 
    1334             : iterator_range<imported_symbol_iterator>
    1335           4 : ImportDirectoryEntryRef::imported_symbols() const {
    1336           8 :   return make_range(imported_symbol_begin(), imported_symbol_end());
    1337             : }
    1338             : 
    1339          16 : imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
    1340          16 :   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
    1341          32 :                              OwningObject);
    1342             : }
    1343             : 
    1344          16 : imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
    1345          16 :   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
    1346          32 :                            OwningObject);
    1347             : }
    1348             : 
    1349             : iterator_range<imported_symbol_iterator>
    1350          16 : ImportDirectoryEntryRef::lookup_table_symbols() const {
    1351          32 :   return make_range(lookup_table_begin(), lookup_table_end());
    1352             : }
    1353             : 
    1354          21 : std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
    1355          21 :   uintptr_t IntPtr = 0;
    1356          21 :   if (std::error_code EC =
    1357          42 :           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
    1358           0 :     return EC;
    1359          42 :   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
    1360          21 :   return std::error_code();
    1361             : }
    1362             : 
    1363             : std::error_code
    1364          16 : ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
    1365          32 :   Result = ImportTable[Index].ImportLookupTableRVA;
    1366          16 :   return std::error_code();
    1367             : }
    1368             : 
    1369             : std::error_code
    1370          16 : ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
    1371          32 :   Result = ImportTable[Index].ImportAddressTableRVA;
    1372          16 :   return std::error_code();
    1373             : }
    1374             : 
    1375          21 : bool DelayImportDirectoryEntryRef::
    1376             : operator==(const DelayImportDirectoryEntryRef &Other) const {
    1377          21 :   return Table == Other.Table && Index == Other.Index;
    1378             : }
    1379             : 
    1380           5 : void DelayImportDirectoryEntryRef::moveNext() {
    1381           5 :   ++Index;
    1382           5 : }
    1383             : 
    1384             : imported_symbol_iterator
    1385           5 : DelayImportDirectoryEntryRef::imported_symbol_begin() const {
    1386           5 :   return importedSymbolBegin(Table[Index].DelayImportNameTable,
    1387          10 :                              OwningObject);
    1388             : }
    1389             : 
    1390             : imported_symbol_iterator
    1391           5 : DelayImportDirectoryEntryRef::imported_symbol_end() const {
    1392           5 :   return importedSymbolEnd(Table[Index].DelayImportNameTable,
    1393          10 :                            OwningObject);
    1394             : }
    1395             : 
    1396             : iterator_range<imported_symbol_iterator>
    1397           5 : DelayImportDirectoryEntryRef::imported_symbols() const {
    1398          10 :   return make_range(imported_symbol_begin(), imported_symbol_end());
    1399             : }
    1400             : 
    1401           5 : std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
    1402           5 :   uintptr_t IntPtr = 0;
    1403          10 :   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
    1404           0 :     return EC;
    1405          10 :   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
    1406           5 :   return std::error_code();
    1407             : }
    1408             : 
    1409           5 : std::error_code DelayImportDirectoryEntryRef::
    1410             : getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
    1411           5 :   Result = Table;
    1412           5 :   return std::error_code();
    1413             : }
    1414             : 
    1415          10 : std::error_code DelayImportDirectoryEntryRef::
    1416             : getImportAddress(int AddrIndex, uint64_t &Result) const {
    1417          10 :   uint32_t RVA = Table[Index].DelayImportAddressTable +
    1418          10 :       AddrIndex * (OwningObject->is64() ? 8 : 4);
    1419          10 :   uintptr_t IntPtr = 0;
    1420          10 :   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
    1421           0 :     return EC;
    1422          10 :   if (OwningObject->is64())
    1423          10 :     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
    1424             :   else
    1425          10 :     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
    1426          10 :   return std::error_code();
    1427             : }
    1428             : 
    1429         767 : bool ExportDirectoryEntryRef::
    1430             : operator==(const ExportDirectoryEntryRef &Other) const {
    1431         767 :   return ExportTable == Other.ExportTable && Index == Other.Index;
    1432             : }
    1433             : 
    1434         639 : void ExportDirectoryEntryRef::moveNext() {
    1435         639 :   ++Index;
    1436         639 : }
    1437             : 
    1438             : // Returns the name of the current export symbol. If the symbol is exported only
    1439             : // by ordinal, the empty string is set as a result.
    1440          22 : std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
    1441          22 :   uintptr_t IntPtr = 0;
    1442          22 :   if (std::error_code EC =
    1443          44 :           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
    1444           0 :     return EC;
    1445          44 :   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
    1446          22 :   return std::error_code();
    1447             : }
    1448             : 
    1449             : // Returns the starting ordinal number.
    1450             : std::error_code
    1451          22 : ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
    1452          44 :   Result = ExportTable->OrdinalBase;
    1453          22 :   return std::error_code();
    1454             : }
    1455             : 
    1456             : // Returns the export ordinal of the current export symbol.
    1457         149 : std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
    1458         298 :   Result = ExportTable->OrdinalBase + Index;
    1459         149 :   return std::error_code();
    1460             : }
    1461             : 
    1462             : // Returns the address of the current export symbol.
    1463         743 : std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
    1464         743 :   uintptr_t IntPtr = 0;
    1465         743 :   if (std::error_code EC =
    1466        1486 :           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
    1467           0 :     return EC;
    1468         743 :   const export_address_table_entry *entry =
    1469             :       reinterpret_cast<const export_address_table_entry *>(IntPtr);
    1470        1486 :   Result = entry[Index].ExportRVA;
    1471         743 :   return std::error_code();
    1472             : }
    1473             : 
    1474             : // Returns the name of the current export symbol. If the symbol is exported only
    1475             : // by ordinal, the empty string is set as a result.
    1476             : std::error_code
    1477         639 : ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
    1478         639 :   uintptr_t IntPtr = 0;
    1479         639 :   if (std::error_code EC =
    1480        1278 :           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
    1481           0 :     return EC;
    1482         639 :   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
    1483             : 
    1484         639 :   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
    1485             :   int Offset = 0;
    1486       60185 :   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
    1487       60185 :        I < E; ++I, ++Offset) {
    1488       60132 :     if (*I != Index)
    1489             :       continue;
    1490         586 :     if (std::error_code EC =
    1491        1172 :             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
    1492           0 :       return EC;
    1493         586 :     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
    1494        1172 :     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
    1495           0 :       return EC;
    1496        1172 :     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
    1497         586 :     return std::error_code();
    1498             :   }
    1499          53 :   Result = "";
    1500          53 :   return std::error_code();
    1501             : }
    1502             : 
    1503         102 : std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
    1504             :   const data_directory *DataEntry;
    1505         102 :   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
    1506           0 :     return EC;
    1507             :   uint32_t RVA;
    1508         102 :   if (auto EC = getExportRVA(RVA))
    1509           0 :     return EC;
    1510         102 :   uint32_t Begin = DataEntry->RelativeVirtualAddress;
    1511         102 :   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
    1512         102 :   Result = (Begin <= RVA && RVA < End);
    1513         102 :   return std::error_code();
    1514             : }
    1515             : 
    1516           2 : std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
    1517             :   uint32_t RVA;
    1518           2 :   if (auto EC = getExportRVA(RVA))
    1519           0 :     return EC;
    1520           2 :   uintptr_t IntPtr = 0;
    1521           2 :   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
    1522           0 :     return EC;
    1523           4 :   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
    1524           2 :   return std::error_code();
    1525             : }
    1526             : 
    1527         145 : bool ImportedSymbolRef::
    1528             : operator==(const ImportedSymbolRef &Other) const {
    1529         290 :   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
    1530         290 :       && Index == Other.Index;
    1531             : }
    1532             : 
    1533         120 : void ImportedSymbolRef::moveNext() {
    1534         120 :   ++Index;
    1535         120 : }
    1536             : 
    1537             : std::error_code
    1538          50 : ImportedSymbolRef::getSymbolName(StringRef &Result) const {
    1539             :   uint32_t RVA;
    1540          50 :   if (Entry32) {
    1541             :     // If a symbol is imported only by ordinal, it has no name.
    1542          36 :     if (Entry32[Index].isOrdinal())
    1543           1 :       return std::error_code();
    1544             :     RVA = Entry32[Index].getHintNameRVA();
    1545             :   } else {
    1546          64 :     if (Entry64[Index].isOrdinal())
    1547           5 :       return std::error_code();
    1548             :     RVA = Entry64[Index].getHintNameRVA();
    1549             :   }
    1550          44 :   uintptr_t IntPtr = 0;
    1551          44 :   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
    1552           0 :     return EC;
    1553             :   // +2 because the first two bytes is hint.
    1554          88 :   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
    1555          44 :   return std::error_code();
    1556             : }
    1557             : 
    1558          70 : std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
    1559          70 :   if (Entry32)
    1560         140 :     Result = Entry32[Index].isOrdinal();
    1561             :   else
    1562           0 :     Result = Entry64[Index].isOrdinal();
    1563          70 :   return std::error_code();
    1564             : }
    1565             : 
    1566          70 : std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
    1567          70 :   if (Entry32)
    1568         140 :     Result = Entry32[Index].getHintNameRVA();
    1569             :   else
    1570           0 :     Result = Entry64[Index].getHintNameRVA();
    1571          70 :   return std::error_code();
    1572             : }
    1573             : 
    1574          50 : std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
    1575             :   uint32_t RVA;
    1576          50 :   if (Entry32) {
    1577          36 :     if (Entry32[Index].isOrdinal()) {
    1578           1 :       Result = Entry32[Index].getOrdinal();
    1579           1 :       return std::error_code();
    1580             :     }
    1581             :     RVA = Entry32[Index].getHintNameRVA();
    1582             :   } else {
    1583          64 :     if (Entry64[Index].isOrdinal()) {
    1584           5 :       Result = Entry64[Index].getOrdinal();
    1585           5 :       return std::error_code();
    1586             :     }
    1587             :     RVA = Entry64[Index].getHintNameRVA();
    1588             :   }
    1589          44 :   uintptr_t IntPtr = 0;
    1590          44 :   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
    1591           0 :     return EC;
    1592          88 :   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
    1593          44 :   return std::error_code();
    1594             : }
    1595             : 
    1596             : Expected<std::unique_ptr<COFFObjectFile>>
    1597        1659 : ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
    1598             :   std::error_code EC;
    1599        1659 :   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
    1600        1659 :   if (EC)
    1601           0 :     return errorCodeToError(EC);
    1602             :   return std::move(Ret);
    1603             : }
    1604             : 
    1605         113 : bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
    1606         113 :   return Header == Other.Header && Index == Other.Index;
    1607             : }
    1608             : 
    1609         100 : void BaseRelocRef::moveNext() {
    1610             :   // Header->BlockSize is the size of the current block, including the
    1611             :   // size of the header itself.
    1612         100 :   uint32_t Size = sizeof(*Header) +
    1613         100 :       sizeof(coff_base_reloc_block_entry) * (Index + 1);
    1614         200 :   if (Size == Header->BlockSize) {
    1615             :     // .reloc contains a list of base relocation blocks. Each block
    1616             :     // consists of the header followed by entries. The header contains
    1617             :     // how many entories will follow. When we reach the end of the
    1618             :     // current block, proceed to the next block.
    1619          15 :     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
    1620             :         reinterpret_cast<const uint8_t *>(Header) + Size);
    1621          15 :     Index = 0;
    1622             :   } else {
    1623          85 :     ++Index;
    1624             :   }
    1625         100 : }
    1626             : 
    1627         100 : std::error_code BaseRelocRef::getType(uint8_t &Type) const {
    1628         100 :   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
    1629         200 :   Type = Entry[Index].getType();
    1630         100 :   return std::error_code();
    1631             : }
    1632             : 
    1633         100 : std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
    1634         100 :   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
    1635         200 :   Result = Header->PageRVA + Entry[Index].getOffset();
    1636         100 :   return std::error_code();
    1637             : }
    1638             : 
    1639             : #define RETURN_IF_ERROR(E)                                                     \
    1640             :   if (E)                                                                       \
    1641             :     return E;
    1642             : 
    1643             : Expected<ArrayRef<UTF16>>
    1644          28 : ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
    1645          28 :   BinaryStreamReader Reader = BinaryStreamReader(BBS);
    1646             :   Reader.setOffset(Offset);
    1647             :   uint16_t Length;
    1648          56 :   RETURN_IF_ERROR(Reader.readInteger(Length));
    1649          28 :   ArrayRef<UTF16> RawDirString;
    1650          56 :   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
    1651             :   return RawDirString;
    1652             : }
    1653             : 
    1654             : Expected<ArrayRef<UTF16>>
    1655          28 : ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
    1656          28 :   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
    1657             : }
    1658             : 
    1659             : Expected<const coff_resource_dir_table &>
    1660         126 : ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
    1661         126 :   const coff_resource_dir_table *Table = nullptr;
    1662             : 
    1663         126 :   BinaryStreamReader Reader(BBS);
    1664             :   Reader.setOffset(Offset);
    1665         252 :   RETURN_IF_ERROR(Reader.readObject(Table));
    1666             :   assert(Table != nullptr);
    1667         126 :   return *Table;
    1668             : }
    1669             : 
    1670             : Expected<const coff_resource_dir_table &>
    1671         120 : ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
    1672         120 :   return getTableAtOffset(Entry.Offset.value());
    1673             : }
    1674             : 
    1675           6 : Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
    1676           6 :   return getTableAtOffset(0);
    1677             : }

Generated by: LCOV version 1.13