xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/iterator_range.h"
170b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
180b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
190b57cec5SDimitry Andric #include "llvm/Object/Error.h"
200b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
21*0fca6ea1SDimitry Andric #include "llvm/Object/WindowsMachineFlag.h"
220b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
230b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
240b57cec5SDimitry Andric #include "llvm/Support/Error.h"
250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
260b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
2781ad6265SDimitry Andric #include "llvm/Support/MemoryBufferRef.h"
280b57cec5SDimitry Andric #include <algorithm>
290b57cec5SDimitry Andric #include <cassert>
30e8d8bef9SDimitry Andric #include <cinttypes>
310b57cec5SDimitry Andric #include <cstddef>
320b57cec5SDimitry Andric #include <cstring>
330b57cec5SDimitry Andric #include <limits>
340b57cec5SDimitry Andric #include <memory>
350b57cec5SDimitry Andric #include <system_error>
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric using namespace object;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using support::ulittle16_t;
410b57cec5SDimitry Andric using support::ulittle32_t;
420b57cec5SDimitry Andric using support::ulittle64_t;
430b57cec5SDimitry Andric using support::little16_t;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric // Returns false if size is greater than the buffer size. And sets ec.
460b57cec5SDimitry Andric static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
470b57cec5SDimitry Andric   if (M.getBufferSize() < Size) {
480b57cec5SDimitry Andric     EC = object_error::unexpected_eof;
490b57cec5SDimitry Andric     return false;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric   return true;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
550b57cec5SDimitry Andric // Returns unexpected_eof if error.
560b57cec5SDimitry Andric template <typename T>
575ffd83dbSDimitry Andric static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,
580b57cec5SDimitry Andric                        const uint64_t Size = sizeof(T)) {
59e8d8bef9SDimitry Andric   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
605ffd83dbSDimitry Andric   if (Error E = Binary::checkOffset(M, Addr, Size))
615ffd83dbSDimitry Andric     return E;
620b57cec5SDimitry Andric   Obj = reinterpret_cast<const T *>(Addr);
635ffd83dbSDimitry Andric   return Error::success();
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
670b57cec5SDimitry Andric // prefixed slashes.
680b57cec5SDimitry Andric static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
690b57cec5SDimitry Andric   assert(Str.size() <= 6 && "String too long, possible overflow.");
700b57cec5SDimitry Andric   if (Str.size() > 6)
710b57cec5SDimitry Andric     return true;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   uint64_t Value = 0;
740b57cec5SDimitry Andric   while (!Str.empty()) {
750b57cec5SDimitry Andric     unsigned CharVal;
760b57cec5SDimitry Andric     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
770b57cec5SDimitry Andric       CharVal = Str[0] - 'A';
780b57cec5SDimitry Andric     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
790b57cec5SDimitry Andric       CharVal = Str[0] - 'a' + 26;
800b57cec5SDimitry Andric     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
810b57cec5SDimitry Andric       CharVal = Str[0] - '0' + 52;
820b57cec5SDimitry Andric     else if (Str[0] == '+') // 62
830b57cec5SDimitry Andric       CharVal = 62;
840b57cec5SDimitry Andric     else if (Str[0] == '/') // 63
850b57cec5SDimitry Andric       CharVal = 63;
860b57cec5SDimitry Andric     else
870b57cec5SDimitry Andric       return true;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     Value = (Value * 64) + CharVal;
900b57cec5SDimitry Andric     Str = Str.substr(1);
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   if (Value > std::numeric_limits<uint32_t>::max())
940b57cec5SDimitry Andric     return true;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   Result = static_cast<uint32_t>(Value);
970b57cec5SDimitry Andric   return false;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric template <typename coff_symbol_type>
1010b57cec5SDimitry Andric const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
1020b57cec5SDimitry Andric   const coff_symbol_type *Addr =
1030b57cec5SDimitry Andric       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1040b57cec5SDimitry Andric 
105e8d8bef9SDimitry Andric   assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr)));
1060b57cec5SDimitry Andric #ifndef NDEBUG
1070b57cec5SDimitry Andric   // Verify that the symbol points to a valid entry in the symbol table.
108e8d8bef9SDimitry Andric   uintptr_t Offset =
109e8d8bef9SDimitry Andric       reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base());
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
1120b57cec5SDimitry Andric          "Symbol did not point to the beginning of a symbol");
1130b57cec5SDimitry Andric #endif
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   return Addr;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1190b57cec5SDimitry Andric   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric #ifndef NDEBUG
1220b57cec5SDimitry Andric   // Verify that the section points to a valid entry in the section table.
1230b57cec5SDimitry Andric   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1240b57cec5SDimitry Andric     report_fatal_error("Section was outside of section table.");
1250b57cec5SDimitry Andric 
126e8d8bef9SDimitry Andric   uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -
127e8d8bef9SDimitry Andric                      reinterpret_cast<uintptr_t>(SectionTable);
1280b57cec5SDimitry Andric   assert(Offset % sizeof(coff_section) == 0 &&
1290b57cec5SDimitry Andric          "Section did not point to the beginning of a section");
1300b57cec5SDimitry Andric #endif
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   return Addr;
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
1360b57cec5SDimitry Andric   auto End = reinterpret_cast<uintptr_t>(StringTable);
1370b57cec5SDimitry Andric   if (SymbolTable16) {
1380b57cec5SDimitry Andric     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1390b57cec5SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
1400b57cec5SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
1410b57cec5SDimitry Andric   } else if (SymbolTable32) {
1420b57cec5SDimitry Andric     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
1430b57cec5SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
1440b57cec5SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
1450b57cec5SDimitry Andric   } else {
1460b57cec5SDimitry Andric     llvm_unreachable("no symbol table pointer!");
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
1515ffd83dbSDimitry Andric   return getSymbolName(getCOFFSymbol(Ref));
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
1550b57cec5SDimitry Andric   return getCOFFSymbol(Ref).getValue();
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1590b57cec5SDimitry Andric   // MSVC/link.exe seems to align symbols to the next-power-of-2
1600b57cec5SDimitry Andric   // up to 32 bytes.
1610b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1620b57cec5SDimitry Andric   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
1665ffd83dbSDimitry Andric   uint64_t Result = cantFail(getSymbolValue(Ref));
1670b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1680b57cec5SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   if (Symb.isAnyUndefined() || Symb.isCommon() ||
1710b57cec5SDimitry Andric       COFF::isReservedSectionNumber(SectionNumber))
1720b57cec5SDimitry Andric     return Result;
1730b57cec5SDimitry Andric 
1745ffd83dbSDimitry Andric   Expected<const coff_section *> Section = getSection(SectionNumber);
1755ffd83dbSDimitry Andric   if (!Section)
1765ffd83dbSDimitry Andric     return Section.takeError();
1775ffd83dbSDimitry Andric   Result += (*Section)->VirtualAddress;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
1800b57cec5SDimitry Andric   // return virtual addresses.
1810b57cec5SDimitry Andric   Result += getImageBase();
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   return Result;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
1870b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1880b57cec5SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
1910b57cec5SDimitry Andric     return SymbolRef::ST_Function;
1920b57cec5SDimitry Andric   if (Symb.isAnyUndefined())
1930b57cec5SDimitry Andric     return SymbolRef::ST_Unknown;
1940b57cec5SDimitry Andric   if (Symb.isCommon())
1950b57cec5SDimitry Andric     return SymbolRef::ST_Data;
1960b57cec5SDimitry Andric   if (Symb.isFileRecord())
1970b57cec5SDimitry Andric     return SymbolRef::ST_File;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   // TODO: perhaps we need a new symbol type ST_Section.
2000b57cec5SDimitry Andric   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2010b57cec5SDimitry Andric     return SymbolRef::ST_Debug;
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   if (!COFF::isReservedSectionNumber(SectionNumber))
2040b57cec5SDimitry Andric     return SymbolRef::ST_Data;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   return SymbolRef::ST_Other;
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
2095ffd83dbSDimitry Andric Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
2100b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2110b57cec5SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   if (Symb.isExternal() || Symb.isWeakExternal())
2140b57cec5SDimitry Andric     Result |= SymbolRef::SF_Global;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2170b57cec5SDimitry Andric     Result |= SymbolRef::SF_Weak;
2180b57cec5SDimitry Andric     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
2190b57cec5SDimitry Andric       Result |= SymbolRef::SF_Undefined;
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2230b57cec5SDimitry Andric     Result |= SymbolRef::SF_Absolute;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   if (Symb.isFileRecord())
2260b57cec5SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   if (Symb.isSectionDefinition())
2290b57cec5SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   if (Symb.isCommon())
2320b57cec5SDimitry Andric     Result |= SymbolRef::SF_Common;
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   if (Symb.isUndefined())
2350b57cec5SDimitry Andric     Result |= SymbolRef::SF_Undefined;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   return Result;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
2410b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2420b57cec5SDimitry Andric   return Symb.getValue();
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric Expected<section_iterator>
2460b57cec5SDimitry Andric COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
2470b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2480b57cec5SDimitry Andric   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2490b57cec5SDimitry Andric     return section_end();
2505ffd83dbSDimitry Andric   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
2515ffd83dbSDimitry Andric   if (!Sec)
2525ffd83dbSDimitry Andric     return Sec.takeError();
2530b57cec5SDimitry Andric   DataRefImpl Ret;
2545ffd83dbSDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2550b57cec5SDimitry Andric   return section_iterator(SectionRef(Ret, this));
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2590b57cec5SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2600b57cec5SDimitry Andric   return Symb.getSectionNumber();
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2640b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2650b57cec5SDimitry Andric   Sec += 1;
2660b57cec5SDimitry Andric   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2700b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2710b57cec5SDimitry Andric   return getSectionName(Sec);
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2750b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2760b57cec5SDimitry Andric   uint64_t Result = Sec->VirtualAddress;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
2790b57cec5SDimitry Andric   // return virtual addresses.
2800b57cec5SDimitry Andric   Result += getImageBase();
2810b57cec5SDimitry Andric   return Result;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
2850b57cec5SDimitry Andric   return toSec(Sec) - SectionTable;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
2890b57cec5SDimitry Andric   return getSectionSize(toSec(Ref));
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
2930b57cec5SDimitry Andric COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2940b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
2950b57cec5SDimitry Andric   ArrayRef<uint8_t> Res;
2960b57cec5SDimitry Andric   if (Error E = getSectionContents(Sec, Res))
297*0fca6ea1SDimitry Andric     return E;
2980b57cec5SDimitry Andric   return Res;
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3020b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3030b57cec5SDimitry Andric   return Sec->getAlignment();
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
3070b57cec5SDimitry Andric   return false;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3110b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3120b57cec5SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3160b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3170b57cec5SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3210b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3220b57cec5SDimitry Andric   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3230b57cec5SDimitry Andric                             COFF::IMAGE_SCN_MEM_READ |
3240b57cec5SDimitry Andric                             COFF::IMAGE_SCN_MEM_WRITE;
3250b57cec5SDimitry Andric   return (Sec->Characteristics & BssFlags) == BssFlags;
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric 
3285ffd83dbSDimitry Andric // The .debug sections are the only debug sections for COFF
3295ffd83dbSDimitry Andric // (\see MCObjectFileInfo.cpp).
330fe6060f1SDimitry Andric bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {
331fe6060f1SDimitry Andric   Expected<StringRef> SectionNameOrErr = getSectionName(Ref);
332fe6060f1SDimitry Andric   if (!SectionNameOrErr) {
333fe6060f1SDimitry Andric     // TODO: Report the error message properly.
334fe6060f1SDimitry Andric     consumeError(SectionNameOrErr.takeError());
335fe6060f1SDimitry Andric     return false;
336fe6060f1SDimitry Andric   }
337fe6060f1SDimitry Andric   StringRef SectionName = SectionNameOrErr.get();
3385f757f3fSDimitry Andric   return SectionName.starts_with(".debug");
3395ffd83dbSDimitry Andric }
3405ffd83dbSDimitry Andric 
3410b57cec5SDimitry Andric unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3420b57cec5SDimitry Andric   uintptr_t Offset =
343e8d8bef9SDimitry Andric       Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3440b57cec5SDimitry Andric   assert((Offset % sizeof(coff_section)) == 0);
3450b57cec5SDimitry Andric   return (Offset / sizeof(coff_section)) + 1;
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3490b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3500b57cec5SDimitry Andric   // In COFF, a virtual section won't have any in-file
3510b57cec5SDimitry Andric   // content, so the file pointer to the content will be zero.
3520b57cec5SDimitry Andric   return Sec->PointerToRawData == 0;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric static uint32_t getNumberOfRelocations(const coff_section *Sec,
3560b57cec5SDimitry Andric                                        MemoryBufferRef M, const uint8_t *base) {
3570b57cec5SDimitry Andric   // The field for the number of relocations in COFF section table is only
3580b57cec5SDimitry Andric   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
3590b57cec5SDimitry Andric   // NumberOfRelocations field, and the actual relocation count is stored in the
3600b57cec5SDimitry Andric   // VirtualAddress field in the first relocation entry.
3610b57cec5SDimitry Andric   if (Sec->hasExtendedRelocations()) {
3620b57cec5SDimitry Andric     const coff_relocation *FirstReloc;
3635ffd83dbSDimitry Andric     if (Error E = getObject(FirstReloc, M,
3645ffd83dbSDimitry Andric                             reinterpret_cast<const coff_relocation *>(
3655ffd83dbSDimitry Andric                                 base + Sec->PointerToRelocations))) {
3665ffd83dbSDimitry Andric       consumeError(std::move(E));
3670b57cec5SDimitry Andric       return 0;
3685ffd83dbSDimitry Andric     }
3690b57cec5SDimitry Andric     // -1 to exclude this first relocation entry.
3700b57cec5SDimitry Andric     return FirstReloc->VirtualAddress - 1;
3710b57cec5SDimitry Andric   }
3720b57cec5SDimitry Andric   return Sec->NumberOfRelocations;
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric static const coff_relocation *
3760b57cec5SDimitry Andric getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
3770b57cec5SDimitry Andric   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
3780b57cec5SDimitry Andric   if (!NumRelocs)
3790b57cec5SDimitry Andric     return nullptr;
3800b57cec5SDimitry Andric   auto begin = reinterpret_cast<const coff_relocation *>(
3810b57cec5SDimitry Andric       Base + Sec->PointerToRelocations);
3820b57cec5SDimitry Andric   if (Sec->hasExtendedRelocations()) {
3830b57cec5SDimitry Andric     // Skip the first relocation entry repurposed to store the number of
3840b57cec5SDimitry Andric     // relocations.
3850b57cec5SDimitry Andric     begin++;
3860b57cec5SDimitry Andric   }
387e8d8bef9SDimitry Andric   if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
3885ffd83dbSDimitry Andric                                    sizeof(coff_relocation) * NumRelocs)) {
3895ffd83dbSDimitry Andric     consumeError(std::move(E));
3900b57cec5SDimitry Andric     return nullptr;
3915ffd83dbSDimitry Andric   }
3920b57cec5SDimitry Andric   return begin;
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
3960b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
3970b57cec5SDimitry Andric   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
3980b57cec5SDimitry Andric   if (begin && Sec->VirtualAddress != 0)
3990b57cec5SDimitry Andric     report_fatal_error("Sections with relocations should have an address of 0");
4000b57cec5SDimitry Andric   DataRefImpl Ret;
4010b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(begin);
4020b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4060b57cec5SDimitry Andric   const coff_section *Sec = toSec(Ref);
4070b57cec5SDimitry Andric   const coff_relocation *I = getFirstReloc(Sec, Data, base());
4080b57cec5SDimitry Andric   if (I)
4090b57cec5SDimitry Andric     I += getNumberOfRelocations(Sec, Data, base());
4100b57cec5SDimitry Andric   DataRefImpl Ret;
4110b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(I);
4120b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric // Initialize the pointer to the symbol table.
4165ffd83dbSDimitry Andric Error COFFObjectFile::initSymbolTablePtr() {
4170b57cec5SDimitry Andric   if (COFFHeader)
4185ffd83dbSDimitry Andric     if (Error E = getObject(
4190b57cec5SDimitry Andric             SymbolTable16, Data, base() + getPointerToSymbolTable(),
4200b57cec5SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4215ffd83dbSDimitry Andric       return E;
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   if (COFFBigObjHeader)
4245ffd83dbSDimitry Andric     if (Error E = getObject(
4250b57cec5SDimitry Andric             SymbolTable32, Data, base() + getPointerToSymbolTable(),
4260b57cec5SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4275ffd83dbSDimitry Andric       return E;
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // Find string table. The first four byte of the string table contains the
4300b57cec5SDimitry Andric   // total size of the string table, including the size field itself. If the
4310b57cec5SDimitry Andric   // string table is empty, the value of the first four byte would be 4.
4320b57cec5SDimitry Andric   uint32_t StringTableOffset = getPointerToSymbolTable() +
4330b57cec5SDimitry Andric                                getNumberOfSymbols() * getSymbolTableEntrySize();
4340b57cec5SDimitry Andric   const uint8_t *StringTableAddr = base() + StringTableOffset;
4350b57cec5SDimitry Andric   const ulittle32_t *StringTableSizePtr;
4365ffd83dbSDimitry Andric   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4375ffd83dbSDimitry Andric     return E;
4380b57cec5SDimitry Andric   StringTableSize = *StringTableSizePtr;
4395ffd83dbSDimitry Andric   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4405ffd83dbSDimitry Andric     return E;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
4430b57cec5SDimitry Andric   // tools like cvtres write a size of 0 for an empty table instead of 4.
4440b57cec5SDimitry Andric   if (StringTableSize < 4)
4450b57cec5SDimitry Andric     StringTableSize = 4;
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   // Check that the string table is null terminated if has any in it.
4480b57cec5SDimitry Andric   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
44981ad6265SDimitry Andric     return createStringError(object_error::parse_failed,
45081ad6265SDimitry Andric                              "string table missing null terminator");
4515ffd83dbSDimitry Andric   return Error::success();
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry 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.
4645ffd83dbSDimitry 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.
47281ad6265SDimitry Andric Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,
47381ad6265SDimitry Andric                                 const char *ErrorContext) const {
4740b57cec5SDimitry Andric   for (const SectionRef &S : sections()) {
4750b57cec5SDimitry Andric     const coff_section *Section = getCOFFSection(S);
4760b57cec5SDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
4770b57cec5SDimitry Andric     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
4780b57cec5SDimitry Andric     if (SectionStart <= Addr && Addr < SectionEnd) {
47981ad6265SDimitry Andric       // A table/directory entry can be pointing to somewhere in a stripped
48081ad6265SDimitry Andric       // section, in an object that went through `objcopy --only-keep-debug`.
48181ad6265SDimitry Andric       // In this case we don't want to cause the parsing of the object file to
48281ad6265SDimitry Andric       // fail, otherwise it will be impossible to use this object as debug info
48381ad6265SDimitry Andric       // in LLDB. Return SectionStrippedError here so that
48481ad6265SDimitry Andric       // COFFObjectFile::initialize can ignore the error.
48581ad6265SDimitry Andric       // Somewhat common binaries may have RVAs pointing outside of the
48681ad6265SDimitry Andric       // provided raw data. Instead of rejecting the binaries, just
48781ad6265SDimitry Andric       // treat the section as stripped for these purposes.
48881ad6265SDimitry Andric       if (Section->SizeOfRawData < Section->VirtualSize &&
48981ad6265SDimitry Andric           Addr >= SectionStart + Section->SizeOfRawData) {
49081ad6265SDimitry Andric         return make_error<SectionStrippedError>();
49181ad6265SDimitry Andric       }
4920b57cec5SDimitry Andric       uint32_t Offset = Addr - SectionStart;
493e8d8bef9SDimitry Andric       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
494e8d8bef9SDimitry Andric             Offset;
4955ffd83dbSDimitry Andric       return Error::success();
4960b57cec5SDimitry Andric     }
4970b57cec5SDimitry Andric   }
49881ad6265SDimitry Andric   if (ErrorContext)
49981ad6265SDimitry Andric     return createStringError(object_error::parse_failed,
50081ad6265SDimitry Andric                              "RVA 0x%" PRIx32 " for %s not found", Addr,
50181ad6265SDimitry Andric                              ErrorContext);
50281ad6265SDimitry Andric   return createStringError(object_error::parse_failed,
50381ad6265SDimitry Andric                            "RVA 0x%" PRIx32 " not found", Addr);
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
5065ffd83dbSDimitry Andric Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
50781ad6265SDimitry Andric                                            ArrayRef<uint8_t> &Contents,
50881ad6265SDimitry Andric                                            const char *ErrorContext) const {
5090b57cec5SDimitry Andric   for (const SectionRef &S : sections()) {
5100b57cec5SDimitry Andric     const coff_section *Section = getCOFFSection(S);
5110b57cec5SDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
5120b57cec5SDimitry Andric     // Check if this RVA is within the section bounds. Be careful about integer
5130b57cec5SDimitry Andric     // overflow.
5140b57cec5SDimitry Andric     uint32_t OffsetIntoSection = RVA - SectionStart;
5150b57cec5SDimitry Andric     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
5160b57cec5SDimitry Andric         Size <= Section->VirtualSize - OffsetIntoSection) {
517e8d8bef9SDimitry Andric       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
518e8d8bef9SDimitry Andric                         Section->PointerToRawData + OffsetIntoSection;
5190b57cec5SDimitry Andric       Contents =
5200b57cec5SDimitry Andric           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5215ffd83dbSDimitry Andric       return Error::success();
5220b57cec5SDimitry Andric     }
5230b57cec5SDimitry Andric   }
52481ad6265SDimitry Andric   if (ErrorContext)
52581ad6265SDimitry Andric     return createStringError(object_error::parse_failed,
52681ad6265SDimitry Andric                              "RVA 0x%" PRIx32 " for %s not found", RVA,
52781ad6265SDimitry Andric                              ErrorContext);
52881ad6265SDimitry Andric   return createStringError(object_error::parse_failed,
52981ad6265SDimitry Andric                            "RVA 0x%" PRIx32 " not found", RVA);
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
5330b57cec5SDimitry Andric // table entry.
5345ffd83dbSDimitry Andric Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
5350b57cec5SDimitry Andric                                   StringRef &Name) const {
5360b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
5375ffd83dbSDimitry Andric   if (Error E = getRvaPtr(Rva, IntPtr))
5385ffd83dbSDimitry Andric     return E;
5390b57cec5SDimitry Andric   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
5400b57cec5SDimitry Andric   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
5410b57cec5SDimitry Andric   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5425ffd83dbSDimitry Andric   return Error::success();
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric 
5455ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
5460b57cec5SDimitry Andric                                       const codeview::DebugInfo *&PDBInfo,
5470b57cec5SDimitry Andric                                       StringRef &PDBFileName) const {
5480b57cec5SDimitry Andric   ArrayRef<uint8_t> InfoBytes;
54981ad6265SDimitry Andric   if (Error E =
55081ad6265SDimitry Andric           getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData,
55181ad6265SDimitry Andric                                InfoBytes, "PDB info"))
5525ffd83dbSDimitry Andric     return E;
5530b57cec5SDimitry Andric   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
55481ad6265SDimitry Andric     return createStringError(object_error::parse_failed, "PDB info too small");
5550b57cec5SDimitry Andric   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
5560b57cec5SDimitry Andric   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5570b57cec5SDimitry Andric   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5580b57cec5SDimitry Andric                           InfoBytes.size());
5590b57cec5SDimitry Andric   // Truncate the name at the first null byte. Ignore any padding.
5600b57cec5SDimitry Andric   PDBFileName = PDBFileName.split('\0').first;
5615ffd83dbSDimitry Andric   return Error::success();
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5645ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
5650b57cec5SDimitry Andric                                       StringRef &PDBFileName) const {
5660b57cec5SDimitry Andric   for (const debug_directory &D : debug_directories())
5670b57cec5SDimitry Andric     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
5680b57cec5SDimitry Andric       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
5690b57cec5SDimitry Andric   // If we get here, there is no PDB info to return.
5700b57cec5SDimitry Andric   PDBInfo = nullptr;
5710b57cec5SDimitry Andric   PDBFileName = StringRef();
5725ffd83dbSDimitry Andric   return Error::success();
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric // Find the import table.
5765ffd83dbSDimitry Andric Error COFFObjectFile::initImportTablePtr() {
5770b57cec5SDimitry Andric   // First, we get the RVA of the import table. If the file lacks a pointer to
5780b57cec5SDimitry Andric   // the import table, do nothing.
5795ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5805ffd83dbSDimitry Andric   if (!DataEntry)
5815ffd83dbSDimitry Andric     return Error::success();
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   // Do nothing if the pointer to import table is NULL.
5840b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
5855ffd83dbSDimitry Andric     return Error::success();
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   // Find the section that contains the RVA. This is needed because the RVA is
5900b57cec5SDimitry Andric   // the import table's memory address which is different from its file offset.
5910b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
59281ad6265SDimitry Andric   if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table"))
5935ffd83dbSDimitry Andric     return E;
5945ffd83dbSDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5955ffd83dbSDimitry Andric     return E;
5960b57cec5SDimitry Andric   ImportDirectory = reinterpret_cast<
5970b57cec5SDimitry Andric       const coff_import_directory_table_entry *>(IntPtr);
5985ffd83dbSDimitry Andric   return Error::success();
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
6025ffd83dbSDimitry Andric Error COFFObjectFile::initDelayImportTablePtr() {
6035ffd83dbSDimitry Andric   const data_directory *DataEntry =
6045ffd83dbSDimitry Andric       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
6055ffd83dbSDimitry Andric   if (!DataEntry)
6065ffd83dbSDimitry Andric     return Error::success();
6070b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6085ffd83dbSDimitry Andric     return Error::success();
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   uint32_t RVA = DataEntry->RelativeVirtualAddress;
6110b57cec5SDimitry Andric   NumberOfDelayImportDirectory = DataEntry->Size /
6120b57cec5SDimitry Andric       sizeof(delay_import_directory_table_entry) - 1;
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
61581ad6265SDimitry Andric   if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))
6165ffd83dbSDimitry Andric     return E;
61781ad6265SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
61881ad6265SDimitry Andric     return E;
61981ad6265SDimitry Andric 
6200b57cec5SDimitry Andric   DelayImportDirectory = reinterpret_cast<
6210b57cec5SDimitry Andric       const delay_import_directory_table_entry *>(IntPtr);
6225ffd83dbSDimitry Andric   return Error::success();
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric // Find the export table.
6265ffd83dbSDimitry Andric Error COFFObjectFile::initExportTablePtr() {
6270b57cec5SDimitry Andric   // First, we get the RVA of the export table. If the file lacks a pointer to
6280b57cec5SDimitry Andric   // the export table, do nothing.
6295ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6305ffd83dbSDimitry Andric   if (!DataEntry)
6315ffd83dbSDimitry Andric     return Error::success();
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   // Do nothing if the pointer to export table is NULL.
6340b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6355ffd83dbSDimitry Andric     return Error::success();
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
6380b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
63981ad6265SDimitry Andric   if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))
6405ffd83dbSDimitry Andric     return E;
64181ad6265SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
64281ad6265SDimitry Andric     return E;
64381ad6265SDimitry Andric 
6440b57cec5SDimitry Andric   ExportDirectory =
6450b57cec5SDimitry Andric       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6465ffd83dbSDimitry Andric   return Error::success();
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6495ffd83dbSDimitry Andric Error COFFObjectFile::initBaseRelocPtr() {
6505ffd83dbSDimitry Andric   const data_directory *DataEntry =
6515ffd83dbSDimitry Andric       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6525ffd83dbSDimitry Andric   if (!DataEntry)
6535ffd83dbSDimitry Andric     return Error::success();
6540b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6555ffd83dbSDimitry Andric     return Error::success();
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
65881ad6265SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
65981ad6265SDimitry Andric                           "base reloc table"))
6605ffd83dbSDimitry Andric     return E;
66181ad6265SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
66281ad6265SDimitry Andric     return E;
66381ad6265SDimitry Andric 
6640b57cec5SDimitry Andric   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
6650b57cec5SDimitry Andric       IntPtr);
6660b57cec5SDimitry Andric   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
6670b57cec5SDimitry Andric       IntPtr + DataEntry->Size);
6680b57cec5SDimitry Andric   // FIXME: Verify the section containing BaseRelocHeader has at least
6690b57cec5SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6705ffd83dbSDimitry Andric   return Error::success();
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric 
6735ffd83dbSDimitry Andric Error COFFObjectFile::initDebugDirectoryPtr() {
6740b57cec5SDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
6755ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6765ffd83dbSDimitry Andric   if (!DataEntry)
6775ffd83dbSDimitry Andric     return Error::success();
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   // Do nothing if the RVA is NULL.
6800b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6815ffd83dbSDimitry Andric     return Error::success();
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   // Check that the size is a multiple of the entry size.
6840b57cec5SDimitry Andric   if (DataEntry->Size % sizeof(debug_directory) != 0)
68581ad6265SDimitry Andric     return createStringError(object_error::parse_failed,
68681ad6265SDimitry Andric                              "debug directory has uneven size");
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
68981ad6265SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
69081ad6265SDimitry Andric                           "debug directory"))
6915ffd83dbSDimitry Andric     return E;
69281ad6265SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
69381ad6265SDimitry Andric     return E;
69481ad6265SDimitry Andric 
6950b57cec5SDimitry Andric   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6960b57cec5SDimitry Andric   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
6970b57cec5SDimitry Andric       IntPtr + DataEntry->Size);
6980b57cec5SDimitry Andric   // FIXME: Verify the section containing DebugDirectoryBegin has at least
6990b57cec5SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
7005ffd83dbSDimitry Andric   return Error::success();
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric 
703e8d8bef9SDimitry Andric Error COFFObjectFile::initTLSDirectoryPtr() {
704e8d8bef9SDimitry Andric   // Get the RVA of the TLS directory. Do nothing if it does not exist.
705e8d8bef9SDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
706e8d8bef9SDimitry Andric   if (!DataEntry)
707e8d8bef9SDimitry Andric     return Error::success();
708e8d8bef9SDimitry Andric 
709e8d8bef9SDimitry Andric   // Do nothing if the RVA is NULL.
710e8d8bef9SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
711e8d8bef9SDimitry Andric     return Error::success();
712e8d8bef9SDimitry Andric 
713e8d8bef9SDimitry Andric   uint64_t DirSize =
714e8d8bef9SDimitry Andric       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
715e8d8bef9SDimitry Andric 
716e8d8bef9SDimitry Andric   // Check that the size is correct.
717e8d8bef9SDimitry Andric   if (DataEntry->Size != DirSize)
718e8d8bef9SDimitry Andric     return createStringError(
719e8d8bef9SDimitry Andric         object_error::parse_failed,
720e8d8bef9SDimitry Andric         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
721e8d8bef9SDimitry Andric         static_cast<uint32_t>(DataEntry->Size), DirSize);
722e8d8bef9SDimitry Andric 
723e8d8bef9SDimitry Andric   uintptr_t IntPtr = 0;
72481ad6265SDimitry Andric   if (Error E =
72581ad6265SDimitry Andric           getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))
72681ad6265SDimitry Andric     return E;
72781ad6265SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
728e8d8bef9SDimitry Andric     return E;
729e8d8bef9SDimitry Andric 
730e8d8bef9SDimitry Andric   if (is64())
731e8d8bef9SDimitry Andric     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
732e8d8bef9SDimitry Andric   else
733e8d8bef9SDimitry Andric     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
734e8d8bef9SDimitry Andric 
735e8d8bef9SDimitry Andric   return Error::success();
736e8d8bef9SDimitry Andric }
737e8d8bef9SDimitry Andric 
7385ffd83dbSDimitry Andric Error COFFObjectFile::initLoadConfigPtr() {
7390b57cec5SDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
7405ffd83dbSDimitry Andric   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
7415ffd83dbSDimitry Andric   if (!DataEntry)
7425ffd83dbSDimitry Andric     return Error::success();
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   // Do nothing if the RVA is NULL.
7450b57cec5SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
7465ffd83dbSDimitry Andric     return Error::success();
7470b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
74881ad6265SDimitry Andric   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
74981ad6265SDimitry Andric                           "load config table"))
75081ad6265SDimitry Andric     return E;
75181ad6265SDimitry Andric   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
7525ffd83dbSDimitry Andric     return E;
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   LoadConfig = (const void *)IntPtr;
75506c3fb27SDimitry Andric 
75606c3fb27SDimitry Andric   if (is64()) {
75706c3fb27SDimitry Andric     auto Config = getLoadConfig64();
75806c3fb27SDimitry Andric     if (Config->Size >=
75906c3fb27SDimitry Andric             offsetof(coff_load_configuration64, CHPEMetadataPointer) +
76006c3fb27SDimitry Andric                 sizeof(Config->CHPEMetadataPointer) &&
76106c3fb27SDimitry Andric         Config->CHPEMetadataPointer) {
76206c3fb27SDimitry Andric       uint64_t ChpeOff = Config->CHPEMetadataPointer;
76306c3fb27SDimitry Andric       if (Error E =
76406c3fb27SDimitry Andric               getRvaPtr(ChpeOff - getImageBase(), IntPtr, "CHPE metadata"))
76506c3fb27SDimitry Andric         return E;
76606c3fb27SDimitry Andric       if (Error E = checkOffset(Data, IntPtr, sizeof(CHPEMetadata)))
76706c3fb27SDimitry Andric         return E;
76806c3fb27SDimitry Andric 
76906c3fb27SDimitry Andric       CHPEMetadata = reinterpret_cast<const chpe_metadata *>(IntPtr);
77006c3fb27SDimitry Andric 
77106c3fb27SDimitry Andric       // Validate CHPE metadata
77206c3fb27SDimitry Andric       if (CHPEMetadata->CodeMapCount) {
77306c3fb27SDimitry Andric         if (Error E = getRvaPtr(CHPEMetadata->CodeMap, IntPtr, "CHPE code map"))
77406c3fb27SDimitry Andric           return E;
77506c3fb27SDimitry Andric         if (Error E = checkOffset(Data, IntPtr,
77606c3fb27SDimitry Andric                                   CHPEMetadata->CodeMapCount *
77706c3fb27SDimitry Andric                                       sizeof(chpe_range_entry)))
77806c3fb27SDimitry Andric           return E;
77906c3fb27SDimitry Andric       }
78006c3fb27SDimitry Andric 
78106c3fb27SDimitry Andric       if (CHPEMetadata->CodeRangesToEntryPointsCount) {
78206c3fb27SDimitry Andric         if (Error E = getRvaPtr(CHPEMetadata->CodeRangesToEntryPoints, IntPtr,
78306c3fb27SDimitry Andric                                 "CHPE entry point ranges"))
78406c3fb27SDimitry Andric           return E;
78506c3fb27SDimitry Andric         if (Error E = checkOffset(Data, IntPtr,
78606c3fb27SDimitry Andric                                   CHPEMetadata->CodeRangesToEntryPointsCount *
78706c3fb27SDimitry Andric                                       sizeof(chpe_code_range_entry)))
78806c3fb27SDimitry Andric           return E;
78906c3fb27SDimitry Andric       }
79006c3fb27SDimitry Andric 
79106c3fb27SDimitry Andric       if (CHPEMetadata->RedirectionMetadataCount) {
79206c3fb27SDimitry Andric         if (Error E = getRvaPtr(CHPEMetadata->RedirectionMetadata, IntPtr,
79306c3fb27SDimitry Andric                                 "CHPE redirection metadata"))
79406c3fb27SDimitry Andric           return E;
79506c3fb27SDimitry Andric         if (Error E = checkOffset(Data, IntPtr,
79606c3fb27SDimitry Andric                                   CHPEMetadata->RedirectionMetadataCount *
79706c3fb27SDimitry Andric                                       sizeof(chpe_redirection_entry)))
79806c3fb27SDimitry Andric           return E;
79906c3fb27SDimitry Andric       }
80006c3fb27SDimitry Andric     }
80106c3fb27SDimitry Andric   }
80206c3fb27SDimitry Andric 
8035ffd83dbSDimitry Andric   return Error::success();
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric 
8065ffd83dbSDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
8075ffd83dbSDimitry Andric COFFObjectFile::create(MemoryBufferRef Object) {
8085ffd83dbSDimitry Andric   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
8095ffd83dbSDimitry Andric   if (Error E = Obj->initialize())
810*0fca6ea1SDimitry Andric     return E;
8115ffd83dbSDimitry Andric   return std::move(Obj);
8125ffd83dbSDimitry Andric }
8135ffd83dbSDimitry Andric 
8145ffd83dbSDimitry Andric COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
8150b57cec5SDimitry Andric     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
8160b57cec5SDimitry Andric       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
8170b57cec5SDimitry Andric       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
8180b57cec5SDimitry Andric       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
8195ffd83dbSDimitry Andric       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
8205ffd83dbSDimitry Andric       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
8215ffd83dbSDimitry Andric       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
822e8d8bef9SDimitry Andric       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
823e8d8bef9SDimitry Andric       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
8245ffd83dbSDimitry Andric 
82581ad6265SDimitry Andric static Error ignoreStrippedErrors(Error E) {
82681ad6265SDimitry Andric   if (E.isA<SectionStrippedError>()) {
82781ad6265SDimitry Andric     consumeError(std::move(E));
82881ad6265SDimitry Andric     return Error::success();
82981ad6265SDimitry Andric   }
83081ad6265SDimitry Andric   return E;
83181ad6265SDimitry Andric }
83281ad6265SDimitry Andric 
8335ffd83dbSDimitry Andric Error COFFObjectFile::initialize() {
8340b57cec5SDimitry Andric   // Check that we at least have enough room for a header.
8355ffd83dbSDimitry Andric   std::error_code EC;
8360b57cec5SDimitry Andric   if (!checkSize(Data, EC, sizeof(coff_file_header)))
8375ffd83dbSDimitry Andric     return errorCodeToError(EC);
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric   // The current location in the file where we are looking at.
8400b57cec5SDimitry Andric   uint64_t CurPtr = 0;
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   // PE header is optional and is present only in executables. If it exists,
8430b57cec5SDimitry Andric   // it is placed right after COFF header.
8440b57cec5SDimitry Andric   bool HasPEHeader = false;
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric   // Check if this is a PE/COFF file.
8470b57cec5SDimitry Andric   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
8480b57cec5SDimitry Andric     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
8490b57cec5SDimitry Andric     // PE signature to find 'normal' COFF header.
8500b57cec5SDimitry Andric     const auto *DH = reinterpret_cast<const dos_header *>(base());
8510b57cec5SDimitry Andric     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
8520b57cec5SDimitry Andric       CurPtr = DH->AddressOfNewExeHeader;
8530b57cec5SDimitry Andric       // Check the PE magic bytes. ("PE\0\0")
8540b57cec5SDimitry Andric       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
85581ad6265SDimitry Andric         return createStringError(object_error::parse_failed,
85681ad6265SDimitry Andric                                  "incorrect PE magic");
8570b57cec5SDimitry Andric       }
8580b57cec5SDimitry Andric       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
8590b57cec5SDimitry Andric       HasPEHeader = true;
8600b57cec5SDimitry Andric     }
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric 
8635ffd83dbSDimitry Andric   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
8645ffd83dbSDimitry Andric     return E;
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
8670b57cec5SDimitry Andric   // import libraries share a common prefix but bigobj is more restrictive.
8680b57cec5SDimitry Andric   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
8690b57cec5SDimitry Andric       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
8700b57cec5SDimitry Andric       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
8715ffd83dbSDimitry Andric     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
8725ffd83dbSDimitry Andric       return E;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric     // Verify that we are dealing with bigobj.
8750b57cec5SDimitry Andric     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
8760b57cec5SDimitry Andric         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
8770b57cec5SDimitry Andric                     sizeof(COFF::BigObjMagic)) == 0) {
8780b57cec5SDimitry Andric       COFFHeader = nullptr;
8790b57cec5SDimitry Andric       CurPtr += sizeof(coff_bigobj_file_header);
8800b57cec5SDimitry Andric     } else {
8810b57cec5SDimitry Andric       // It's not a bigobj.
8820b57cec5SDimitry Andric       COFFBigObjHeader = nullptr;
8830b57cec5SDimitry Andric     }
8840b57cec5SDimitry Andric   }
8850b57cec5SDimitry Andric   if (COFFHeader) {
8860b57cec5SDimitry Andric     // The prior checkSize call may have failed.  This isn't a hard error
8870b57cec5SDimitry Andric     // because we were just trying to sniff out bigobj.
8880b57cec5SDimitry Andric     EC = std::error_code();
8890b57cec5SDimitry Andric     CurPtr += sizeof(coff_file_header);
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric     if (COFFHeader->isImportLibrary())
8925ffd83dbSDimitry Andric       return errorCodeToError(EC);
8930b57cec5SDimitry Andric   }
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   if (HasPEHeader) {
8960b57cec5SDimitry Andric     const pe32_header *Header;
8975ffd83dbSDimitry Andric     if (Error E = getObject(Header, Data, base() + CurPtr))
8985ffd83dbSDimitry Andric       return E;
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric     const uint8_t *DataDirAddr;
9010b57cec5SDimitry Andric     uint64_t DataDirSize;
9020b57cec5SDimitry Andric     if (Header->Magic == COFF::PE32Header::PE32) {
9030b57cec5SDimitry Andric       PE32Header = Header;
9040b57cec5SDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
9050b57cec5SDimitry Andric       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
9060b57cec5SDimitry Andric     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
9070b57cec5SDimitry Andric       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
9080b57cec5SDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
9090b57cec5SDimitry Andric       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
9100b57cec5SDimitry Andric     } else {
9110b57cec5SDimitry Andric       // It's neither PE32 nor PE32+.
91281ad6265SDimitry Andric       return createStringError(object_error::parse_failed,
91381ad6265SDimitry Andric                                "incorrect PE magic");
9140b57cec5SDimitry Andric     }
9155ffd83dbSDimitry Andric     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
9165ffd83dbSDimitry Andric       return E;
9170b57cec5SDimitry Andric   }
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   if (COFFHeader)
9200b57cec5SDimitry Andric     CurPtr += COFFHeader->SizeOfOptionalHeader;
9210b57cec5SDimitry Andric 
9225ffd83dbSDimitry Andric   assert(COFFHeader || COFFBigObjHeader);
9235ffd83dbSDimitry Andric 
9245ffd83dbSDimitry Andric   if (Error E =
9255ffd83dbSDimitry Andric           getObject(SectionTable, Data, base() + CurPtr,
9265ffd83dbSDimitry Andric                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
9275ffd83dbSDimitry Andric     return E;
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   // Initialize the pointer to the symbol table.
9300b57cec5SDimitry Andric   if (getPointerToSymbolTable() != 0) {
9315ffd83dbSDimitry Andric     if (Error E = initSymbolTablePtr()) {
9325ffd83dbSDimitry Andric       // Recover from errors reading the symbol table.
9335ffd83dbSDimitry Andric       consumeError(std::move(E));
9340b57cec5SDimitry Andric       SymbolTable16 = nullptr;
9350b57cec5SDimitry Andric       SymbolTable32 = nullptr;
9360b57cec5SDimitry Andric       StringTable = nullptr;
9370b57cec5SDimitry Andric       StringTableSize = 0;
9380b57cec5SDimitry Andric     }
9390b57cec5SDimitry Andric   } else {
9400b57cec5SDimitry Andric     // We had better not have any symbols if we don't have a symbol table.
9410b57cec5SDimitry Andric     if (getNumberOfSymbols() != 0) {
94281ad6265SDimitry Andric       return createStringError(object_error::parse_failed,
94381ad6265SDimitry Andric                                "symbol table missing");
9440b57cec5SDimitry Andric     }
9450b57cec5SDimitry Andric   }
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric   // Initialize the pointer to the beginning of the import table.
94881ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initImportTablePtr()))
9495ffd83dbSDimitry Andric     return E;
95081ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initDelayImportTablePtr()))
9515ffd83dbSDimitry Andric     return E;
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   // Initialize the pointer to the export table.
95481ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initExportTablePtr()))
9555ffd83dbSDimitry Andric     return E;
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   // Initialize the pointer to the base relocation table.
95881ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initBaseRelocPtr()))
9595ffd83dbSDimitry Andric     return E;
9600b57cec5SDimitry Andric 
961e8d8bef9SDimitry Andric   // Initialize the pointer to the debug directory.
96281ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr()))
9635ffd83dbSDimitry Andric     return E;
9640b57cec5SDimitry Andric 
965e8d8bef9SDimitry Andric   // Initialize the pointer to the TLS directory.
96681ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr()))
967e8d8bef9SDimitry Andric     return E;
968e8d8bef9SDimitry Andric 
96981ad6265SDimitry Andric   if (Error E = ignoreStrippedErrors(initLoadConfigPtr()))
9705ffd83dbSDimitry Andric     return E;
9710b57cec5SDimitry Andric 
9725ffd83dbSDimitry Andric   return Error::success();
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_begin() const {
9760b57cec5SDimitry Andric   DataRefImpl Ret;
9770b57cec5SDimitry Andric   Ret.p = getSymbolTable();
9780b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_end() const {
9820b57cec5SDimitry Andric   // The symbol table ends where the string table begins.
9830b57cec5SDimitry Andric   DataRefImpl Ret;
9840b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
9850b57cec5SDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_begin() const {
9890b57cec5SDimitry Andric   if (!ImportDirectory)
9900b57cec5SDimitry Andric     return import_directory_end();
9910b57cec5SDimitry Andric   if (ImportDirectory->isNull())
9920b57cec5SDimitry Andric     return import_directory_end();
9930b57cec5SDimitry Andric   return import_directory_iterator(
9940b57cec5SDimitry Andric       ImportDirectoryEntryRef(ImportDirectory, 0, this));
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_end() const {
9980b57cec5SDimitry Andric   return import_directory_iterator(
9990b57cec5SDimitry Andric       ImportDirectoryEntryRef(nullptr, -1, this));
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric delay_import_directory_iterator
10030b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_begin() const {
10040b57cec5SDimitry Andric   return delay_import_directory_iterator(
10050b57cec5SDimitry Andric       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
10060b57cec5SDimitry Andric }
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric delay_import_directory_iterator
10090b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_end() const {
10100b57cec5SDimitry Andric   return delay_import_directory_iterator(
10110b57cec5SDimitry Andric       DelayImportDirectoryEntryRef(
10120b57cec5SDimitry Andric           DelayImportDirectory, NumberOfDelayImportDirectory, this));
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_begin() const {
10160b57cec5SDimitry Andric   return export_directory_iterator(
10170b57cec5SDimitry Andric       ExportDirectoryEntryRef(ExportDirectory, 0, this));
10180b57cec5SDimitry Andric }
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_end() const {
10210b57cec5SDimitry Andric   if (!ExportDirectory)
10220b57cec5SDimitry Andric     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
10230b57cec5SDimitry Andric   ExportDirectoryEntryRef Ref(ExportDirectory,
10240b57cec5SDimitry Andric                               ExportDirectory->AddressTableEntries, this);
10250b57cec5SDimitry Andric   return export_directory_iterator(Ref);
10260b57cec5SDimitry Andric }
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric section_iterator COFFObjectFile::section_begin() const {
10290b57cec5SDimitry Andric   DataRefImpl Ret;
10300b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
10310b57cec5SDimitry Andric   return section_iterator(SectionRef(Ret, this));
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric section_iterator COFFObjectFile::section_end() const {
10350b57cec5SDimitry Andric   DataRefImpl Ret;
10360b57cec5SDimitry Andric   int NumSections =
10370b57cec5SDimitry Andric       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
10380b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
10390b57cec5SDimitry Andric   return section_iterator(SectionRef(Ret, this));
10400b57cec5SDimitry Andric }
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
10430b57cec5SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_end() const {
10470b57cec5SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
10480b57cec5SDimitry Andric }
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric uint8_t COFFObjectFile::getBytesInAddress() const {
10510b57cec5SDimitry Andric   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric StringRef COFFObjectFile::getFileFormatName() const {
10550b57cec5SDimitry Andric   switch(getMachine()) {
10560b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
10570b57cec5SDimitry Andric     return "COFF-i386";
10580b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
10590b57cec5SDimitry Andric     return "COFF-x86-64";
10600b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
10610b57cec5SDimitry Andric     return "COFF-ARM";
10620b57cec5SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
10630b57cec5SDimitry Andric     return "COFF-ARM64";
1064bdd1243dSDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64EC:
1065bdd1243dSDimitry Andric     return "COFF-ARM64EC";
106606c3fb27SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64X:
106706c3fb27SDimitry Andric     return "COFF-ARM64X";
10680b57cec5SDimitry Andric   default:
10690b57cec5SDimitry Andric     return "COFF-<unknown arch>";
10700b57cec5SDimitry Andric   }
10710b57cec5SDimitry Andric }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric Triple::ArchType COFFObjectFile::getArch() const {
1074*0fca6ea1SDimitry Andric   return getMachineArchType(getMachine());
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getStartAddress() const {
10780b57cec5SDimitry Andric   if (PE32Header)
10790b57cec5SDimitry Andric     return PE32Header->AddressOfEntryPoint;
10800b57cec5SDimitry Andric   return 0;
10810b57cec5SDimitry Andric }
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric iterator_range<import_directory_iterator>
10840b57cec5SDimitry Andric COFFObjectFile::import_directories() const {
10850b57cec5SDimitry Andric   return make_range(import_directory_begin(), import_directory_end());
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric iterator_range<delay_import_directory_iterator>
10890b57cec5SDimitry Andric COFFObjectFile::delay_import_directories() const {
10900b57cec5SDimitry Andric   return make_range(delay_import_directory_begin(),
10910b57cec5SDimitry Andric                     delay_import_directory_end());
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric iterator_range<export_directory_iterator>
10950b57cec5SDimitry Andric COFFObjectFile::export_directories() const {
10960b57cec5SDimitry Andric   return make_range(export_directory_begin(), export_directory_end());
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
11000b57cec5SDimitry Andric   return make_range(base_reloc_begin(), base_reloc_end());
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric 
11035ffd83dbSDimitry Andric const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
11045ffd83dbSDimitry Andric   if (!DataDirectory)
11055ffd83dbSDimitry Andric     return nullptr;
11060b57cec5SDimitry Andric   assert(PE32Header || PE32PlusHeader);
11070b57cec5SDimitry Andric   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
11080b57cec5SDimitry Andric                                : PE32PlusHeader->NumberOfRvaAndSize;
11095ffd83dbSDimitry Andric   if (Index >= NumEnt)
11105ffd83dbSDimitry Andric     return nullptr;
11115ffd83dbSDimitry Andric   return &DataDirectory[Index];
11120b57cec5SDimitry Andric }
11130b57cec5SDimitry Andric 
11145ffd83dbSDimitry Andric Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
11155ffd83dbSDimitry Andric   // Perhaps getting the section of a reserved section index should be an error,
11165ffd83dbSDimitry Andric   // but callers rely on this to return null.
11170b57cec5SDimitry Andric   if (COFF::isReservedSectionNumber(Index))
11185ffd83dbSDimitry Andric     return (const coff_section *)nullptr;
11190b57cec5SDimitry Andric   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
11200b57cec5SDimitry Andric     // We already verified the section table data, so no need to check again.
11215ffd83dbSDimitry Andric     return SectionTable + (Index - 1);
11220b57cec5SDimitry Andric   }
112381ad6265SDimitry Andric   return createStringError(object_error::parse_failed,
112481ad6265SDimitry Andric                            "section index out of bounds");
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric 
11275ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
11280b57cec5SDimitry Andric   if (StringTableSize <= 4)
11290b57cec5SDimitry Andric     // Tried to get a string from an empty string table.
113081ad6265SDimitry Andric     return createStringError(object_error::parse_failed, "string table empty");
11310b57cec5SDimitry Andric   if (Offset >= StringTableSize)
11325ffd83dbSDimitry Andric     return errorCodeToError(object_error::unexpected_eof);
11335ffd83dbSDimitry Andric   return StringRef(StringTable + Offset);
11340b57cec5SDimitry Andric }
11350b57cec5SDimitry Andric 
11365ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
11375ffd83dbSDimitry Andric   return getSymbolName(Symbol.getGeneric());
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric 
11405ffd83dbSDimitry Andric Expected<StringRef>
11415ffd83dbSDimitry Andric COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
11420b57cec5SDimitry Andric   // Check for string table entry. First 4 bytes are 0.
11435ffd83dbSDimitry Andric   if (Symbol->Name.Offset.Zeroes == 0)
11445ffd83dbSDimitry Andric     return getString(Symbol->Name.Offset.Offset);
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric   // Null terminated, let ::strlen figure out the length.
11475ffd83dbSDimitry Andric   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
11485ffd83dbSDimitry Andric     return StringRef(Symbol->Name.ShortName);
11495ffd83dbSDimitry Andric 
11500b57cec5SDimitry Andric   // Not null terminated, use all 8 bytes.
11515ffd83dbSDimitry Andric   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
11520b57cec5SDimitry Andric }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric ArrayRef<uint8_t>
11550b57cec5SDimitry Andric COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
11560b57cec5SDimitry Andric   const uint8_t *Aux = nullptr;
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric   size_t SymbolSize = getSymbolTableEntrySize();
11590b57cec5SDimitry Andric   if (Symbol.getNumberOfAuxSymbols() > 0) {
11600b57cec5SDimitry Andric     // AUX data comes immediately after the symbol in COFF
11610b57cec5SDimitry Andric     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
11620b57cec5SDimitry Andric #ifndef NDEBUG
11630b57cec5SDimitry Andric     // Verify that the Aux symbol points to a valid entry in the symbol table.
11640b57cec5SDimitry Andric     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
11650b57cec5SDimitry Andric     if (Offset < getPointerToSymbolTable() ||
11660b57cec5SDimitry Andric         Offset >=
11670b57cec5SDimitry Andric             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
11680b57cec5SDimitry Andric       report_fatal_error("Aux Symbol data was outside of symbol table.");
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
11710b57cec5SDimitry Andric            "Aux Symbol data did not point to the beginning of a symbol");
11720b57cec5SDimitry Andric #endif
11730b57cec5SDimitry Andric   }
1174bdd1243dSDimitry Andric   return ArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
11780b57cec5SDimitry Andric   uintptr_t Offset =
11790b57cec5SDimitry Andric       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
11800b57cec5SDimitry Andric   assert(Offset % getSymbolTableEntrySize() == 0 &&
11810b57cec5SDimitry Andric          "Symbol did not point to the beginning of a symbol");
11820b57cec5SDimitry Andric   size_t Index = Offset / getSymbolTableEntrySize();
11830b57cec5SDimitry Andric   assert(Index < getNumberOfSymbols());
11840b57cec5SDimitry Andric   return Index;
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric 
11870b57cec5SDimitry Andric Expected<StringRef>
11880b57cec5SDimitry Andric COFFObjectFile::getSectionName(const coff_section *Sec) const {
118981ad6265SDimitry Andric   StringRef Name = StringRef(Sec->Name, COFF::NameSize).split('\0').first;
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   // Check for string table entry. First byte is '/'.
11925f757f3fSDimitry Andric   if (Name.starts_with("/")) {
11930b57cec5SDimitry Andric     uint32_t Offset;
11945f757f3fSDimitry Andric     if (Name.starts_with("//")) {
11950b57cec5SDimitry Andric       if (decodeBase64StringEntry(Name.substr(2), Offset))
11960b57cec5SDimitry Andric         return createStringError(object_error::parse_failed,
11975ffd83dbSDimitry Andric                                  "invalid section name");
11980b57cec5SDimitry Andric     } else {
11990b57cec5SDimitry Andric       if (Name.substr(1).getAsInteger(10, Offset))
12000b57cec5SDimitry Andric         return createStringError(object_error::parse_failed,
12010b57cec5SDimitry Andric                                  "invalid section name");
12020b57cec5SDimitry Andric     }
12035ffd83dbSDimitry Andric     return getString(Offset);
12040b57cec5SDimitry Andric   }
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric   return Name;
12070b57cec5SDimitry Andric }
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
12100b57cec5SDimitry Andric   // SizeOfRawData and VirtualSize change what they represent depending on
12110b57cec5SDimitry Andric   // whether or not we have an executable image.
12120b57cec5SDimitry Andric   //
12130b57cec5SDimitry Andric   // For object files, SizeOfRawData contains the size of section's data;
12140b57cec5SDimitry Andric   // VirtualSize should be zero but isn't due to buggy COFF writers.
12150b57cec5SDimitry Andric   //
12160b57cec5SDimitry Andric   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
12170b57cec5SDimitry Andric   // actual section size is in VirtualSize.  It is possible for VirtualSize to
12180b57cec5SDimitry Andric   // be greater than SizeOfRawData; the contents past that point should be
12190b57cec5SDimitry Andric   // considered to be zero.
12200b57cec5SDimitry Andric   if (getDOSHeader())
12210b57cec5SDimitry Andric     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
12220b57cec5SDimitry Andric   return Sec->SizeOfRawData;
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric Error COFFObjectFile::getSectionContents(const coff_section *Sec,
12260b57cec5SDimitry Andric                                          ArrayRef<uint8_t> &Res) const {
12270b57cec5SDimitry Andric   // In COFF, a virtual section won't have any in-file
12280b57cec5SDimitry Andric   // content, so the file pointer to the content will be zero.
12290b57cec5SDimitry Andric   if (Sec->PointerToRawData == 0)
12300b57cec5SDimitry Andric     return Error::success();
12310b57cec5SDimitry Andric   // The only thing that we need to verify is that the contents is contained
12320b57cec5SDimitry Andric   // within the file bounds. We don't need to make sure it doesn't cover other
12330b57cec5SDimitry Andric   // data, as there's nothing that says that is not allowed.
1234e8d8bef9SDimitry Andric   uintptr_t ConStart =
1235e8d8bef9SDimitry Andric       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
12360b57cec5SDimitry Andric   uint32_t SectionSize = getSectionSize(Sec);
12375ffd83dbSDimitry Andric   if (Error E = checkOffset(Data, ConStart, SectionSize))
12385ffd83dbSDimitry Andric     return E;
1239bdd1243dSDimitry Andric   Res = ArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
12400b57cec5SDimitry Andric   return Error::success();
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
12440b57cec5SDimitry Andric   return reinterpret_cast<const coff_relocation*>(Rel.p);
12450b57cec5SDimitry Andric }
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
12480b57cec5SDimitry Andric   Rel.p = reinterpret_cast<uintptr_t>(
12490b57cec5SDimitry Andric             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
12530b57cec5SDimitry Andric   const coff_relocation *R = toRel(Rel);
12540b57cec5SDimitry Andric   return R->VirtualAddress;
12550b57cec5SDimitry Andric }
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
12580b57cec5SDimitry Andric   const coff_relocation *R = toRel(Rel);
12590b57cec5SDimitry Andric   DataRefImpl Ref;
12600b57cec5SDimitry Andric   if (R->SymbolTableIndex >= getNumberOfSymbols())
12610b57cec5SDimitry Andric     return symbol_end();
12620b57cec5SDimitry Andric   if (SymbolTable16)
12630b57cec5SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
12640b57cec5SDimitry Andric   else if (SymbolTable32)
12650b57cec5SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
12660b57cec5SDimitry Andric   else
12670b57cec5SDimitry Andric     llvm_unreachable("no symbol table pointer!");
12680b57cec5SDimitry Andric   return symbol_iterator(SymbolRef(Ref, this));
12690b57cec5SDimitry Andric }
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
12720b57cec5SDimitry Andric   const coff_relocation* R = toRel(Rel);
12730b57cec5SDimitry Andric   return R->Type;
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric const coff_section *
12770b57cec5SDimitry Andric COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
12780b57cec5SDimitry Andric   return toSec(Section.getRawDataRefImpl());
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
12820b57cec5SDimitry Andric   if (SymbolTable16)
12830b57cec5SDimitry Andric     return toSymb<coff_symbol16>(Ref);
12840b57cec5SDimitry Andric   if (SymbolTable32)
12850b57cec5SDimitry Andric     return toSymb<coff_symbol32>(Ref);
12860b57cec5SDimitry Andric   llvm_unreachable("no symbol table pointer!");
12870b57cec5SDimitry Andric }
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
12900b57cec5SDimitry Andric   return getCOFFSymbol(Symbol.getRawDataRefImpl());
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric const coff_relocation *
12940b57cec5SDimitry Andric COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
12950b57cec5SDimitry Andric   return toRel(Reloc.getRawDataRefImpl());
12960b57cec5SDimitry Andric }
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric ArrayRef<coff_relocation>
12990b57cec5SDimitry Andric COFFObjectFile::getRelocations(const coff_section *Sec) const {
13000b57cec5SDimitry Andric   return {getFirstReloc(Sec, Data, base()),
13010b57cec5SDimitry Andric           getNumberOfRelocations(Sec, Data, base())};
13020b57cec5SDimitry Andric }
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
13050b57cec5SDimitry Andric   case COFF::reloc_type:                                                       \
13060b57cec5SDimitry Andric     return #reloc_type;
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
1309*0fca6ea1SDimitry Andric   switch (getArch()) {
1310*0fca6ea1SDimitry Andric   case Triple::x86_64:
13110b57cec5SDimitry Andric     switch (Type) {
13120b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
13130b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
13140b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
13150b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
13160b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
13170b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
13180b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
13190b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
13200b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
13210b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
13220b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
13230b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
13240b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
13250b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
13260b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
13270b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
13280b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
13290b57cec5SDimitry Andric     default:
13300b57cec5SDimitry Andric       return "Unknown";
13310b57cec5SDimitry Andric     }
13320b57cec5SDimitry Andric     break;
1333*0fca6ea1SDimitry Andric   case Triple::thumb:
13340b57cec5SDimitry Andric     switch (Type) {
13350b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
13360b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
13370b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
13380b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
13390b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
13400b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
13410b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
13420b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
13430b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
13440b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
13450b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
13460b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
13470b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
13480b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
13490b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
13500b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
13510b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
13520b57cec5SDimitry Andric     default:
13530b57cec5SDimitry Andric       return "Unknown";
13540b57cec5SDimitry Andric     }
13550b57cec5SDimitry Andric     break;
1356*0fca6ea1SDimitry Andric   case Triple::aarch64:
13570b57cec5SDimitry Andric     switch (Type) {
13580b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
13590b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
13600b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
13610b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
13620b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
13630b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
13640b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
13650b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
13660b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
13670b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
13680b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
13690b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
13700b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
13710b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
13720b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
13730b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
13740b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
13750b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
13760b57cec5SDimitry Andric     default:
13770b57cec5SDimitry Andric       return "Unknown";
13780b57cec5SDimitry Andric     }
13790b57cec5SDimitry Andric     break;
1380*0fca6ea1SDimitry Andric   case Triple::x86:
13810b57cec5SDimitry Andric     switch (Type) {
13820b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
13830b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
13840b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
13850b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
13860b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
13870b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
13880b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
13890b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
13900b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
13910b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
13920b57cec5SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
13930b57cec5SDimitry Andric     default:
13940b57cec5SDimitry Andric       return "Unknown";
13950b57cec5SDimitry Andric     }
13960b57cec5SDimitry Andric     break;
13970b57cec5SDimitry Andric   default:
13980b57cec5SDimitry Andric     return "Unknown";
13990b57cec5SDimitry Andric   }
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric void COFFObjectFile::getRelocationTypeName(
14050b57cec5SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
14060b57cec5SDimitry Andric   const coff_relocation *Reloc = toRel(Rel);
14070b57cec5SDimitry Andric   StringRef Res = getRelocationTypeName(Reloc->Type);
14080b57cec5SDimitry Andric   Result.append(Res.begin(), Res.end());
14090b57cec5SDimitry Andric }
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric bool COFFObjectFile::isRelocatableObject() const {
14120b57cec5SDimitry Andric   return !DataDirectory;
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric 
14150b57cec5SDimitry Andric StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
14160b57cec5SDimitry Andric   return StringSwitch<StringRef>(Name)
14170b57cec5SDimitry Andric       .Case("eh_fram", "eh_frame")
14180b57cec5SDimitry Andric       .Default(Name);
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric 
14210b57cec5SDimitry Andric bool ImportDirectoryEntryRef::
14220b57cec5SDimitry Andric operator==(const ImportDirectoryEntryRef &Other) const {
14230b57cec5SDimitry Andric   return ImportTable == Other.ImportTable && Index == Other.Index;
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric void ImportDirectoryEntryRef::moveNext() {
14270b57cec5SDimitry Andric   ++Index;
14280b57cec5SDimitry Andric   if (ImportTable[Index].isNull()) {
14290b57cec5SDimitry Andric     Index = -1;
14300b57cec5SDimitry Andric     ImportTable = nullptr;
14310b57cec5SDimitry Andric   }
14320b57cec5SDimitry Andric }
14330b57cec5SDimitry Andric 
14345ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportTableEntry(
14350b57cec5SDimitry Andric     const coff_import_directory_table_entry *&Result) const {
14360b57cec5SDimitry Andric   return getObject(Result, OwningObject->Data, ImportTable + Index);
14370b57cec5SDimitry Andric }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric static imported_symbol_iterator
14400b57cec5SDimitry Andric makeImportedSymbolIterator(const COFFObjectFile *Object,
14410b57cec5SDimitry Andric                            uintptr_t Ptr, int Index) {
14420b57cec5SDimitry Andric   if (Object->getBytesInAddress() == 4) {
14430b57cec5SDimitry Andric     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
14440b57cec5SDimitry Andric     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
14450b57cec5SDimitry Andric   }
14460b57cec5SDimitry Andric   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
14470b57cec5SDimitry Andric   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric static imported_symbol_iterator
14510b57cec5SDimitry Andric importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
14520b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
14535ffd83dbSDimitry Andric   // FIXME: Handle errors.
14545ffd83dbSDimitry Andric   cantFail(Object->getRvaPtr(RVA, IntPtr));
14550b57cec5SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, 0);
14560b57cec5SDimitry Andric }
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric static imported_symbol_iterator
14590b57cec5SDimitry Andric importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
14600b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
14615ffd83dbSDimitry Andric   // FIXME: Handle errors.
14625ffd83dbSDimitry Andric   cantFail(Object->getRvaPtr(RVA, IntPtr));
14630b57cec5SDimitry Andric   // Forward the pointer to the last entry which is null.
14640b57cec5SDimitry Andric   int Index = 0;
14650b57cec5SDimitry Andric   if (Object->getBytesInAddress() == 4) {
14660b57cec5SDimitry Andric     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
14670b57cec5SDimitry Andric     while (*Entry++)
14680b57cec5SDimitry Andric       ++Index;
14690b57cec5SDimitry Andric   } else {
14700b57cec5SDimitry Andric     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
14710b57cec5SDimitry Andric     while (*Entry++)
14720b57cec5SDimitry Andric       ++Index;
14730b57cec5SDimitry Andric   }
14740b57cec5SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, Index);
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric imported_symbol_iterator
14780b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_begin() const {
14790b57cec5SDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
14800b57cec5SDimitry Andric                              OwningObject);
14810b57cec5SDimitry Andric }
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric imported_symbol_iterator
14840b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_end() const {
14850b57cec5SDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
14860b57cec5SDimitry Andric                            OwningObject);
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
14900b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbols() const {
14910b57cec5SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
14950b57cec5SDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
14960b57cec5SDimitry Andric                              OwningObject);
14970b57cec5SDimitry Andric }
14980b57cec5SDimitry Andric 
14990b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
15000b57cec5SDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
15010b57cec5SDimitry Andric                            OwningObject);
15020b57cec5SDimitry Andric }
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
15050b57cec5SDimitry Andric ImportDirectoryEntryRef::lookup_table_symbols() const {
15060b57cec5SDimitry Andric   return make_range(lookup_table_begin(), lookup_table_end());
15070b57cec5SDimitry Andric }
15080b57cec5SDimitry Andric 
15095ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
15100b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
151181ad6265SDimitry Andric   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,
151281ad6265SDimitry Andric                                         "import directory name"))
15135ffd83dbSDimitry Andric     return E;
15140b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15155ffd83dbSDimitry Andric   return Error::success();
15160b57cec5SDimitry Andric }
15170b57cec5SDimitry Andric 
15185ffd83dbSDimitry Andric Error
15190b57cec5SDimitry Andric ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
15200b57cec5SDimitry Andric   Result = ImportTable[Index].ImportLookupTableRVA;
15215ffd83dbSDimitry Andric   return Error::success();
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric 
15245ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportAddressTableRVA(
15255ffd83dbSDimitry Andric     uint32_t &Result) const {
15260b57cec5SDimitry Andric   Result = ImportTable[Index].ImportAddressTableRVA;
15275ffd83dbSDimitry Andric   return Error::success();
15280b57cec5SDimitry Andric }
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric bool DelayImportDirectoryEntryRef::
15310b57cec5SDimitry Andric operator==(const DelayImportDirectoryEntryRef &Other) const {
15320b57cec5SDimitry Andric   return Table == Other.Table && Index == Other.Index;
15330b57cec5SDimitry Andric }
15340b57cec5SDimitry Andric 
15350b57cec5SDimitry Andric void DelayImportDirectoryEntryRef::moveNext() {
15360b57cec5SDimitry Andric   ++Index;
15370b57cec5SDimitry Andric }
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric imported_symbol_iterator
15400b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_begin() const {
15410b57cec5SDimitry Andric   return importedSymbolBegin(Table[Index].DelayImportNameTable,
15420b57cec5SDimitry Andric                              OwningObject);
15430b57cec5SDimitry Andric }
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric imported_symbol_iterator
15460b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_end() const {
15470b57cec5SDimitry Andric   return importedSymbolEnd(Table[Index].DelayImportNameTable,
15480b57cec5SDimitry Andric                            OwningObject);
15490b57cec5SDimitry Andric }
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
15520b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbols() const {
15530b57cec5SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
15540b57cec5SDimitry Andric }
15550b57cec5SDimitry Andric 
15565ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
15570b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
155881ad6265SDimitry Andric   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,
155981ad6265SDimitry Andric                                         "delay import directory name"))
15605ffd83dbSDimitry Andric     return E;
15610b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15625ffd83dbSDimitry Andric   return Error::success();
15630b57cec5SDimitry Andric }
15640b57cec5SDimitry Andric 
15655ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getDelayImportTable(
15665ffd83dbSDimitry Andric     const delay_import_directory_table_entry *&Result) const {
15670b57cec5SDimitry Andric   Result = &Table[Index];
15685ffd83dbSDimitry Andric   return Error::success();
15690b57cec5SDimitry Andric }
15700b57cec5SDimitry Andric 
15715ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
15725ffd83dbSDimitry Andric                                                      uint64_t &Result) const {
15730b57cec5SDimitry Andric   uint32_t RVA = Table[Index].DelayImportAddressTable +
15740b57cec5SDimitry Andric       AddrIndex * (OwningObject->is64() ? 8 : 4);
15750b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
157681ad6265SDimitry Andric   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address"))
15775ffd83dbSDimitry Andric     return E;
15780b57cec5SDimitry Andric   if (OwningObject->is64())
15790b57cec5SDimitry Andric     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
15800b57cec5SDimitry Andric   else
15810b57cec5SDimitry Andric     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
15825ffd83dbSDimitry Andric   return Error::success();
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric bool ExportDirectoryEntryRef::
15860b57cec5SDimitry Andric operator==(const ExportDirectoryEntryRef &Other) const {
15870b57cec5SDimitry Andric   return ExportTable == Other.ExportTable && Index == Other.Index;
15880b57cec5SDimitry Andric }
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric void ExportDirectoryEntryRef::moveNext() {
15910b57cec5SDimitry Andric   ++Index;
15920b57cec5SDimitry Andric }
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
15950b57cec5SDimitry Andric // by ordinal, the empty string is set as a result.
15965ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
15970b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
159881ad6265SDimitry Andric   if (Error E =
159981ad6265SDimitry Andric           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name"))
16005ffd83dbSDimitry Andric     return E;
16010b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16025ffd83dbSDimitry Andric   return Error::success();
16030b57cec5SDimitry Andric }
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric // Returns the starting ordinal number.
16065ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
16070b57cec5SDimitry Andric   Result = ExportTable->OrdinalBase;
16085ffd83dbSDimitry Andric   return Error::success();
16090b57cec5SDimitry Andric }
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric // Returns the export ordinal of the current export symbol.
16125ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
16130b57cec5SDimitry Andric   Result = ExportTable->OrdinalBase + Index;
16145ffd83dbSDimitry Andric   return Error::success();
16150b57cec5SDimitry Andric }
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric // Returns the address of the current export symbol.
16185ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
16190b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
162081ad6265SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,
162181ad6265SDimitry Andric                                          IntPtr, "export address"))
16220b57cec5SDimitry Andric     return EC;
16230b57cec5SDimitry Andric   const export_address_table_entry *entry =
16240b57cec5SDimitry Andric       reinterpret_cast<const export_address_table_entry *>(IntPtr);
16250b57cec5SDimitry Andric   Result = entry[Index].ExportRVA;
16265ffd83dbSDimitry Andric   return Error::success();
16270b57cec5SDimitry Andric }
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
16300b57cec5SDimitry Andric // by ordinal, the empty string is set as a result.
16315ffd83dbSDimitry Andric Error
16320b57cec5SDimitry Andric ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
16330b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
163481ad6265SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,
163581ad6265SDimitry Andric                                          "export ordinal table"))
16360b57cec5SDimitry Andric     return EC;
16370b57cec5SDimitry Andric   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
16380b57cec5SDimitry Andric 
16390b57cec5SDimitry Andric   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
16400b57cec5SDimitry Andric   int Offset = 0;
16410b57cec5SDimitry Andric   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
16420b57cec5SDimitry Andric        I < E; ++I, ++Offset) {
16430b57cec5SDimitry Andric     if (*I != Index)
16440b57cec5SDimitry Andric       continue;
164581ad6265SDimitry Andric     if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,
164681ad6265SDimitry Andric                                            "export table entry"))
16470b57cec5SDimitry Andric       return EC;
16480b57cec5SDimitry Andric     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
164981ad6265SDimitry Andric     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr,
165081ad6265SDimitry Andric                                            "export symbol name"))
16510b57cec5SDimitry Andric       return EC;
16520b57cec5SDimitry Andric     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16535ffd83dbSDimitry Andric     return Error::success();
16540b57cec5SDimitry Andric   }
16550b57cec5SDimitry Andric   Result = "";
16565ffd83dbSDimitry Andric   return Error::success();
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric 
16595ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
16605ffd83dbSDimitry Andric   const data_directory *DataEntry =
16615ffd83dbSDimitry Andric       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
16625ffd83dbSDimitry Andric   if (!DataEntry)
166381ad6265SDimitry Andric     return createStringError(object_error::parse_failed,
166481ad6265SDimitry Andric                              "export table missing");
16650b57cec5SDimitry Andric   uint32_t RVA;
16660b57cec5SDimitry Andric   if (auto EC = getExportRVA(RVA))
16670b57cec5SDimitry Andric     return EC;
16680b57cec5SDimitry Andric   uint32_t Begin = DataEntry->RelativeVirtualAddress;
16690b57cec5SDimitry Andric   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
16700b57cec5SDimitry Andric   Result = (Begin <= RVA && RVA < End);
16715ffd83dbSDimitry Andric   return Error::success();
16720b57cec5SDimitry Andric }
16730b57cec5SDimitry Andric 
16745ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
16750b57cec5SDimitry Andric   uint32_t RVA;
16760b57cec5SDimitry Andric   if (auto EC = getExportRVA(RVA))
16770b57cec5SDimitry Andric     return EC;
16780b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
167981ad6265SDimitry Andric   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target"))
16800b57cec5SDimitry Andric     return EC;
16810b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16825ffd83dbSDimitry Andric   return Error::success();
16830b57cec5SDimitry Andric }
16840b57cec5SDimitry Andric 
16850b57cec5SDimitry Andric bool ImportedSymbolRef::
16860b57cec5SDimitry Andric operator==(const ImportedSymbolRef &Other) const {
16870b57cec5SDimitry Andric   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
16880b57cec5SDimitry Andric       && Index == Other.Index;
16890b57cec5SDimitry Andric }
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric void ImportedSymbolRef::moveNext() {
16920b57cec5SDimitry Andric   ++Index;
16930b57cec5SDimitry Andric }
16940b57cec5SDimitry Andric 
16955ffd83dbSDimitry Andric Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
16960b57cec5SDimitry Andric   uint32_t RVA;
16970b57cec5SDimitry Andric   if (Entry32) {
16980b57cec5SDimitry Andric     // If a symbol is imported only by ordinal, it has no name.
16990b57cec5SDimitry Andric     if (Entry32[Index].isOrdinal())
17005ffd83dbSDimitry Andric       return Error::success();
17010b57cec5SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
17020b57cec5SDimitry Andric   } else {
17030b57cec5SDimitry Andric     if (Entry64[Index].isOrdinal())
17045ffd83dbSDimitry Andric       return Error::success();
17050b57cec5SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
17060b57cec5SDimitry Andric   }
17070b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
170881ad6265SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name"))
17090b57cec5SDimitry Andric     return EC;
17100b57cec5SDimitry Andric   // +2 because the first two bytes is hint.
17110b57cec5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
17125ffd83dbSDimitry Andric   return Error::success();
17130b57cec5SDimitry Andric }
17140b57cec5SDimitry Andric 
17155ffd83dbSDimitry Andric Error ImportedSymbolRef::isOrdinal(bool &Result) const {
17160b57cec5SDimitry Andric   if (Entry32)
17170b57cec5SDimitry Andric     Result = Entry32[Index].isOrdinal();
17180b57cec5SDimitry Andric   else
17190b57cec5SDimitry Andric     Result = Entry64[Index].isOrdinal();
17205ffd83dbSDimitry Andric   return Error::success();
17210b57cec5SDimitry Andric }
17220b57cec5SDimitry Andric 
17235ffd83dbSDimitry Andric Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
17240b57cec5SDimitry Andric   if (Entry32)
17250b57cec5SDimitry Andric     Result = Entry32[Index].getHintNameRVA();
17260b57cec5SDimitry Andric   else
17270b57cec5SDimitry Andric     Result = Entry64[Index].getHintNameRVA();
17285ffd83dbSDimitry Andric   return Error::success();
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric 
17315ffd83dbSDimitry Andric Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
17320b57cec5SDimitry Andric   uint32_t RVA;
17330b57cec5SDimitry Andric   if (Entry32) {
17340b57cec5SDimitry Andric     if (Entry32[Index].isOrdinal()) {
17350b57cec5SDimitry Andric       Result = Entry32[Index].getOrdinal();
17365ffd83dbSDimitry Andric       return Error::success();
17370b57cec5SDimitry Andric     }
17380b57cec5SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
17390b57cec5SDimitry Andric   } else {
17400b57cec5SDimitry Andric     if (Entry64[Index].isOrdinal()) {
17410b57cec5SDimitry Andric       Result = Entry64[Index].getOrdinal();
17425ffd83dbSDimitry Andric       return Error::success();
17430b57cec5SDimitry Andric     }
17440b57cec5SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
17450b57cec5SDimitry Andric   }
17460b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
174781ad6265SDimitry Andric   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal"))
17480b57cec5SDimitry Andric     return EC;
17490b57cec5SDimitry Andric   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
17505ffd83dbSDimitry Andric   return Error::success();
17510b57cec5SDimitry Andric }
17520b57cec5SDimitry Andric 
17530b57cec5SDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
17540b57cec5SDimitry Andric ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
17555ffd83dbSDimitry Andric   return COFFObjectFile::create(Object);
17560b57cec5SDimitry Andric }
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
17590b57cec5SDimitry Andric   return Header == Other.Header && Index == Other.Index;
17600b57cec5SDimitry Andric }
17610b57cec5SDimitry Andric 
17620b57cec5SDimitry Andric void BaseRelocRef::moveNext() {
17630b57cec5SDimitry Andric   // Header->BlockSize is the size of the current block, including the
17640b57cec5SDimitry Andric   // size of the header itself.
17650b57cec5SDimitry Andric   uint32_t Size = sizeof(*Header) +
17660b57cec5SDimitry Andric       sizeof(coff_base_reloc_block_entry) * (Index + 1);
17670b57cec5SDimitry Andric   if (Size == Header->BlockSize) {
17680b57cec5SDimitry Andric     // .reloc contains a list of base relocation blocks. Each block
17690b57cec5SDimitry Andric     // consists of the header followed by entries. The header contains
17700b57cec5SDimitry Andric     // how many entories will follow. When we reach the end of the
17710b57cec5SDimitry Andric     // current block, proceed to the next block.
17720b57cec5SDimitry Andric     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
17730b57cec5SDimitry Andric         reinterpret_cast<const uint8_t *>(Header) + Size);
17740b57cec5SDimitry Andric     Index = 0;
17750b57cec5SDimitry Andric   } else {
17760b57cec5SDimitry Andric     ++Index;
17770b57cec5SDimitry Andric   }
17780b57cec5SDimitry Andric }
17790b57cec5SDimitry Andric 
17805ffd83dbSDimitry Andric Error BaseRelocRef::getType(uint8_t &Type) const {
17810b57cec5SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
17820b57cec5SDimitry Andric   Type = Entry[Index].getType();
17835ffd83dbSDimitry Andric   return Error::success();
17840b57cec5SDimitry Andric }
17850b57cec5SDimitry Andric 
17865ffd83dbSDimitry Andric Error BaseRelocRef::getRVA(uint32_t &Result) const {
17870b57cec5SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
17880b57cec5SDimitry Andric   Result = Header->PageRVA + Entry[Index].getOffset();
17895ffd83dbSDimitry Andric   return Error::success();
17900b57cec5SDimitry Andric }
17910b57cec5SDimitry Andric 
17928bcb0991SDimitry Andric #define RETURN_IF_ERROR(Expr)                                                  \
17938bcb0991SDimitry Andric   do {                                                                         \
17948bcb0991SDimitry Andric     Error E = (Expr);                                                          \
17950b57cec5SDimitry Andric     if (E)                                                                     \
17968bcb0991SDimitry Andric       return std::move(E);                                                     \
17978bcb0991SDimitry Andric   } while (0)
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric Expected<ArrayRef<UTF16>>
18000b57cec5SDimitry Andric ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
18010b57cec5SDimitry Andric   BinaryStreamReader Reader = BinaryStreamReader(BBS);
18020b57cec5SDimitry Andric   Reader.setOffset(Offset);
18030b57cec5SDimitry Andric   uint16_t Length;
18040b57cec5SDimitry Andric   RETURN_IF_ERROR(Reader.readInteger(Length));
18050b57cec5SDimitry Andric   ArrayRef<UTF16> RawDirString;
18060b57cec5SDimitry Andric   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
18070b57cec5SDimitry Andric   return RawDirString;
18080b57cec5SDimitry Andric }
18090b57cec5SDimitry Andric 
18100b57cec5SDimitry Andric Expected<ArrayRef<UTF16>>
18110b57cec5SDimitry Andric ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
18120b57cec5SDimitry Andric   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
18130b57cec5SDimitry Andric }
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric Expected<const coff_resource_dir_table &>
18160b57cec5SDimitry Andric ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
18170b57cec5SDimitry Andric   const coff_resource_dir_table *Table = nullptr;
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric   BinaryStreamReader Reader(BBS);
18200b57cec5SDimitry Andric   Reader.setOffset(Offset);
18210b57cec5SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Table));
18220b57cec5SDimitry Andric   assert(Table != nullptr);
18230b57cec5SDimitry Andric   return *Table;
18240b57cec5SDimitry Andric }
18250b57cec5SDimitry Andric 
18268bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &>
18278bcb0991SDimitry Andric ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
18288bcb0991SDimitry Andric   const coff_resource_dir_entry *Entry = nullptr;
18298bcb0991SDimitry Andric 
18308bcb0991SDimitry Andric   BinaryStreamReader Reader(BBS);
18318bcb0991SDimitry Andric   Reader.setOffset(Offset);
18328bcb0991SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Entry));
18338bcb0991SDimitry Andric   assert(Entry != nullptr);
18348bcb0991SDimitry Andric   return *Entry;
18358bcb0991SDimitry Andric }
18368bcb0991SDimitry Andric 
18378bcb0991SDimitry Andric Expected<const coff_resource_data_entry &>
18388bcb0991SDimitry Andric ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
18398bcb0991SDimitry Andric   const coff_resource_data_entry *Entry = nullptr;
18408bcb0991SDimitry Andric 
18418bcb0991SDimitry Andric   BinaryStreamReader Reader(BBS);
18428bcb0991SDimitry Andric   Reader.setOffset(Offset);
18438bcb0991SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Entry));
18448bcb0991SDimitry Andric   assert(Entry != nullptr);
18458bcb0991SDimitry Andric   return *Entry;
18468bcb0991SDimitry Andric }
18478bcb0991SDimitry Andric 
18480b57cec5SDimitry Andric Expected<const coff_resource_dir_table &>
18490b57cec5SDimitry Andric ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
18508bcb0991SDimitry Andric   assert(Entry.Offset.isSubDir());
18510b57cec5SDimitry Andric   return getTableAtOffset(Entry.Offset.value());
18520b57cec5SDimitry Andric }
18530b57cec5SDimitry Andric 
18548bcb0991SDimitry Andric Expected<const coff_resource_data_entry &>
18558bcb0991SDimitry Andric ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
18568bcb0991SDimitry Andric   assert(!Entry.Offset.isSubDir());
18578bcb0991SDimitry Andric   return getDataEntryAtOffset(Entry.Offset.value());
18588bcb0991SDimitry Andric }
18598bcb0991SDimitry Andric 
18600b57cec5SDimitry Andric Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
18610b57cec5SDimitry Andric   return getTableAtOffset(0);
18620b57cec5SDimitry Andric }
18638bcb0991SDimitry Andric 
18648bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &>
18658bcb0991SDimitry Andric ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
18668bcb0991SDimitry Andric                                   uint32_t Index) {
18678bcb0991SDimitry Andric   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
18688bcb0991SDimitry Andric     return createStringError(object_error::parse_failed, "index out of range");
18698bcb0991SDimitry Andric   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
18708bcb0991SDimitry Andric   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
18718bcb0991SDimitry Andric   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
18728bcb0991SDimitry Andric                                Index * sizeof(coff_resource_dir_entry));
18738bcb0991SDimitry Andric }
18748bcb0991SDimitry Andric 
18758bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O) {
18768bcb0991SDimitry Andric   for (const SectionRef &S : O->sections()) {
18778bcb0991SDimitry Andric     Expected<StringRef> Name = S.getName();
18788bcb0991SDimitry Andric     if (!Name)
18798bcb0991SDimitry Andric       return Name.takeError();
18808bcb0991SDimitry Andric 
18818bcb0991SDimitry Andric     if (*Name == ".rsrc" || *Name == ".rsrc$01")
18828bcb0991SDimitry Andric       return load(O, S);
18838bcb0991SDimitry Andric   }
18848bcb0991SDimitry Andric   return createStringError(object_error::parse_failed,
18858bcb0991SDimitry Andric                            "no resource section found");
18868bcb0991SDimitry Andric }
18878bcb0991SDimitry Andric 
18888bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
18898bcb0991SDimitry Andric   Obj = O;
18908bcb0991SDimitry Andric   Section = S;
18918bcb0991SDimitry Andric   Expected<StringRef> Contents = Section.getContents();
18928bcb0991SDimitry Andric   if (!Contents)
18938bcb0991SDimitry Andric     return Contents.takeError();
18945f757f3fSDimitry Andric   BBS = BinaryByteStream(*Contents, llvm::endianness::little);
18958bcb0991SDimitry Andric   const coff_section *COFFSect = Obj->getCOFFSection(Section);
18968bcb0991SDimitry Andric   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
18978bcb0991SDimitry Andric   Relocs.reserve(OrigRelocs.size());
18988bcb0991SDimitry Andric   for (const coff_relocation &R : OrigRelocs)
18998bcb0991SDimitry Andric     Relocs.push_back(&R);
1900e8d8bef9SDimitry Andric   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
19018bcb0991SDimitry Andric     return A->VirtualAddress < B->VirtualAddress;
19028bcb0991SDimitry Andric   });
19038bcb0991SDimitry Andric   return Error::success();
19048bcb0991SDimitry Andric }
19058bcb0991SDimitry Andric 
19068bcb0991SDimitry Andric Expected<StringRef>
19078bcb0991SDimitry Andric ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
19088bcb0991SDimitry Andric   if (!Obj)
19098bcb0991SDimitry Andric     return createStringError(object_error::parse_failed, "no object provided");
19108bcb0991SDimitry Andric 
19118bcb0991SDimitry Andric   // Find a potential relocation at the DataRVA field (first member of
19128bcb0991SDimitry Andric   // the coff_resource_data_entry struct).
19138bcb0991SDimitry Andric   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
19148bcb0991SDimitry Andric   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
19158bcb0991SDimitry Andric   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
19168bcb0991SDimitry Andric                               ulittle16_t(0)};
19178bcb0991SDimitry Andric   auto RelocsForOffset =
19188bcb0991SDimitry Andric       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
19198bcb0991SDimitry Andric                        [](const coff_relocation *A, const coff_relocation *B) {
19208bcb0991SDimitry Andric                          return A->VirtualAddress < B->VirtualAddress;
19218bcb0991SDimitry Andric                        });
19228bcb0991SDimitry Andric 
19238bcb0991SDimitry Andric   if (RelocsForOffset.first != RelocsForOffset.second) {
19248bcb0991SDimitry Andric     // We found a relocation with the right offset. Check that it does have
19258bcb0991SDimitry Andric     // the expected type.
19268bcb0991SDimitry Andric     const coff_relocation &R = **RelocsForOffset.first;
19278bcb0991SDimitry Andric     uint16_t RVAReloc;
1928*0fca6ea1SDimitry Andric     switch (Obj->getArch()) {
1929*0fca6ea1SDimitry Andric     case Triple::x86:
19308bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
19318bcb0991SDimitry Andric       break;
1932*0fca6ea1SDimitry Andric     case Triple::x86_64:
19338bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
19348bcb0991SDimitry Andric       break;
1935*0fca6ea1SDimitry Andric     case Triple::thumb:
19368bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
19378bcb0991SDimitry Andric       break;
1938*0fca6ea1SDimitry Andric     case Triple::aarch64:
19398bcb0991SDimitry Andric       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
19408bcb0991SDimitry Andric       break;
19418bcb0991SDimitry Andric     default:
19428bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
19438bcb0991SDimitry Andric                                "unsupported architecture");
19448bcb0991SDimitry Andric     }
19458bcb0991SDimitry Andric     if (R.Type != RVAReloc)
19468bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
19478bcb0991SDimitry Andric                                "unexpected relocation type");
19488bcb0991SDimitry Andric     // Get the relocation's symbol
19498bcb0991SDimitry Andric     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
19508bcb0991SDimitry Andric     if (!Sym)
19518bcb0991SDimitry Andric       return Sym.takeError();
19528bcb0991SDimitry Andric     // And the symbol's section
19535ffd83dbSDimitry Andric     Expected<const coff_section *> Section =
19545ffd83dbSDimitry Andric         Obj->getSection(Sym->getSectionNumber());
19555ffd83dbSDimitry Andric     if (!Section)
19565ffd83dbSDimitry Andric       return Section.takeError();
19578bcb0991SDimitry Andric     // Add the initial value of DataRVA to the symbol's offset to find the
19588bcb0991SDimitry Andric     // data it points at.
19598bcb0991SDimitry Andric     uint64_t Offset = Entry.DataRVA + Sym->getValue();
19608bcb0991SDimitry Andric     ArrayRef<uint8_t> Contents;
19615ffd83dbSDimitry Andric     if (Error E = Obj->getSectionContents(*Section, Contents))
1962*0fca6ea1SDimitry Andric       return E;
19638bcb0991SDimitry Andric     if (Offset + Entry.DataSize > Contents.size())
19648bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
19658bcb0991SDimitry Andric                                "data outside of section");
19668bcb0991SDimitry Andric     // Return a reference to the data inside the section.
19678bcb0991SDimitry Andric     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
19688bcb0991SDimitry Andric                      Entry.DataSize);
19698bcb0991SDimitry Andric   } else {
19708bcb0991SDimitry Andric     // Relocatable objects need a relocation for the DataRVA field.
19718bcb0991SDimitry Andric     if (Obj->isRelocatableObject())
19728bcb0991SDimitry Andric       return createStringError(object_error::parse_failed,
19738bcb0991SDimitry Andric                                "no relocation found for DataRVA");
19748bcb0991SDimitry Andric 
19758bcb0991SDimitry Andric     // Locate the section that contains the address that DataRVA points at.
19768bcb0991SDimitry Andric     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
19778bcb0991SDimitry Andric     for (const SectionRef &S : Obj->sections()) {
19788bcb0991SDimitry Andric       if (VA >= S.getAddress() &&
19798bcb0991SDimitry Andric           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
19808bcb0991SDimitry Andric         uint64_t Offset = VA - S.getAddress();
19818bcb0991SDimitry Andric         Expected<StringRef> Contents = S.getContents();
19828bcb0991SDimitry Andric         if (!Contents)
19838bcb0991SDimitry Andric           return Contents.takeError();
19848bcb0991SDimitry Andric         return Contents->slice(Offset, Offset + Entry.DataSize);
19858bcb0991SDimitry Andric       }
19868bcb0991SDimitry Andric     }
19878bcb0991SDimitry Andric     return createStringError(object_error::parse_failed,
19888bcb0991SDimitry Andric                              "address not found in image");
19898bcb0991SDimitry Andric   }
19908bcb0991SDimitry Andric }
1991