1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
28e90adafSMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68e90adafSMichael J. Spencer //
78e90adafSMichael J. Spencer //===----------------------------------------------------------------------===//
88e90adafSMichael J. Spencer //
98e90adafSMichael J. Spencer // This file declares the COFFObjectFile class.
108e90adafSMichael J. Spencer //
118e90adafSMichael J. Spencer //===----------------------------------------------------------------------===//
128e90adafSMichael J. Spencer 
139da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h"
14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h"
158e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h"
166a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h"
17264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h"
18d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
19d341c932SEugene Zelenko #include "llvm/Object/COFF.h"
20d341c932SEugene Zelenko #include "llvm/Object/Error.h"
21d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h"
22efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
23d341c932SEugene Zelenko #include "llvm/Support/Endian.h"
24d341c932SEugene Zelenko #include "llvm/Support/Error.h"
25d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
26d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h"
27d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
28d341c932SEugene Zelenko #include <algorithm>
29d341c932SEugene Zelenko #include <cassert>
30d341c932SEugene Zelenko #include <cstddef>
31d341c932SEugene Zelenko #include <cstdint>
32d341c932SEugene Zelenko #include <cstring>
339d2c15efSNico Rieck #include <limits>
34d341c932SEugene Zelenko #include <memory>
35d341c932SEugene Zelenko #include <system_error>
368e90adafSMichael J. Spencer 
378e90adafSMichael J. Spencer using namespace llvm;
388e90adafSMichael J. Spencer using namespace object;
398e90adafSMichael J. Spencer 
408e90adafSMichael J. Spencer using support::ulittle16_t;
418e90adafSMichael J. Spencer using support::ulittle32_t;
42861021f9SRui Ueyama using support::ulittle64_t;
438e90adafSMichael J. Spencer using support::little16_t;
448e90adafSMichael J. Spencer 
451d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4648af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
47c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
488ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
491d6167fdSMichael J. Spencer     return false;
501d6167fdSMichael J. Spencer   }
511d6167fdSMichael J. Spencer   return true;
528e90adafSMichael J. Spencer }
538e90adafSMichael J. Spencer 
54ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
55ed64342bSRui Ueyama // Returns unexpected_eof if error.
56ed64342bSRui Ueyama template <typename T>
5748af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
5858323a97SDavid Majnemer                                  const void *Ptr,
59236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
60ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
61cbc7ee45SBenjamin Kramer   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62e830c60dSDavid Majnemer     return EC;
63ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
647d099195SRui Ueyama   return std::error_code();
651d6167fdSMichael J. Spencer }
661d6167fdSMichael J. Spencer 
679d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
689d2c15efSNico Rieck // prefixed slashes.
699d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
709d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
719d2c15efSNico Rieck   if (Str.size() > 6)
729d2c15efSNico Rieck     return true;
739d2c15efSNico Rieck 
749d2c15efSNico Rieck   uint64_t Value = 0;
759d2c15efSNico Rieck   while (!Str.empty()) {
769d2c15efSNico Rieck     unsigned CharVal;
779d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
789d2c15efSNico Rieck       CharVal = Str[0] - 'A';
799d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
809d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
819d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
829d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
839d2c15efSNico Rieck     else if (Str[0] == '+') // 62
845500b07cSRui Ueyama       CharVal = 62;
859d2c15efSNico Rieck     else if (Str[0] == '/') // 63
865500b07cSRui Ueyama       CharVal = 63;
879d2c15efSNico Rieck     else
889d2c15efSNico Rieck       return true;
899d2c15efSNico Rieck 
909d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
919d2c15efSNico Rieck     Str = Str.substr(1);
929d2c15efSNico Rieck   }
939d2c15efSNico Rieck 
949d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
959d2c15efSNico Rieck     return true;
969d2c15efSNico Rieck 
979d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
989d2c15efSNico Rieck   return false;
999d2c15efSNico Rieck }
1009d2c15efSNico Rieck 
10144f51e51SDavid Majnemer template <typename coff_symbol_type>
10244f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10344f51e51SDavid Majnemer   const coff_symbol_type *Addr =
10444f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1051d6167fdSMichael J. Spencer 
106236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1071d6167fdSMichael J. Spencer #ifndef NDEBUG
1081d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1098ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1101d6167fdSMichael J. Spencer 
11144f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11244f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1131d6167fdSMichael J. Spencer #endif
1141d6167fdSMichael J. Spencer 
1158ff24d25SRui Ueyama   return Addr;
1161d6167fdSMichael J. Spencer }
1171d6167fdSMichael J. Spencer 
1188ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1198ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1201d6167fdSMichael J. Spencer 
1211d6167fdSMichael J. Spencer #ifndef NDEBUG
1221d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
12344f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1241d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1251d6167fdSMichael J. Spencer 
1268ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1278ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1281d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1291d6167fdSMichael J. Spencer #endif
1301d6167fdSMichael J. Spencer 
1318ff24d25SRui Ueyama   return Addr;
1321d6167fdSMichael J. Spencer }
1331d6167fdSMichael J. Spencer 
1345e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
135236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13644f51e51SDavid Majnemer   if (SymbolTable16) {
13744f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1388ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
139236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14044f51e51SDavid Majnemer   } else if (SymbolTable32) {
14144f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14244f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
143236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14444f51e51SDavid Majnemer   } else {
14544f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14644f51e51SDavid Majnemer   }
1471d6167fdSMichael J. Spencer }
1481d6167fdSMichael J. Spencer 
14981e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1515d0c2ffaSRafael Espindola   StringRef Result;
152efef15a0SEric Beckmann   if (std::error_code EC = getSymbolName(Symb, Result))
15381e8b7d9SKevin Enderby     return errorCodeToError(EC);
1545d0c2ffaSRafael Espindola   return Result;
1558e90adafSMichael J. Spencer }
1568e90adafSMichael J. Spencer 
157be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
158be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
159991af666SRafael Espindola }
160991af666SRafael Espindola 
1616b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1626b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1636b2bba14SDavide Italiano   // up to 32 bytes.
1646b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16503a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1666b2bba14SDavide Italiano }
1676b2bba14SDavide Italiano 
168931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
169ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
17044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
171c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
172991af666SRafael Espindola 
173991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
174991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
175ed067c45SRafael Espindola     return Result;
17654c9f3daSRafael Espindola 
1772617dcceSCraig Topper   const coff_section *Section = nullptr;
178c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
179931cb65dSKevin Enderby     return errorCodeToError(EC);
180991af666SRafael Espindola   Result += Section->VirtualAddress;
18147ea9eceSReid Kleckner 
18247ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18347ea9eceSReid Kleckner   // return virtual addresses.
18421427adaSReid Kleckner   Result += getImageBase();
18547ea9eceSReid Kleckner 
186ed067c45SRafael Espindola   return Result;
187c7d7c6fbSDavid Majnemer }
188c7d7c6fbSDavid Majnemer 
1897bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
19044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
191c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
19244f51e51SDavid Majnemer 
193e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
194e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1952fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1962fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1972fa80cc5SRafael Espindola   if (Symb.isCommon())
1982fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1992fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2002fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2012fa80cc5SRafael Espindola 
2021a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2032fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2042fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2052fa80cc5SRafael Espindola 
2062fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2072fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2082fa80cc5SRafael Espindola 
2092fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
21075d1cf33SBenjamin Kramer }
21175d1cf33SBenjamin Kramer 
21220122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21344f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21420122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21575d1cf33SBenjamin Kramer 
216c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2179dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2181df4b84dSDavid Meyer 
219a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2201df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
221a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
222a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2231079ef8dSMartell Malone   }
2241df4b84dSDavid Meyer 
22544f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2261df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2271df4b84dSDavid Meyer 
228c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
229c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
230c7d7c6fbSDavid Majnemer 
231c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
232c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
233c7d7c6fbSDavid Majnemer 
234c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
235c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
236c7d7c6fbSDavid Majnemer 
237a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
238c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
239c7d7c6fbSDavid Majnemer 
24020122a43SRafael Espindola   return Result;
24101759754SMichael J. Spencer }
24201759754SMichael J. Spencer 
243d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
244c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2455eb02e45SRafael Espindola   return Symb.getValue();
2468e90adafSMichael J. Spencer }
2478e90adafSMichael J. Spencer 
2487bd8d994SKevin Enderby Expected<section_iterator>
2498bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
25044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2518bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2528bab889bSRafael Espindola     return section_end();
2532617dcceSCraig Topper   const coff_section *Sec = nullptr;
25444f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2557bd8d994SKevin Enderby     return errorCodeToError(EC);
2568bab889bSRafael Espindola   DataRefImpl Ret;
2578bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2588bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25932173153SMichael J. Spencer }
26032173153SMichael J. Spencer 
2616bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2626bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2636bf32210SRafael Espindola   return Symb.getSectionNumber();
2646bf32210SRafael Espindola }
2656bf32210SRafael Espindola 
2665e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2678ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2688ff24d25SRui Ueyama   Sec += 1;
2698ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2708e90adafSMichael J. Spencer }
2718e90adafSMichael J. Spencer 
272db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2731d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2748ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2758ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2768e90adafSMichael J. Spencer }
2778e90adafSMichael J. Spencer 
27880291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2798ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2807c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2817c6a071bSDavid Majnemer 
2827c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2837c6a071bSDavid Majnemer   // return virtual addresses.
28421427adaSReid Kleckner   Result += getImageBase();
2857c6a071bSDavid Majnemer   return Result;
2868e90adafSMichael J. Spencer }
2878e90adafSMichael J. Spencer 
288a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
289a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
290a25d329bSGeorge Rimar }
291a25d329bSGeorge Rimar 
29280291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
293a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2948e90adafSMichael J. Spencer }
2958e90adafSMichael J. Spencer 
296db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
2971d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
2988ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2999da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
300db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
3019da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
3029da9e693SMichael J. Spencer   return EC;
3038e90adafSMichael J. Spencer }
3048e90adafSMichael J. Spencer 
30580291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3068ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
307511391feSDavid Majnemer   return Sec->getAlignment();
3087989460aSMichael J. Spencer }
3097989460aSMichael J. Spencer 
310401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
311401e4e57SGeorge Rimar   return false;
312401e4e57SGeorge Rimar }
313401e4e57SGeorge Rimar 
31480291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3158ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31680291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3178e90adafSMichael J. Spencer }
3188e90adafSMichael J. Spencer 
31980291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3208ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32180291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
322800619f2SMichael J. Spencer }
323800619f2SMichael J. Spencer 
32480291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3258ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3261a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3271a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3281a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3291a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
330800619f2SMichael J. Spencer }
331800619f2SMichael J. Spencer 
3326bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3336bf32210SRafael Espindola   uintptr_t Offset =
3346bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3356bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3366bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3376bf32210SRafael Espindola }
3386bf32210SRafael Espindola 
33980291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3408ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3411a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3421a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3431a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3442138ef6dSPreston Gurd }
3452138ef6dSPreston Gurd 
346e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
347e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
348e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
349e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
350e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
351e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
352e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
353e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
354e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
355e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
356e830c60dSDavid Majnemer       return 0;
35798fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
35898fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
359e830c60dSDavid Majnemer   }
360e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
361e830c60dSDavid Majnemer }
362e830c60dSDavid Majnemer 
36394751be7SDavid Majnemer static const coff_relocation *
36494751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36594751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36694751be7SDavid Majnemer   if (!NumRelocs)
36794751be7SDavid Majnemer     return nullptr;
368827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
36994751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
370827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
371827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
372827c8a2bSRui Ueyama     // relocations.
373827c8a2bSRui Ueyama     begin++;
374827c8a2bSRui Ueyama   }
375cbc7ee45SBenjamin Kramer   if (Binary::checkOffset(M, uintptr_t(begin),
376cbc7ee45SBenjamin Kramer                           sizeof(coff_relocation) * NumRelocs))
37794751be7SDavid Majnemer     return nullptr;
37894751be7SDavid Majnemer   return begin;
379827c8a2bSRui Ueyama }
38094751be7SDavid Majnemer 
38194751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38294751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38394751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38476d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38576d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
38694751be7SDavid Majnemer   DataRefImpl Ret;
38794751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3888ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
389e5fd0047SMichael J. Spencer }
390e5fd0047SMichael J. Spencer 
3918ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3928ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39394751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39494751be7SDavid Majnemer   if (I)
39594751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3968ff24d25SRui Ueyama   DataRefImpl Ret;
39794751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
3988ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
399e5fd0047SMichael J. Spencer }
400e5fd0047SMichael J. Spencer 
401c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
402db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40344f51e51SDavid Majnemer   if (COFFHeader)
404236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
405236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
406236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40744f51e51SDavid Majnemer       return EC;
40844f51e51SDavid Majnemer 
40944f51e51SDavid Majnemer   if (COFFBigObjHeader)
410236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
411236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
412236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4138ff24d25SRui Ueyama       return EC;
414c2bed429SRui Ueyama 
415c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
416c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
417c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
418f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
41944f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
420f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
421c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42248af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4238ff24d25SRui Ueyama     return EC;
424c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
425db4ed0bdSRafael Espindola   if (std::error_code EC =
42648af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4278ff24d25SRui Ueyama     return EC;
428c2bed429SRui Ueyama 
429773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
430773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
431773a5795SNico Rieck   if (StringTableSize < 4)
432773a5795SNico Rieck       StringTableSize = 4;
433773a5795SNico Rieck 
434c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
435773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
436c2bed429SRui Ueyama     return  object_error::parse_failed;
4377d099195SRui Ueyama   return std::error_code();
438c2bed429SRui Ueyama }
439c2bed429SRui Ueyama 
44021427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
441e94fef7bSReid Kleckner   if (PE32Header)
44221427adaSReid Kleckner     return PE32Header->ImageBase;
443e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44421427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44521427adaSReid Kleckner   // This actually comes up in practice.
44621427adaSReid Kleckner   return 0;
447e94fef7bSReid Kleckner }
448e94fef7bSReid Kleckner 
449215a586cSRui Ueyama // Returns the file offset for the given VA.
450db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45121427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
452b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
453b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
454b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
455215a586cSRui Ueyama }
456215a586cSRui Ueyama 
457c2bed429SRui Ueyama // Returns the file offset for the given RVA.
458db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
45927dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46027dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
461c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
462c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
463215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
464215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
465c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4667d099195SRui Ueyama       return std::error_code();
467c2bed429SRui Ueyama     }
468c2bed429SRui Ueyama   }
469c2bed429SRui Ueyama   return object_error::parse_failed;
470c2bed429SRui Ueyama }
471c2bed429SRui Ueyama 
4722da433eaSReid Kleckner std::error_code
4732da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4742da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4752da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4762da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4772da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4782da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4792da433eaSReid Kleckner     // overflow.
4802da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4812da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4822da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4832da433eaSReid Kleckner       uintptr_t Begin =
4842da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4852da433eaSReid Kleckner       Contents =
4862da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4872da433eaSReid Kleckner       return std::error_code();
4882da433eaSReid Kleckner     }
4892da433eaSReid Kleckner   }
4902da433eaSReid Kleckner   return object_error::parse_failed;
4912da433eaSReid Kleckner }
4922da433eaSReid Kleckner 
493c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
494c2bed429SRui Ueyama // table entry.
495db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
496db4ed0bdSRafael Espindola                                             StringRef &Name) const {
497c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
498db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
4998ff24d25SRui Ueyama     return EC;
500c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
501c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
502c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5037d099195SRui Ueyama   return std::error_code();
504c2bed429SRui Ueyama }
505c2bed429SRui Ueyama 
50601528021SSaleem Abdulrasool std::error_code
50701528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
50801528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5092da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5102da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5112da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5122da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5132da433eaSReid Kleckner     return EC;
51401528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5152da433eaSReid Kleckner     return object_error::parse_failed;
51601528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
51701528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5182da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5192da433eaSReid Kleckner                           InfoBytes.size());
5202da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5212da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5222da433eaSReid Kleckner   return std::error_code();
5232da433eaSReid Kleckner }
5242da433eaSReid Kleckner 
52501528021SSaleem Abdulrasool std::error_code
52601528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
527f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
528f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
529f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
530f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
531f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
532f27f3f84SReid Kleckner   PDBInfo = nullptr;
533f27f3f84SReid Kleckner   PDBFileName = StringRef();
534f27f3f84SReid Kleckner   return std::error_code();
535f27f3f84SReid Kleckner }
536f27f3f84SReid Kleckner 
537c2bed429SRui Ueyama // Find the import table.
538db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
539c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
540c2bed429SRui Ueyama   // the import table, do nothing.
541c2bed429SRui Ueyama   const data_directory *DataEntry;
542c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5437d099195SRui Ueyama     return std::error_code();
544c2bed429SRui Ueyama 
545c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
546c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5477d099195SRui Ueyama     return std::error_code();
548c2bed429SRui Ueyama 
549c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
550c2bed429SRui Ueyama 
551c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
552c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
553c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
554db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5558ff24d25SRui Ueyama     return EC;
556ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
557ad7b7e73SDavid Majnemer     return EC;
558c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5591c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5607d099195SRui Ueyama   return std::error_code();
561ad882ba8SRui Ueyama }
562c2bed429SRui Ueyama 
56315d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56415d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56515d99359SRui Ueyama   const data_directory *DataEntry;
56615d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5677d099195SRui Ueyama     return std::error_code();
56815d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5697d099195SRui Ueyama     return std::error_code();
57015d99359SRui Ueyama 
57115d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57215d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57315d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57415d99359SRui Ueyama 
57515d99359SRui Ueyama   uintptr_t IntPtr = 0;
57615d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57715d99359SRui Ueyama     return EC;
57815d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
57915d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5807d099195SRui Ueyama   return std::error_code();
58115d99359SRui Ueyama }
58215d99359SRui Ueyama 
583ad882ba8SRui Ueyama // Find the export table.
584db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
585ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
586ad882ba8SRui Ueyama   // the export table, do nothing.
587ad882ba8SRui Ueyama   const data_directory *DataEntry;
588ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5897d099195SRui Ueyama     return std::error_code();
590ad882ba8SRui Ueyama 
591ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
592ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5937d099195SRui Ueyama     return std::error_code();
594ad882ba8SRui Ueyama 
595ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
596ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
597db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
598ad882ba8SRui Ueyama     return EC;
59924fc2d64SRui Ueyama   ExportDirectory =
60024fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6017d099195SRui Ueyama   return std::error_code();
602c2bed429SRui Ueyama }
603c2bed429SRui Ueyama 
60474e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60574e85130SRui Ueyama   const data_directory *DataEntry;
60674e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6077d099195SRui Ueyama     return std::error_code();
60874e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6097d099195SRui Ueyama     return std::error_code();
61074e85130SRui Ueyama 
61174e85130SRui Ueyama   uintptr_t IntPtr = 0;
61274e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61374e85130SRui Ueyama     return EC;
61474e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61574e85130SRui Ueyama       IntPtr);
61674e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61774e85130SRui Ueyama       IntPtr + DataEntry->Size);
618893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
619893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6207d099195SRui Ueyama   return std::error_code();
62174e85130SRui Ueyama }
62274e85130SRui Ueyama 
6232da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6242da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6252da433eaSReid Kleckner   const data_directory *DataEntry;
6262da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6272da433eaSReid Kleckner     return std::error_code();
6282da433eaSReid Kleckner 
6292da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6302da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6312da433eaSReid Kleckner     return std::error_code();
6322da433eaSReid Kleckner 
6332da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6342da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6352da433eaSReid Kleckner     return object_error::parse_failed;
6362da433eaSReid Kleckner 
6372da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6382da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6392da433eaSReid Kleckner     return EC;
6402da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
641893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
642893c6469SNico Weber       IntPtr + DataEntry->Size);
643893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
644893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6452da433eaSReid Kleckner   return std::error_code();
6462da433eaSReid Kleckner }
6472da433eaSReid Kleckner 
648b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
649b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
650b7d716c0SReid Kleckner   const data_directory *DataEntry;
651b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
652b7d716c0SReid Kleckner     return std::error_code();
653b7d716c0SReid Kleckner 
654b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
655b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
656b7d716c0SReid Kleckner     return std::error_code();
657b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
658b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
659b7d716c0SReid Kleckner     return EC;
660b7d716c0SReid Kleckner 
661b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
662b7d716c0SReid Kleckner   return std::error_code();
663b7d716c0SReid Kleckner }
664b7d716c0SReid Kleckner 
66548af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
66648af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
66744f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
66844f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
66944f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
670ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
67115d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6722da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6732da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6741d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
67548af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
676c3f9b5a5SRafael Espindola     return;
677ee066fc4SEric Christopher 
67882ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
67982ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
68082ebd8e3SRui Ueyama 
68182ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
68282ebd8e3SRui Ueyama   // it is placed right after COFF header.
6838ff24d25SRui Ueyama   bool HasPEHeader = false;
684ee066fc4SEric Christopher 
6851d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
68650267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
687ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
688ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
68950267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
69050267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69150267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
69282ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
69350267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6948ff24d25SRui Ueyama         EC = object_error::parse_failed;
6951d6167fdSMichael J. Spencer         return;
6961d6167fdSMichael J. Spencer       }
69744f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6988ff24d25SRui Ueyama       HasPEHeader = true;
699ee066fc4SEric Christopher     }
70050267222SDavid Majnemer   }
701ee066fc4SEric Christopher 
70248af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
7031d6167fdSMichael J. Spencer     return;
70444f51e51SDavid Majnemer 
70544f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
70644f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
70744f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
70844f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
70944f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
71044f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71144f51e51SDavid Majnemer       return;
71244f51e51SDavid Majnemer 
71344f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
71444f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
71544f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
71644f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
71744f51e51SDavid Majnemer       COFFHeader = nullptr;
71844f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
71944f51e51SDavid Majnemer     } else {
72044f51e51SDavid Majnemer       // It's not a bigobj.
72144f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
72244f51e51SDavid Majnemer     }
72344f51e51SDavid Majnemer   }
72444f51e51SDavid Majnemer   if (COFFHeader) {
72544f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
72644f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7277d099195SRui Ueyama     EC = std::error_code();
72882ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
72982ebd8e3SRui Ueyama 
73044f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
73144f51e51SDavid Majnemer       return;
73244f51e51SDavid Majnemer   }
73344f51e51SDavid Majnemer 
7348ff24d25SRui Ueyama   if (HasPEHeader) {
73510ed9ddcSRui Ueyama     const pe32_header *Header;
73648af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
73782ebd8e3SRui Ueyama       return;
73810ed9ddcSRui Ueyama 
73910ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
74010ed9ddcSRui Ueyama     uint64_t DataDirSize;
74150267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
74210ed9ddcSRui Ueyama       PE32Header = Header;
74310ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
74410ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
74550267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
74610ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
74710ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
74810ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
74910ed9ddcSRui Ueyama     } else {
75010ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
75110ed9ddcSRui Ueyama       EC = object_error::parse_failed;
752ed64342bSRui Ueyama       return;
753ed64342bSRui Ueyama     }
75448af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
75510ed9ddcSRui Ueyama       return;
756f53c8cb4SRui Ueyama   }
757776c6828SRui Ueyama 
7588950a538SRui Ueyama   if (COFFHeader)
7598950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7608950a538SRui Ueyama 
76148af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
762236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7631d6167fdSMichael J. Spencer     return;
7641d6167fdSMichael J. Spencer 
765c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
766236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
767ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
768ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
769ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
770ac8cfab5SDavid Majnemer       StringTable = nullptr;
771ac8cfab5SDavid Majnemer       StringTableSize = 0;
772ac8cfab5SDavid Majnemer     }
773236b0ca7SDavid Majnemer   } else {
774236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
775236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
776236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
777236b0ca7SDavid Majnemer       return;
778236b0ca7SDavid Majnemer     }
779236b0ca7SDavid Majnemer   }
7808e90adafSMichael J. Spencer 
781c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7828ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
783ed64342bSRui Ueyama     return;
78415d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
78515d99359SRui Ueyama     return;
7861d6167fdSMichael J. Spencer 
787ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7888ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
789ad882ba8SRui Ueyama     return;
790ad882ba8SRui Ueyama 
79174e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
79274e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
79374e85130SRui Ueyama     return;
79474e85130SRui Ueyama 
7952da433eaSReid Kleckner   // Initialize the pointer to the export table.
7962da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7972da433eaSReid Kleckner     return;
7982da433eaSReid Kleckner 
799b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
800b7d716c0SReid Kleckner     return;
801b7d716c0SReid Kleckner 
8027d099195SRui Ueyama   EC = std::error_code();
8038e90adafSMichael J. Spencer }
8048e90adafSMichael J. Spencer 
805435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8068ff24d25SRui Ueyama   DataRefImpl Ret;
80744f51e51SDavid Majnemer   Ret.p = getSymbolTable();
808f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8098e90adafSMichael J. Spencer }
8108e90adafSMichael J. Spencer 
811435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8128e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8138ff24d25SRui Ueyama   DataRefImpl Ret;
8148ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
815f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8168e90adafSMichael J. Spencer }
8178e90adafSMichael J. Spencer 
818bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
819ad7b7e73SDavid Majnemer   if (!ImportDirectory)
820ad7b7e73SDavid Majnemer     return import_directory_end();
8211c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
822ad7b7e73SDavid Majnemer     return import_directory_end();
823a045b73aSRui Ueyama   return import_directory_iterator(
824a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
825c2bed429SRui Ueyama }
826c2bed429SRui Ueyama 
827bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
828a045b73aSRui Ueyama   return import_directory_iterator(
829ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
830c2bed429SRui Ueyama }
831c429b80dSDavid Meyer 
83215d99359SRui Ueyama delay_import_directory_iterator
83315d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
83415d99359SRui Ueyama   return delay_import_directory_iterator(
83515d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
83615d99359SRui Ueyama }
83715d99359SRui Ueyama 
83815d99359SRui Ueyama delay_import_directory_iterator
83915d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
84015d99359SRui Ueyama   return delay_import_directory_iterator(
84115d99359SRui Ueyama       DelayImportDirectoryEntryRef(
84215d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
84315d99359SRui Ueyama }
84415d99359SRui Ueyama 
845ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
846ad882ba8SRui Ueyama   return export_directory_iterator(
847ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
848ad882ba8SRui Ueyama }
849ad882ba8SRui Ueyama 
850ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8512617dcceSCraig Topper   if (!ExportDirectory)
8522617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8538ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
854ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8558ff24d25SRui Ueyama   return export_directory_iterator(Ref);
856ad882ba8SRui Ueyama }
857ad882ba8SRui Ueyama 
858b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8598ff24d25SRui Ueyama   DataRefImpl Ret;
8608ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8618ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8628e90adafSMichael J. Spencer }
8638e90adafSMichael J. Spencer 
864b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8658ff24d25SRui Ueyama   DataRefImpl Ret;
86644f51e51SDavid Majnemer   int NumSections =
86744f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8688ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8698ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8708e90adafSMichael J. Spencer }
8718e90adafSMichael J. Spencer 
87274e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
87374e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
87474e85130SRui Ueyama }
87574e85130SRui Ueyama 
87674e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
87774e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
87874e85130SRui Ueyama }
87974e85130SRui Ueyama 
8808e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
88143c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8828e90adafSMichael J. Spencer }
8838e90adafSMichael J. Spencer 
8848e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
88544f51e51SDavid Majnemer   switch(getMachine()) {
8868e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8878e90adafSMichael J. Spencer     return "COFF-i386";
8888e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8898e90adafSMichael J. Spencer     return "COFF-x86-64";
8909b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8919b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8921eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8931eff5c9cSMartell Malone     return "COFF-ARM64";
8948e90adafSMichael J. Spencer   default:
8958e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8968e90adafSMichael J. Spencer   }
8978e90adafSMichael J. Spencer }
8988e90adafSMichael J. Spencer 
899260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
90044f51e51SDavid Majnemer   switch (getMachine()) {
9018e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9028e90adafSMichael J. Spencer     return Triple::x86;
9038e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9048e90adafSMichael J. Spencer     return Triple::x86_64;
9059b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9069b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9071eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9081eff5c9cSMartell Malone     return Triple::aarch64;
9098e90adafSMichael J. Spencer   default:
9108e90adafSMichael J. Spencer     return Triple::UnknownArch;
9118e90adafSMichael J. Spencer   }
9128e90adafSMichael J. Spencer }
9138e90adafSMichael J. Spencer 
914d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
915d2af4d6fSPaul Semel   if (PE32Header)
916d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
917d2af4d6fSPaul Semel   return 0;
918d2af4d6fSPaul Semel }
919d2af4d6fSPaul Semel 
920979fb40bSRui Ueyama iterator_range<import_directory_iterator>
921979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
922979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
923979fb40bSRui Ueyama }
924979fb40bSRui Ueyama 
925979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
926979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
927979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
928979fb40bSRui Ueyama                     delay_import_directory_end());
929979fb40bSRui Ueyama }
930979fb40bSRui Ueyama 
931979fb40bSRui Ueyama iterator_range<export_directory_iterator>
932979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
933979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
934979fb40bSRui Ueyama }
935979fb40bSRui Ueyama 
93674e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
93774e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
93874e85130SRui Ueyama }
93974e85130SRui Ueyama 
940e84a0b5aSMartin Storsjo std::error_code
941e84a0b5aSMartin Storsjo COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
942e84a0b5aSMartin Storsjo   Res = COFFHeader;
943e84a0b5aSMartin Storsjo   return std::error_code();
944e84a0b5aSMartin Storsjo }
945e84a0b5aSMartin Storsjo 
946e84a0b5aSMartin Storsjo std::error_code
947e84a0b5aSMartin Storsjo COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const {
948e84a0b5aSMartin Storsjo   Res = COFFBigObjHeader;
949e84a0b5aSMartin Storsjo   return std::error_code();
950e84a0b5aSMartin Storsjo }
951e84a0b5aSMartin Storsjo 
952db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
95382ebd8e3SRui Ueyama   Res = PE32Header;
9547d099195SRui Ueyama   return std::error_code();
95589a7a5eaSMichael J. Spencer }
95689a7a5eaSMichael J. Spencer 
957db4ed0bdSRafael Espindola std::error_code
95810ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
95910ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9607d099195SRui Ueyama   return std::error_code();
96110ed9ddcSRui Ueyama }
96210ed9ddcSRui Ueyama 
963db4ed0bdSRafael Espindola std::error_code
964db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
965ed64342bSRui Ueyama                                  const data_directory *&Res) const {
966bcadfee2SHiroshi Inoue   // Error if there's no data directory or the index is out of range.
967f69b0585SDavid Majnemer   if (!DataDirectory) {
968f69b0585SDavid Majnemer     Res = nullptr;
96910ed9ddcSRui Ueyama     return object_error::parse_failed;
970f69b0585SDavid Majnemer   }
97110ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
97210ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
97310ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
974f69b0585SDavid Majnemer   if (Index >= NumEnt) {
975f69b0585SDavid Majnemer     Res = nullptr;
976ed64342bSRui Ueyama     return object_error::parse_failed;
977f69b0585SDavid Majnemer   }
9788ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9797d099195SRui Ueyama   return std::error_code();
980ed64342bSRui Ueyama }
981ed64342bSRui Ueyama 
982db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9831d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9842617dcceSCraig Topper   Result = nullptr;
985236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9867d099195SRui Ueyama     return std::error_code();
987236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9881d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9898ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9907d099195SRui Ueyama     return std::error_code();
9918e90adafSMichael J. Spencer   }
992236b0ca7SDavid Majnemer   return object_error::parse_failed;
993236b0ca7SDavid Majnemer }
9948e90adafSMichael J. Spencer 
995b98f5048SPaul Semel std::error_code COFFObjectFile::getSection(StringRef SectionName,
996b98f5048SPaul Semel                                            const coff_section *&Result) const {
997b98f5048SPaul Semel   Result = nullptr;
998b98f5048SPaul Semel   StringRef SecName;
999b98f5048SPaul Semel   for (const SectionRef &Section : sections()) {
1000b98f5048SPaul Semel     if (std::error_code E = Section.getName(SecName))
1001b98f5048SPaul Semel       return E;
1002b98f5048SPaul Semel     if (SecName == SectionName) {
1003b98f5048SPaul Semel       Result = getCOFFSection(Section);
1004b98f5048SPaul Semel       return std::error_code();
1005b98f5048SPaul Semel     }
1006b98f5048SPaul Semel   }
1007b98f5048SPaul Semel   return object_error::parse_failed;
1008b98f5048SPaul Semel }
1009b98f5048SPaul Semel 
1010db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
10111d6167fdSMichael J. Spencer                                           StringRef &Result) const {
10121d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10131d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
10141d6167fdSMichael J. Spencer     return object_error::parse_failed;
10158ff24d25SRui Ueyama   if (Offset >= StringTableSize)
10161d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
10178ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
10187d099195SRui Ueyama   return std::error_code();
10198e90adafSMichael J. Spencer }
1020022ecdf2SBenjamin Kramer 
102144f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
102289a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
1023e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
1024e40d30f3SRui Ueyama }
1025e40d30f3SRui Ueyama 
1026e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1027e40d30f3SRui Ueyama                                               StringRef &Res) const {
102889a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
1029e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
1030e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
10318ff24d25SRui Ueyama       return EC;
10327d099195SRui Ueyama     return std::error_code();
103389a7a5eaSMichael J. Spencer   }
103489a7a5eaSMichael J. Spencer 
1035e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
103689a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
1037e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
103889a7a5eaSMichael J. Spencer   else
103989a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
1040e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
10417d099195SRui Ueyama   return std::error_code();
104289a7a5eaSMichael J. Spencer }
104389a7a5eaSMichael J. Spencer 
104444f51e51SDavid Majnemer ArrayRef<uint8_t>
104544f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10462617dcceSCraig Topper   const uint8_t *Aux = nullptr;
104771757ef3SMarshall Clow 
104844f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
104944f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
105071757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
105144f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
105271757ef3SMarshall Clow #ifndef NDEBUG
10538ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10548ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
105544f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
105644f51e51SDavid Majnemer         Offset >=
105744f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
105871757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
105971757ef3SMarshall Clow 
106044f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
106144f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
106271757ef3SMarshall Clow #endif
1063bfb85e67SMarshall Clow   }
106444f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
106571757ef3SMarshall Clow }
106671757ef3SMarshall Clow 
106774e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
106874e7d260SMartin Storsjo   uintptr_t Offset =
106974e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
107074e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
107174e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
107274e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
107374e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
107474e7d260SMartin Storsjo   return Index;
107574e7d260SMartin Storsjo }
107674e7d260SMartin Storsjo 
1077db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
107853c2d547SMichael J. Spencer                                                StringRef &Res) const {
107953c2d547SMichael J. Spencer   StringRef Name;
108044f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
108153c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
108253c2d547SMichael J. Spencer     Name = Sec->Name;
108353c2d547SMichael J. Spencer   else
108453c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
108544f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
108653c2d547SMichael J. Spencer 
108753c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10882314b3deSDavid Majnemer   if (Name.startswith("/")) {
108953c2d547SMichael J. Spencer     uint32_t Offset;
10902314b3deSDavid Majnemer     if (Name.startswith("//")) {
10919d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10929d2c15efSNico Rieck         return object_error::parse_failed;
10939d2c15efSNico Rieck     } else {
109453c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
109553c2d547SMichael J. Spencer         return object_error::parse_failed;
10969d2c15efSNico Rieck     }
1097db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10988ff24d25SRui Ueyama       return EC;
109953c2d547SMichael J. Spencer   }
110053c2d547SMichael J. Spencer 
110153c2d547SMichael J. Spencer   Res = Name;
11027d099195SRui Ueyama   return std::error_code();
110353c2d547SMichael J. Spencer }
110453c2d547SMichael J. Spencer 
1105a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1106a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1107a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1108a9ee5c06SDavid Majnemer   //
1109a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1110d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1111a9ee5c06SDavid Majnemer   //
1112a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1113a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1114a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1115a9ee5c06SDavid Majnemer   // considered to be zero.
1116d5297ee7SRui Ueyama   if (getDOSHeader())
1117d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1118d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1119a9ee5c06SDavid Majnemer }
1120a9ee5c06SDavid Majnemer 
1121db4ed0bdSRafael Espindola std::error_code
1122db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
11239da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1124e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1125e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1126e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1127ee97c5f0SShoaib Meenai     return std::error_code();
11289da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11299da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11309da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
11319da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1132a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1133e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
11349da9e693SMichael J. Spencer     return object_error::parse_failed;
1135a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
11367d099195SRui Ueyama   return std::error_code();
11379da9e693SMichael J. Spencer }
11389da9e693SMichael J. Spencer 
1139022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1140e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1141022ecdf2SBenjamin Kramer }
11428ff24d25SRui Ueyama 
11435e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1144e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1145e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1146022ecdf2SBenjamin Kramer }
11478ff24d25SRui Ueyama 
114896d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
114958323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
115096d071cdSRafael Espindola   return R->VirtualAddress;
1151cbe72fc9SDanil Malyshev }
11528ff24d25SRui Ueyama 
1153806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1154022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11558ff24d25SRui Ueyama   DataRefImpl Ref;
1156236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1157236b0ca7SDavid Majnemer     return symbol_end();
115844f51e51SDavid Majnemer   if (SymbolTable16)
115944f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
116044f51e51SDavid Majnemer   else if (SymbolTable32)
116144f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
116244f51e51SDavid Majnemer   else
1163c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11648ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1165022ecdf2SBenjamin Kramer }
11668ff24d25SRui Ueyama 
116799c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1168022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
116999c041b7SRafael Espindola   return R->Type;
1170022ecdf2SBenjamin Kramer }
1171e5fd0047SMichael J. Spencer 
117227dc8394SAlexey Samsonov const coff_section *
117327dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
117427dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
117571757ef3SMarshall Clow }
117671757ef3SMarshall Clow 
117744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
117844f51e51SDavid Majnemer   if (SymbolTable16)
117944f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
118044f51e51SDavid Majnemer   if (SymbolTable32)
118144f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
118244f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
118344f51e51SDavid Majnemer }
118444f51e51SDavid Majnemer 
118544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
118644f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
118771757ef3SMarshall Clow }
118871757ef3SMarshall Clow 
1189f12b8282SRafael Espindola const coff_relocation *
119027dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
119127dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1192d3e2a76cSMarshall Clow }
1193d3e2a76cSMarshall Clow 
11942f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11956a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11962f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
11972f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
11986a75acb1SRui Ueyama }
11996a75acb1SRui Ueyama 
120027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
120127dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1202114ebf4aSMartin Storsjo     return #reloc_type;
1203e5fd0047SMichael J. Spencer 
1204114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
120544f51e51SDavid Majnemer   switch (getMachine()) {
1206e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1207114ebf4aSMartin Storsjo     switch (Type) {
1208e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1209e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1210e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1211e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1212e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1213e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1214e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1215e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1216e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1217e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1218e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1219e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1220e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1221e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1222e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1223e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1224e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1225e5fd0047SMichael J. Spencer     default:
1226114ebf4aSMartin Storsjo       return "Unknown";
1227e5fd0047SMichael J. Spencer     }
1228e5fd0047SMichael J. Spencer     break;
12295c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1230114ebf4aSMartin Storsjo     switch (Type) {
12315c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12325c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12335c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12345c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12355c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12365c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12375c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12385c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1239*e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12405c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12415c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12425c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12435c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12445c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12455c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12465c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1247*e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12485c503bf4SSaleem Abdulrasool     default:
1249114ebf4aSMartin Storsjo       return "Unknown";
12505c503bf4SSaleem Abdulrasool     }
12515c503bf4SSaleem Abdulrasool     break;
12520c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1253114ebf4aSMartin Storsjo     switch (Type) {
12540c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12550c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12560c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12570c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12580c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12590c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12600c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12610c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12620c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12630c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12640c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12650c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12660c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12670c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12680c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12690c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12700c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1271*e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12720c72172eSMandeep Singh Grang     default:
1273114ebf4aSMartin Storsjo       return "Unknown";
12740c72172eSMandeep Singh Grang     }
12750c72172eSMandeep Singh Grang     break;
1276e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1277114ebf4aSMartin Storsjo     switch (Type) {
1278e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1279e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1280e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1281e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1282e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1283e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1284e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1285e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1286e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1287e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1288e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1289e5fd0047SMichael J. Spencer     default:
1290114ebf4aSMartin Storsjo       return "Unknown";
1291e5fd0047SMichael J. Spencer     }
1292e5fd0047SMichael J. Spencer     break;
1293e5fd0047SMichael J. Spencer   default:
1294114ebf4aSMartin Storsjo     return "Unknown";
1295e5fd0047SMichael J. Spencer   }
1296e5fd0047SMichael J. Spencer }
1297e5fd0047SMichael J. Spencer 
1298e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1299e5fd0047SMichael J. Spencer 
1300114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1301114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1302114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1303114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1304114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1305114ebf4aSMartin Storsjo }
1306114ebf4aSMartin Storsjo 
1307c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1308c66d761bSRafael Espindola   return !DataDirectory;
1309c66d761bSRafael Espindola }
1310c66d761bSRafael Espindola 
1311e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1312e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1313e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1314e3093808SMartin Storsjo       .Default(Name);
1315e3093808SMartin Storsjo }
1316e3093808SMartin Storsjo 
1317c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1318c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1319a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1320c2bed429SRui Ueyama }
1321c2bed429SRui Ueyama 
13225e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13235e812afaSRafael Espindola   ++Index;
13241c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1325ad7b7e73SDavid Majnemer     Index = -1;
1326ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1327ad7b7e73SDavid Majnemer   }
1328c2bed429SRui Ueyama }
1329c2bed429SRui Ueyama 
1330db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
13311c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1332ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1333c2bed429SRui Ueyama }
1334c2bed429SRui Ueyama 
1335861021f9SRui Ueyama static imported_symbol_iterator
133615d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1337861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
133815d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1339861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
134015d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1341861021f9SRui Ueyama   }
1342861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
134315d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1344861021f9SRui Ueyama }
1345861021f9SRui Ueyama 
134615d99359SRui Ueyama static imported_symbol_iterator
134715d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1348861021f9SRui Ueyama   uintptr_t IntPtr = 0;
134915d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
135015d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1351861021f9SRui Ueyama }
1352861021f9SRui Ueyama 
135315d99359SRui Ueyama static imported_symbol_iterator
135415d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1355861021f9SRui Ueyama   uintptr_t IntPtr = 0;
135615d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1357861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1358861021f9SRui Ueyama   int Index = 0;
135915d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1360861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1361861021f9SRui Ueyama     while (*Entry++)
1362861021f9SRui Ueyama       ++Index;
1363861021f9SRui Ueyama   } else {
1364861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1365861021f9SRui Ueyama     while (*Entry++)
1366861021f9SRui Ueyama       ++Index;
1367861021f9SRui Ueyama   }
136815d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
136915d99359SRui Ueyama }
137015d99359SRui Ueyama 
137115d99359SRui Ueyama imported_symbol_iterator
137215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
137360049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
137415d99359SRui Ueyama                              OwningObject);
137515d99359SRui Ueyama }
137615d99359SRui Ueyama 
137715d99359SRui Ueyama imported_symbol_iterator
137815d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
137960049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
138015d99359SRui Ueyama                            OwningObject);
1381861021f9SRui Ueyama }
1382861021f9SRui Ueyama 
1383979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1384979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1385979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1386979fb40bSRui Ueyama }
1387979fb40bSRui Ueyama 
138860049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
138960049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
139060049526SDavid Majnemer                              OwningObject);
139160049526SDavid Majnemer }
139260049526SDavid Majnemer 
139360049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
139460049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
139560049526SDavid Majnemer                            OwningObject);
139660049526SDavid Majnemer }
139760049526SDavid Majnemer 
139860049526SDavid Majnemer iterator_range<imported_symbol_iterator>
139960049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
140060049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
140160049526SDavid Majnemer }
140260049526SDavid Majnemer 
1403db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1404c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1405db4ed0bdSRafael Espindola   if (std::error_code EC =
14061e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1407a045b73aSRui Ueyama     return EC;
1408a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14097d099195SRui Ueyama   return std::error_code();
1410c2bed429SRui Ueyama }
1411c2bed429SRui Ueyama 
14121e152d5eSRui Ueyama std::error_code
14131e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14141e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14157d099195SRui Ueyama   return std::error_code();
14161e152d5eSRui Ueyama }
14171e152d5eSRui Ueyama 
14181e152d5eSRui Ueyama std::error_code
14191e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
14201e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14217d099195SRui Ueyama   return std::error_code();
14221e152d5eSRui Ueyama }
14231e152d5eSRui Ueyama 
142415d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
142515d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
142615d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
142715d99359SRui Ueyama }
142815d99359SRui Ueyama 
142915d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
143015d99359SRui Ueyama   ++Index;
143115d99359SRui Ueyama }
143215d99359SRui Ueyama 
143315d99359SRui Ueyama imported_symbol_iterator
143415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
143515d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
143615d99359SRui Ueyama                              OwningObject);
143715d99359SRui Ueyama }
143815d99359SRui Ueyama 
143915d99359SRui Ueyama imported_symbol_iterator
144015d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
144115d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
144215d99359SRui Ueyama                            OwningObject);
144315d99359SRui Ueyama }
144415d99359SRui Ueyama 
1445979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1446979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1447979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1448979fb40bSRui Ueyama }
1449979fb40bSRui Ueyama 
145015d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
145115d99359SRui Ueyama   uintptr_t IntPtr = 0;
145215d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
145315d99359SRui Ueyama     return EC;
145415d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14557d099195SRui Ueyama   return std::error_code();
145615d99359SRui Ueyama }
145715d99359SRui Ueyama 
14581af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14591af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14601af08658SRui Ueyama   Result = Table;
14617d099195SRui Ueyama   return std::error_code();
14621af08658SRui Ueyama }
14631af08658SRui Ueyama 
1464ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1465ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1466ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1467ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1468ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1469ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1470ffa4cebeSRui Ueyama     return EC;
1471ffa4cebeSRui Ueyama   if (OwningObject->is64())
14725dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1473ffa4cebeSRui Ueyama   else
14745dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14757d099195SRui Ueyama   return std::error_code();
1476ffa4cebeSRui Ueyama }
1477ffa4cebeSRui Ueyama 
1478ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1479ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1480ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1481ad882ba8SRui Ueyama }
1482ad882ba8SRui Ueyama 
14835e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14845e812afaSRafael Espindola   ++Index;
1485ad882ba8SRui Ueyama }
1486ad882ba8SRui Ueyama 
1487da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1488da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1489db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1490da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1491db4ed0bdSRafael Espindola   if (std::error_code EC =
1492db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1493da49d0d4SRui Ueyama     return EC;
1494da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14957d099195SRui Ueyama   return std::error_code();
1496da49d0d4SRui Ueyama }
1497da49d0d4SRui Ueyama 
1498e5df6095SRui Ueyama // Returns the starting ordinal number.
1499db4ed0bdSRafael Espindola std::error_code
1500db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1501e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15027d099195SRui Ueyama   return std::error_code();
1503e5df6095SRui Ueyama }
1504e5df6095SRui Ueyama 
1505ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1506db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1507ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15087d099195SRui Ueyama   return std::error_code();
1509ad882ba8SRui Ueyama }
1510ad882ba8SRui Ueyama 
1511ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1512db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1513ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1514db4ed0bdSRafael Espindola   if (std::error_code EC =
1515db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1516ad882ba8SRui Ueyama     return EC;
151724fc2d64SRui Ueyama   const export_address_table_entry *entry =
151824fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1519ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15207d099195SRui Ueyama   return std::error_code();
1521ad882ba8SRui Ueyama }
1522ad882ba8SRui Ueyama 
1523ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1524ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1525db4ed0bdSRafael Espindola std::error_code
1526db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1527ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1528db4ed0bdSRafael Espindola   if (std::error_code EC =
1529db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1530ad882ba8SRui Ueyama     return EC;
1531ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1532ad882ba8SRui Ueyama 
1533ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1534ad882ba8SRui Ueyama   int Offset = 0;
1535ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1536ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1537ad882ba8SRui Ueyama     if (*I != Index)
1538ad882ba8SRui Ueyama       continue;
1539db4ed0bdSRafael Espindola     if (std::error_code EC =
1540db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1541ad882ba8SRui Ueyama       return EC;
1542ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1543db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1544ad882ba8SRui Ueyama       return EC;
1545ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15467d099195SRui Ueyama     return std::error_code();
1547ad882ba8SRui Ueyama   }
1548ad882ba8SRui Ueyama   Result = "";
15497d099195SRui Ueyama   return std::error_code();
1550ad882ba8SRui Ueyama }
1551ad882ba8SRui Ueyama 
15526161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15536161b38dSRui Ueyama   const data_directory *DataEntry;
15546161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15556161b38dSRui Ueyama     return EC;
15566161b38dSRui Ueyama   uint32_t RVA;
15576161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15586161b38dSRui Ueyama     return EC;
15596161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15606161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15616161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15626161b38dSRui Ueyama   return std::error_code();
15636161b38dSRui Ueyama }
15646161b38dSRui Ueyama 
15656161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15666161b38dSRui Ueyama   uint32_t RVA;
15676161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15686161b38dSRui Ueyama     return EC;
15696161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15706161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15716161b38dSRui Ueyama     return EC;
15726161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15736161b38dSRui Ueyama   return std::error_code();
15746161b38dSRui Ueyama }
15756161b38dSRui Ueyama 
1576861021f9SRui Ueyama bool ImportedSymbolRef::
1577861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1578861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1579861021f9SRui Ueyama       && Index == Other.Index;
1580861021f9SRui Ueyama }
1581861021f9SRui Ueyama 
1582861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1583861021f9SRui Ueyama   ++Index;
1584861021f9SRui Ueyama }
1585861021f9SRui Ueyama 
1586861021f9SRui Ueyama std::error_code
1587861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1588861021f9SRui Ueyama   uint32_t RVA;
1589861021f9SRui Ueyama   if (Entry32) {
1590861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1591861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15927d099195SRui Ueyama       return std::error_code();
1593861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1594861021f9SRui Ueyama   } else {
1595861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15967d099195SRui Ueyama       return std::error_code();
1597861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1598861021f9SRui Ueyama   }
1599861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1600861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1601861021f9SRui Ueyama     return EC;
1602861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1603861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16047d099195SRui Ueyama   return std::error_code();
1605861021f9SRui Ueyama }
1606861021f9SRui Ueyama 
1607ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1608ad7b7e73SDavid Majnemer   if (Entry32)
1609ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1610ad7b7e73SDavid Majnemer   else
1611ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1612ad7b7e73SDavid Majnemer   return std::error_code();
1613ad7b7e73SDavid Majnemer }
1614ad7b7e73SDavid Majnemer 
1615ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1616ad7b7e73SDavid Majnemer   if (Entry32)
1617ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1618ad7b7e73SDavid Majnemer   else
1619ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1620ad7b7e73SDavid Majnemer   return std::error_code();
1621ad7b7e73SDavid Majnemer }
1622ad7b7e73SDavid Majnemer 
1623861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1624861021f9SRui Ueyama   uint32_t RVA;
1625861021f9SRui Ueyama   if (Entry32) {
1626861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1627861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16287d099195SRui Ueyama       return std::error_code();
1629861021f9SRui Ueyama     }
1630861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1631861021f9SRui Ueyama   } else {
1632861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1633861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16347d099195SRui Ueyama       return std::error_code();
1635861021f9SRui Ueyama     }
1636861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1637861021f9SRui Ueyama   }
1638861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1639861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1640861021f9SRui Ueyama     return EC;
1641861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16427d099195SRui Ueyama   return std::error_code();
1643861021f9SRui Ueyama }
1644861021f9SRui Ueyama 
164512db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
164648af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1647db4ed0bdSRafael Espindola   std::error_code EC;
164848af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1649692410efSRafael Espindola   if (EC)
165012db383eSRafael Espindola     return errorCodeToError(EC);
1651437b0d58SRafael Espindola   return std::move(Ret);
1652686738e2SRui Ueyama }
165374e85130SRui Ueyama 
165474e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
165574e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
165674e85130SRui Ueyama }
165774e85130SRui Ueyama 
165874e85130SRui Ueyama void BaseRelocRef::moveNext() {
165974e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
166074e85130SRui Ueyama   // size of the header itself.
166174e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1662970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
166374e85130SRui Ueyama   if (Size == Header->BlockSize) {
166474e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
166574e85130SRui Ueyama     // consists of the header followed by entries. The header contains
166674e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
166774e85130SRui Ueyama     // current block, proceed to the next block.
166874e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
166974e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
167074e85130SRui Ueyama     Index = 0;
167174e85130SRui Ueyama   } else {
167274e85130SRui Ueyama     ++Index;
167374e85130SRui Ueyama   }
167474e85130SRui Ueyama }
167574e85130SRui Ueyama 
167674e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
167774e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
167874e85130SRui Ueyama   Type = Entry[Index].getType();
16797d099195SRui Ueyama   return std::error_code();
168074e85130SRui Ueyama }
168174e85130SRui Ueyama 
168274e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
168374e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
168474e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16857d099195SRui Ueyama   return std::error_code();
168674e85130SRui Ueyama }
1687efef15a0SEric Beckmann 
168887867988SRafael Espindola #define RETURN_IF_ERROR(E)                                                     \
168987867988SRafael Espindola   if (E)                                                                       \
169087867988SRafael Espindola     return E;
1691efef15a0SEric Beckmann 
169287867988SRafael Espindola Expected<ArrayRef<UTF16>>
169387867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1694efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1695efef15a0SEric Beckmann   Reader.setOffset(Offset);
1696efef15a0SEric Beckmann   uint16_t Length;
1697efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1698efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1699efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1700cd704cb6SEric Beckmann   return RawDirString;
1701efef15a0SEric Beckmann }
1702efef15a0SEric Beckmann 
1703f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1704efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1705f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1706efef15a0SEric Beckmann }
1707efef15a0SEric Beckmann 
170887867988SRafael Espindola Expected<const coff_resource_dir_table &>
1709efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1710efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1711efef15a0SEric Beckmann 
1712efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1713efef15a0SEric Beckmann   Reader.setOffset(Offset);
1714efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1715efef15a0SEric Beckmann   assert(Table != nullptr);
1716efef15a0SEric Beckmann   return *Table;
1717efef15a0SEric Beckmann }
1718efef15a0SEric Beckmann 
1719f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1720efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1721f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1722efef15a0SEric Beckmann }
1723efef15a0SEric Beckmann 
1724f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1725f3404674SRafael Espindola   return getTableAtOffset(0);
1726efef15a0SEric Beckmann }
1727