brintos

brintos / llvm-project-archived public Read only

0
0
Text · 84.8 KiB · 242c123 Raw
2402 lines · cpp
1//===- COFFObjectFile.cpp - COFF object file implementation ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file declares the COFFObjectFile class.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/StringSwitch.h"16#include "llvm/ADT/iterator_range.h"17#include "llvm/Object/Binary.h"18#include "llvm/Object/COFF.h"19#include "llvm/Object/Error.h"20#include "llvm/Object/ObjectFile.h"21#include "llvm/Object/WindowsMachineFlag.h"22#include "llvm/Support/BinaryStreamReader.h"23#include "llvm/Support/Endian.h"24#include "llvm/Support/Error.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/Support/MathExtras.h"27#include "llvm/Support/MemoryBufferRef.h"28#include <algorithm>29#include <cassert>30#include <cinttypes>31#include <cstddef>32#include <cstring>33#include <limits>34#include <memory>35#include <system_error>36 37using namespace llvm;38using namespace object;39 40using support::ulittle16_t;41using support::ulittle32_t;42using support::ulittle64_t;43using support::little16_t;44 45// Returns false if size is greater than the buffer size. And sets ec.46static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {47  if (M.getBufferSize() < Size) {48    EC = object_error::unexpected_eof;49    return false;50  }51  return true;52}53 54// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.55// Returns unexpected_eof if error.56template <typename T>57static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,58                       const uint64_t Size = sizeof(T)) {59  uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);60  if (Error E = Binary::checkOffset(M, Addr, Size))61    return E;62  Obj = reinterpret_cast<const T *>(Addr);63  return Error::success();64}65 66// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without67// prefixed slashes.68static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {69  assert(Str.size() <= 6 && "String too long, possible overflow.");70  if (Str.size() > 6)71    return true;72 73  uint64_t Value = 0;74  while (!Str.empty()) {75    unsigned CharVal;76    if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..2577      CharVal = Str[0] - 'A';78    else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..5179      CharVal = Str[0] - 'a' + 26;80    else if (Str[0] >= '0' && Str[0] <= '9') // 52..6181      CharVal = Str[0] - '0' + 52;82    else if (Str[0] == '+') // 6283      CharVal = 62;84    else if (Str[0] == '/') // 6385      CharVal = 63;86    else87      return true;88 89    Value = (Value * 64) + CharVal;90    Str = Str.substr(1);91  }92 93  if (Value > std::numeric_limits<uint32_t>::max())94    return true;95 96  Result = static_cast<uint32_t>(Value);97  return false;98}99 100template <typename coff_symbol_type>101const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {102  const coff_symbol_type *Addr =103      reinterpret_cast<const coff_symbol_type *>(Ref.p);104 105  assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr)));106#ifndef NDEBUG107  // Verify that the symbol points to a valid entry in the symbol table.108  uintptr_t Offset =109      reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base());110 111  assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&112         "Symbol did not point to the beginning of a symbol");113#endif114 115  return Addr;116}117 118const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {119  const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);120 121#ifndef NDEBUG122  // Verify that the section points to a valid entry in the section table.123  if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))124    report_fatal_error("Section was outside of section table.");125 126  uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -127                     reinterpret_cast<uintptr_t>(SectionTable);128  assert(Offset % sizeof(coff_section) == 0 &&129         "Section did not point to the beginning of a section");130#endif131 132  return Addr;133}134 135void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {136  auto End = reinterpret_cast<uintptr_t>(StringTable);137  if (SymbolTable16) {138    const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);139    Symb += 1 + Symb->NumberOfAuxSymbols;140    Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);141  } else if (SymbolTable32) {142    const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);143    Symb += 1 + Symb->NumberOfAuxSymbols;144    Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);145  } else {146    llvm_unreachable("no symbol table pointer!");147  }148}149 150Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {151  return getSymbolName(getCOFFSymbol(Ref));152}153 154uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {155  return getCOFFSymbol(Ref).getValue();156}157 158uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {159  // MSVC/link.exe seems to align symbols to the next-power-of-2160  // up to 32 bytes.161  COFFSymbolRef Symb = getCOFFSymbol(Ref);162  return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));163}164 165Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {166  uint64_t Result = cantFail(getSymbolValue(Ref));167  COFFSymbolRef Symb = getCOFFSymbol(Ref);168  int32_t SectionNumber = Symb.getSectionNumber();169 170  if (Symb.isAnyUndefined() || Symb.isCommon() ||171      COFF::isReservedSectionNumber(SectionNumber))172    return Result;173 174  Expected<const coff_section *> Section = getSection(SectionNumber);175  if (!Section)176    return Section.takeError();177  Result += (*Section)->VirtualAddress;178 179  // The section VirtualAddress does not include ImageBase, and we want to180  // return virtual addresses.181  Result += getImageBase();182 183  return Result;184}185 186Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {187  COFFSymbolRef Symb = getCOFFSymbol(Ref);188  int32_t SectionNumber = Symb.getSectionNumber();189 190  if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)191    return SymbolRef::ST_Function;192  if (Symb.isAnyUndefined())193    return SymbolRef::ST_Unknown;194  if (Symb.isCommon())195    return SymbolRef::ST_Data;196  if (Symb.isFileRecord())197    return SymbolRef::ST_File;198 199  // TODO: perhaps we need a new symbol type ST_Section.200  if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())201    return SymbolRef::ST_Debug;202 203  if (!COFF::isReservedSectionNumber(SectionNumber))204    return SymbolRef::ST_Data;205 206  return SymbolRef::ST_Other;207}208 209Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {210  COFFSymbolRef Symb = getCOFFSymbol(Ref);211  uint32_t Result = SymbolRef::SF_None;212 213  if (Symb.isExternal() || Symb.isWeakExternal())214    Result |= SymbolRef::SF_Global;215 216  if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {217    Result |= SymbolRef::SF_Weak;218    if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)219      Result |= SymbolRef::SF_Undefined;220  }221 222  if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)223    Result |= SymbolRef::SF_Absolute;224 225  if (Symb.isFileRecord())226    Result |= SymbolRef::SF_FormatSpecific;227 228  if (Symb.isSectionDefinition())229    Result |= SymbolRef::SF_FormatSpecific;230 231  if (Symb.isCommon())232    Result |= SymbolRef::SF_Common;233 234  if (Symb.isUndefined())235    Result |= SymbolRef::SF_Undefined;236 237  return Result;238}239 240uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {241  COFFSymbolRef Symb = getCOFFSymbol(Ref);242  return Symb.getValue();243}244 245Expected<section_iterator>246COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {247  COFFSymbolRef Symb = getCOFFSymbol(Ref);248  if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))249    return section_end();250  Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());251  if (!Sec)252    return Sec.takeError();253  DataRefImpl Ret;254  Ret.p = reinterpret_cast<uintptr_t>(*Sec);255  return section_iterator(SectionRef(Ret, this));256}257 258unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {259  COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());260  return Symb.getSectionNumber();261}262 263void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {264  const coff_section *Sec = toSec(Ref);265  Sec += 1;266  Ref.p = reinterpret_cast<uintptr_t>(Sec);267}268 269Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {270  const coff_section *Sec = toSec(Ref);271  return getSectionName(Sec);272}273 274uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {275  const coff_section *Sec = toSec(Ref);276  uint64_t Result = Sec->VirtualAddress;277 278  // The section VirtualAddress does not include ImageBase, and we want to279  // return virtual addresses.280  Result += getImageBase();281  return Result;282}283 284uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {285  return toSec(Sec) - SectionTable;286}287 288uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {289  return getSectionSize(toSec(Ref));290}291 292Expected<ArrayRef<uint8_t>>293COFFObjectFile::getSectionContents(DataRefImpl Ref) const {294  const coff_section *Sec = toSec(Ref);295  ArrayRef<uint8_t> Res;296  if (Error E = getSectionContents(Sec, Res))297    return E;298  return Res;299}300 301uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {302  const coff_section *Sec = toSec(Ref);303  return Sec->getAlignment();304}305 306bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {307  return false;308}309 310bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {311  const coff_section *Sec = toSec(Ref);312  return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;313}314 315bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {316  const coff_section *Sec = toSec(Ref);317  return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;318}319 320bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {321  const coff_section *Sec = toSec(Ref);322  const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |323                            COFF::IMAGE_SCN_MEM_READ |324                            COFF::IMAGE_SCN_MEM_WRITE;325  return (Sec->Characteristics & BssFlags) == BssFlags;326}327 328// The .debug sections are the only debug sections for COFF329// (\see MCObjectFileInfo.cpp).330bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {331  Expected<StringRef> SectionNameOrErr = getSectionName(Ref);332  if (!SectionNameOrErr) {333    // TODO: Report the error message properly.334    consumeError(SectionNameOrErr.takeError());335    return false;336  }337  StringRef SectionName = SectionNameOrErr.get();338  return SectionName.starts_with(".debug");339}340 341unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {342  uintptr_t Offset =343      Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);344  assert((Offset % sizeof(coff_section)) == 0);345  return (Offset / sizeof(coff_section)) + 1;346}347 348bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {349  const coff_section *Sec = toSec(Ref);350  // In COFF, a virtual section won't have any in-file351  // content, so the file pointer to the content will be zero.352  return Sec->PointerToRawData == 0;353}354 355static uint32_t getNumberOfRelocations(const coff_section *Sec,356                                       MemoryBufferRef M, const uint8_t *base) {357  // The field for the number of relocations in COFF section table is only358  // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to359  // NumberOfRelocations field, and the actual relocation count is stored in the360  // VirtualAddress field in the first relocation entry.361  if (Sec->hasExtendedRelocations()) {362    const coff_relocation *FirstReloc;363    if (Error E = getObject(FirstReloc, M,364                            reinterpret_cast<const coff_relocation *>(365                                base + Sec->PointerToRelocations))) {366      consumeError(std::move(E));367      return 0;368    }369    // -1 to exclude this first relocation entry.370    return FirstReloc->VirtualAddress - 1;371  }372  return Sec->NumberOfRelocations;373}374 375static const coff_relocation *376getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {377  uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);378  if (!NumRelocs)379    return nullptr;380  auto begin = reinterpret_cast<const coff_relocation *>(381      Base + Sec->PointerToRelocations);382  if (Sec->hasExtendedRelocations()) {383    // Skip the first relocation entry repurposed to store the number of384    // relocations.385    begin++;386  }387  if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),388                                   sizeof(coff_relocation) * NumRelocs)) {389    consumeError(std::move(E));390    return nullptr;391  }392  return begin;393}394 395relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {396  const coff_section *Sec = toSec(Ref);397  const coff_relocation *begin = getFirstReloc(Sec, Data, base());398  if (begin && Sec->VirtualAddress != 0)399    report_fatal_error("Sections with relocations should have an address of 0");400  DataRefImpl Ret;401  Ret.p = reinterpret_cast<uintptr_t>(begin);402  return relocation_iterator(RelocationRef(Ret, this));403}404 405relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {406  const coff_section *Sec = toSec(Ref);407  const coff_relocation *I = getFirstReloc(Sec, Data, base());408  if (I)409    I += getNumberOfRelocations(Sec, Data, base());410  DataRefImpl Ret;411  Ret.p = reinterpret_cast<uintptr_t>(I);412  return relocation_iterator(RelocationRef(Ret, this));413}414 415// Initialize the pointer to the symbol table.416Error COFFObjectFile::initSymbolTablePtr() {417  if (COFFHeader)418    if (Error E = getObject(419            SymbolTable16, Data, base() + getPointerToSymbolTable(),420            (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))421      return E;422 423  if (COFFBigObjHeader)424    if (Error E = getObject(425            SymbolTable32, Data, base() + getPointerToSymbolTable(),426            (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))427      return E;428 429  // Find string table. The first four byte of the string table contains the430  // total size of the string table, including the size field itself. If the431  // string table is empty, the value of the first four byte would be 4.432  uint32_t StringTableOffset = getPointerToSymbolTable() +433                               getNumberOfSymbols() * getSymbolTableEntrySize();434  const uint8_t *StringTableAddr = base() + StringTableOffset;435  const ulittle32_t *StringTableSizePtr;436  if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))437    return E;438  StringTableSize = *StringTableSizePtr;439  if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))440    return E;441 442  // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some443  // tools like cvtres write a size of 0 for an empty table instead of 4.444  if (StringTableSize < 4)445    StringTableSize = 4;446 447  // Check that the string table is null terminated if has any in it.448  if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)449    return createStringError(object_error::parse_failed,450                             "string table missing null terminator");451  return Error::success();452}453 454uint64_t COFFObjectFile::getImageBase() const {455  if (PE32Header)456    return PE32Header->ImageBase;457  else if (PE32PlusHeader)458    return PE32PlusHeader->ImageBase;459  // This actually comes up in practice.460  return 0;461}462 463// Returns the file offset for the given VA.464Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {465  uint64_t ImageBase = getImageBase();466  uint64_t Rva = Addr - ImageBase;467  assert(Rva <= UINT32_MAX);468  return getRvaPtr((uint32_t)Rva, Res);469}470 471// Returns the file offset for the given RVA.472Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,473                                const char *ErrorContext) const {474  for (const SectionRef &S : sections()) {475    const coff_section *Section = getCOFFSection(S);476    uint32_t SectionStart = Section->VirtualAddress;477    uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;478    if (SectionStart <= Addr && Addr < SectionEnd) {479      // A table/directory entry can be pointing to somewhere in a stripped480      // section, in an object that went through `objcopy --only-keep-debug`.481      // In this case we don't want to cause the parsing of the object file to482      // fail, otherwise it will be impossible to use this object as debug info483      // in LLDB. Return SectionStrippedError here so that484      // COFFObjectFile::initialize can ignore the error.485      // Somewhat common binaries may have RVAs pointing outside of the486      // provided raw data. Instead of rejecting the binaries, just487      // treat the section as stripped for these purposes.488      if (Section->SizeOfRawData < Section->VirtualSize &&489          Addr >= SectionStart + Section->SizeOfRawData) {490        return make_error<SectionStrippedError>();491      }492      uint32_t Offset = Addr - SectionStart;493      Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +494            Offset;495      return Error::success();496    }497  }498  if (ErrorContext)499    return createStringError(object_error::parse_failed,500                             "RVA 0x%" PRIx32 " for %s not found", Addr,501                             ErrorContext);502  return createStringError(object_error::parse_failed,503                           "RVA 0x%" PRIx32 " not found", Addr);504}505 506Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,507                                           ArrayRef<uint8_t> &Contents,508                                           const char *ErrorContext) const {509  for (const SectionRef &S : sections()) {510    const coff_section *Section = getCOFFSection(S);511    uint32_t SectionStart = Section->VirtualAddress;512    // Check if this RVA is within the section bounds. Be careful about integer513    // overflow.514    uint32_t OffsetIntoSection = RVA - SectionStart;515    if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&516        Size <= Section->VirtualSize - OffsetIntoSection) {517      uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +518                        Section->PointerToRawData + OffsetIntoSection;519      Contents =520          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);521      return Error::success();522    }523  }524  if (ErrorContext)525    return createStringError(object_error::parse_failed,526                             "RVA 0x%" PRIx32 " for %s not found", RVA,527                             ErrorContext);528  return createStringError(object_error::parse_failed,529                           "RVA 0x%" PRIx32 " not found", RVA);530}531 532// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name533// table entry.534Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,535                                  StringRef &Name) const {536  uintptr_t IntPtr = 0;537  if (Error E = getRvaPtr(Rva, IntPtr))538    return E;539  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);540  Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);541  Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));542  return Error::success();543}544 545Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,546                                      const codeview::DebugInfo *&PDBInfo,547                                      StringRef &PDBFileName) const {548  ArrayRef<uint8_t> InfoBytes;549  if (Error E =550          getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData,551                               InfoBytes, "PDB info"))552    return E;553  if (InfoBytes.size() < sizeof(*PDBInfo) + 1)554    return createStringError(object_error::parse_failed, "PDB info too small");555  PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());556  InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));557  PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),558                          InfoBytes.size());559  // Truncate the name at the first null byte. Ignore any padding.560  PDBFileName = PDBFileName.split('\0').first;561  return Error::success();562}563 564Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,565                                      StringRef &PDBFileName) const {566  for (const debug_directory &D : debug_directories())567    if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)568      return getDebugPDBInfo(&D, PDBInfo, PDBFileName);569  // If we get here, there is no PDB info to return.570  PDBInfo = nullptr;571  PDBFileName = StringRef();572  return Error::success();573}574 575// Find the import table.576Error COFFObjectFile::initImportTablePtr() {577  // First, we get the RVA of the import table. If the file lacks a pointer to578  // the import table, do nothing.579  const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);580  if (!DataEntry)581    return Error::success();582 583  // Do nothing if the pointer to import table is NULL.584  if (DataEntry->RelativeVirtualAddress == 0)585    return Error::success();586 587  uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;588 589  // Find the section that contains the RVA. This is needed because the RVA is590  // the import table's memory address which is different from its file offset.591  uintptr_t IntPtr = 0;592  if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table"))593    return E;594  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))595    return E;596  ImportDirectory = reinterpret_cast<597      const coff_import_directory_table_entry *>(IntPtr);598  return Error::success();599}600 601// Initializes DelayImportDirectory and NumberOfDelayImportDirectory.602Error COFFObjectFile::initDelayImportTablePtr() {603  const data_directory *DataEntry =604      getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);605  if (!DataEntry)606    return Error::success();607  if (DataEntry->RelativeVirtualAddress == 0)608    return Error::success();609 610  uint32_t RVA = DataEntry->RelativeVirtualAddress;611  NumberOfDelayImportDirectory = DataEntry->Size /612      sizeof(delay_import_directory_table_entry) - 1;613 614  uintptr_t IntPtr = 0;615  if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))616    return E;617  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))618    return E;619 620  DelayImportDirectory = reinterpret_cast<621      const delay_import_directory_table_entry *>(IntPtr);622  return Error::success();623}624 625// Find the export table.626Error COFFObjectFile::initExportTablePtr() {627  // First, we get the RVA of the export table. If the file lacks a pointer to628  // the export table, do nothing.629  const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);630  if (!DataEntry)631    return Error::success();632 633  // Do nothing if the pointer to export table is NULL.634  if (DataEntry->RelativeVirtualAddress == 0)635    return Error::success();636 637  uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;638  uintptr_t IntPtr = 0;639  if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))640    return E;641  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))642    return E;643 644  ExportDirectory =645      reinterpret_cast<const export_directory_table_entry *>(IntPtr);646  return Error::success();647}648 649Error COFFObjectFile::initBaseRelocPtr() {650  const data_directory *DataEntry =651      getDataDirectory(COFF::BASE_RELOCATION_TABLE);652  if (!DataEntry)653    return Error::success();654  if (DataEntry->RelativeVirtualAddress == 0)655    return Error::success();656 657  uintptr_t IntPtr = 0;658  if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,659                          "base reloc table"))660    return E;661  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))662    return E;663 664  BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(665      IntPtr);666  BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(667      IntPtr + DataEntry->Size);668  // FIXME: Verify the section containing BaseRelocHeader has at least669  // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.670  return Error::success();671}672 673Error COFFObjectFile::initDebugDirectoryPtr() {674  // Get the RVA of the debug directory. Do nothing if it does not exist.675  const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);676  if (!DataEntry)677    return Error::success();678 679  // Do nothing if the RVA is NULL.680  if (DataEntry->RelativeVirtualAddress == 0)681    return Error::success();682 683  // Check that the size is a multiple of the entry size.684  if (DataEntry->Size % sizeof(debug_directory) != 0)685    return createStringError(object_error::parse_failed,686                             "debug directory has uneven size");687 688  uintptr_t IntPtr = 0;689  if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,690                          "debug directory"))691    return E;692  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))693    return E;694 695  DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);696  DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(697      IntPtr + DataEntry->Size);698  // FIXME: Verify the section containing DebugDirectoryBegin has at least699  // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.700  return Error::success();701}702 703Error COFFObjectFile::initTLSDirectoryPtr() {704  // Get the RVA of the TLS directory. Do nothing if it does not exist.705  const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);706  if (!DataEntry)707    return Error::success();708 709  // Do nothing if the RVA is NULL.710  if (DataEntry->RelativeVirtualAddress == 0)711    return Error::success();712 713  uint64_t DirSize =714      is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);715 716  // Check that the size is correct.717  if (DataEntry->Size != DirSize)718    return createStringError(719        object_error::parse_failed,720        "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",721        static_cast<uint32_t>(DataEntry->Size), DirSize);722 723  uintptr_t IntPtr = 0;724  if (Error E =725          getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))726    return E;727  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))728    return E;729 730  if (is64())731    TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);732  else733    TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);734 735  return Error::success();736}737 738Error COFFObjectFile::initLoadConfigPtr() {739  // Get the RVA of the debug directory. Do nothing if it does not exist.740  const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);741  if (!DataEntry)742    return Error::success();743 744  // Do nothing if the RVA is NULL.745  if (DataEntry->RelativeVirtualAddress == 0)746    return Error::success();747  uintptr_t IntPtr = 0;748  if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,749                          "load config table"))750    return E;751  if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))752    return E;753 754  LoadConfig = (const void *)IntPtr;755 756  if (is64()) {757    auto Config = getLoadConfig64();758    if (Config->Size >=759            offsetof(coff_load_configuration64, CHPEMetadataPointer) +760                sizeof(Config->CHPEMetadataPointer) &&761        Config->CHPEMetadataPointer) {762      uint64_t ChpeOff = Config->CHPEMetadataPointer;763      if (Error E =764              getRvaPtr(ChpeOff - getImageBase(), IntPtr, "CHPE metadata"))765        return E;766      if (Error E = checkOffset(Data, IntPtr, sizeof(*CHPEMetadata)))767        return E;768 769      CHPEMetadata = reinterpret_cast<const chpe_metadata *>(IntPtr);770 771      // Validate CHPE metadata772      if (CHPEMetadata->CodeMapCount) {773        if (Error E = getRvaPtr(CHPEMetadata->CodeMap, IntPtr, "CHPE code map"))774          return E;775        if (Error E = checkOffset(Data, IntPtr,776                                  CHPEMetadata->CodeMapCount *777                                      sizeof(chpe_range_entry)))778          return E;779      }780 781      if (CHPEMetadata->CodeRangesToEntryPointsCount) {782        if (Error E = getRvaPtr(CHPEMetadata->CodeRangesToEntryPoints, IntPtr,783                                "CHPE entry point ranges"))784          return E;785        if (Error E = checkOffset(Data, IntPtr,786                                  CHPEMetadata->CodeRangesToEntryPointsCount *787                                      sizeof(chpe_code_range_entry)))788          return E;789      }790 791      if (CHPEMetadata->RedirectionMetadataCount) {792        if (Error E = getRvaPtr(CHPEMetadata->RedirectionMetadata, IntPtr,793                                "CHPE redirection metadata"))794          return E;795        if (Error E = checkOffset(Data, IntPtr,796                                  CHPEMetadata->RedirectionMetadataCount *797                                      sizeof(chpe_redirection_entry)))798          return E;799      }800    }801 802    if (Config->Size >=803        offsetof(coff_load_configuration64, DynamicValueRelocTableSection) +804            sizeof(Config->DynamicValueRelocTableSection))805      if (Error E = initDynamicRelocPtr(Config->DynamicValueRelocTableSection,806                                        Config->DynamicValueRelocTableOffset))807        return E;808  } else {809    auto Config = getLoadConfig32();810    if (Config->Size >=811        offsetof(coff_load_configuration32, DynamicValueRelocTableSection) +812            sizeof(Config->DynamicValueRelocTableSection)) {813      if (Error E = initDynamicRelocPtr(Config->DynamicValueRelocTableSection,814                                        Config->DynamicValueRelocTableOffset))815        return E;816    }817  }818  return Error::success();819}820 821Error COFFObjectFile::initDynamicRelocPtr(uint32_t SectionIndex,822                                          uint32_t SectionOffset) {823  Expected<const coff_section *> Section = getSection(SectionIndex);824  if (!Section)825    return Section.takeError();826  if (!*Section)827    return Error::success();828 829  // Interpret and validate dynamic relocations.830  ArrayRef<uint8_t> Contents;831  if (Error E = getSectionContents(*Section, Contents))832    return E;833 834  Contents = Contents.drop_front(SectionOffset);835  if (Contents.size() < sizeof(coff_dynamic_reloc_table))836    return createStringError(object_error::parse_failed,837                             "Too large DynamicValueRelocTableOffset (" +838                                 Twine(SectionOffset) + ")");839 840  DynamicRelocTable =841      reinterpret_cast<const coff_dynamic_reloc_table *>(Contents.data());842 843  if (DynamicRelocTable->Version != 1 && DynamicRelocTable->Version != 2)844    return createStringError(object_error::parse_failed,845                             "Unsupported dynamic relocations table version (" +846                                 Twine(DynamicRelocTable->Version) + ")");847  if (DynamicRelocTable->Size > Contents.size() - sizeof(*DynamicRelocTable))848    return createStringError(object_error::parse_failed,849                             "Indvalid dynamic relocations directory size (" +850                                 Twine(DynamicRelocTable->Size) + ")");851 852  for (auto DynReloc : dynamic_relocs()) {853    if (Error e = DynReloc.validate())854      return e;855  }856 857  return Error::success();858}859 860Expected<std::unique_ptr<COFFObjectFile>>861COFFObjectFile::create(MemoryBufferRef Object) {862  std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));863  if (Error E = Obj->initialize())864    return E;865  return std::move(Obj);866}867 868COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)869    : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),870      COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),871      DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),872      SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),873      ImportDirectory(nullptr), DelayImportDirectory(nullptr),874      NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),875      BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),876      DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),877      TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}878 879static Error ignoreStrippedErrors(Error E) {880  if (E.isA<SectionStrippedError>()) {881    consumeError(std::move(E));882    return Error::success();883  }884  return E;885}886 887Error COFFObjectFile::initialize() {888  // Check that we at least have enough room for a header.889  std::error_code EC;890  if (!checkSize(Data, EC, sizeof(coff_file_header)))891    return errorCodeToError(EC);892 893  // The current location in the file where we are looking at.894  uint64_t CurPtr = 0;895 896  // PE header is optional and is present only in executables. If it exists,897  // it is placed right after COFF header.898  bool HasPEHeader = false;899 900  // Check if this is a PE/COFF file.901  if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {902    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte903    // PE signature to find 'normal' COFF header.904    const auto *DH = reinterpret_cast<const dos_header *>(base());905    if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {906      CurPtr = DH->AddressOfNewExeHeader;907      // Check the PE magic bytes. ("PE\0\0")908      if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {909        return createStringError(object_error::parse_failed,910                                 "incorrect PE magic");911      }912      CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.913      HasPEHeader = true;914    }915  }916 917  if (Error E = getObject(COFFHeader, Data, base() + CurPtr))918    return E;919 920  // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF921  // import libraries share a common prefix but bigobj is more restrictive.922  if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&923      COFFHeader->NumberOfSections == uint16_t(0xffff) &&924      checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {925    if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))926      return E;927 928    // Verify that we are dealing with bigobj.929    if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&930        std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,931                    sizeof(COFF::BigObjMagic)) == 0) {932      COFFHeader = nullptr;933      CurPtr += sizeof(coff_bigobj_file_header);934    } else {935      // It's not a bigobj.936      COFFBigObjHeader = nullptr;937    }938  }939  if (COFFHeader) {940    // The prior checkSize call may have failed.  This isn't a hard error941    // because we were just trying to sniff out bigobj.942    EC = std::error_code();943    CurPtr += sizeof(coff_file_header);944 945    if (COFFHeader->isImportLibrary())946      return errorCodeToError(EC);947  }948 949  if (HasPEHeader) {950    const pe32_header *Header;951    if (Error E = getObject(Header, Data, base() + CurPtr))952      return E;953 954    const uint8_t *DataDirAddr;955    uint64_t DataDirSize;956    if (Header->Magic == COFF::PE32Header::PE32) {957      PE32Header = Header;958      DataDirAddr = base() + CurPtr + sizeof(pe32_header);959      DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;960    } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {961      PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);962      DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);963      DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;964    } else {965      // It's neither PE32 nor PE32+.966      return createStringError(object_error::parse_failed,967                               "incorrect PE magic");968    }969    if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))970      return E;971  }972 973  if (COFFHeader)974    CurPtr += COFFHeader->SizeOfOptionalHeader;975 976  assert(COFFHeader || COFFBigObjHeader);977 978  if (Error E =979          getObject(SectionTable, Data, base() + CurPtr,980                    (uint64_t)getNumberOfSections() * sizeof(coff_section)))981    return E;982 983  // Initialize the pointer to the symbol table.984  if (getPointerToSymbolTable() != 0) {985    if (Error E = initSymbolTablePtr()) {986      // Recover from errors reading the symbol table.987      consumeError(std::move(E));988      SymbolTable16 = nullptr;989      SymbolTable32 = nullptr;990      StringTable = nullptr;991      StringTableSize = 0;992    }993  } else {994    // We had better not have any symbols if we don't have a symbol table.995    if (getNumberOfSymbols() != 0) {996      return createStringError(object_error::parse_failed,997                               "symbol table missing");998    }999  }1000 1001  // Initialize the pointer to the beginning of the import table.1002  if (Error E = ignoreStrippedErrors(initImportTablePtr()))1003    return E;1004  if (Error E = ignoreStrippedErrors(initDelayImportTablePtr()))1005    return E;1006 1007  // Initialize the pointer to the export table.1008  if (Error E = ignoreStrippedErrors(initExportTablePtr()))1009    return E;1010 1011  // Initialize the pointer to the base relocation table.1012  if (Error E = ignoreStrippedErrors(initBaseRelocPtr()))1013    return E;1014 1015  // Initialize the pointer to the debug directory.1016  if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr()))1017    return E;1018 1019  // Initialize the pointer to the TLS directory.1020  if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr()))1021    return E;1022 1023  if (Error E = ignoreStrippedErrors(initLoadConfigPtr()))1024    return E;1025 1026  return Error::success();1027}1028 1029basic_symbol_iterator COFFObjectFile::symbol_begin() const {1030  DataRefImpl Ret;1031  Ret.p = getSymbolTable();1032  return basic_symbol_iterator(SymbolRef(Ret, this));1033}1034 1035basic_symbol_iterator COFFObjectFile::symbol_end() const {1036  // The symbol table ends where the string table begins.1037  DataRefImpl Ret;1038  Ret.p = reinterpret_cast<uintptr_t>(StringTable);1039  return basic_symbol_iterator(SymbolRef(Ret, this));1040}1041 1042import_directory_iterator COFFObjectFile::import_directory_begin() const {1043  if (!ImportDirectory)1044    return import_directory_end();1045  if (ImportDirectory->isNull())1046    return import_directory_end();1047  return import_directory_iterator(1048      ImportDirectoryEntryRef(ImportDirectory, 0, this));1049}1050 1051import_directory_iterator COFFObjectFile::import_directory_end() const {1052  return import_directory_iterator(1053      ImportDirectoryEntryRef(nullptr, -1, this));1054}1055 1056delay_import_directory_iterator1057COFFObjectFile::delay_import_directory_begin() const {1058  return delay_import_directory_iterator(1059      DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));1060}1061 1062delay_import_directory_iterator1063COFFObjectFile::delay_import_directory_end() const {1064  return delay_import_directory_iterator(1065      DelayImportDirectoryEntryRef(1066          DelayImportDirectory, NumberOfDelayImportDirectory, this));1067}1068 1069export_directory_iterator COFFObjectFile::export_directory_begin() const {1070  return export_directory_iterator(1071      ExportDirectoryEntryRef(ExportDirectory, 0, this));1072}1073 1074export_directory_iterator COFFObjectFile::export_directory_end() const {1075  if (!ExportDirectory)1076    return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));1077  ExportDirectoryEntryRef Ref(ExportDirectory,1078                              ExportDirectory->AddressTableEntries, this);1079  return export_directory_iterator(Ref);1080}1081 1082section_iterator COFFObjectFile::section_begin() const {1083  DataRefImpl Ret;1084  Ret.p = reinterpret_cast<uintptr_t>(SectionTable);1085  return section_iterator(SectionRef(Ret, this));1086}1087 1088section_iterator COFFObjectFile::section_end() const {1089  DataRefImpl Ret;1090  int NumSections =1091      COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();1092  Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);1093  return section_iterator(SectionRef(Ret, this));1094}1095 1096base_reloc_iterator COFFObjectFile::base_reloc_begin() const {1097  return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));1098}1099 1100base_reloc_iterator COFFObjectFile::base_reloc_end() const {1101  return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));1102}1103 1104dynamic_reloc_iterator COFFObjectFile::dynamic_reloc_begin() const {1105  const void *Header = DynamicRelocTable ? DynamicRelocTable + 1 : nullptr;1106  return dynamic_reloc_iterator(DynamicRelocRef(Header, this));1107}1108 1109dynamic_reloc_iterator COFFObjectFile::dynamic_reloc_end() const {1110  const void *Header = nullptr;1111  if (DynamicRelocTable)1112    Header = reinterpret_cast<const uint8_t *>(DynamicRelocTable + 1) +1113             DynamicRelocTable->Size;1114  return dynamic_reloc_iterator(DynamicRelocRef(Header, this));1115}1116 1117uint8_t COFFObjectFile::getBytesInAddress() const {1118  return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;1119}1120 1121StringRef COFFObjectFile::getFileFormatName() const {1122  switch(getMachine()) {1123  case COFF::IMAGE_FILE_MACHINE_I386:1124    return "COFF-i386";1125  case COFF::IMAGE_FILE_MACHINE_AMD64:1126    return "COFF-x86-64";1127  case COFF::IMAGE_FILE_MACHINE_ARMNT:1128    return "COFF-ARM";1129  case COFF::IMAGE_FILE_MACHINE_ARM64:1130    return "COFF-ARM64";1131  case COFF::IMAGE_FILE_MACHINE_ARM64EC:1132    return "COFF-ARM64EC";1133  case COFF::IMAGE_FILE_MACHINE_ARM64X:1134    return "COFF-ARM64X";1135  case COFF::IMAGE_FILE_MACHINE_R4000:1136    return "COFF-MIPS";1137  default:1138    return "COFF-<unknown arch>";1139  }1140}1141 1142Triple::ArchType COFFObjectFile::getArch() const {1143  return getMachineArchType(getMachine());1144}1145 1146Expected<uint64_t> COFFObjectFile::getStartAddress() const {1147  if (PE32Header)1148    return PE32Header->AddressOfEntryPoint;1149  return 0;1150}1151 1152iterator_range<import_directory_iterator>1153COFFObjectFile::import_directories() const {1154  return make_range(import_directory_begin(), import_directory_end());1155}1156 1157iterator_range<delay_import_directory_iterator>1158COFFObjectFile::delay_import_directories() const {1159  return make_range(delay_import_directory_begin(),1160                    delay_import_directory_end());1161}1162 1163iterator_range<export_directory_iterator>1164COFFObjectFile::export_directories() const {1165  return make_range(export_directory_begin(), export_directory_end());1166}1167 1168iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {1169  return make_range(base_reloc_begin(), base_reloc_end());1170}1171 1172iterator_range<dynamic_reloc_iterator> COFFObjectFile::dynamic_relocs() const {1173  return make_range(dynamic_reloc_begin(), dynamic_reloc_end());1174}1175 1176const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {1177  if (!DataDirectory)1178    return nullptr;1179  assert(PE32Header || PE32PlusHeader);1180  uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize1181                               : PE32PlusHeader->NumberOfRvaAndSize;1182  if (Index >= NumEnt)1183    return nullptr;1184  return &DataDirectory[Index];1185}1186 1187Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {1188  // Perhaps getting the section of a reserved section index should be an error,1189  // but callers rely on this to return null.1190  if (COFF::isReservedSectionNumber(Index))1191    return (const coff_section *)nullptr;1192  if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {1193    // We already verified the section table data, so no need to check again.1194    return SectionTable + (Index - 1);1195  }1196  return createStringError(object_error::parse_failed,1197                           "section index out of bounds");1198}1199 1200Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {1201  if (StringTableSize <= 4)1202    // Tried to get a string from an empty string table.1203    return createStringError(object_error::parse_failed, "string table empty");1204  if (Offset >= StringTableSize)1205    return errorCodeToError(object_error::unexpected_eof);1206  return StringRef(StringTable + Offset);1207}1208 1209Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {1210  return getSymbolName(Symbol.getGeneric());1211}1212 1213Expected<StringRef>1214COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {1215  // Check for string table entry. First 4 bytes are 0.1216  if (Symbol->Name.Offset.Zeroes == 0)1217    return getString(Symbol->Name.Offset.Offset);1218 1219  // Null terminated, let ::strlen figure out the length.1220  if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)1221    return StringRef(Symbol->Name.ShortName);1222 1223  // Not null terminated, use all 8 bytes.1224  return StringRef(Symbol->Name.ShortName, COFF::NameSize);1225}1226 1227ArrayRef<uint8_t>1228COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {1229  const uint8_t *Aux = nullptr;1230 1231  size_t SymbolSize = getSymbolTableEntrySize();1232  if (Symbol.getNumberOfAuxSymbols() > 0) {1233    // AUX data comes immediately after the symbol in COFF1234    Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;1235#ifndef NDEBUG1236    // Verify that the Aux symbol points to a valid entry in the symbol table.1237    uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());1238    if (Offset < getPointerToSymbolTable() ||1239        Offset >=1240            getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))1241      report_fatal_error("Aux Symbol data was outside of symbol table.");1242 1243    assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&1244           "Aux Symbol data did not point to the beginning of a symbol");1245#endif1246  }1247  return ArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);1248}1249 1250uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {1251  uintptr_t Offset =1252      reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();1253  assert(Offset % getSymbolTableEntrySize() == 0 &&1254         "Symbol did not point to the beginning of a symbol");1255  size_t Index = Offset / getSymbolTableEntrySize();1256  assert(Index < getNumberOfSymbols());1257  return Index;1258}1259 1260Expected<StringRef>1261COFFObjectFile::getSectionName(const coff_section *Sec) const {1262  StringRef Name = StringRef(Sec->Name, COFF::NameSize).split('\0').first;1263 1264  // Check for string table entry. First byte is '/'.1265  if (Name.starts_with("/")) {1266    uint32_t Offset;1267    if (Name.starts_with("//")) {1268      if (decodeBase64StringEntry(Name.substr(2), Offset))1269        return createStringError(object_error::parse_failed,1270                                 "invalid section name");1271    } else {1272      if (Name.substr(1).getAsInteger(10, Offset))1273        return createStringError(object_error::parse_failed,1274                                 "invalid section name");1275    }1276    return getString(Offset);1277  }1278 1279  return Name;1280}1281 1282uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {1283  // SizeOfRawData and VirtualSize change what they represent depending on1284  // whether or not we have an executable image.1285  //1286  // For object files, SizeOfRawData contains the size of section's data;1287  // VirtualSize should be zero but isn't due to buggy COFF writers.1288  //1289  // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the1290  // actual section size is in VirtualSize.  It is possible for VirtualSize to1291  // be greater than SizeOfRawData; the contents past that point should be1292  // considered to be zero.1293  if (getDOSHeader())1294    return std::min(Sec->VirtualSize, Sec->SizeOfRawData);1295  return Sec->SizeOfRawData;1296}1297 1298Error COFFObjectFile::getSectionContents(const coff_section *Sec,1299                                         ArrayRef<uint8_t> &Res) const {1300  // In COFF, a virtual section won't have any in-file1301  // content, so the file pointer to the content will be zero.1302  if (Sec->PointerToRawData == 0)1303    return Error::success();1304  // The only thing that we need to verify is that the contents is contained1305  // within the file bounds. We don't need to make sure it doesn't cover other1306  // data, as there's nothing that says that is not allowed.1307  uintptr_t ConStart =1308      reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;1309  uint32_t SectionSize = getSectionSize(Sec);1310  if (Error E = checkOffset(Data, ConStart, SectionSize))1311    return E;1312  Res = ArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);1313  return Error::success();1314}1315 1316const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {1317  return reinterpret_cast<const coff_relocation*>(Rel.p);1318}1319 1320void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {1321  Rel.p = reinterpret_cast<uintptr_t>(1322            reinterpret_cast<const coff_relocation*>(Rel.p) + 1);1323}1324 1325uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {1326  const coff_relocation *R = toRel(Rel);1327  return R->VirtualAddress;1328}1329 1330symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {1331  const coff_relocation *R = toRel(Rel);1332  DataRefImpl Ref;1333  if (R->SymbolTableIndex >= getNumberOfSymbols())1334    return symbol_end();1335  if (SymbolTable16)1336    Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);1337  else if (SymbolTable32)1338    Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);1339  else1340    llvm_unreachable("no symbol table pointer!");1341  return symbol_iterator(SymbolRef(Ref, this));1342}1343 1344uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {1345  const coff_relocation* R = toRel(Rel);1346  return R->Type;1347}1348 1349const coff_section *1350COFFObjectFile::getCOFFSection(const SectionRef &Section) const {1351  return toSec(Section.getRawDataRefImpl());1352}1353 1354COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {1355  if (SymbolTable16)1356    return toSymb<coff_symbol16>(Ref);1357  if (SymbolTable32)1358    return toSymb<coff_symbol32>(Ref);1359  llvm_unreachable("no symbol table pointer!");1360}1361 1362COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {1363  return getCOFFSymbol(Symbol.getRawDataRefImpl());1364}1365 1366const coff_relocation *1367COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {1368  return toRel(Reloc.getRawDataRefImpl());1369}1370 1371ArrayRef<coff_relocation>1372COFFObjectFile::getRelocations(const coff_section *Sec) const {1373  return {getFirstReloc(Sec, Data, base()),1374          getNumberOfRelocations(Sec, Data, base())};1375}1376 1377#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \1378  case COFF::reloc_type:                                                       \1379    return #reloc_type;1380 1381StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {1382  switch (getArch()) {1383  case Triple::x86_64:1384    switch (Type) {1385    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);1386    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);1387    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);1388    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);1389    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);1390    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);1391    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);1392    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);1393    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);1394    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);1395    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);1396    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);1397    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);1398    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);1399    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);1400    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);1401    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);1402    default:1403      return "Unknown";1404    }1405    break;1406  case Triple::thumb:1407    switch (Type) {1408    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);1409    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);1410    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);1411    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);1412    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);1413    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);1414    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);1415    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);1416    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);1417    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);1418    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);1419    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);1420    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);1421    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);1422    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);1423    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);1424    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);1425    default:1426      return "Unknown";1427    }1428    break;1429  case Triple::aarch64:1430    switch (Type) {1431    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);1432    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);1433    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);1434    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);1435    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);1436    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);1437    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);1438    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);1439    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);1440    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);1441    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);1442    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);1443    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);1444    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);1445    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);1446    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);1447    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);1448    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);1449    default:1450      return "Unknown";1451    }1452    break;1453  case Triple::x86:1454    switch (Type) {1455    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);1456    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);1457    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);1458    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);1459    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);1460    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);1461    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);1462    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);1463    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);1464    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);1465    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);1466    default:1467      return "Unknown";1468    }1469    break;1470  case Triple::mipsel:1471    switch (Type) {1472      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_ABSOLUTE);1473      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFHALF);1474      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFWORD);1475      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_JMPADDR);1476      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFHI);1477      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFLO);1478      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_GPREL);1479      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_LITERAL);1480      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECTION);1481      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECREL);1482      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECRELLO);1483      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECRELHI);1484      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_JMPADDR16);1485      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFWORDNB);1486      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_PAIR);1487    default:1488      return "Unknown";1489    }1490    break;1491  default:1492    return "Unknown";1493  }1494}1495 1496#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME1497 1498void COFFObjectFile::getRelocationTypeName(1499    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {1500  const coff_relocation *Reloc = toRel(Rel);1501  StringRef Res = getRelocationTypeName(Reloc->Type);1502  Result.append(Res.begin(), Res.end());1503}1504 1505bool COFFObjectFile::isRelocatableObject() const {1506  return !DataDirectory;1507}1508 1509StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {1510  return StringSwitch<StringRef>(Name)1511      .Case("eh_fram", "eh_frame")1512      .Default(Name);1513}1514 1515std::unique_ptr<MemoryBuffer> COFFObjectFile::getHybridObjectView() const {1516  if (getMachine() != COFF::IMAGE_FILE_MACHINE_ARM64X)1517    return nullptr;1518 1519  std::unique_ptr<WritableMemoryBuffer> HybridView;1520 1521  for (auto DynReloc : dynamic_relocs()) {1522    if (DynReloc.getType() != COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X)1523      continue;1524 1525    for (auto reloc : DynReloc.arm64x_relocs()) {1526      if (!HybridView) {1527        HybridView =1528            WritableMemoryBuffer::getNewUninitMemBuffer(Data.getBufferSize());1529        memcpy(HybridView->getBufferStart(), Data.getBufferStart(),1530               Data.getBufferSize());1531      }1532 1533      uint32_t RVA = reloc.getRVA();1534      void *Ptr;1535      uintptr_t IntPtr;1536      if (RVA & ~0xfff) {1537        cantFail(getRvaPtr(RVA, IntPtr));1538        Ptr = HybridView->getBufferStart() + IntPtr -1539              reinterpret_cast<uintptr_t>(base());1540      } else {1541        // PE header relocation.1542        Ptr = HybridView->getBufferStart() + RVA;1543      }1544 1545      switch (reloc.getType()) {1546      case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:1547        memset(Ptr, 0, reloc.getSize());1548        break;1549      case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: {1550        auto Value = static_cast<ulittle64_t>(reloc.getValue());1551        memcpy(Ptr, &Value, reloc.getSize());1552        break;1553      }1554      case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:1555        *reinterpret_cast<ulittle32_t *>(Ptr) += reloc.getValue();1556        break;1557      }1558    }1559  }1560  return HybridView;1561}1562 1563bool ImportDirectoryEntryRef::1564operator==(const ImportDirectoryEntryRef &Other) const {1565  return ImportTable == Other.ImportTable && Index == Other.Index;1566}1567 1568void ImportDirectoryEntryRef::moveNext() {1569  ++Index;1570  if (ImportTable[Index].isNull()) {1571    Index = -1;1572    ImportTable = nullptr;1573  }1574}1575 1576Error ImportDirectoryEntryRef::getImportTableEntry(1577    const coff_import_directory_table_entry *&Result) const {1578  return getObject(Result, OwningObject->Data, ImportTable + Index);1579}1580 1581static imported_symbol_iterator1582makeImportedSymbolIterator(const COFFObjectFile *Object,1583                           uintptr_t Ptr, int Index) {1584  if (Object->getBytesInAddress() == 4) {1585    auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);1586    return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));1587  }1588  auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);1589  return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));1590}1591 1592static imported_symbol_iterator1593importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {1594  uintptr_t IntPtr = 0;1595  // FIXME: Handle errors.1596  cantFail(Object->getRvaPtr(RVA, IntPtr));1597  return makeImportedSymbolIterator(Object, IntPtr, 0);1598}1599 1600static imported_symbol_iterator1601importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {1602  uintptr_t IntPtr = 0;1603  // FIXME: Handle errors.1604  cantFail(Object->getRvaPtr(RVA, IntPtr));1605  // Forward the pointer to the last entry which is null.1606  int Index = 0;1607  if (Object->getBytesInAddress() == 4) {1608    auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);1609    while (*Entry++)1610      ++Index;1611  } else {1612    auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);1613    while (*Entry++)1614      ++Index;1615  }1616  return makeImportedSymbolIterator(Object, IntPtr, Index);1617}1618 1619imported_symbol_iterator1620ImportDirectoryEntryRef::imported_symbol_begin() const {1621  return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,1622                             OwningObject);1623}1624 1625imported_symbol_iterator1626ImportDirectoryEntryRef::imported_symbol_end() const {1627  return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,1628                           OwningObject);1629}1630 1631iterator_range<imported_symbol_iterator>1632ImportDirectoryEntryRef::imported_symbols() const {1633  return make_range(imported_symbol_begin(), imported_symbol_end());1634}1635 1636imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {1637  return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,1638                             OwningObject);1639}1640 1641imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {1642  return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,1643                           OwningObject);1644}1645 1646iterator_range<imported_symbol_iterator>1647ImportDirectoryEntryRef::lookup_table_symbols() const {1648  return make_range(lookup_table_begin(), lookup_table_end());1649}1650 1651Error ImportDirectoryEntryRef::getName(StringRef &Result) const {1652  uintptr_t IntPtr = 0;1653  if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,1654                                        "import directory name"))1655    return E;1656  Result = StringRef(reinterpret_cast<const char *>(IntPtr));1657  return Error::success();1658}1659 1660Error1661ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {1662  Result = ImportTable[Index].ImportLookupTableRVA;1663  return Error::success();1664}1665 1666Error ImportDirectoryEntryRef::getImportAddressTableRVA(1667    uint32_t &Result) const {1668  Result = ImportTable[Index].ImportAddressTableRVA;1669  return Error::success();1670}1671 1672bool DelayImportDirectoryEntryRef::1673operator==(const DelayImportDirectoryEntryRef &Other) const {1674  return Table == Other.Table && Index == Other.Index;1675}1676 1677void DelayImportDirectoryEntryRef::moveNext() {1678  ++Index;1679}1680 1681imported_symbol_iterator1682DelayImportDirectoryEntryRef::imported_symbol_begin() const {1683  return importedSymbolBegin(Table[Index].DelayImportNameTable,1684                             OwningObject);1685}1686 1687imported_symbol_iterator1688DelayImportDirectoryEntryRef::imported_symbol_end() const {1689  return importedSymbolEnd(Table[Index].DelayImportNameTable,1690                           OwningObject);1691}1692 1693iterator_range<imported_symbol_iterator>1694DelayImportDirectoryEntryRef::imported_symbols() const {1695  return make_range(imported_symbol_begin(), imported_symbol_end());1696}1697 1698Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {1699  uintptr_t IntPtr = 0;1700  if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,1701                                        "delay import directory name"))1702    return E;1703  Result = StringRef(reinterpret_cast<const char *>(IntPtr));1704  return Error::success();1705}1706 1707Error DelayImportDirectoryEntryRef::getDelayImportTable(1708    const delay_import_directory_table_entry *&Result) const {1709  Result = &Table[Index];1710  return Error::success();1711}1712 1713Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,1714                                                     uint64_t &Result) const {1715  uint32_t RVA = Table[Index].DelayImportAddressTable +1716      AddrIndex * (OwningObject->is64() ? 8 : 4);1717  uintptr_t IntPtr = 0;1718  if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address"))1719    return E;1720  if (OwningObject->is64())1721    Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);1722  else1723    Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);1724  return Error::success();1725}1726 1727bool ExportDirectoryEntryRef::1728operator==(const ExportDirectoryEntryRef &Other) const {1729  return ExportTable == Other.ExportTable && Index == Other.Index;1730}1731 1732void ExportDirectoryEntryRef::moveNext() {1733  ++Index;1734}1735 1736// Returns the name of the current export symbol. If the symbol is exported only1737// by ordinal, the empty string is set as a result.1738Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {1739  uintptr_t IntPtr = 0;1740  if (Error E =1741          OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name"))1742    return E;1743  Result = StringRef(reinterpret_cast<const char *>(IntPtr));1744  return Error::success();1745}1746 1747// Returns the starting ordinal number.1748Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {1749  Result = ExportTable->OrdinalBase;1750  return Error::success();1751}1752 1753// Returns the export ordinal of the current export symbol.1754Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {1755  Result = ExportTable->OrdinalBase + Index;1756  return Error::success();1757}1758 1759// Returns the address of the current export symbol.1760Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {1761  uintptr_t IntPtr = 0;1762  if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,1763                                         IntPtr, "export address"))1764    return EC;1765  const export_address_table_entry *entry =1766      reinterpret_cast<const export_address_table_entry *>(IntPtr);1767  Result = entry[Index].ExportRVA;1768  return Error::success();1769}1770 1771// Returns the name of the current export symbol. If the symbol is exported only1772// by ordinal, the empty string is set as a result.1773Error1774ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {1775  uintptr_t IntPtr = 0;1776  if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,1777                                         "export ordinal table"))1778    return EC;1779  const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);1780 1781  uint32_t NumEntries = ExportTable->NumberOfNamePointers;1782  int Offset = 0;1783  for (const ulittle16_t *I = Start, *E = Start + NumEntries;1784       I < E; ++I, ++Offset) {1785    if (*I != Index)1786      continue;1787    if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,1788                                           "export table entry"))1789      return EC;1790    const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);1791    if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr,1792                                           "export symbol name"))1793      return EC;1794    Result = StringRef(reinterpret_cast<const char *>(IntPtr));1795    return Error::success();1796  }1797  Result = "";1798  return Error::success();1799}1800 1801Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {1802  const data_directory *DataEntry =1803      OwningObject->getDataDirectory(COFF::EXPORT_TABLE);1804  if (!DataEntry)1805    return createStringError(object_error::parse_failed,1806                             "export table missing");1807  uint32_t RVA;1808  if (auto EC = getExportRVA(RVA))1809    return EC;1810  uint32_t Begin = DataEntry->RelativeVirtualAddress;1811  uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;1812  Result = (Begin <= RVA && RVA < End);1813  return Error::success();1814}1815 1816Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {1817  uint32_t RVA;1818  if (auto EC = getExportRVA(RVA))1819    return EC;1820  uintptr_t IntPtr = 0;1821  if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target"))1822    return EC;1823  Result = StringRef(reinterpret_cast<const char *>(IntPtr));1824  return Error::success();1825}1826 1827bool ImportedSymbolRef::1828operator==(const ImportedSymbolRef &Other) const {1829  return Entry32 == Other.Entry32 && Entry64 == Other.Entry641830      && Index == Other.Index;1831}1832 1833void ImportedSymbolRef::moveNext() {1834  ++Index;1835}1836 1837Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {1838  uint32_t RVA;1839  if (Entry32) {1840    // If a symbol is imported only by ordinal, it has no name.1841    if (Entry32[Index].isOrdinal())1842      return Error::success();1843    RVA = Entry32[Index].getHintNameRVA();1844  } else {1845    if (Entry64[Index].isOrdinal())1846      return Error::success();1847    RVA = Entry64[Index].getHintNameRVA();1848  }1849  uintptr_t IntPtr = 0;1850  if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name"))1851    return EC;1852  // +2 because the first two bytes is hint.1853  Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));1854  return Error::success();1855}1856 1857Error ImportedSymbolRef::isOrdinal(bool &Result) const {1858  if (Entry32)1859    Result = Entry32[Index].isOrdinal();1860  else1861    Result = Entry64[Index].isOrdinal();1862  return Error::success();1863}1864 1865Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {1866  if (Entry32)1867    Result = Entry32[Index].getHintNameRVA();1868  else1869    Result = Entry64[Index].getHintNameRVA();1870  return Error::success();1871}1872 1873Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {1874  uint32_t RVA;1875  if (Entry32) {1876    if (Entry32[Index].isOrdinal()) {1877      Result = Entry32[Index].getOrdinal();1878      return Error::success();1879    }1880    RVA = Entry32[Index].getHintNameRVA();1881  } else {1882    if (Entry64[Index].isOrdinal()) {1883      Result = Entry64[Index].getOrdinal();1884      return Error::success();1885    }1886    RVA = Entry64[Index].getHintNameRVA();1887  }1888  uintptr_t IntPtr = 0;1889  if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal"))1890    return EC;1891  Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);1892  return Error::success();1893}1894 1895Expected<std::unique_ptr<COFFObjectFile>>1896ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {1897  return COFFObjectFile::create(Object);1898}1899 1900bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {1901  return Header == Other.Header && Index == Other.Index;1902}1903 1904void BaseRelocRef::moveNext() {1905  // Header->BlockSize is the size of the current block, including the1906  // size of the header itself.1907  uint32_t Size = sizeof(*Header) +1908      sizeof(coff_base_reloc_block_entry) * (Index + 1);1909  if (Size == Header->BlockSize) {1910    // .reloc contains a list of base relocation blocks. Each block1911    // consists of the header followed by entries. The header contains1912    // how many entories will follow. When we reach the end of the1913    // current block, proceed to the next block.1914    Header = reinterpret_cast<const coff_base_reloc_block_header *>(1915        reinterpret_cast<const uint8_t *>(Header) + Size);1916    Index = 0;1917  } else {1918    ++Index;1919  }1920}1921 1922Error BaseRelocRef::getType(uint8_t &Type) const {1923  auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);1924  Type = Entry[Index].getType();1925  return Error::success();1926}1927 1928Error BaseRelocRef::getRVA(uint32_t &Result) const {1929  auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);1930  Result = Header->PageRVA + Entry[Index].getOffset();1931  return Error::success();1932}1933 1934bool DynamicRelocRef::operator==(const DynamicRelocRef &Other) const {1935  return Header == Other.Header;1936}1937 1938void DynamicRelocRef::moveNext() {1939  switch (Obj->getDynamicRelocTable()->Version) {1940  case 1:1941    if (Obj->is64()) {1942      auto H = reinterpret_cast<const coff_dynamic_relocation64 *>(Header);1943      Header += sizeof(*H) + H->BaseRelocSize;1944    } else {1945      auto H = reinterpret_cast<const coff_dynamic_relocation32 *>(Header);1946      Header += sizeof(*H) + H->BaseRelocSize;1947    }1948    break;1949  case 2:1950    if (Obj->is64()) {1951      auto H = reinterpret_cast<const coff_dynamic_relocation64_v2 *>(Header);1952      Header += H->HeaderSize + H->FixupInfoSize;1953    } else {1954      auto H = reinterpret_cast<const coff_dynamic_relocation32_v2 *>(Header);1955      Header += H->HeaderSize + H->FixupInfoSize;1956    }1957    break;1958  }1959}1960 1961uint32_t DynamicRelocRef::getType() const {1962  switch (Obj->getDynamicRelocTable()->Version) {1963  case 1:1964    if (Obj->is64()) {1965      auto H = reinterpret_cast<const coff_dynamic_relocation64 *>(Header);1966      return H->Symbol;1967    } else {1968      auto H = reinterpret_cast<const coff_dynamic_relocation32 *>(Header);1969      return H->Symbol;1970    }1971    break;1972  case 2:1973    if (Obj->is64()) {1974      auto H = reinterpret_cast<const coff_dynamic_relocation64_v2 *>(Header);1975      return H->Symbol;1976    } else {1977      auto H = reinterpret_cast<const coff_dynamic_relocation32_v2 *>(Header);1978      return H->Symbol;1979    }1980    break;1981  default:1982    llvm_unreachable("invalid version");1983  }1984}1985 1986void DynamicRelocRef::getContents(ArrayRef<uint8_t> &Ref) const {1987  switch (Obj->getDynamicRelocTable()->Version) {1988  case 1:1989    if (Obj->is64()) {1990      auto H = reinterpret_cast<const coff_dynamic_relocation64 *>(Header);1991      Ref = ArrayRef(Header + sizeof(*H), H->BaseRelocSize);1992    } else {1993      auto H = reinterpret_cast<const coff_dynamic_relocation32 *>(Header);1994      Ref = ArrayRef(Header + sizeof(*H), H->BaseRelocSize);1995    }1996    break;1997  case 2:1998    if (Obj->is64()) {1999      auto H = reinterpret_cast<const coff_dynamic_relocation64_v2 *>(Header);2000      Ref = ArrayRef(Header + H->HeaderSize, H->FixupInfoSize);2001    } else {2002      auto H = reinterpret_cast<const coff_dynamic_relocation32_v2 *>(Header);2003      Ref = ArrayRef(Header + H->HeaderSize, H->FixupInfoSize);2004    }2005    break;2006  }2007}2008 2009Error DynamicRelocRef::validate() const {2010  const coff_dynamic_reloc_table *Table = Obj->getDynamicRelocTable();2011  size_t ContentsSize =2012      reinterpret_cast<const uint8_t *>(Table + 1) + Table->Size - Header;2013  size_t HeaderSize;2014  if (Table->Version == 1)2015    HeaderSize = Obj->is64() ? sizeof(coff_dynamic_relocation64)2016                             : sizeof(coff_dynamic_relocation32);2017  else2018    HeaderSize = Obj->is64() ? sizeof(coff_dynamic_relocation64_v2)2019                             : sizeof(coff_dynamic_relocation32_v2);2020  if (HeaderSize > ContentsSize)2021    return createStringError(object_error::parse_failed,2022                             "Unexpected end of dynamic relocations data");2023 2024  if (Table->Version == 2) {2025    size_t Size =2026        Obj->is64()2027            ? reinterpret_cast<const coff_dynamic_relocation64_v2 *>(Header)2028                  ->HeaderSize2029            : reinterpret_cast<const coff_dynamic_relocation32_v2 *>(Header)2030                  ->HeaderSize;2031    if (Size < HeaderSize || Size > ContentsSize)2032      return createStringError(object_error::parse_failed,2033                               "Invalid dynamic relocation header size (" +2034                                   Twine(Size) + ")");2035    HeaderSize = Size;2036  }2037 2038  ArrayRef<uint8_t> Contents;2039  getContents(Contents);2040  if (Contents.size() > ContentsSize - HeaderSize)2041    return createStringError(object_error::parse_failed,2042                             "Too large dynamic relocation size (" +2043                                 Twine(Contents.size()) + ")");2044 2045  switch (getType()) {2046  case COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X:2047    for (auto Reloc : arm64x_relocs()) {2048      if (Error E = Reloc.validate(Obj))2049        return E;2050    }2051    break;2052  }2053 2054  return Error::success();2055}2056 2057arm64x_reloc_iterator DynamicRelocRef::arm64x_reloc_begin() const {2058  assert(getType() == COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X);2059  ArrayRef<uint8_t> Content;2060  getContents(Content);2061  auto Header =2062      reinterpret_cast<const coff_base_reloc_block_header *>(Content.begin());2063  return arm64x_reloc_iterator(Arm64XRelocRef(Header));2064}2065 2066arm64x_reloc_iterator DynamicRelocRef::arm64x_reloc_end() const {2067  assert(getType() == COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X);2068  ArrayRef<uint8_t> Content;2069  getContents(Content);2070  auto Header =2071      reinterpret_cast<const coff_base_reloc_block_header *>(Content.end());2072  return arm64x_reloc_iterator(Arm64XRelocRef(Header, 0));2073}2074 2075iterator_range<arm64x_reloc_iterator> DynamicRelocRef::arm64x_relocs() const {2076  return make_range(arm64x_reloc_begin(), arm64x_reloc_end());2077}2078 2079bool Arm64XRelocRef::operator==(const Arm64XRelocRef &Other) const {2080  return Header == Other.Header && Index == Other.Index;2081}2082 2083uint8_t Arm64XRelocRef::getEntrySize() const {2084  switch (getType()) {2085  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:2086    return (1ull << getArg()) / sizeof(uint16_t) + 1;2087  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:2088    return 2;2089  default:2090    return 1;2091  }2092}2093 2094void Arm64XRelocRef::moveNext() {2095  Index += getEntrySize();2096  if (sizeof(*Header) + Index * sizeof(uint16_t) < Header->BlockSize &&2097      !getReloc())2098    ++Index; // Skip padding2099  if (sizeof(*Header) + Index * sizeof(uint16_t) == Header->BlockSize) {2100    // The end of the block, move to the next one.2101    Header =2102        reinterpret_cast<const coff_base_reloc_block_header *>(&getReloc());2103    Index = 0;2104  }2105}2106 2107uint8_t Arm64XRelocRef::getSize() const {2108  switch (getType()) {2109  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:2110  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:2111    return 1 << getArg();2112  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:2113    return sizeof(uint32_t);2114  }2115  llvm_unreachable("Unknown Arm64XFixupType enum");2116}2117 2118uint64_t Arm64XRelocRef::getValue() const {2119  auto Ptr = reinterpret_cast<const ulittle16_t *>(Header + 1) + Index + 1;2120 2121  switch (getType()) {2122  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: {2123    ulittle64_t Value(0);2124    memcpy(&Value, Ptr, getSize());2125    return Value;2126  }2127  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA: {2128    uint16_t arg = getArg();2129    int delta = *Ptr;2130 2131    if (arg & 1)2132      delta = -delta;2133    delta *= (arg & 2) ? 8 : 4;2134    return delta;2135  }2136  default:2137    return 0;2138  }2139}2140 2141Error Arm64XRelocRef::validate(const COFFObjectFile *Obj) const {2142  if (!Index) {2143    const coff_dynamic_reloc_table *Table = Obj->getDynamicRelocTable();2144    size_t ContentsSize = reinterpret_cast<const uint8_t *>(Table + 1) +2145                          Table->Size -2146                          reinterpret_cast<const uint8_t *>(Header);2147    if (ContentsSize < sizeof(coff_base_reloc_block_header))2148      return createStringError(object_error::parse_failed,2149                               "Unexpected end of ARM64X relocations data");2150    if (Header->BlockSize <= sizeof(*Header))2151      return createStringError(object_error::parse_failed,2152                               "ARM64X relocations block size (" +2153                                   Twine(Header->BlockSize) + ") is too small");2154    if (Header->BlockSize % sizeof(uint32_t))2155      return createStringError(object_error::parse_failed,2156                               "Unaligned ARM64X relocations block size (" +2157                                   Twine(Header->BlockSize) + ")");2158    if (Header->BlockSize > ContentsSize)2159      return createStringError(object_error::parse_failed,2160                               "ARM64X relocations block size (" +2161                                   Twine(Header->BlockSize) + ") is too large");2162    if (Header->PageRVA & 0xfff)2163      return createStringError(object_error::parse_failed,2164                               "Unaligned ARM64X relocations page RVA (" +2165                                   Twine(Header->PageRVA) + ")");2166  }2167 2168  switch ((getReloc() >> 12) & 3) {2169  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:2170  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:2171    break;2172  case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:2173    if (!getArg())2174      return createStringError(object_error::parse_failed,2175                               "Invalid ARM64X relocation value size (0)");2176    break;2177  default:2178    return createStringError(object_error::parse_failed,2179                             "Invalid relocation type");2180  }2181 2182  uint32_t RelocsSize =2183      (Header->BlockSize - sizeof(*Header)) / sizeof(uint16_t);2184  uint16_t EntrySize = getEntrySize();2185  if (!getReloc() ||2186      (Index + EntrySize + 1 < RelocsSize && !getReloc(EntrySize)))2187    return createStringError(object_error::parse_failed,2188                             "Unexpected ARM64X relocations terminator");2189  if (Index + EntrySize > RelocsSize)2190    return createStringError(object_error::parse_failed,2191                             "Unexpected end of ARM64X relocations");2192  if (getRVA() % getSize())2193    return createStringError(object_error::parse_failed,2194                             "Unaligned ARM64X relocation RVA (" +2195                                 Twine(getRVA()) + ")");2196  if (Header->PageRVA) {2197    uintptr_t IntPtr;2198    return Obj->getRvaPtr(getRVA() + getSize(), IntPtr, "ARM64X reloc");2199  }2200  return Error::success();2201}2202 2203#define RETURN_IF_ERROR(Expr)                                                  \2204  do {                                                                         \2205    Error E = (Expr);                                                          \2206    if (E)                                                                     \2207      return std::move(E);                                                     \2208  } while (0)2209 2210Expected<ArrayRef<UTF16>>2211ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {2212  BinaryStreamReader Reader = BinaryStreamReader(BBS);2213  Reader.setOffset(Offset);2214  uint16_t Length;2215  RETURN_IF_ERROR(Reader.readInteger(Length));2216  ArrayRef<UTF16> RawDirString;2217  RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));2218  return RawDirString;2219}2220 2221Expected<ArrayRef<UTF16>>2222ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {2223  return getDirStringAtOffset(Entry.Identifier.getNameOffset());2224}2225 2226Expected<const coff_resource_dir_table &>2227ResourceSectionRef::getTableAtOffset(uint32_t Offset) {2228  const coff_resource_dir_table *Table = nullptr;2229 2230  BinaryStreamReader Reader(BBS);2231  Reader.setOffset(Offset);2232  RETURN_IF_ERROR(Reader.readObject(Table));2233  assert(Table != nullptr);2234  return *Table;2235}2236 2237Expected<const coff_resource_dir_entry &>2238ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {2239  const coff_resource_dir_entry *Entry = nullptr;2240 2241  BinaryStreamReader Reader(BBS);2242  Reader.setOffset(Offset);2243  RETURN_IF_ERROR(Reader.readObject(Entry));2244  assert(Entry != nullptr);2245  return *Entry;2246}2247 2248Expected<const coff_resource_data_entry &>2249ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {2250  const coff_resource_data_entry *Entry = nullptr;2251 2252  BinaryStreamReader Reader(BBS);2253  Reader.setOffset(Offset);2254  RETURN_IF_ERROR(Reader.readObject(Entry));2255  assert(Entry != nullptr);2256  return *Entry;2257}2258 2259Expected<const coff_resource_dir_table &>2260ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {2261  assert(Entry.Offset.isSubDir());2262  return getTableAtOffset(Entry.Offset.value());2263}2264 2265Expected<const coff_resource_data_entry &>2266ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {2267  assert(!Entry.Offset.isSubDir());2268  return getDataEntryAtOffset(Entry.Offset.value());2269}2270 2271Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {2272  return getTableAtOffset(0);2273}2274 2275Expected<const coff_resource_dir_entry &>2276ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,2277                                  uint32_t Index) {2278  if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))2279    return createStringError(object_error::parse_failed, "index out of range");2280  const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);2281  ptrdiff_t TableOffset = TablePtr - BBS.data().data();2282  return getTableEntryAtOffset(TableOffset + sizeof(Table) +2283                               Index * sizeof(coff_resource_dir_entry));2284}2285 2286Error ResourceSectionRef::load(const COFFObjectFile *O) {2287  for (const SectionRef &S : O->sections()) {2288    Expected<StringRef> Name = S.getName();2289    if (!Name)2290      return Name.takeError();2291 2292    if (*Name == ".rsrc" || *Name == ".rsrc$01")2293      return load(O, S);2294  }2295  return createStringError(object_error::parse_failed,2296                           "no resource section found");2297}2298 2299Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {2300  Obj = O;2301  Section = S;2302  Expected<StringRef> Contents = Section.getContents();2303  if (!Contents)2304    return Contents.takeError();2305  BBS = BinaryByteStream(*Contents, llvm::endianness::little);2306  const coff_section *COFFSect = Obj->getCOFFSection(Section);2307  ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);2308  Relocs.reserve(OrigRelocs.size());2309  for (const coff_relocation &R : OrigRelocs)2310    Relocs.push_back(&R);2311  llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {2312    return A->VirtualAddress < B->VirtualAddress;2313  });2314  return Error::success();2315}2316 2317Expected<StringRef>2318ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {2319  if (!Obj)2320    return createStringError(object_error::parse_failed, "no object provided");2321 2322  // Find a potential relocation at the DataRVA field (first member of2323  // the coff_resource_data_entry struct).2324  const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);2325  ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();2326  coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),2327                              ulittle16_t(0)};2328  auto RelocsForOffset =2329      std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,2330                       [](const coff_relocation *A, const coff_relocation *B) {2331                         return A->VirtualAddress < B->VirtualAddress;2332                       });2333 2334  if (RelocsForOffset.first != RelocsForOffset.second) {2335    // We found a relocation with the right offset. Check that it does have2336    // the expected type.2337    const coff_relocation &R = **RelocsForOffset.first;2338    uint16_t RVAReloc;2339    switch (Obj->getArch()) {2340    case Triple::x86:2341      RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;2342      break;2343    case Triple::x86_64:2344      RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;2345      break;2346    case Triple::thumb:2347      RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;2348      break;2349    case Triple::aarch64:2350      RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;2351      break;2352    default:2353      return createStringError(object_error::parse_failed,2354                               "unsupported architecture");2355    }2356    if (R.Type != RVAReloc)2357      return createStringError(object_error::parse_failed,2358                               "unexpected relocation type");2359    // Get the relocation's symbol2360    Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);2361    if (!Sym)2362      return Sym.takeError();2363    // And the symbol's section2364    Expected<const coff_section *> Section =2365        Obj->getSection(Sym->getSectionNumber());2366    if (!Section)2367      return Section.takeError();2368    // Add the initial value of DataRVA to the symbol's offset to find the2369    // data it points at.2370    uint64_t Offset = Entry.DataRVA + Sym->getValue();2371    ArrayRef<uint8_t> Contents;2372    if (Error E = Obj->getSectionContents(*Section, Contents))2373      return E;2374    if (Offset + Entry.DataSize > Contents.size())2375      return createStringError(object_error::parse_failed,2376                               "data outside of section");2377    // Return a reference to the data inside the section.2378    return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,2379                     Entry.DataSize);2380  } else {2381    // Relocatable objects need a relocation for the DataRVA field.2382    if (Obj->isRelocatableObject())2383      return createStringError(object_error::parse_failed,2384                               "no relocation found for DataRVA");2385 2386    // Locate the section that contains the address that DataRVA points at.2387    uint64_t VA = Entry.DataRVA + Obj->getImageBase();2388    for (const SectionRef &S : Obj->sections()) {2389      if (VA >= S.getAddress() &&2390          VA + Entry.DataSize <= S.getAddress() + S.getSize()) {2391        uint64_t Offset = VA - S.getAddress();2392        Expected<StringRef> Contents = S.getContents();2393        if (!Contents)2394          return Contents.takeError();2395        return Contents->substr(Offset, Entry.DataSize);2396      }2397    }2398    return createStringError(object_error::parse_failed,2399                             "address not found in image");2400  }2401}2402