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

Generated by: LCOV version 1.13