10b57cec5SDimitry Andric //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file declares the COFFObjectFile class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
155ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
170b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
180b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
190b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
200b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
210b57cec5SDimitry Andric #include "llvm/Object/Error.h"
220b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
230b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
240b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
250b57cec5SDimitry Andric #include "llvm/Support/Error.h"
260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
270b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
280b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
290b57cec5SDimitry Andric #include <algorithm>
300b57cec5SDimitry Andric #include <cassert>
31af732203SDimitry Andric #include <cinttypes>
320b57cec5SDimitry Andric #include <cstddef>
330b57cec5SDimitry Andric #include <cstring>
340b57cec5SDimitry Andric #include <limits>
350b57cec5SDimitry Andric #include <memory>
360b57cec5SDimitry Andric #include <system_error>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric using namespace object;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric using support::ulittle16_t;
420b57cec5SDimitry Andric using support::ulittle32_t;
430b57cec5SDimitry Andric using support::ulittle64_t;
440b57cec5SDimitry Andric using support::little16_t;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric // Returns false if size is greater than the buffer size. And sets ec.
checkSize(MemoryBufferRef M,std::error_code & EC,uint64_t Size)470b57cec5SDimitry Andric static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
480b57cec5SDimitry Andric   if (M.getBufferSize() < Size) {
490b57cec5SDimitry Andric     EC = object_error::unexpected_eof;
500b57cec5SDimitry Andric     return false;
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric   return true;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
560b57cec5SDimitry Andric // Returns unexpected_eof if error.
570b57cec5SDimitry Andric template <typename T>
getObject(const T * & Obj,MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))585ffd83dbSDimitry Andric static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,
590b57cec5SDimitry Andric                        const uint64_t Size = sizeof(T)) {
60af732203SDimitry Andric   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
615ffd83dbSDimitry Andric   if (Error E = Binary::checkOffset(M, Addr, Size))
625ffd83dbSDimitry Andric     return E;
630b57cec5SDimitry Andric   Obj = reinterpret_cast<const T *>(Addr);
645ffd83dbSDimitry Andric   return Error::success();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
680b57cec5SDimitry Andric // prefixed slashes.
decodeBase64StringEntry(StringRef Str,uint32_t & Result)690b57cec5SDimitry Andric static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
700b57cec5SDimitry Andric   assert(Str.size() <= 6 && "String too long, possible overflow.");
710b57cec5SDimitry Andric   if (Str.size() > 6)
720b57cec5SDimitry Andric     return true;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   uint64_t Value = 0;
750b57cec5SDimitry Andric   while (!Str.empty()) {
760b57cec5SDimitry Andric     unsigned CharVal;
770b57cec5SDimitry Andric     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
780b57cec5SDimitry Andric       CharVal = Str[0] - 'A';
790b57cec5SDimitry Andric     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
800b57cec5SDimitry Andric       CharVal = Str[0] - 'a' + 26;
810b57cec5SDimitry Andric     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
820b57cec5SDimitry Andric       CharVal = Str[0] - '0' + 52;
830b57cec5SDimitry Andric     else if (Str[0] == '+') // 62
840b57cec5SDimitry Andric       CharVal = 62;
850b57cec5SDimitry Andric     else if (Str[0] == '/') // 63
860b57cec5SDimitry Andric       CharVal = 63;
870b57cec5SDimitry Andric     else
880b57cec5SDimitry Andric       return true;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric     Value = (Value * 64) + CharVal;
910b57cec5SDimitry Andric     Str = Str.substr(1);
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   if (Value > std::numeric_limits<uint32_t>::max())
950b57cec5SDimitry Andric     return true;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   Result = static_cast<uint32_t>(Value);
980b57cec5SDimitry Andric   return false;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric template <typename coff_symbol_type>
toSymb(DataRefImpl Ref) const1020b57cec5SDimitry Andric const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
1030b57cec5SDimitry Andric   const coff_symbol_type *Addr =
1040b57cec5SDimitry Andric       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1050b57cec5SDimitry Andric 
106af732203SDimitry Andric   assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr)));
1070b57cec5SDimitry Andric #ifndef NDEBUG
1080b57cec5SDimitry Andric   // Verify that the symbol points to a valid entry in the symbol table.
109af732203SDimitry Andric   uintptr_t Offset =
110af732203SDimitry Andric       reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base());
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
1130b57cec5SDimitry Andric          "Symbol did not point to the beginning of a symbol");
1140b57cec5SDimitry Andric #endif
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   return Addr;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
toSec(DataRefImpl Ref) const1190b57cec5SDimitry Andric const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1200b57cec5SDimitry Andric   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric #ifndef NDEBUG
1230b57cec5SDimitry Andric   // Verify that the section points to a valid entry in the section table.
1240b57cec5SDimitry Andric   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1250b57cec5SDimitry Andric     report_fatal_error("Section was outside of section table.");
1260b57cec5SDimitry Andric 
127af732203SDimitry Andric   uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -
128af732203SDimitry Andric                      reinterpret_cast<uintptr_t>(SectionTable);
1290b57cec5SDimitry Andric   assert(Offset % sizeof(coff_section) == 0 &&
1300b57cec5SDimitry Andric          "Section did not point to the beginning of a section");
1310b57cec5SDimitry Andric #endif
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   return Addr;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
moveSymbolNext(DataRefImpl & Ref) const1360b57cec5SDimitry Andric void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
1370b57cec5SDimitry Andric   auto End = reinterpret_cast<uintptr_t>(StringTable);
1380b57cec5SDimitry Andric   if (SymbolTable16) {
1390b57cec5SDimitry Andric     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1400b57cec5SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
1410b57cec5SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
1420b57cec5SDimitry Andric   } else if (SymbolTable32) {
1430b57cec5SDimitry Andric     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
1440b57cec5SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
1450b57cec5SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
1460b57cec5SDimitry Andric   } else {
1470b57cec5SDimitry Andric     llvm_unreachable("no symbol table pointer!");
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric 
getSymbolName(DataRefImpl Ref) const1510b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
1525ffd83dbSDimitry Andric   return getSymbolName(getCOFFSymbol(Ref));
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
getSymbolValueImpl(DataRefImpl Ref) const1550b57cec5SDimitry Andric uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
1560b57cec5SDimitry Andric   return getCOFFSymbol(Ref).getValue();
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
getSymbolAlignment(DataRefImpl Ref) const1590b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1600b57cec5SDimitry Andric   // MSVC/link.exe seems to align symbols to the next-power-of-2
1610b57cec5SDimitry Andric   // up to 32 bytes.
1620b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1630b57cec5SDimitry Andric   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
getSymbolAddress(DataRefImpl Ref) const1660b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
1675ffd83dbSDimitry Andric   uint64_t Result = cantFail(getSymbolValue(Ref));
1680b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1690b57cec5SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   if (Symb.isAnyUndefined() || Symb.isCommon() ||
1720b57cec5SDimitry Andric       COFF::isReservedSectionNumber(SectionNumber))
1730b57cec5SDimitry Andric     return Result;
1740b57cec5SDimitry Andric 
1755ffd83dbSDimitry Andric   Expected<const coff_section *> Section = getSection(SectionNumber);
1765ffd83dbSDimitry Andric   if (!Section)
1775ffd83dbSDimitry Andric     return Section.takeError();
1785ffd83dbSDimitry Andric   Result += (*Section)->VirtualAddress;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
1810b57cec5SDimitry Andric   // return virtual addresses.
1820b57cec5SDimitry Andric   Result += getImageBase();
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   return Result;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
getSymbolType(DataRefImpl Ref) const1870b57cec5SDimitry Andric Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
1880b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1890b57cec5SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
1920b57cec5SDimitry Andric     return SymbolRef::ST_Function;
1930b57cec5SDimitry Andric   if (Symb.isAnyUndefined())
1940b57cec5SDimitry Andric     return SymbolRef::ST_Unknown;
1950b57cec5SDimitry Andric   if (Symb.isCommon())
1960b57cec5SDimitry Andric     return SymbolRef::ST_Data;
1970b57cec5SDimitry Andric   if (Symb.isFileRecord())
1980b57cec5SDimitry Andric     return SymbolRef::ST_File;
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   // TODO: perhaps we need a new symbol type ST_Section.
2010b57cec5SDimitry Andric   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2020b57cec5SDimitry Andric     return SymbolRef::ST_Debug;
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   if (!COFF::isReservedSectionNumber(SectionNumber))
2050b57cec5SDimitry Andric     return SymbolRef::ST_Data;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   return SymbolRef::ST_Other;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
getSymbolFlags(DataRefImpl Ref) const2105ffd83dbSDimitry Andric Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
2110b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2120b57cec5SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   if (Symb.isExternal() || Symb.isWeakExternal())
2150b57cec5SDimitry Andric     Result |= SymbolRef::SF_Global;
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2180b57cec5SDimitry Andric     Result |= SymbolRef::SF_Weak;
2190b57cec5SDimitry Andric     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
2200b57cec5SDimitry Andric       Result |= SymbolRef::SF_Undefined;
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2240b57cec5SDimitry Andric     Result |= SymbolRef::SF_Absolute;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   if (Symb.isFileRecord())
2270b57cec5SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   if (Symb.isSectionDefinition())
2300b57cec5SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   if (Symb.isCommon())
2330b57cec5SDimitry Andric     Result |= SymbolRef::SF_Common;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   if (Symb.isUndefined())
2360b57cec5SDimitry Andric     Result |= SymbolRef::SF_Undefined;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   return Result;
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Ref) const2410b57cec5SDimitry Andric uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
2420b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2430b57cec5SDimitry Andric   return Symb.getValue();
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Ref) const2470b57cec5SDimitry Andric COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
2480b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2490b57cec5SDimitry Andric   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2500b57cec5SDimitry Andric     return section_end();
2515ffd83dbSDimitry Andric   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
2525ffd83dbSDimitry Andric   if (!Sec)
2535ffd83dbSDimitry Andric     return Sec.takeError();
2540b57cec5SDimitry Andric   DataRefImpl Ret;
2555ffd83dbSDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2560b57cec5SDimitry Andric   return section_iterator(SectionRef(Ret, this));
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric 
getSymbolSectionID(SymbolRef Sym) const2590b57cec5SDimitry Andric unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2600b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2610b57cec5SDimitry Andric   return Symb.getSectionNumber();
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
moveSectionNext(DataRefImpl & Ref) const2640b57cec5SDimitry Andric void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2650b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2660b57cec5SDimitry Andric   Sec += 1;
2670b57cec5SDimitry Andric   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
getSectionName(DataRefImpl Ref) const2700b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2710b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2720b57cec5SDimitry Andric   return getSectionName(Sec);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
getSectionAddress(DataRefImpl Ref) const2750b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2760b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2770b57cec5SDimitry Andric   uint64_t Result = Sec->VirtualAddress;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
2800b57cec5SDimitry Andric   // return virtual addresses.
2810b57cec5SDimitry Andric   Result += getImageBase();
2820b57cec5SDimitry Andric   return Result;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const2850b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
2860b57cec5SDimitry Andric   return toSec(Sec) - SectionTable;
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
getSectionSize(DataRefImpl Ref) const2890b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
2900b57cec5SDimitry Andric   return getSectionSize(toSec(Ref));
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Ref) const2940b57cec5SDimitry Andric COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2950b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2960b57cec5SDimitry Andric   ArrayRef<uint8_t> Res;
2970b57cec5SDimitry Andric   if (Error E = getSectionContents(Sec, Res))
2980b57cec5SDimitry Andric     return std::move(E);
2990b57cec5SDimitry Andric   return Res;
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
getSectionAlignment(DataRefImpl Ref) const3020b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3030b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3040b57cec5SDimitry Andric   return Sec->getAlignment();
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const3070b57cec5SDimitry Andric bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
3080b57cec5SDimitry Andric   return false;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric 
isSectionText(DataRefImpl Ref) const3110b57cec5SDimitry Andric bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3120b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3130b57cec5SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
isSectionData(DataRefImpl Ref) const3160b57cec5SDimitry Andric bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3170b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3180b57cec5SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
isSectionBSS(DataRefImpl Ref) const3210b57cec5SDimitry Andric bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3220b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3230b57cec5SDimitry Andric   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3240b57cec5SDimitry Andric                             COFF::IMAGE_SCN_MEM_READ |
3250b57cec5SDimitry Andric                             COFF::IMAGE_SCN_MEM_WRITE;
3260b57cec5SDimitry Andric   return (Sec->Characteristics & BssFlags) == BssFlags;
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
3295ffd83dbSDimitry Andric // The .debug sections are the only debug sections for COFF
3305ffd83dbSDimitry Andric // (\see MCObjectFileInfo.cpp).
isDebugSection(DataRefImpl Ref) const331*5f7ddb14SDimitry Andric bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {
332*5f7ddb14SDimitry Andric   Expected<StringRef> SectionNameOrErr = getSectionName(Ref);
333*5f7ddb14SDimitry Andric   if (!SectionNameOrErr) {
334*5f7ddb14SDimitry Andric     // TODO: Report the error message properly.
335*5f7ddb14SDimitry Andric     consumeError(SectionNameOrErr.takeError());
336*5f7ddb14SDimitry Andric     return false;
337*5f7ddb14SDimitry Andric   }
338*5f7ddb14SDimitry Andric   StringRef SectionName = SectionNameOrErr.get();
3395ffd83dbSDimitry Andric   return SectionName.startswith(".debug");
3405ffd83dbSDimitry Andric }
3415ffd83dbSDimitry Andric 
getSectionID(SectionRef Sec) const3420b57cec5SDimitry Andric unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3430b57cec5SDimitry Andric   uintptr_t Offset =
344af732203SDimitry Andric       Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3450b57cec5SDimitry Andric   assert((Offset % sizeof(coff_section)) == 0);
3460b57cec5SDimitry Andric   return (Offset / sizeof(coff_section)) + 1;
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
isSectionVirtual(DataRefImpl Ref) const3490b57cec5SDimitry Andric bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3500b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3510b57cec5SDimitry Andric   // In COFF, a virtual section won't have any in-file
3520b57cec5SDimitry Andric   // content, so the file pointer to the content will be zero.
3530b57cec5SDimitry Andric   return Sec->PointerToRawData == 0;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
getNumberOfRelocations(const coff_section * Sec,MemoryBufferRef M,const uint8_t * base)3560b57cec5SDimitry Andric static uint32_t getNumberOfRelocations(const coff_section *Sec,
3570b57cec5SDimitry Andric                                        MemoryBufferRef M, const uint8_t *base) {
3580b57cec5SDimitry Andric   // The field for the number of relocations in COFF section table is only
3590b57cec5SDimitry Andric   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
3600b57cec5SDimitry Andric   // NumberOfRelocations field, and the actual relocation count is stored in the
3610b57cec5SDimitry Andric   // VirtualAddress field in the first relocation entry.
3620b57cec5SDimitry Andric   if (Sec->hasExtendedRelocations()) {
3630b57cec5SDimitry Andric     const coff_relocation *FirstReloc;
3645ffd83dbSDimitry Andric     if (Error E = getObject(FirstReloc, M,
3655ffd83dbSDimitry Andric                             reinterpret_cast<const coff_relocation *>(
3665ffd83dbSDimitry Andric                                 base + Sec->PointerToRelocations))) {
3675ffd83dbSDimitry Andric       consumeError(std::move(E));
3680b57cec5SDimitry Andric       return 0;
3695ffd83dbSDimitry Andric     }
3700b57cec5SDimitry Andric     // -1 to exclude this first relocation entry.
3710b57cec5SDimitry Andric     return FirstReloc->VirtualAddress - 1;
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric   return Sec->NumberOfRelocations;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric static const coff_relocation *
getFirstReloc(const coff_section * Sec,MemoryBufferRef M,const uint8_t * Base)3770b57cec5SDimitry Andric getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
3780b57cec5SDimitry Andric   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
3790b57cec5SDimitry Andric   if (!NumRelocs)
3800b57cec5SDimitry Andric     return nullptr;
3810b57cec5SDimitry Andric   auto begin = reinterpret_cast<const coff_relocation *>(
3820b57cec5SDimitry Andric       Base + Sec->PointerToRelocations);
3830b57cec5SDimitry Andric   if (Sec->hasExtendedRelocations()) {
3840b57cec5SDimitry Andric     // Skip the first relocation entry repurposed to store the number of
3850b57cec5SDimitry Andric     // relocations.
3860b57cec5SDimitry Andric     begin++;
3870b57cec5SDimitry Andric   }
388af732203SDimitry Andric   if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
3895ffd83dbSDimitry Andric                                    sizeof(coff_relocation) * NumRelocs)) {
3905ffd83dbSDimitry Andric     consumeError(std::move(E));
3910b57cec5SDimitry Andric     return nullptr;
3925ffd83dbSDimitry Andric   }
3930b57cec5SDimitry Andric   return begin;
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
section_rel_begin(DataRefImpl Ref) const3960b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
3970b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3980b57cec5SDimitry Andric   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
3990b57cec5SDimitry Andric   if (begin && Sec->VirtualAddress != 0)
4000b57cec5SDimitry Andric     report_fatal_error("Sections with relocations should have an address of 0");
4010b57cec5SDimitry Andric   DataRefImpl Ret;
4020b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(begin);
4030b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
section_rel_end(DataRefImpl Ref) const4060b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4070b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
4080b57cec5SDimitry Andric   const coff_relocation *I = getFirstReloc(Sec, Data, base());
4090b57cec5SDimitry Andric   if (I)
4100b57cec5SDimitry Andric     I += getNumberOfRelocations(Sec, Data, base());
4110b57cec5SDimitry Andric   DataRefImpl Ret;
4120b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(I);
4130b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric // Initialize the pointer to the symbol table.
initSymbolTablePtr()4175ffd83dbSDimitry Andric Error COFFObjectFile::initSymbolTablePtr() {
4180b57cec5SDimitry Andric   if (COFFHeader)
4195ffd83dbSDimitry Andric     if (Error E = getObject(
4200b57cec5SDimitry Andric             SymbolTable16, Data, base() + getPointerToSymbolTable(),
4210b57cec5SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4225ffd83dbSDimitry Andric       return E;
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   if (COFFBigObjHeader)
4255ffd83dbSDimitry Andric     if (Error E = getObject(
4260b57cec5SDimitry Andric             SymbolTable32, Data, base() + getPointerToSymbolTable(),
4270b57cec5SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4285ffd83dbSDimitry Andric       return E;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   // Find string table. The first four byte of the string table contains the
4310b57cec5SDimitry Andric   // total size of the string table, including the size field itself. If the
4320b57cec5SDimitry Andric   // string table is empty, the value of the first four byte would be 4.
4330b57cec5SDimitry Andric   uint32_t StringTableOffset = getPointerToSymbolTable() +
4340b57cec5SDimitry Andric                                getNumberOfSymbols() * getSymbolTableEntrySize();
4350b57cec5SDimitry Andric   const uint8_t *StringTableAddr = base() + StringTableOffset;
4360b57cec5SDimitry Andric   const ulittle32_t *StringTableSizePtr;
4375ffd83dbSDimitry Andric   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4385ffd83dbSDimitry Andric     return E;
4390b57cec5SDimitry Andric   StringTableSize = *StringTableSizePtr;
4405ffd83dbSDimitry Andric   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4415ffd83dbSDimitry Andric     return E;
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
4440b57cec5SDimitry Andric   // tools like cvtres write a size of 0 for an empty table instead of 4.
4450b57cec5SDimitry Andric   if (StringTableSize < 4)
4460b57cec5SDimitry Andric     StringTableSize = 4;
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   // Check that the string table is null terminated if has any in it.
4490b57cec5SDimitry Andric   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
4505ffd83dbSDimitry Andric     return errorCodeToError(object_error::parse_failed);
4515ffd83dbSDimitry Andric   return Error::success();
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
getImageBase() const4540b57cec5SDimitry Andric uint64_t COFFObjectFile::getImageBase() const {
4550b57cec5SDimitry Andric   if (PE32Header)
4560b57cec5SDimitry Andric     return PE32Header->ImageBase;
4570b57cec5SDimitry Andric   else if (PE32PlusHeader)
4580b57cec5SDimitry Andric     return PE32PlusHeader->ImageBase;
4590b57cec5SDimitry Andric   // This actually comes up in practice.
4600b57cec5SDimitry Andric   return 0;
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric // Returns the file offset for the given VA.
getVaPtr(uint64_t Addr,uintptr_t & Res) const4645ffd83dbSDimitry Andric Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
4650b57cec5SDimitry Andric   uint64_t ImageBase = getImageBase();
4660b57cec5SDimitry Andric   uint64_t Rva = Addr - ImageBase;
4670b57cec5SDimitry Andric   assert(Rva <= UINT32_MAX);
4680b57cec5SDimitry Andric   return getRvaPtr((uint32_t)Rva, Res);
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric // Returns the file offset for the given RVA.
getRvaPtr(uint32_t Addr,uintptr_t & Res) const4725ffd83dbSDimitry Andric Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
4730b57cec5SDimitry Andric   for (const SectionRef &S : sections()) {
4740b57cec5SDimitry Andric     const coff_section *Section = getCOFFSection(S);
4750b57cec5SDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
4760b57cec5SDimitry Andric     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
4770b57cec5SDimitry Andric     if (SectionStart <= Addr && Addr < SectionEnd) {
4780b57cec5SDimitry Andric       uint32_t Offset = Addr - SectionStart;
479af732203SDimitry Andric       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
480af732203SDimitry Andric             Offset;
4815ffd83dbSDimitry Andric       return Error::success();
4820b57cec5SDimitry Andric     }
4830b57cec5SDimitry Andric   }
4845ffd83dbSDimitry Andric   return errorCodeToError(object_error::parse_failed);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
getRvaAndSizeAsBytes(uint32_t RVA,uint32_t Size,ArrayRef<uint8_t> & Contents) const4875ffd83dbSDimitry Andric Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4880b57cec5SDimitry Andric                                            ArrayRef<uint8_t> &Contents) const {
4890b57cec5SDimitry Andric   for (const SectionRef &S : sections()) {
4900b57cec5SDimitry Andric     const coff_section *Section = getCOFFSection(S);
4910b57cec5SDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
4920b57cec5SDimitry Andric     // Check if this RVA is within the section bounds. Be careful about integer
4930b57cec5SDimitry Andric     // overflow.
4940b57cec5SDimitry Andric     uint32_t OffsetIntoSection = RVA - SectionStart;
4950b57cec5SDimitry Andric     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4960b57cec5SDimitry Andric         Size <= Section->VirtualSize - OffsetIntoSection) {
497af732203SDimitry Andric       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
498af732203SDimitry Andric                         Section->PointerToRawData + OffsetIntoSection;
4990b57cec5SDimitry Andric       Contents =
5000b57cec5SDimitry Andric           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5015ffd83dbSDimitry Andric       return Error::success();
5020b57cec5SDimitry Andric     }
5030b57cec5SDimitry Andric   }
5045ffd83dbSDimitry Andric   return errorCodeToError(object_error::parse_failed);
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
5080b57cec5SDimitry Andric // table entry.
getHintName(uint32_t Rva,uint16_t & Hint,StringRef & Name) const5095ffd83dbSDimitry Andric Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
5100b57cec5SDimitry Andric                                   StringRef &Name) const {
5110b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
5125ffd83dbSDimitry Andric   if (Error E = getRvaPtr(Rva, IntPtr))
5135ffd83dbSDimitry Andric     return E;
5140b57cec5SDimitry Andric   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
5150b57cec5SDimitry Andric   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
5160b57cec5SDimitry Andric   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5175ffd83dbSDimitry Andric   return Error::success();
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric 
getDebugPDBInfo(const debug_directory * DebugDir,const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const5205ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
5210b57cec5SDimitry Andric                                       const codeview::DebugInfo *&PDBInfo,
5220b57cec5SDimitry Andric                                       StringRef &PDBFileName) const {
5230b57cec5SDimitry Andric   ArrayRef<uint8_t> InfoBytes;
5245ffd83dbSDimitry Andric   if (Error E = getRvaAndSizeAsBytes(
5250b57cec5SDimitry Andric           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5265ffd83dbSDimitry Andric     return E;
5270b57cec5SDimitry Andric   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5285ffd83dbSDimitry Andric     return errorCodeToError(object_error::parse_failed);
5290b57cec5SDimitry Andric   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
5300b57cec5SDimitry Andric   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5310b57cec5SDimitry Andric   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5320b57cec5SDimitry Andric                           InfoBytes.size());
5330b57cec5SDimitry Andric   // Truncate the name at the first null byte. Ignore any padding.
5340b57cec5SDimitry Andric   PDBFileName = PDBFileName.split('\0').first;
5355ffd83dbSDimitry Andric   return Error::success();
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
getDebugPDBInfo(const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const5385ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
5390b57cec5SDimitry Andric                                       StringRef &PDBFileName) const {
5400b57cec5SDimitry Andric   for (const debug_directory &D : debug_directories())
5410b57cec5SDimitry Andric     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
5420b57cec5SDimitry Andric       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
5430b57cec5SDimitry Andric   // If we get here, there is no PDB info to return.
5440b57cec5SDimitry Andric   PDBInfo = nullptr;
5450b57cec5SDimitry Andric   PDBFileName = StringRef();
5465ffd83dbSDimitry Andric   return Error::success();
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric // Find the import table.
initImportTablePtr()5505ffd83dbSDimitry Andric Error COFFObjectFile::initImportTablePtr() {
5510b57cec5SDimitry Andric   // First, we get the RVA of the import table. If the file lacks a pointer to
5520b57cec5SDimitry Andric   // the import table, do nothing.
5535ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5545ffd83dbSDimitry Andric   if (!DataEntry)
5555ffd83dbSDimitry Andric     return Error::success();
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   // Do nothing if the pointer to import table is NULL.
5580b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
5595ffd83dbSDimitry Andric     return Error::success();
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   // Find the section that contains the RVA. This is needed because the RVA is
5640b57cec5SDimitry Andric   // the import table's memory address which is different from its file offset.
5650b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
5665ffd83dbSDimitry Andric   if (Error E = getRvaPtr(ImportTableRva, IntPtr))
5675ffd83dbSDimitry Andric     return E;
5685ffd83dbSDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5695ffd83dbSDimitry Andric     return E;
5700b57cec5SDimitry Andric   ImportDirectory = reinterpret_cast<
5710b57cec5SDimitry Andric       const coff_import_directory_table_entry *>(IntPtr);
5725ffd83dbSDimitry Andric   return Error::success();
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
initDelayImportTablePtr()5765ffd83dbSDimitry Andric Error COFFObjectFile::initDelayImportTablePtr() {
5775ffd83dbSDimitry Andric   const data_directory *DataEntry =
5785ffd83dbSDimitry Andric       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
5795ffd83dbSDimitry Andric   if (!DataEntry)
5805ffd83dbSDimitry Andric     return Error::success();
5810b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
5825ffd83dbSDimitry Andric     return Error::success();
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   uint32_t RVA = DataEntry->RelativeVirtualAddress;
5850b57cec5SDimitry Andric   NumberOfDelayImportDirectory = DataEntry->Size /
5860b57cec5SDimitry Andric       sizeof(delay_import_directory_table_entry) - 1;
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
5895ffd83dbSDimitry Andric   if (Error E = getRvaPtr(RVA, IntPtr))
5905ffd83dbSDimitry Andric     return E;
5910b57cec5SDimitry Andric   DelayImportDirectory = reinterpret_cast<
5920b57cec5SDimitry Andric       const delay_import_directory_table_entry *>(IntPtr);
5935ffd83dbSDimitry Andric   return Error::success();
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric // Find the export table.
initExportTablePtr()5975ffd83dbSDimitry Andric Error COFFObjectFile::initExportTablePtr() {
5980b57cec5SDimitry Andric   // First, we get the RVA of the export table. If the file lacks a pointer to
5990b57cec5SDimitry Andric   // the export table, do nothing.
6005ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6015ffd83dbSDimitry Andric   if (!DataEntry)
6025ffd83dbSDimitry Andric     return Error::success();
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   // Do nothing if the pointer to export table is NULL.
6050b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6065ffd83dbSDimitry Andric     return Error::success();
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
6090b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
6105ffd83dbSDimitry Andric   if (Error E = getRvaPtr(ExportTableRva, IntPtr))
6115ffd83dbSDimitry Andric     return E;
6120b57cec5SDimitry Andric   ExportDirectory =
6130b57cec5SDimitry Andric       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6145ffd83dbSDimitry Andric   return Error::success();
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
initBaseRelocPtr()6175ffd83dbSDimitry Andric Error COFFObjectFile::initBaseRelocPtr() {
6185ffd83dbSDimitry Andric   const data_directory *DataEntry =
6195ffd83dbSDimitry Andric       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6205ffd83dbSDimitry Andric   if (!DataEntry)
6215ffd83dbSDimitry Andric     return Error::success();
6220b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6235ffd83dbSDimitry Andric     return Error::success();
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
6265ffd83dbSDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6275ffd83dbSDimitry Andric     return E;
6280b57cec5SDimitry Andric   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
6290b57cec5SDimitry Andric       IntPtr);
6300b57cec5SDimitry Andric   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
6310b57cec5SDimitry Andric       IntPtr + DataEntry->Size);
6320b57cec5SDimitry Andric   // FIXME: Verify the section containing BaseRelocHeader has at least
6330b57cec5SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6345ffd83dbSDimitry Andric   return Error::success();
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric 
initDebugDirectoryPtr()6375ffd83dbSDimitry Andric Error COFFObjectFile::initDebugDirectoryPtr() {
6380b57cec5SDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
6395ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6405ffd83dbSDimitry Andric   if (!DataEntry)
6415ffd83dbSDimitry Andric     return Error::success();
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   // Do nothing if the RVA is NULL.
6440b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6455ffd83dbSDimitry Andric     return Error::success();
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   // Check that the size is a multiple of the entry size.
6480b57cec5SDimitry Andric   if (DataEntry->Size % sizeof(debug_directory) != 0)
6495ffd83dbSDimitry Andric     return errorCodeToError(object_error::parse_failed);
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
6525ffd83dbSDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6535ffd83dbSDimitry Andric     return E;
6540b57cec5SDimitry Andric   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6550b57cec5SDimitry Andric   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
6560b57cec5SDimitry Andric       IntPtr + DataEntry->Size);
6570b57cec5SDimitry Andric   // FIXME: Verify the section containing DebugDirectoryBegin has at least
6580b57cec5SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6595ffd83dbSDimitry Andric   return Error::success();
6600b57cec5SDimitry Andric }
6610b57cec5SDimitry Andric 
initTLSDirectoryPtr()662af732203SDimitry Andric Error COFFObjectFile::initTLSDirectoryPtr() {
663af732203SDimitry Andric   // Get the RVA of the TLS directory. Do nothing if it does not exist.
664af732203SDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
665af732203SDimitry Andric   if (!DataEntry)
666af732203SDimitry Andric     return Error::success();
667af732203SDimitry Andric 
668af732203SDimitry Andric   // Do nothing if the RVA is NULL.
669af732203SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
670af732203SDimitry Andric     return Error::success();
671af732203SDimitry Andric 
672af732203SDimitry Andric   uint64_t DirSize =
673af732203SDimitry Andric       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
674af732203SDimitry Andric 
675af732203SDimitry Andric   // Check that the size is correct.
676af732203SDimitry Andric   if (DataEntry->Size != DirSize)
677af732203SDimitry Andric     return createStringError(
678af732203SDimitry Andric         object_error::parse_failed,
679af732203SDimitry Andric         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
680af732203SDimitry Andric         static_cast<uint32_t>(DataEntry->Size), DirSize);
681af732203SDimitry Andric 
682af732203SDimitry Andric   uintptr_t IntPtr = 0;
683af732203SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
684af732203SDimitry Andric     return E;
685af732203SDimitry Andric 
686af732203SDimitry Andric   if (is64())
687af732203SDimitry Andric     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
688af732203SDimitry Andric   else
689af732203SDimitry Andric     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
690af732203SDimitry Andric 
691af732203SDimitry Andric   return Error::success();
692af732203SDimitry Andric }
693af732203SDimitry Andric 
initLoadConfigPtr()6945ffd83dbSDimitry Andric Error COFFObjectFile::initLoadConfigPtr() {
6950b57cec5SDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
6965ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
6975ffd83dbSDimitry Andric   if (!DataEntry)
6985ffd83dbSDimitry Andric     return Error::success();
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   // Do nothing if the RVA is NULL.
7010b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
7025ffd83dbSDimitry Andric     return Error::success();
7030b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
7045ffd83dbSDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
7055ffd83dbSDimitry Andric     return E;
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   LoadConfig = (const void *)IntPtr;
7085ffd83dbSDimitry Andric   return Error::success();
7090b57cec5SDimitry Andric }
7100b57cec5SDimitry Andric 
7115ffd83dbSDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
create(MemoryBufferRef Object)7125ffd83dbSDimitry Andric COFFObjectFile::create(MemoryBufferRef Object) {
7135ffd83dbSDimitry Andric   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
7145ffd83dbSDimitry Andric   if (Error E = Obj->initialize())
7155ffd83dbSDimitry Andric     return std::move(E);
7165ffd83dbSDimitry Andric   return std::move(Obj);
7175ffd83dbSDimitry Andric }
7185ffd83dbSDimitry Andric 
COFFObjectFile(MemoryBufferRef Object)7195ffd83dbSDimitry Andric COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
7200b57cec5SDimitry Andric     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
7210b57cec5SDimitry Andric       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
7220b57cec5SDimitry Andric       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
7230b57cec5SDimitry Andric       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
7245ffd83dbSDimitry Andric       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
7255ffd83dbSDimitry Andric       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
7265ffd83dbSDimitry Andric       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
727af732203SDimitry Andric       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
728af732203SDimitry Andric       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
7295ffd83dbSDimitry Andric 
initialize()7305ffd83dbSDimitry Andric Error COFFObjectFile::initialize() {
7310b57cec5SDimitry Andric   // Check that we at least have enough room for a header.
7325ffd83dbSDimitry Andric   std::error_code EC;
7330b57cec5SDimitry Andric   if (!checkSize(Data, EC, sizeof(coff_file_header)))
7345ffd83dbSDimitry Andric     return errorCodeToError(EC);
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   // The current location in the file where we are looking at.
7370b57cec5SDimitry Andric   uint64_t CurPtr = 0;
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric   // PE header is optional and is present only in executables. If it exists,
7400b57cec5SDimitry Andric   // it is placed right after COFF header.
7410b57cec5SDimitry Andric   bool HasPEHeader = false;
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   // Check if this is a PE/COFF file.
7440b57cec5SDimitry Andric   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
7450b57cec5SDimitry Andric     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
7460b57cec5SDimitry Andric     // PE signature to find 'normal' COFF header.
7470b57cec5SDimitry Andric     const auto *DH = reinterpret_cast<const dos_header *>(base());
7480b57cec5SDimitry Andric     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
7490b57cec5SDimitry Andric       CurPtr = DH->AddressOfNewExeHeader;
7500b57cec5SDimitry Andric       // Check the PE magic bytes. ("PE\0\0")
7510b57cec5SDimitry Andric       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
7525ffd83dbSDimitry Andric         return errorCodeToError(object_error::parse_failed);
7530b57cec5SDimitry Andric       }
7540b57cec5SDimitry Andric       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7550b57cec5SDimitry Andric       HasPEHeader = true;
7560b57cec5SDimitry Andric     }
7570b57cec5SDimitry Andric   }
7580b57cec5SDimitry Andric 
7595ffd83dbSDimitry Andric   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
7605ffd83dbSDimitry Andric     return E;
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
7630b57cec5SDimitry Andric   // import libraries share a common prefix but bigobj is more restrictive.
7640b57cec5SDimitry Andric   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
7650b57cec5SDimitry Andric       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
7660b57cec5SDimitry Andric       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
7675ffd83dbSDimitry Andric     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
7685ffd83dbSDimitry Andric       return E;
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric     // Verify that we are dealing with bigobj.
7710b57cec5SDimitry Andric     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
7720b57cec5SDimitry Andric         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
7730b57cec5SDimitry Andric                     sizeof(COFF::BigObjMagic)) == 0) {
7740b57cec5SDimitry Andric       COFFHeader = nullptr;
7750b57cec5SDimitry Andric       CurPtr += sizeof(coff_bigobj_file_header);
7760b57cec5SDimitry Andric     } else {
7770b57cec5SDimitry Andric       // It's not a bigobj.
7780b57cec5SDimitry Andric       COFFBigObjHeader = nullptr;
7790b57cec5SDimitry Andric     }
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric   if (COFFHeader) {
7820b57cec5SDimitry Andric     // The prior checkSize call may have failed.  This isn't a hard error
7830b57cec5SDimitry Andric     // because we were just trying to sniff out bigobj.
7840b57cec5SDimitry Andric     EC = std::error_code();
7850b57cec5SDimitry Andric     CurPtr += sizeof(coff_file_header);
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric     if (COFFHeader->isImportLibrary())
7885ffd83dbSDimitry Andric       return errorCodeToError(EC);
7890b57cec5SDimitry Andric   }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   if (HasPEHeader) {
7920b57cec5SDimitry Andric     const pe32_header *Header;
7935ffd83dbSDimitry Andric     if (Error E = getObject(Header, Data, base() + CurPtr))
7945ffd83dbSDimitry Andric       return E;
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric     const uint8_t *DataDirAddr;
7970b57cec5SDimitry Andric     uint64_t DataDirSize;
7980b57cec5SDimitry Andric     if (Header->Magic == COFF::PE32Header::PE32) {
7990b57cec5SDimitry Andric       PE32Header = Header;
8000b57cec5SDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
8010b57cec5SDimitry Andric       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
8020b57cec5SDimitry Andric     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
8030b57cec5SDimitry Andric       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
8040b57cec5SDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
8050b57cec5SDimitry Andric       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
8060b57cec5SDimitry Andric     } else {
8070b57cec5SDimitry Andric       // It's neither PE32 nor PE32+.
8085ffd83dbSDimitry Andric       return errorCodeToError(object_error::parse_failed);
8090b57cec5SDimitry Andric     }
8105ffd83dbSDimitry Andric     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8115ffd83dbSDimitry Andric       return E;
8120b57cec5SDimitry Andric   }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   if (COFFHeader)
8150b57cec5SDimitry Andric     CurPtr += COFFHeader->SizeOfOptionalHeader;
8160b57cec5SDimitry Andric 
8175ffd83dbSDimitry Andric   assert(COFFHeader || COFFBigObjHeader);
8185ffd83dbSDimitry Andric 
8195ffd83dbSDimitry Andric   if (Error E =
8205ffd83dbSDimitry Andric           getObject(SectionTable, Data, base() + CurPtr,
8215ffd83dbSDimitry Andric                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8225ffd83dbSDimitry Andric     return E;
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   // Initialize the pointer to the symbol table.
8250b57cec5SDimitry Andric   if (getPointerToSymbolTable() != 0) {
8265ffd83dbSDimitry Andric     if (Error E = initSymbolTablePtr()) {
8275ffd83dbSDimitry Andric       // Recover from errors reading the symbol table.
8285ffd83dbSDimitry Andric       consumeError(std::move(E));
8290b57cec5SDimitry Andric       SymbolTable16 = nullptr;
8300b57cec5SDimitry Andric       SymbolTable32 = nullptr;
8310b57cec5SDimitry Andric       StringTable = nullptr;
8320b57cec5SDimitry Andric       StringTableSize = 0;
8330b57cec5SDimitry Andric     }
8340b57cec5SDimitry Andric   } else {
8350b57cec5SDimitry Andric     // We had better not have any symbols if we don't have a symbol table.
8360b57cec5SDimitry Andric     if (getNumberOfSymbols() != 0) {
8375ffd83dbSDimitry Andric       return errorCodeToError(object_error::parse_failed);
8380b57cec5SDimitry Andric     }
8390b57cec5SDimitry Andric   }
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric   // Initialize the pointer to the beginning of the import table.
8425ffd83dbSDimitry Andric   if (Error E = initImportTablePtr())
8435ffd83dbSDimitry Andric     return E;
8445ffd83dbSDimitry Andric   if (Error E = initDelayImportTablePtr())
8455ffd83dbSDimitry Andric     return E;
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // Initialize the pointer to the export table.
8485ffd83dbSDimitry Andric   if (Error E = initExportTablePtr())
8495ffd83dbSDimitry Andric     return E;
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric   // Initialize the pointer to the base relocation table.
8525ffd83dbSDimitry Andric   if (Error E = initBaseRelocPtr())
8535ffd83dbSDimitry Andric     return E;
8540b57cec5SDimitry Andric 
855af732203SDimitry Andric   // Initialize the pointer to the debug directory.
8565ffd83dbSDimitry Andric   if (Error E = initDebugDirectoryPtr())
8575ffd83dbSDimitry Andric     return E;
8580b57cec5SDimitry Andric 
859af732203SDimitry Andric   // Initialize the pointer to the TLS directory.
860af732203SDimitry Andric   if (Error E = initTLSDirectoryPtr())
861af732203SDimitry Andric     return E;
862af732203SDimitry Andric 
8635ffd83dbSDimitry Andric   if (Error E = initLoadConfigPtr())
8645ffd83dbSDimitry Andric     return E;
8650b57cec5SDimitry Andric 
8665ffd83dbSDimitry Andric   return Error::success();
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric 
symbol_begin() const8690b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8700b57cec5SDimitry Andric   DataRefImpl Ret;
8710b57cec5SDimitry Andric   Ret.p = getSymbolTable();
8720b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric 
symbol_end() const8750b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_end() const {
8760b57cec5SDimitry Andric   // The symbol table ends where the string table begins.
8770b57cec5SDimitry Andric   DataRefImpl Ret;
8780b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
8790b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
8800b57cec5SDimitry Andric }
8810b57cec5SDimitry Andric 
import_directory_begin() const8820b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_begin() const {
8830b57cec5SDimitry Andric   if (!ImportDirectory)
8840b57cec5SDimitry Andric     return import_directory_end();
8850b57cec5SDimitry Andric   if (ImportDirectory->isNull())
8860b57cec5SDimitry Andric     return import_directory_end();
8870b57cec5SDimitry Andric   return import_directory_iterator(
8880b57cec5SDimitry Andric       ImportDirectoryEntryRef(ImportDirectory, 0, this));
8890b57cec5SDimitry Andric }
8900b57cec5SDimitry Andric 
import_directory_end() const8910b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_end() const {
8920b57cec5SDimitry Andric   return import_directory_iterator(
8930b57cec5SDimitry Andric       ImportDirectoryEntryRef(nullptr, -1, this));
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric delay_import_directory_iterator
delay_import_directory_begin() const8970b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_begin() const {
8980b57cec5SDimitry Andric   return delay_import_directory_iterator(
8990b57cec5SDimitry Andric       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
9000b57cec5SDimitry Andric }
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric delay_import_directory_iterator
delay_import_directory_end() const9030b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_end() const {
9040b57cec5SDimitry Andric   return delay_import_directory_iterator(
9050b57cec5SDimitry Andric       DelayImportDirectoryEntryRef(
9060b57cec5SDimitry Andric           DelayImportDirectory, NumberOfDelayImportDirectory, this));
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric 
export_directory_begin() const9090b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_begin() const {
9100b57cec5SDimitry Andric   return export_directory_iterator(
9110b57cec5SDimitry Andric       ExportDirectoryEntryRef(ExportDirectory, 0, this));
9120b57cec5SDimitry Andric }
9130b57cec5SDimitry Andric 
export_directory_end() const9140b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_end() const {
9150b57cec5SDimitry Andric   if (!ExportDirectory)
9160b57cec5SDimitry Andric     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9170b57cec5SDimitry Andric   ExportDirectoryEntryRef Ref(ExportDirectory,
9180b57cec5SDimitry Andric                               ExportDirectory->AddressTableEntries, this);
9190b57cec5SDimitry Andric   return export_directory_iterator(Ref);
9200b57cec5SDimitry Andric }
9210b57cec5SDimitry Andric 
section_begin() const9220b57cec5SDimitry Andric section_iterator COFFObjectFile::section_begin() const {
9230b57cec5SDimitry Andric   DataRefImpl Ret;
9240b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9250b57cec5SDimitry Andric   return section_iterator(SectionRef(Ret, this));
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric 
section_end() const9280b57cec5SDimitry Andric section_iterator COFFObjectFile::section_end() const {
9290b57cec5SDimitry Andric   DataRefImpl Ret;
9300b57cec5SDimitry Andric   int NumSections =
9310b57cec5SDimitry Andric       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9320b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9330b57cec5SDimitry Andric   return section_iterator(SectionRef(Ret, this));
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric 
base_reloc_begin() const9360b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
9370b57cec5SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
9380b57cec5SDimitry Andric }
9390b57cec5SDimitry Andric 
base_reloc_end() const9400b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_end() const {
9410b57cec5SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric 
getBytesInAddress() const9440b57cec5SDimitry Andric uint8_t COFFObjectFile::getBytesInAddress() const {
9450b57cec5SDimitry Andric   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
getFileFormatName() const9480b57cec5SDimitry Andric StringRef COFFObjectFile::getFileFormatName() const {
9490b57cec5SDimitry Andric   switch(getMachine()) {
9500b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
9510b57cec5SDimitry Andric     return "COFF-i386";
9520b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
9530b57cec5SDimitry Andric     return "COFF-x86-64";
9540b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9550b57cec5SDimitry Andric     return "COFF-ARM";
9560b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
9570b57cec5SDimitry Andric     return "COFF-ARM64";
9580b57cec5SDimitry Andric   default:
9590b57cec5SDimitry Andric     return "COFF-<unknown arch>";
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
getArch() const9630b57cec5SDimitry Andric Triple::ArchType COFFObjectFile::getArch() const {
9640b57cec5SDimitry Andric   switch (getMachine()) {
9650b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
9660b57cec5SDimitry Andric     return Triple::x86;
9670b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
9680b57cec5SDimitry Andric     return Triple::x86_64;
9690b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9700b57cec5SDimitry Andric     return Triple::thumb;
9710b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
9720b57cec5SDimitry Andric     return Triple::aarch64;
9730b57cec5SDimitry Andric   default:
9740b57cec5SDimitry Andric     return Triple::UnknownArch;
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric 
getStartAddress() const9780b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getStartAddress() const {
9790b57cec5SDimitry Andric   if (PE32Header)
9800b57cec5SDimitry Andric     return PE32Header->AddressOfEntryPoint;
9810b57cec5SDimitry Andric   return 0;
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric iterator_range<import_directory_iterator>
import_directories() const9850b57cec5SDimitry Andric COFFObjectFile::import_directories() const {
9860b57cec5SDimitry Andric   return make_range(import_directory_begin(), import_directory_end());
9870b57cec5SDimitry Andric }
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric iterator_range<delay_import_directory_iterator>
delay_import_directories() const9900b57cec5SDimitry Andric COFFObjectFile::delay_import_directories() const {
9910b57cec5SDimitry Andric   return make_range(delay_import_directory_begin(),
9920b57cec5SDimitry Andric                     delay_import_directory_end());
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric iterator_range<export_directory_iterator>
export_directories() const9960b57cec5SDimitry Andric COFFObjectFile::export_directories() const {
9970b57cec5SDimitry Andric   return make_range(export_directory_begin(), export_directory_end());
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric 
base_relocs() const10000b57cec5SDimitry Andric iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
10010b57cec5SDimitry Andric   return make_range(base_reloc_begin(), base_reloc_end());
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric 
getDataDirectory(uint32_t Index) const10045ffd83dbSDimitry Andric const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
10055ffd83dbSDimitry Andric   if (!DataDirectory)
10065ffd83dbSDimitry Andric     return nullptr;
10070b57cec5SDimitry Andric   assert(PE32Header || PE32PlusHeader);
10080b57cec5SDimitry Andric   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
10090b57cec5SDimitry Andric                                : PE32PlusHeader->NumberOfRvaAndSize;
10105ffd83dbSDimitry Andric   if (Index >= NumEnt)
10115ffd83dbSDimitry Andric     return nullptr;
10125ffd83dbSDimitry Andric   return &DataDirectory[Index];
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
getSection(int32_t Index) const10155ffd83dbSDimitry Andric Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
10165ffd83dbSDimitry Andric   // Perhaps getting the section of a reserved section index should be an error,
10175ffd83dbSDimitry Andric   // but callers rely on this to return null.
10180b57cec5SDimitry Andric   if (COFF::isReservedSectionNumber(Index))
10195ffd83dbSDimitry Andric     return (const coff_section *)nullptr;
10200b57cec5SDimitry Andric   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10210b57cec5SDimitry Andric     // We already verified the section table data, so no need to check again.
10225ffd83dbSDimitry Andric     return SectionTable + (Index - 1);
10230b57cec5SDimitry Andric   }
10245ffd83dbSDimitry Andric   return errorCodeToError(object_error::parse_failed);
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
getString(uint32_t Offset) const10275ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10280b57cec5SDimitry Andric   if (StringTableSize <= 4)
10290b57cec5SDimitry Andric     // Tried to get a string from an empty string table.
10305ffd83dbSDimitry Andric     return errorCodeToError(object_error::parse_failed);
10310b57cec5SDimitry Andric   if (Offset >= StringTableSize)
10325ffd83dbSDimitry Andric     return errorCodeToError(object_error::unexpected_eof);
10335ffd83dbSDimitry Andric   return StringRef(StringTable + Offset);
10340b57cec5SDimitry Andric }
10350b57cec5SDimitry Andric 
getSymbolName(COFFSymbolRef Symbol) const10365ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
10375ffd83dbSDimitry Andric   return getSymbolName(Symbol.getGeneric());
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
10405ffd83dbSDimitry Andric Expected<StringRef>
getSymbolName(const coff_symbol_generic * Symbol) const10415ffd83dbSDimitry Andric COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
10420b57cec5SDimitry Andric   // Check for string table entry. First 4 bytes are 0.
10435ffd83dbSDimitry Andric   if (Symbol->Name.Offset.Zeroes == 0)
10445ffd83dbSDimitry Andric     return getString(Symbol->Name.Offset.Offset);
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric   // Null terminated, let ::strlen figure out the length.
10475ffd83dbSDimitry Andric   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
10485ffd83dbSDimitry Andric     return StringRef(Symbol->Name.ShortName);
10495ffd83dbSDimitry Andric 
10500b57cec5SDimitry Andric   // Not null terminated, use all 8 bytes.
10515ffd83dbSDimitry Andric   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric ArrayRef<uint8_t>
getSymbolAuxData(COFFSymbolRef Symbol) const10550b57cec5SDimitry Andric COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10560b57cec5SDimitry Andric   const uint8_t *Aux = nullptr;
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric   size_t SymbolSize = getSymbolTableEntrySize();
10590b57cec5SDimitry Andric   if (Symbol.getNumberOfAuxSymbols() > 0) {
10600b57cec5SDimitry Andric     // AUX data comes immediately after the symbol in COFF
10610b57cec5SDimitry Andric     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
10620b57cec5SDimitry Andric #ifndef NDEBUG
10630b57cec5SDimitry Andric     // Verify that the Aux symbol points to a valid entry in the symbol table.
10640b57cec5SDimitry Andric     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
10650b57cec5SDimitry Andric     if (Offset < getPointerToSymbolTable() ||
10660b57cec5SDimitry Andric         Offset >=
10670b57cec5SDimitry Andric             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
10680b57cec5SDimitry Andric       report_fatal_error("Aux Symbol data was outside of symbol table.");
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
10710b57cec5SDimitry Andric            "Aux Symbol data did not point to the beginning of a symbol");
10720b57cec5SDimitry Andric #endif
10730b57cec5SDimitry Andric   }
10740b57cec5SDimitry Andric   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
getSymbolIndex(COFFSymbolRef Symbol) const10770b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
10780b57cec5SDimitry Andric   uintptr_t Offset =
10790b57cec5SDimitry Andric       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
10800b57cec5SDimitry Andric   assert(Offset % getSymbolTableEntrySize() == 0 &&
10810b57cec5SDimitry Andric          "Symbol did not point to the beginning of a symbol");
10820b57cec5SDimitry Andric   size_t Index = Offset / getSymbolTableEntrySize();
10830b57cec5SDimitry Andric   assert(Index < getNumberOfSymbols());
10840b57cec5SDimitry Andric   return Index;
10850b57cec5SDimitry Andric }
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric Expected<StringRef>
getSectionName(const coff_section * Sec) const10880b57cec5SDimitry Andric COFFObjectFile::getSectionName(const coff_section *Sec) const {
10890b57cec5SDimitry Andric   StringRef Name;
10900b57cec5SDimitry Andric   if (Sec->Name[COFF::NameSize - 1] == 0)
10910b57cec5SDimitry Andric     // Null terminated, let ::strlen figure out the length.
10920b57cec5SDimitry Andric     Name = Sec->Name;
10930b57cec5SDimitry Andric   else
10940b57cec5SDimitry Andric     // Not null terminated, use all 8 bytes.
10950b57cec5SDimitry Andric     Name = StringRef(Sec->Name, COFF::NameSize);
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   // Check for string table entry. First byte is '/'.
10980b57cec5SDimitry Andric   if (Name.startswith("/")) {
10990b57cec5SDimitry Andric     uint32_t Offset;
11000b57cec5SDimitry Andric     if (Name.startswith("//")) {
11010b57cec5SDimitry Andric       if (decodeBase64StringEntry(Name.substr(2), Offset))
11020b57cec5SDimitry Andric         return createStringError(object_error::parse_failed,
11035ffd83dbSDimitry Andric                                  "invalid section name");
11040b57cec5SDimitry Andric     } else {
11050b57cec5SDimitry Andric       if (Name.substr(1).getAsInteger(10, Offset))
11060b57cec5SDimitry Andric         return createStringError(object_error::parse_failed,
11070b57cec5SDimitry Andric                                  "invalid section name");
11080b57cec5SDimitry Andric     }
11095ffd83dbSDimitry Andric     return getString(Offset);
11100b57cec5SDimitry Andric   }
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   return Name;
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric 
getSectionSize(const coff_section * Sec) const11150b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
11160b57cec5SDimitry Andric   // SizeOfRawData and VirtualSize change what they represent depending on
11170b57cec5SDimitry Andric   // whether or not we have an executable image.
11180b57cec5SDimitry Andric   //
11190b57cec5SDimitry Andric   // For object files, SizeOfRawData contains the size of section's data;
11200b57cec5SDimitry Andric   // VirtualSize should be zero but isn't due to buggy COFF writers.
11210b57cec5SDimitry Andric   //
11220b57cec5SDimitry Andric   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
11230b57cec5SDimitry Andric   // actual section size is in VirtualSize.  It is possible for VirtualSize to
11240b57cec5SDimitry Andric   // be greater than SizeOfRawData; the contents past that point should be
11250b57cec5SDimitry Andric   // considered to be zero.
11260b57cec5SDimitry Andric   if (getDOSHeader())
11270b57cec5SDimitry Andric     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
11280b57cec5SDimitry Andric   return Sec->SizeOfRawData;
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric 
getSectionContents(const coff_section * Sec,ArrayRef<uint8_t> & Res) const11310b57cec5SDimitry Andric Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11320b57cec5SDimitry Andric                                          ArrayRef<uint8_t> &Res) const {
11330b57cec5SDimitry Andric   // In COFF, a virtual section won't have any in-file
11340b57cec5SDimitry Andric   // content, so the file pointer to the content will be zero.
11350b57cec5SDimitry Andric   if (Sec->PointerToRawData == 0)
11360b57cec5SDimitry Andric     return Error::success();
11370b57cec5SDimitry Andric   // The only thing that we need to verify is that the contents is contained
11380b57cec5SDimitry Andric   // within the file bounds. We don't need to make sure it doesn't cover other
11390b57cec5SDimitry Andric   // data, as there's nothing that says that is not allowed.
1140af732203SDimitry Andric   uintptr_t ConStart =
1141af732203SDimitry Andric       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
11420b57cec5SDimitry Andric   uint32_t SectionSize = getSectionSize(Sec);
11435ffd83dbSDimitry Andric   if (Error E = checkOffset(Data, ConStart, SectionSize))
11445ffd83dbSDimitry Andric     return E;
11450b57cec5SDimitry Andric   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
11460b57cec5SDimitry Andric   return Error::success();
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric 
toRel(DataRefImpl Rel) const11490b57cec5SDimitry Andric const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
11500b57cec5SDimitry Andric   return reinterpret_cast<const coff_relocation*>(Rel.p);
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const11530b57cec5SDimitry Andric void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
11540b57cec5SDimitry Andric   Rel.p = reinterpret_cast<uintptr_t>(
11550b57cec5SDimitry Andric             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric 
getRelocationOffset(DataRefImpl Rel) const11580b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
11590b57cec5SDimitry Andric   const coff_relocation *R = toRel(Rel);
11600b57cec5SDimitry Andric   return R->VirtualAddress;
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric 
getRelocationSymbol(DataRefImpl Rel) const11630b57cec5SDimitry Andric symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
11640b57cec5SDimitry Andric   const coff_relocation *R = toRel(Rel);
11650b57cec5SDimitry Andric   DataRefImpl Ref;
11660b57cec5SDimitry Andric   if (R->SymbolTableIndex >= getNumberOfSymbols())
11670b57cec5SDimitry Andric     return symbol_end();
11680b57cec5SDimitry Andric   if (SymbolTable16)
11690b57cec5SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
11700b57cec5SDimitry Andric   else if (SymbolTable32)
11710b57cec5SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
11720b57cec5SDimitry Andric   else
11730b57cec5SDimitry Andric     llvm_unreachable("no symbol table pointer!");
11740b57cec5SDimitry Andric   return symbol_iterator(SymbolRef(Ref, this));
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric 
getRelocationType(DataRefImpl Rel) const11770b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
11780b57cec5SDimitry Andric   const coff_relocation* R = toRel(Rel);
11790b57cec5SDimitry Andric   return R->Type;
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric const coff_section *
getCOFFSection(const SectionRef & Section) const11830b57cec5SDimitry Andric COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
11840b57cec5SDimitry Andric   return toSec(Section.getRawDataRefImpl());
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric 
getCOFFSymbol(const DataRefImpl & Ref) const11870b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
11880b57cec5SDimitry Andric   if (SymbolTable16)
11890b57cec5SDimitry Andric     return toSymb<coff_symbol16>(Ref);
11900b57cec5SDimitry Andric   if (SymbolTable32)
11910b57cec5SDimitry Andric     return toSymb<coff_symbol32>(Ref);
11920b57cec5SDimitry Andric   llvm_unreachable("no symbol table pointer!");
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric 
getCOFFSymbol(const SymbolRef & Symbol) const11950b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
11960b57cec5SDimitry Andric   return getCOFFSymbol(Symbol.getRawDataRefImpl());
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric const coff_relocation *
getCOFFRelocation(const RelocationRef & Reloc) const12000b57cec5SDimitry Andric COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
12010b57cec5SDimitry Andric   return toRel(Reloc.getRawDataRefImpl());
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric ArrayRef<coff_relocation>
getRelocations(const coff_section * Sec) const12050b57cec5SDimitry Andric COFFObjectFile::getRelocations(const coff_section *Sec) const {
12060b57cec5SDimitry Andric   return {getFirstReloc(Sec, Data, base()),
12070b57cec5SDimitry Andric           getNumberOfRelocations(Sec, Data, base())};
12080b57cec5SDimitry Andric }
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
12110b57cec5SDimitry Andric   case COFF::reloc_type:                                                       \
12120b57cec5SDimitry Andric     return #reloc_type;
12130b57cec5SDimitry Andric 
getRelocationTypeName(uint16_t Type) const12140b57cec5SDimitry Andric StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
12150b57cec5SDimitry Andric   switch (getMachine()) {
12160b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
12170b57cec5SDimitry Andric     switch (Type) {
12180b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
12190b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
12200b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
12210b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
12220b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
12230b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
12240b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
12250b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
12260b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
12270b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
12280b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
12290b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
12300b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
12310b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
12320b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
12330b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
12340b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
12350b57cec5SDimitry Andric     default:
12360b57cec5SDimitry Andric       return "Unknown";
12370b57cec5SDimitry Andric     }
12380b57cec5SDimitry Andric     break;
12390b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
12400b57cec5SDimitry Andric     switch (Type) {
12410b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12420b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12430b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12440b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12450b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12460b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12470b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12480b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
12490b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12500b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12510b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12520b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12530b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12540b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12550b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12560b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
12570b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12580b57cec5SDimitry Andric     default:
12590b57cec5SDimitry Andric       return "Unknown";
12600b57cec5SDimitry Andric     }
12610b57cec5SDimitry Andric     break;
12620b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
12630b57cec5SDimitry Andric     switch (Type) {
12640b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12650b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12660b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12670b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12680b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12690b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12700b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12710b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12720b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12730b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12740b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12750b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12760b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12770b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12780b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12790b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12800b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
12810b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12820b57cec5SDimitry Andric     default:
12830b57cec5SDimitry Andric       return "Unknown";
12840b57cec5SDimitry Andric     }
12850b57cec5SDimitry Andric     break;
12860b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
12870b57cec5SDimitry Andric     switch (Type) {
12880b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
12890b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
12900b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
12910b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
12920b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
12930b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
12940b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
12950b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
12960b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
12970b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
12980b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
12990b57cec5SDimitry Andric     default:
13000b57cec5SDimitry Andric       return "Unknown";
13010b57cec5SDimitry Andric     }
13020b57cec5SDimitry Andric     break;
13030b57cec5SDimitry Andric   default:
13040b57cec5SDimitry Andric     return "Unknown";
13050b57cec5SDimitry Andric   }
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
13090b57cec5SDimitry Andric 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const13100b57cec5SDimitry Andric void COFFObjectFile::getRelocationTypeName(
13110b57cec5SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
13120b57cec5SDimitry Andric   const coff_relocation *Reloc = toRel(Rel);
13130b57cec5SDimitry Andric   StringRef Res = getRelocationTypeName(Reloc->Type);
13140b57cec5SDimitry Andric   Result.append(Res.begin(), Res.end());
13150b57cec5SDimitry Andric }
13160b57cec5SDimitry Andric 
isRelocatableObject() const13170b57cec5SDimitry Andric bool COFFObjectFile::isRelocatableObject() const {
13180b57cec5SDimitry Andric   return !DataDirectory;
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric 
mapDebugSectionName(StringRef Name) const13210b57cec5SDimitry Andric StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
13220b57cec5SDimitry Andric   return StringSwitch<StringRef>(Name)
13230b57cec5SDimitry Andric       .Case("eh_fram", "eh_frame")
13240b57cec5SDimitry Andric       .Default(Name);
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric bool ImportDirectoryEntryRef::
operator ==(const ImportDirectoryEntryRef & Other) const13280b57cec5SDimitry Andric operator==(const ImportDirectoryEntryRef &Other) const {
13290b57cec5SDimitry Andric   return ImportTable == Other.ImportTable && Index == Other.Index;
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric 
moveNext()13320b57cec5SDimitry Andric void ImportDirectoryEntryRef::moveNext() {
13330b57cec5SDimitry Andric   ++Index;
13340b57cec5SDimitry Andric   if (ImportTable[Index].isNull()) {
13350b57cec5SDimitry Andric     Index = -1;
13360b57cec5SDimitry Andric     ImportTable = nullptr;
13370b57cec5SDimitry Andric   }
13380b57cec5SDimitry Andric }
13390b57cec5SDimitry Andric 
getImportTableEntry(const coff_import_directory_table_entry * & Result) const13405ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportTableEntry(
13410b57cec5SDimitry Andric     const coff_import_directory_table_entry *&Result) const {
13420b57cec5SDimitry Andric   return getObject(Result, OwningObject->Data, ImportTable + Index);
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric 
13450b57cec5SDimitry Andric static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile * Object,uintptr_t Ptr,int Index)13460b57cec5SDimitry Andric makeImportedSymbolIterator(const COFFObjectFile *Object,
13470b57cec5SDimitry Andric                            uintptr_t Ptr, int Index) {
13480b57cec5SDimitry Andric   if (Object->getBytesInAddress() == 4) {
13490b57cec5SDimitry Andric     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
13500b57cec5SDimitry Andric     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
13510b57cec5SDimitry Andric   }
13520b57cec5SDimitry Andric   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
13530b57cec5SDimitry Andric   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric 
13560b57cec5SDimitry Andric static imported_symbol_iterator
importedSymbolBegin(uint32_t RVA,const COFFObjectFile * Object)13570b57cec5SDimitry Andric importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
13580b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
13595ffd83dbSDimitry Andric   // FIXME: Handle errors.
13605ffd83dbSDimitry Andric   cantFail(Object->getRvaPtr(RVA, IntPtr));
13610b57cec5SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, 0);
13620b57cec5SDimitry Andric }
13630b57cec5SDimitry Andric 
13640b57cec5SDimitry Andric static imported_symbol_iterator
importedSymbolEnd(uint32_t RVA,const COFFObjectFile * Object)13650b57cec5SDimitry Andric importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
13660b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
13675ffd83dbSDimitry Andric   // FIXME: Handle errors.
13685ffd83dbSDimitry Andric   cantFail(Object->getRvaPtr(RVA, IntPtr));
13690b57cec5SDimitry Andric   // Forward the pointer to the last entry which is null.
13700b57cec5SDimitry Andric   int Index = 0;
13710b57cec5SDimitry Andric   if (Object->getBytesInAddress() == 4) {
13720b57cec5SDimitry Andric     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
13730b57cec5SDimitry Andric     while (*Entry++)
13740b57cec5SDimitry Andric       ++Index;
13750b57cec5SDimitry Andric   } else {
13760b57cec5SDimitry Andric     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
13770b57cec5SDimitry Andric     while (*Entry++)
13780b57cec5SDimitry Andric       ++Index;
13790b57cec5SDimitry Andric   }
13800b57cec5SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, Index);
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric 
13830b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const13840b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_begin() const {
13850b57cec5SDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
13860b57cec5SDimitry Andric                              OwningObject);
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_end() const13900b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_end() const {
13910b57cec5SDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
13920b57cec5SDimitry Andric                            OwningObject);
13930b57cec5SDimitry Andric }
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const13960b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbols() const {
13970b57cec5SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
13980b57cec5SDimitry Andric }
13990b57cec5SDimitry Andric 
lookup_table_begin() const14000b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
14010b57cec5SDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
14020b57cec5SDimitry Andric                              OwningObject);
14030b57cec5SDimitry Andric }
14040b57cec5SDimitry Andric 
lookup_table_end() const14050b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
14060b57cec5SDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
14070b57cec5SDimitry Andric                            OwningObject);
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
lookup_table_symbols() const14110b57cec5SDimitry Andric ImportDirectoryEntryRef::lookup_table_symbols() const {
14120b57cec5SDimitry Andric   return make_range(lookup_table_begin(), lookup_table_end());
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric 
getName(StringRef & Result) const14155ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
14160b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
14175ffd83dbSDimitry Andric   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
14185ffd83dbSDimitry Andric     return E;
14190b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14205ffd83dbSDimitry Andric   return Error::success();
14210b57cec5SDimitry Andric }
14220b57cec5SDimitry Andric 
14235ffd83dbSDimitry Andric Error
getImportLookupTableRVA(uint32_t & Result) const14240b57cec5SDimitry Andric ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14250b57cec5SDimitry Andric   Result = ImportTable[Index].ImportLookupTableRVA;
14265ffd83dbSDimitry Andric   return Error::success();
14270b57cec5SDimitry Andric }
14280b57cec5SDimitry Andric 
getImportAddressTableRVA(uint32_t & Result) const14295ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14305ffd83dbSDimitry Andric     uint32_t &Result) const {
14310b57cec5SDimitry Andric   Result = ImportTable[Index].ImportAddressTableRVA;
14325ffd83dbSDimitry Andric   return Error::success();
14330b57cec5SDimitry Andric }
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric bool DelayImportDirectoryEntryRef::
operator ==(const DelayImportDirectoryEntryRef & Other) const14360b57cec5SDimitry Andric operator==(const DelayImportDirectoryEntryRef &Other) const {
14370b57cec5SDimitry Andric   return Table == Other.Table && Index == Other.Index;
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric 
moveNext()14400b57cec5SDimitry Andric void DelayImportDirectoryEntryRef::moveNext() {
14410b57cec5SDimitry Andric   ++Index;
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const14450b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_begin() const {
14460b57cec5SDimitry Andric   return importedSymbolBegin(Table[Index].DelayImportNameTable,
14470b57cec5SDimitry Andric                              OwningObject);
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_end() const14510b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_end() const {
14520b57cec5SDimitry Andric   return importedSymbolEnd(Table[Index].DelayImportNameTable,
14530b57cec5SDimitry Andric                            OwningObject);
14540b57cec5SDimitry Andric }
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const14570b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbols() const {
14580b57cec5SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
14590b57cec5SDimitry Andric }
14600b57cec5SDimitry Andric 
getName(StringRef & Result) const14615ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
14620b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
14635ffd83dbSDimitry Andric   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
14645ffd83dbSDimitry Andric     return E;
14650b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14665ffd83dbSDimitry Andric   return Error::success();
14670b57cec5SDimitry Andric }
14680b57cec5SDimitry Andric 
getDelayImportTable(const delay_import_directory_table_entry * & Result) const14695ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getDelayImportTable(
14705ffd83dbSDimitry Andric     const delay_import_directory_table_entry *&Result) const {
14710b57cec5SDimitry Andric   Result = &Table[Index];
14725ffd83dbSDimitry Andric   return Error::success();
14730b57cec5SDimitry Andric }
14740b57cec5SDimitry Andric 
getImportAddress(int AddrIndex,uint64_t & Result) const14755ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
14765ffd83dbSDimitry Andric                                                      uint64_t &Result) const {
14770b57cec5SDimitry Andric   uint32_t RVA = Table[Index].DelayImportAddressTable +
14780b57cec5SDimitry Andric       AddrIndex * (OwningObject->is64() ? 8 : 4);
14790b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
14805ffd83dbSDimitry Andric   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr))
14815ffd83dbSDimitry Andric     return E;
14820b57cec5SDimitry Andric   if (OwningObject->is64())
14830b57cec5SDimitry Andric     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
14840b57cec5SDimitry Andric   else
14850b57cec5SDimitry Andric     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14865ffd83dbSDimitry Andric   return Error::success();
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric bool ExportDirectoryEntryRef::
operator ==(const ExportDirectoryEntryRef & Other) const14900b57cec5SDimitry Andric operator==(const ExportDirectoryEntryRef &Other) const {
14910b57cec5SDimitry Andric   return ExportTable == Other.ExportTable && Index == Other.Index;
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric 
moveNext()14940b57cec5SDimitry Andric void ExportDirectoryEntryRef::moveNext() {
14950b57cec5SDimitry Andric   ++Index;
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric 
14980b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
14990b57cec5SDimitry Andric // by ordinal, the empty string is set as a result.
getDllName(StringRef & Result) const15005ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
15010b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
15025ffd83dbSDimitry Andric   if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
15035ffd83dbSDimitry Andric     return E;
15040b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15055ffd83dbSDimitry Andric   return Error::success();
15060b57cec5SDimitry Andric }
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric // Returns the starting ordinal number.
getOrdinalBase(uint32_t & Result) const15095ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
15100b57cec5SDimitry Andric   Result = ExportTable->OrdinalBase;
15115ffd83dbSDimitry Andric   return Error::success();
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric // Returns the export ordinal of the current export symbol.
getOrdinal(uint32_t & Result) const15155ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
15160b57cec5SDimitry Andric   Result = ExportTable->OrdinalBase + Index;
15175ffd83dbSDimitry Andric   return Error::success();
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric // Returns the address of the current export symbol.
getExportRVA(uint32_t & Result) const15215ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
15220b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
15235ffd83dbSDimitry Andric   if (Error EC =
15240b57cec5SDimitry Andric           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
15250b57cec5SDimitry Andric     return EC;
15260b57cec5SDimitry Andric   const export_address_table_entry *entry =
15270b57cec5SDimitry Andric       reinterpret_cast<const export_address_table_entry *>(IntPtr);
15280b57cec5SDimitry Andric   Result = entry[Index].ExportRVA;
15295ffd83dbSDimitry Andric   return Error::success();
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
15330b57cec5SDimitry Andric // by ordinal, the empty string is set as a result.
15345ffd83dbSDimitry Andric Error
getSymbolName(StringRef & Result) const15350b57cec5SDimitry Andric ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
15360b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
15375ffd83dbSDimitry Andric   if (Error EC =
15380b57cec5SDimitry Andric           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
15390b57cec5SDimitry Andric     return EC;
15400b57cec5SDimitry Andric   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
15410b57cec5SDimitry Andric 
15420b57cec5SDimitry Andric   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
15430b57cec5SDimitry Andric   int Offset = 0;
15440b57cec5SDimitry Andric   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
15450b57cec5SDimitry Andric        I < E; ++I, ++Offset) {
15460b57cec5SDimitry Andric     if (*I != Index)
15470b57cec5SDimitry Andric       continue;
15485ffd83dbSDimitry Andric     if (Error EC =
15490b57cec5SDimitry Andric             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
15500b57cec5SDimitry Andric       return EC;
15510b57cec5SDimitry Andric     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
15525ffd83dbSDimitry Andric     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
15530b57cec5SDimitry Andric       return EC;
15540b57cec5SDimitry Andric     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15555ffd83dbSDimitry Andric     return Error::success();
15560b57cec5SDimitry Andric   }
15570b57cec5SDimitry Andric   Result = "";
15585ffd83dbSDimitry Andric   return Error::success();
15590b57cec5SDimitry Andric }
15600b57cec5SDimitry Andric 
isForwarder(bool & Result) const15615ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15625ffd83dbSDimitry Andric   const data_directory *DataEntry =
15635ffd83dbSDimitry Andric       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
15645ffd83dbSDimitry Andric   if (!DataEntry)
15655ffd83dbSDimitry Andric     return errorCodeToError(object_error::parse_failed);
15660b57cec5SDimitry Andric   uint32_t RVA;
15670b57cec5SDimitry Andric   if (auto EC = getExportRVA(RVA))
15680b57cec5SDimitry Andric     return EC;
15690b57cec5SDimitry Andric   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15700b57cec5SDimitry Andric   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15710b57cec5SDimitry Andric   Result = (Begin <= RVA && RVA < End);
15725ffd83dbSDimitry Andric   return Error::success();
15730b57cec5SDimitry Andric }
15740b57cec5SDimitry Andric 
getForwardTo(StringRef & Result) const15755ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15760b57cec5SDimitry Andric   uint32_t RVA;
15770b57cec5SDimitry Andric   if (auto EC = getExportRVA(RVA))
15780b57cec5SDimitry Andric     return EC;
15790b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
15800b57cec5SDimitry Andric   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15810b57cec5SDimitry Andric     return EC;
15820b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15835ffd83dbSDimitry Andric   return Error::success();
15840b57cec5SDimitry Andric }
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric bool ImportedSymbolRef::
operator ==(const ImportedSymbolRef & Other) const15870b57cec5SDimitry Andric operator==(const ImportedSymbolRef &Other) const {
15880b57cec5SDimitry Andric   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
15890b57cec5SDimitry Andric       && Index == Other.Index;
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric 
moveNext()15920b57cec5SDimitry Andric void ImportedSymbolRef::moveNext() {
15930b57cec5SDimitry Andric   ++Index;
15940b57cec5SDimitry Andric }
15950b57cec5SDimitry Andric 
getSymbolName(StringRef & Result) const15965ffd83dbSDimitry Andric Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
15970b57cec5SDimitry Andric   uint32_t RVA;
15980b57cec5SDimitry Andric   if (Entry32) {
15990b57cec5SDimitry Andric     // If a symbol is imported only by ordinal, it has no name.
16000b57cec5SDimitry Andric     if (Entry32[Index].isOrdinal())
16015ffd83dbSDimitry Andric       return Error::success();
16020b57cec5SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
16030b57cec5SDimitry Andric   } else {
16040b57cec5SDimitry Andric     if (Entry64[Index].isOrdinal())
16055ffd83dbSDimitry Andric       return Error::success();
16060b57cec5SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
16070b57cec5SDimitry Andric   }
16080b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
16095ffd83dbSDimitry Andric   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
16100b57cec5SDimitry Andric     return EC;
16110b57cec5SDimitry Andric   // +2 because the first two bytes is hint.
16120b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16135ffd83dbSDimitry Andric   return Error::success();
16140b57cec5SDimitry Andric }
16150b57cec5SDimitry Andric 
isOrdinal(bool & Result) const16165ffd83dbSDimitry Andric Error ImportedSymbolRef::isOrdinal(bool &Result) const {
16170b57cec5SDimitry Andric   if (Entry32)
16180b57cec5SDimitry Andric     Result = Entry32[Index].isOrdinal();
16190b57cec5SDimitry Andric   else
16200b57cec5SDimitry Andric     Result = Entry64[Index].isOrdinal();
16215ffd83dbSDimitry Andric   return Error::success();
16220b57cec5SDimitry Andric }
16230b57cec5SDimitry Andric 
getHintNameRVA(uint32_t & Result) const16245ffd83dbSDimitry Andric Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
16250b57cec5SDimitry Andric   if (Entry32)
16260b57cec5SDimitry Andric     Result = Entry32[Index].getHintNameRVA();
16270b57cec5SDimitry Andric   else
16280b57cec5SDimitry Andric     Result = Entry64[Index].getHintNameRVA();
16295ffd83dbSDimitry Andric   return Error::success();
16300b57cec5SDimitry Andric }
16310b57cec5SDimitry Andric 
getOrdinal(uint16_t & Result) const16325ffd83dbSDimitry Andric Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
16330b57cec5SDimitry Andric   uint32_t RVA;
16340b57cec5SDimitry Andric   if (Entry32) {
16350b57cec5SDimitry Andric     if (Entry32[Index].isOrdinal()) {
16360b57cec5SDimitry Andric       Result = Entry32[Index].getOrdinal();
16375ffd83dbSDimitry Andric       return Error::success();
16380b57cec5SDimitry Andric     }
16390b57cec5SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
16400b57cec5SDimitry Andric   } else {
16410b57cec5SDimitry Andric     if (Entry64[Index].isOrdinal()) {
16420b57cec5SDimitry Andric       Result = Entry64[Index].getOrdinal();
16435ffd83dbSDimitry Andric       return Error::success();
16440b57cec5SDimitry Andric     }
16450b57cec5SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
16460b57cec5SDimitry Andric   }
16470b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
16485ffd83dbSDimitry Andric   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
16490b57cec5SDimitry Andric     return EC;
16500b57cec5SDimitry Andric   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16515ffd83dbSDimitry Andric   return Error::success();
16520b57cec5SDimitry Andric }
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object)16550b57cec5SDimitry Andric ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
16565ffd83dbSDimitry Andric   return COFFObjectFile::create(Object);
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric 
operator ==(const BaseRelocRef & Other) const16590b57cec5SDimitry Andric bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
16600b57cec5SDimitry Andric   return Header == Other.Header && Index == Other.Index;
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric 
moveNext()16630b57cec5SDimitry Andric void BaseRelocRef::moveNext() {
16640b57cec5SDimitry Andric   // Header->BlockSize is the size of the current block, including the
16650b57cec5SDimitry Andric   // size of the header itself.
16660b57cec5SDimitry Andric   uint32_t Size = sizeof(*Header) +
16670b57cec5SDimitry Andric       sizeof(coff_base_reloc_block_entry) * (Index + 1);
16680b57cec5SDimitry Andric   if (Size == Header->BlockSize) {
16690b57cec5SDimitry Andric     // .reloc contains a list of base relocation blocks. Each block
16700b57cec5SDimitry Andric     // consists of the header followed by entries. The header contains
16710b57cec5SDimitry Andric     // how many entories will follow. When we reach the end of the
16720b57cec5SDimitry Andric     // current block, proceed to the next block.
16730b57cec5SDimitry Andric     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
16740b57cec5SDimitry Andric         reinterpret_cast<const uint8_t *>(Header) + Size);
16750b57cec5SDimitry Andric     Index = 0;
16760b57cec5SDimitry Andric   } else {
16770b57cec5SDimitry Andric     ++Index;
16780b57cec5SDimitry Andric   }
16790b57cec5SDimitry Andric }
16800b57cec5SDimitry Andric 
getType(uint8_t & Type) const16815ffd83dbSDimitry Andric Error BaseRelocRef::getType(uint8_t &Type) const {
16820b57cec5SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
16830b57cec5SDimitry Andric   Type = Entry[Index].getType();
16845ffd83dbSDimitry Andric   return Error::success();
16850b57cec5SDimitry Andric }
16860b57cec5SDimitry Andric 
getRVA(uint32_t & Result) const16875ffd83dbSDimitry Andric Error BaseRelocRef::getRVA(uint32_t &Result) const {
16880b57cec5SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
16890b57cec5SDimitry Andric   Result = Header->PageRVA + Entry[Index].getOffset();
16905ffd83dbSDimitry Andric   return Error::success();
16910b57cec5SDimitry Andric }
16920b57cec5SDimitry Andric 
16938bcb0991SDimitry Andric #define RETURN_IF_ERROR(Expr)                                                  \
16948bcb0991SDimitry Andric   do {                                                                         \
16958bcb0991SDimitry Andric     Error E = (Expr);                                                          \
16960b57cec5SDimitry Andric     if (E)                                                                     \
16978bcb0991SDimitry Andric       return std::move(E);                                                     \
16988bcb0991SDimitry Andric   } while (0)
16990b57cec5SDimitry Andric 
17000b57cec5SDimitry Andric Expected<ArrayRef<UTF16>>
getDirStringAtOffset(uint32_t Offset)17010b57cec5SDimitry Andric ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
17020b57cec5SDimitry Andric   BinaryStreamReader Reader = BinaryStreamReader(BBS);
17030b57cec5SDimitry Andric   Reader.setOffset(Offset);
17040b57cec5SDimitry Andric   uint16_t Length;
17050b57cec5SDimitry Andric   RETURN_IF_ERROR(Reader.readInteger(Length));
17060b57cec5SDimitry Andric   ArrayRef<UTF16> RawDirString;
17070b57cec5SDimitry Andric   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
17080b57cec5SDimitry Andric   return RawDirString;
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric 
17110b57cec5SDimitry Andric Expected<ArrayRef<UTF16>>
getEntryNameString(const coff_resource_dir_entry & Entry)17120b57cec5SDimitry Andric ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
17130b57cec5SDimitry Andric   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric Expected<const coff_resource_dir_table &>
getTableAtOffset(uint32_t Offset)17170b57cec5SDimitry Andric ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
17180b57cec5SDimitry Andric   const coff_resource_dir_table *Table = nullptr;
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   BinaryStreamReader Reader(BBS);
17210b57cec5SDimitry Andric   Reader.setOffset(Offset);
17220b57cec5SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Table));
17230b57cec5SDimitry Andric   assert(Table != nullptr);
17240b57cec5SDimitry Andric   return *Table;
17250b57cec5SDimitry Andric }
17260b57cec5SDimitry Andric 
17278bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &>
getTableEntryAtOffset(uint32_t Offset)17288bcb0991SDimitry Andric ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
17298bcb0991SDimitry Andric   const coff_resource_dir_entry *Entry = nullptr;
17308bcb0991SDimitry Andric 
17318bcb0991SDimitry Andric   BinaryStreamReader Reader(BBS);
17328bcb0991SDimitry Andric   Reader.setOffset(Offset);
17338bcb0991SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Entry));
17348bcb0991SDimitry Andric   assert(Entry != nullptr);
17358bcb0991SDimitry Andric   return *Entry;
17368bcb0991SDimitry Andric }
17378bcb0991SDimitry Andric 
17388bcb0991SDimitry Andric Expected<const coff_resource_data_entry &>
getDataEntryAtOffset(uint32_t Offset)17398bcb0991SDimitry Andric ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17408bcb0991SDimitry Andric   const coff_resource_data_entry *Entry = nullptr;
17418bcb0991SDimitry Andric 
17428bcb0991SDimitry Andric   BinaryStreamReader Reader(BBS);
17438bcb0991SDimitry Andric   Reader.setOffset(Offset);
17448bcb0991SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Entry));
17458bcb0991SDimitry Andric   assert(Entry != nullptr);
17468bcb0991SDimitry Andric   return *Entry;
17478bcb0991SDimitry Andric }
17488bcb0991SDimitry Andric 
17490b57cec5SDimitry Andric Expected<const coff_resource_dir_table &>
getEntrySubDir(const coff_resource_dir_entry & Entry)17500b57cec5SDimitry Andric ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17518bcb0991SDimitry Andric   assert(Entry.Offset.isSubDir());
17520b57cec5SDimitry Andric   return getTableAtOffset(Entry.Offset.value());
17530b57cec5SDimitry Andric }
17540b57cec5SDimitry Andric 
17558bcb0991SDimitry Andric Expected<const coff_resource_data_entry &>
getEntryData(const coff_resource_dir_entry & Entry)17568bcb0991SDimitry Andric ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17578bcb0991SDimitry Andric   assert(!Entry.Offset.isSubDir());
17588bcb0991SDimitry Andric   return getDataEntryAtOffset(Entry.Offset.value());
17598bcb0991SDimitry Andric }
17608bcb0991SDimitry Andric 
getBaseTable()17610b57cec5SDimitry Andric Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
17620b57cec5SDimitry Andric   return getTableAtOffset(0);
17630b57cec5SDimitry Andric }
17648bcb0991SDimitry Andric 
17658bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &>
getTableEntry(const coff_resource_dir_table & Table,uint32_t Index)17668bcb0991SDimitry Andric ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
17678bcb0991SDimitry Andric                                   uint32_t Index) {
17688bcb0991SDimitry Andric   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
17698bcb0991SDimitry Andric     return createStringError(object_error::parse_failed, "index out of range");
17708bcb0991SDimitry Andric   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
17718bcb0991SDimitry Andric   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
17728bcb0991SDimitry Andric   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
17738bcb0991SDimitry Andric                                Index * sizeof(coff_resource_dir_entry));
17748bcb0991SDimitry Andric }
17758bcb0991SDimitry Andric 
load(const COFFObjectFile * O)17768bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O) {
17778bcb0991SDimitry Andric   for (const SectionRef &S : O->sections()) {
17788bcb0991SDimitry Andric     Expected<StringRef> Name = S.getName();
17798bcb0991SDimitry Andric     if (!Name)
17808bcb0991SDimitry Andric       return Name.takeError();
17818bcb0991SDimitry Andric 
17828bcb0991SDimitry Andric     if (*Name == ".rsrc" || *Name == ".rsrc$01")
17838bcb0991SDimitry Andric       return load(O, S);
17848bcb0991SDimitry Andric   }
17858bcb0991SDimitry Andric   return createStringError(object_error::parse_failed,
17868bcb0991SDimitry Andric                            "no resource section found");
17878bcb0991SDimitry Andric }
17888bcb0991SDimitry Andric 
load(const COFFObjectFile * O,const SectionRef & S)17898bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
17908bcb0991SDimitry Andric   Obj = O;
17918bcb0991SDimitry Andric   Section = S;
17928bcb0991SDimitry Andric   Expected<StringRef> Contents = Section.getContents();
17938bcb0991SDimitry Andric   if (!Contents)
17948bcb0991SDimitry Andric     return Contents.takeError();
17958bcb0991SDimitry Andric   BBS = BinaryByteStream(*Contents, support::little);
17968bcb0991SDimitry Andric   const coff_section *COFFSect = Obj->getCOFFSection(Section);
17978bcb0991SDimitry Andric   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
17988bcb0991SDimitry Andric   Relocs.reserve(OrigRelocs.size());
17998bcb0991SDimitry Andric   for (const coff_relocation &R : OrigRelocs)
18008bcb0991SDimitry Andric     Relocs.push_back(&R);
1801af732203SDimitry Andric   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
18028bcb0991SDimitry Andric     return A->VirtualAddress < B->VirtualAddress;
18038bcb0991SDimitry Andric   });
18048bcb0991SDimitry Andric   return Error::success();
18058bcb0991SDimitry Andric }
18068bcb0991SDimitry Andric 
18078bcb0991SDimitry Andric Expected<StringRef>
getContents(const coff_resource_data_entry & Entry)18088bcb0991SDimitry Andric ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
18098bcb0991SDimitry Andric   if (!Obj)
18108bcb0991SDimitry Andric     return createStringError(object_error::parse_failed, "no object provided");
18118bcb0991SDimitry Andric 
18128bcb0991SDimitry Andric   // Find a potential relocation at the DataRVA field (first member of
18138bcb0991SDimitry Andric   // the coff_resource_data_entry struct).
18148bcb0991SDimitry Andric   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
18158bcb0991SDimitry Andric   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
18168bcb0991SDimitry Andric   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
18178bcb0991SDimitry Andric                               ulittle16_t(0)};
18188bcb0991SDimitry Andric   auto RelocsForOffset =
18198bcb0991SDimitry Andric       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
18208bcb0991SDimitry Andric                        [](const coff_relocation *A, const coff_relocation *B) {
18218bcb0991SDimitry Andric                          return A->VirtualAddress < B->VirtualAddress;
18228bcb0991SDimitry Andric                        });
18238bcb0991SDimitry Andric 
18248bcb0991SDimitry Andric   if (RelocsForOffset.first != RelocsForOffset.second) {
18258bcb0991SDimitry Andric     // We found a relocation with the right offset. Check that it does have
18268bcb0991SDimitry Andric     // the expected type.
18278bcb0991SDimitry Andric     const coff_relocation &R = **RelocsForOffset.first;
18288bcb0991SDimitry Andric     uint16_t RVAReloc;
18298bcb0991SDimitry Andric     switch (Obj->getMachine()) {
18308bcb0991SDimitry Andric     case COFF::IMAGE_FILE_MACHINE_I386:
18318bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
18328bcb0991SDimitry Andric       break;
18338bcb0991SDimitry Andric     case COFF::IMAGE_FILE_MACHINE_AMD64:
18348bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
18358bcb0991SDimitry Andric       break;
18368bcb0991SDimitry Andric     case COFF::IMAGE_FILE_MACHINE_ARMNT:
18378bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
18388bcb0991SDimitry Andric       break;
18398bcb0991SDimitry Andric     case COFF::IMAGE_FILE_MACHINE_ARM64:
18408bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
18418bcb0991SDimitry Andric       break;
18428bcb0991SDimitry Andric     default:
18438bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
18448bcb0991SDimitry Andric                                "unsupported architecture");
18458bcb0991SDimitry Andric     }
18468bcb0991SDimitry Andric     if (R.Type != RVAReloc)
18478bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
18488bcb0991SDimitry Andric                                "unexpected relocation type");
18498bcb0991SDimitry Andric     // Get the relocation's symbol
18508bcb0991SDimitry Andric     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
18518bcb0991SDimitry Andric     if (!Sym)
18528bcb0991SDimitry Andric       return Sym.takeError();
18538bcb0991SDimitry Andric     // And the symbol's section
18545ffd83dbSDimitry Andric     Expected<const coff_section *> Section =
18555ffd83dbSDimitry Andric         Obj->getSection(Sym->getSectionNumber());
18565ffd83dbSDimitry Andric     if (!Section)
18575ffd83dbSDimitry Andric       return Section.takeError();
18588bcb0991SDimitry Andric     // Add the initial value of DataRVA to the symbol's offset to find the
18598bcb0991SDimitry Andric     // data it points at.
18608bcb0991SDimitry Andric     uint64_t Offset = Entry.DataRVA + Sym->getValue();
18618bcb0991SDimitry Andric     ArrayRef<uint8_t> Contents;
18625ffd83dbSDimitry Andric     if (Error E = Obj->getSectionContents(*Section, Contents))
18638bcb0991SDimitry Andric       return std::move(E);
18648bcb0991SDimitry Andric     if (Offset + Entry.DataSize > Contents.size())
18658bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
18668bcb0991SDimitry Andric                                "data outside of section");
18678bcb0991SDimitry Andric     // Return a reference to the data inside the section.
18688bcb0991SDimitry Andric     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
18698bcb0991SDimitry Andric                      Entry.DataSize);
18708bcb0991SDimitry Andric   } else {
18718bcb0991SDimitry Andric     // Relocatable objects need a relocation for the DataRVA field.
18728bcb0991SDimitry Andric     if (Obj->isRelocatableObject())
18738bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
18748bcb0991SDimitry Andric                                "no relocation found for DataRVA");
18758bcb0991SDimitry Andric 
18768bcb0991SDimitry Andric     // Locate the section that contains the address that DataRVA points at.
18778bcb0991SDimitry Andric     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
18788bcb0991SDimitry Andric     for (const SectionRef &S : Obj->sections()) {
18798bcb0991SDimitry Andric       if (VA >= S.getAddress() &&
18808bcb0991SDimitry Andric           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
18818bcb0991SDimitry Andric         uint64_t Offset = VA - S.getAddress();
18828bcb0991SDimitry Andric         Expected<StringRef> Contents = S.getContents();
18838bcb0991SDimitry Andric         if (!Contents)
18848bcb0991SDimitry Andric           return Contents.takeError();
18858bcb0991SDimitry Andric         return Contents->slice(Offset, Offset + Entry.DataSize);
18868bcb0991SDimitry Andric       }
18878bcb0991SDimitry Andric     }
18888bcb0991SDimitry Andric     return createStringError(object_error::parse_failed,
18898bcb0991SDimitry Andric                              "address not found in image");
18908bcb0991SDimitry Andric   }
18918bcb0991SDimitry Andric }
1892