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

Generated by: LCOV version 1.13