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 
2728be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2738ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2748be28cdcSFangrui Song   return getSectionName(Sec);
2758e90adafSMichael J. Spencer }
2768e90adafSMichael J. Spencer 
27780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2788ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2797c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2807c6a071bSDavid Majnemer 
2817c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2827c6a071bSDavid Majnemer   // return virtual addresses.
28321427adaSReid Kleckner   Result += getImageBase();
2847c6a071bSDavid Majnemer   return Result;
2858e90adafSMichael J. Spencer }
2868e90adafSMichael J. Spencer 
287a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
288a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
289a25d329bSGeorge Rimar }
290a25d329bSGeorge Rimar 
29180291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
292a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2938e90adafSMichael J. Spencer }
2948e90adafSMichael J. Spencer 
295*e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
296*e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2978ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2989da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
299*e1cb2c0fSFangrui Song   if (Error E = getSectionContents(Sec, Res))
300*e1cb2c0fSFangrui Song     return std::move(E);
301*e1cb2c0fSFangrui Song   return Res;
3028e90adafSMichael J. Spencer }
3038e90adafSMichael J. Spencer 
30480291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3058ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
306511391feSDavid Majnemer   return Sec->getAlignment();
3077989460aSMichael J. Spencer }
3087989460aSMichael J. Spencer 
309401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
310401e4e57SGeorge Rimar   return false;
311401e4e57SGeorge Rimar }
312401e4e57SGeorge Rimar 
31380291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3148ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31580291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3168e90adafSMichael J. Spencer }
3178e90adafSMichael J. Spencer 
31880291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3198ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32080291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
321800619f2SMichael J. Spencer }
322800619f2SMichael J. Spencer 
32380291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3248ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3251a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3261a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3271a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3281a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
329800619f2SMichael J. Spencer }
330800619f2SMichael J. Spencer 
3316bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3326bf32210SRafael Espindola   uintptr_t Offset =
3336bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3346bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3356bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3366bf32210SRafael Espindola }
3376bf32210SRafael Espindola 
33880291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3398ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3401a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3411a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3421a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3432138ef6dSPreston Gurd }
3442138ef6dSPreston Gurd 
345e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
346e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
347e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
348e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
349e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
350e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
351e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
352e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
353e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
354e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
355e830c60dSDavid Majnemer       return 0;
35698fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
35798fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
358e830c60dSDavid Majnemer   }
359e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
360e830c60dSDavid Majnemer }
361e830c60dSDavid Majnemer 
36294751be7SDavid Majnemer static const coff_relocation *
36394751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36494751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36594751be7SDavid Majnemer   if (!NumRelocs)
36694751be7SDavid Majnemer     return nullptr;
367827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
36894751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
369827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
370827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
371827c8a2bSRui Ueyama     // relocations.
372827c8a2bSRui Ueyama     begin++;
373827c8a2bSRui Ueyama   }
374cbc7ee45SBenjamin Kramer   if (Binary::checkOffset(M, uintptr_t(begin),
375cbc7ee45SBenjamin Kramer                           sizeof(coff_relocation) * NumRelocs))
37694751be7SDavid Majnemer     return nullptr;
37794751be7SDavid Majnemer   return begin;
378827c8a2bSRui Ueyama }
37994751be7SDavid Majnemer 
38094751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38194751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38294751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38376d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38476d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
38594751be7SDavid Majnemer   DataRefImpl Ret;
38694751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3878ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
388e5fd0047SMichael J. Spencer }
389e5fd0047SMichael J. Spencer 
3908ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3918ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39294751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39394751be7SDavid Majnemer   if (I)
39494751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3958ff24d25SRui Ueyama   DataRefImpl Ret;
39694751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
3978ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
398e5fd0047SMichael J. Spencer }
399e5fd0047SMichael J. Spencer 
400c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
401db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40244f51e51SDavid Majnemer   if (COFFHeader)
403236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
404236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
405236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40644f51e51SDavid Majnemer       return EC;
40744f51e51SDavid Majnemer 
40844f51e51SDavid Majnemer   if (COFFBigObjHeader)
409236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
410236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
411236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4128ff24d25SRui Ueyama       return EC;
413c2bed429SRui Ueyama 
414c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
415c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
416c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
417f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
41844f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
419f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
420c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42148af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4228ff24d25SRui Ueyama     return EC;
423c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
424db4ed0bdSRafael Espindola   if (std::error_code EC =
42548af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4268ff24d25SRui Ueyama     return EC;
427c2bed429SRui Ueyama 
428773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
429773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
430773a5795SNico Rieck   if (StringTableSize < 4)
431773a5795SNico Rieck       StringTableSize = 4;
432773a5795SNico Rieck 
433c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
434773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
435c2bed429SRui Ueyama     return  object_error::parse_failed;
4367d099195SRui Ueyama   return std::error_code();
437c2bed429SRui Ueyama }
438c2bed429SRui Ueyama 
43921427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
440e94fef7bSReid Kleckner   if (PE32Header)
44121427adaSReid Kleckner     return PE32Header->ImageBase;
442e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44321427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44421427adaSReid Kleckner   // This actually comes up in practice.
44521427adaSReid Kleckner   return 0;
446e94fef7bSReid Kleckner }
447e94fef7bSReid Kleckner 
448215a586cSRui Ueyama // Returns the file offset for the given VA.
449db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45021427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
451b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
452b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
453b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
454215a586cSRui Ueyama }
455215a586cSRui Ueyama 
456c2bed429SRui Ueyama // Returns the file offset for the given RVA.
457db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
45827dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
45927dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
460c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
461c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
462215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
463215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
464c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4657d099195SRui Ueyama       return std::error_code();
466c2bed429SRui Ueyama     }
467c2bed429SRui Ueyama   }
468c2bed429SRui Ueyama   return object_error::parse_failed;
469c2bed429SRui Ueyama }
470c2bed429SRui Ueyama 
4712da433eaSReid Kleckner std::error_code
4722da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4732da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4742da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4752da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4762da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4772da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4782da433eaSReid Kleckner     // overflow.
4792da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4802da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4812da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4822da433eaSReid Kleckner       uintptr_t Begin =
4832da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4842da433eaSReid Kleckner       Contents =
4852da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4862da433eaSReid Kleckner       return std::error_code();
4872da433eaSReid Kleckner     }
4882da433eaSReid Kleckner   }
4892da433eaSReid Kleckner   return object_error::parse_failed;
4902da433eaSReid Kleckner }
4912da433eaSReid Kleckner 
492c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
493c2bed429SRui Ueyama // table entry.
494db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
495db4ed0bdSRafael Espindola                                             StringRef &Name) const {
496c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
497db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
4988ff24d25SRui Ueyama     return EC;
499c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
500c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
501c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5027d099195SRui Ueyama   return std::error_code();
503c2bed429SRui Ueyama }
504c2bed429SRui Ueyama 
50501528021SSaleem Abdulrasool std::error_code
50601528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
50701528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5082da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5092da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5102da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5112da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5122da433eaSReid Kleckner     return EC;
51301528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5142da433eaSReid Kleckner     return object_error::parse_failed;
51501528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
51601528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5172da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5182da433eaSReid Kleckner                           InfoBytes.size());
5192da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5202da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5212da433eaSReid Kleckner   return std::error_code();
5222da433eaSReid Kleckner }
5232da433eaSReid Kleckner 
52401528021SSaleem Abdulrasool std::error_code
52501528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
526f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
527f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
528f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
529f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
530f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
531f27f3f84SReid Kleckner   PDBInfo = nullptr;
532f27f3f84SReid Kleckner   PDBFileName = StringRef();
533f27f3f84SReid Kleckner   return std::error_code();
534f27f3f84SReid Kleckner }
535f27f3f84SReid Kleckner 
536c2bed429SRui Ueyama // Find the import table.
537db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
538c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
539c2bed429SRui Ueyama   // the import table, do nothing.
540c2bed429SRui Ueyama   const data_directory *DataEntry;
541c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5427d099195SRui Ueyama     return std::error_code();
543c2bed429SRui Ueyama 
544c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
545c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5467d099195SRui Ueyama     return std::error_code();
547c2bed429SRui Ueyama 
548c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
549c2bed429SRui Ueyama 
550c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
551c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
552c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
553db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5548ff24d25SRui Ueyama     return EC;
555ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
556ad7b7e73SDavid Majnemer     return EC;
557c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5581c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5597d099195SRui Ueyama   return std::error_code();
560ad882ba8SRui Ueyama }
561c2bed429SRui Ueyama 
56215d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56315d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56415d99359SRui Ueyama   const data_directory *DataEntry;
56515d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5667d099195SRui Ueyama     return std::error_code();
56715d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5687d099195SRui Ueyama     return std::error_code();
56915d99359SRui Ueyama 
57015d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57115d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57215d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57315d99359SRui Ueyama 
57415d99359SRui Ueyama   uintptr_t IntPtr = 0;
57515d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57615d99359SRui Ueyama     return EC;
57715d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
57815d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5797d099195SRui Ueyama   return std::error_code();
58015d99359SRui Ueyama }
58115d99359SRui Ueyama 
582ad882ba8SRui Ueyama // Find the export table.
583db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
584ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
585ad882ba8SRui Ueyama   // the export table, do nothing.
586ad882ba8SRui Ueyama   const data_directory *DataEntry;
587ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5887d099195SRui Ueyama     return std::error_code();
589ad882ba8SRui Ueyama 
590ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
591ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5927d099195SRui Ueyama     return std::error_code();
593ad882ba8SRui Ueyama 
594ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
595ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
596db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
597ad882ba8SRui Ueyama     return EC;
59824fc2d64SRui Ueyama   ExportDirectory =
59924fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6007d099195SRui Ueyama   return std::error_code();
601c2bed429SRui Ueyama }
602c2bed429SRui Ueyama 
60374e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60474e85130SRui Ueyama   const data_directory *DataEntry;
60574e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6067d099195SRui Ueyama     return std::error_code();
60774e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6087d099195SRui Ueyama     return std::error_code();
60974e85130SRui Ueyama 
61074e85130SRui Ueyama   uintptr_t IntPtr = 0;
61174e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61274e85130SRui Ueyama     return EC;
61374e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61474e85130SRui Ueyama       IntPtr);
61574e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61674e85130SRui Ueyama       IntPtr + DataEntry->Size);
617893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
618893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6197d099195SRui Ueyama   return std::error_code();
62074e85130SRui Ueyama }
62174e85130SRui Ueyama 
6222da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6232da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6242da433eaSReid Kleckner   const data_directory *DataEntry;
6252da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6262da433eaSReid Kleckner     return std::error_code();
6272da433eaSReid Kleckner 
6282da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6292da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6302da433eaSReid Kleckner     return std::error_code();
6312da433eaSReid Kleckner 
6322da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6332da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6342da433eaSReid Kleckner     return object_error::parse_failed;
6352da433eaSReid Kleckner 
6362da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6372da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6382da433eaSReid Kleckner     return EC;
6392da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
640893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
641893c6469SNico Weber       IntPtr + DataEntry->Size);
642893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
643893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6442da433eaSReid Kleckner   return std::error_code();
6452da433eaSReid Kleckner }
6462da433eaSReid Kleckner 
647b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
648b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
649b7d716c0SReid Kleckner   const data_directory *DataEntry;
650b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
651b7d716c0SReid Kleckner     return std::error_code();
652b7d716c0SReid Kleckner 
653b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
654b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
655b7d716c0SReid Kleckner     return std::error_code();
656b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
657b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
658b7d716c0SReid Kleckner     return EC;
659b7d716c0SReid Kleckner 
660b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
661b7d716c0SReid Kleckner   return std::error_code();
662b7d716c0SReid Kleckner }
663b7d716c0SReid Kleckner 
66448af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
66548af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
66644f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
66744f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
66844f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
669ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
67015d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6712da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6722da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6731d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
67448af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
675c3f9b5a5SRafael Espindola     return;
676ee066fc4SEric Christopher 
67782ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
67882ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
67982ebd8e3SRui Ueyama 
68082ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
68182ebd8e3SRui Ueyama   // it is placed right after COFF header.
6828ff24d25SRui Ueyama   bool HasPEHeader = false;
683ee066fc4SEric Christopher 
6841d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
68550267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
686ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
687ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
68850267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
68950267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69050267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
69182ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
69250267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6938ff24d25SRui Ueyama         EC = object_error::parse_failed;
6941d6167fdSMichael J. Spencer         return;
6951d6167fdSMichael J. Spencer       }
69644f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6978ff24d25SRui Ueyama       HasPEHeader = true;
698ee066fc4SEric Christopher     }
69950267222SDavid Majnemer   }
700ee066fc4SEric Christopher 
70148af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
7021d6167fdSMichael J. Spencer     return;
70344f51e51SDavid Majnemer 
70444f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
70544f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
70644f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
70744f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
70844f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
70944f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71044f51e51SDavid Majnemer       return;
71144f51e51SDavid Majnemer 
71244f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
71344f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
71444f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
71544f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
71644f51e51SDavid Majnemer       COFFHeader = nullptr;
71744f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
71844f51e51SDavid Majnemer     } else {
71944f51e51SDavid Majnemer       // It's not a bigobj.
72044f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
72144f51e51SDavid Majnemer     }
72244f51e51SDavid Majnemer   }
72344f51e51SDavid Majnemer   if (COFFHeader) {
72444f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
72544f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7267d099195SRui Ueyama     EC = std::error_code();
72782ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
72882ebd8e3SRui Ueyama 
72944f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
73044f51e51SDavid Majnemer       return;
73144f51e51SDavid Majnemer   }
73244f51e51SDavid Majnemer 
7338ff24d25SRui Ueyama   if (HasPEHeader) {
73410ed9ddcSRui Ueyama     const pe32_header *Header;
73548af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
73682ebd8e3SRui Ueyama       return;
73710ed9ddcSRui Ueyama 
73810ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
73910ed9ddcSRui Ueyama     uint64_t DataDirSize;
74050267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
74110ed9ddcSRui Ueyama       PE32Header = Header;
74210ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
74310ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
74450267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
74510ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
74610ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
74710ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
74810ed9ddcSRui Ueyama     } else {
74910ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
75010ed9ddcSRui Ueyama       EC = object_error::parse_failed;
751ed64342bSRui Ueyama       return;
752ed64342bSRui Ueyama     }
75348af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
75410ed9ddcSRui Ueyama       return;
755f53c8cb4SRui Ueyama   }
756776c6828SRui Ueyama 
7578950a538SRui Ueyama   if (COFFHeader)
7588950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7598950a538SRui Ueyama 
76048af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
761236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7621d6167fdSMichael J. Spencer     return;
7631d6167fdSMichael J. Spencer 
764c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
765236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
766ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
767ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
768ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
769ac8cfab5SDavid Majnemer       StringTable = nullptr;
770ac8cfab5SDavid Majnemer       StringTableSize = 0;
771ac8cfab5SDavid Majnemer     }
772236b0ca7SDavid Majnemer   } else {
773236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
774236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
775236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
776236b0ca7SDavid Majnemer       return;
777236b0ca7SDavid Majnemer     }
778236b0ca7SDavid Majnemer   }
7798e90adafSMichael J. Spencer 
780c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7818ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
782ed64342bSRui Ueyama     return;
78315d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
78415d99359SRui Ueyama     return;
7851d6167fdSMichael J. Spencer 
786ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7878ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
788ad882ba8SRui Ueyama     return;
789ad882ba8SRui Ueyama 
79074e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
79174e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
79274e85130SRui Ueyama     return;
79374e85130SRui Ueyama 
7942da433eaSReid Kleckner   // Initialize the pointer to the export table.
7952da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7962da433eaSReid Kleckner     return;
7972da433eaSReid Kleckner 
798b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
799b7d716c0SReid Kleckner     return;
800b7d716c0SReid Kleckner 
8017d099195SRui Ueyama   EC = std::error_code();
8028e90adafSMichael J. Spencer }
8038e90adafSMichael J. Spencer 
804435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8058ff24d25SRui Ueyama   DataRefImpl Ret;
80644f51e51SDavid Majnemer   Ret.p = getSymbolTable();
807f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8088e90adafSMichael J. Spencer }
8098e90adafSMichael J. Spencer 
810435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8118e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8128ff24d25SRui Ueyama   DataRefImpl Ret;
8138ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
814f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8158e90adafSMichael J. Spencer }
8168e90adafSMichael J. Spencer 
817bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
818ad7b7e73SDavid Majnemer   if (!ImportDirectory)
819ad7b7e73SDavid Majnemer     return import_directory_end();
8201c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
821ad7b7e73SDavid Majnemer     return import_directory_end();
822a045b73aSRui Ueyama   return import_directory_iterator(
823a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
824c2bed429SRui Ueyama }
825c2bed429SRui Ueyama 
826bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
827a045b73aSRui Ueyama   return import_directory_iterator(
828ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
829c2bed429SRui Ueyama }
830c429b80dSDavid Meyer 
83115d99359SRui Ueyama delay_import_directory_iterator
83215d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
83315d99359SRui Ueyama   return delay_import_directory_iterator(
83415d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
83515d99359SRui Ueyama }
83615d99359SRui Ueyama 
83715d99359SRui Ueyama delay_import_directory_iterator
83815d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
83915d99359SRui Ueyama   return delay_import_directory_iterator(
84015d99359SRui Ueyama       DelayImportDirectoryEntryRef(
84115d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
84215d99359SRui Ueyama }
84315d99359SRui Ueyama 
844ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
845ad882ba8SRui Ueyama   return export_directory_iterator(
846ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
847ad882ba8SRui Ueyama }
848ad882ba8SRui Ueyama 
849ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8502617dcceSCraig Topper   if (!ExportDirectory)
8512617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8528ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
853ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8548ff24d25SRui Ueyama   return export_directory_iterator(Ref);
855ad882ba8SRui Ueyama }
856ad882ba8SRui Ueyama 
857b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8588ff24d25SRui Ueyama   DataRefImpl Ret;
8598ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8608ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8618e90adafSMichael J. Spencer }
8628e90adafSMichael J. Spencer 
863b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8648ff24d25SRui Ueyama   DataRefImpl Ret;
86544f51e51SDavid Majnemer   int NumSections =
86644f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8678ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8688ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8698e90adafSMichael J. Spencer }
8708e90adafSMichael J. Spencer 
87174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
87274e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
87374e85130SRui Ueyama }
87474e85130SRui Ueyama 
87574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
87674e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
87774e85130SRui Ueyama }
87874e85130SRui Ueyama 
8798e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
88043c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8818e90adafSMichael J. Spencer }
8828e90adafSMichael J. Spencer 
8838e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
88444f51e51SDavid Majnemer   switch(getMachine()) {
8858e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8868e90adafSMichael J. Spencer     return "COFF-i386";
8878e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8888e90adafSMichael J. Spencer     return "COFF-x86-64";
8899b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8909b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8911eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8921eff5c9cSMartell Malone     return "COFF-ARM64";
8938e90adafSMichael J. Spencer   default:
8948e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8958e90adafSMichael J. Spencer   }
8968e90adafSMichael J. Spencer }
8978e90adafSMichael J. Spencer 
898260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
89944f51e51SDavid Majnemer   switch (getMachine()) {
9008e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9018e90adafSMichael J. Spencer     return Triple::x86;
9028e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9038e90adafSMichael J. Spencer     return Triple::x86_64;
9049b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9059b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9061eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9071eff5c9cSMartell Malone     return Triple::aarch64;
9088e90adafSMichael J. Spencer   default:
9098e90adafSMichael J. Spencer     return Triple::UnknownArch;
9108e90adafSMichael J. Spencer   }
9118e90adafSMichael J. Spencer }
9128e90adafSMichael J. Spencer 
913d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
914d2af4d6fSPaul Semel   if (PE32Header)
915d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
916d2af4d6fSPaul Semel   return 0;
917d2af4d6fSPaul Semel }
918d2af4d6fSPaul Semel 
919979fb40bSRui Ueyama iterator_range<import_directory_iterator>
920979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
921979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
922979fb40bSRui Ueyama }
923979fb40bSRui Ueyama 
924979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
925979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
926979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
927979fb40bSRui Ueyama                     delay_import_directory_end());
928979fb40bSRui Ueyama }
929979fb40bSRui Ueyama 
930979fb40bSRui Ueyama iterator_range<export_directory_iterator>
931979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
932979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
933979fb40bSRui Ueyama }
934979fb40bSRui Ueyama 
93574e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
93674e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
93774e85130SRui Ueyama }
93874e85130SRui Ueyama 
939e84a0b5aSMartin Storsjo std::error_code
940e84a0b5aSMartin Storsjo COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
941e84a0b5aSMartin Storsjo   Res = COFFHeader;
942e84a0b5aSMartin Storsjo   return std::error_code();
943e84a0b5aSMartin Storsjo }
944e84a0b5aSMartin Storsjo 
945e84a0b5aSMartin Storsjo std::error_code
946e84a0b5aSMartin Storsjo COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const {
947e84a0b5aSMartin Storsjo   Res = COFFBigObjHeader;
948e84a0b5aSMartin Storsjo   return std::error_code();
949e84a0b5aSMartin Storsjo }
950e84a0b5aSMartin Storsjo 
951db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
95282ebd8e3SRui Ueyama   Res = PE32Header;
9537d099195SRui Ueyama   return std::error_code();
95489a7a5eaSMichael J. Spencer }
95589a7a5eaSMichael J. Spencer 
956db4ed0bdSRafael Espindola std::error_code
95710ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
95810ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9597d099195SRui Ueyama   return std::error_code();
96010ed9ddcSRui Ueyama }
96110ed9ddcSRui Ueyama 
962db4ed0bdSRafael Espindola std::error_code
963db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
964ed64342bSRui Ueyama                                  const data_directory *&Res) const {
965bcadfee2SHiroshi Inoue   // Error if there's no data directory or the index is out of range.
966f69b0585SDavid Majnemer   if (!DataDirectory) {
967f69b0585SDavid Majnemer     Res = nullptr;
96810ed9ddcSRui Ueyama     return object_error::parse_failed;
969f69b0585SDavid Majnemer   }
97010ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
97110ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
97210ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
973f69b0585SDavid Majnemer   if (Index >= NumEnt) {
974f69b0585SDavid Majnemer     Res = nullptr;
975ed64342bSRui Ueyama     return object_error::parse_failed;
976f69b0585SDavid Majnemer   }
9778ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9787d099195SRui Ueyama   return std::error_code();
979ed64342bSRui Ueyama }
980ed64342bSRui Ueyama 
981db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9821d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9832617dcceSCraig Topper   Result = nullptr;
984236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9857d099195SRui Ueyama     return std::error_code();
986236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9871d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9888ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9897d099195SRui Ueyama     return std::error_code();
9908e90adafSMichael J. Spencer   }
991236b0ca7SDavid Majnemer   return object_error::parse_failed;
992236b0ca7SDavid Majnemer }
9938e90adafSMichael J. Spencer 
994b98f5048SPaul Semel std::error_code COFFObjectFile::getSection(StringRef SectionName,
995b98f5048SPaul Semel                                            const coff_section *&Result) const {
996b98f5048SPaul Semel   Result = nullptr;
997b98f5048SPaul Semel   StringRef SecName;
998b98f5048SPaul Semel   for (const SectionRef &Section : sections()) {
999b98f5048SPaul Semel     if (std::error_code E = Section.getName(SecName))
1000b98f5048SPaul Semel       return E;
1001b98f5048SPaul Semel     if (SecName == SectionName) {
1002b98f5048SPaul Semel       Result = getCOFFSection(Section);
1003b98f5048SPaul Semel       return std::error_code();
1004b98f5048SPaul Semel     }
1005b98f5048SPaul Semel   }
1006b98f5048SPaul Semel   return object_error::parse_failed;
1007b98f5048SPaul Semel }
1008b98f5048SPaul Semel 
1009db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
10101d6167fdSMichael J. Spencer                                           StringRef &Result) const {
10111d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10121d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
10131d6167fdSMichael J. Spencer     return object_error::parse_failed;
10148ff24d25SRui Ueyama   if (Offset >= StringTableSize)
10151d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
10168ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
10177d099195SRui Ueyama   return std::error_code();
10188e90adafSMichael J. Spencer }
1019022ecdf2SBenjamin Kramer 
102044f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
102189a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
1022e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
1023e40d30f3SRui Ueyama }
1024e40d30f3SRui Ueyama 
1025e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1026e40d30f3SRui Ueyama                                               StringRef &Res) const {
102789a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
1028e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
1029e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
10308ff24d25SRui Ueyama       return EC;
10317d099195SRui Ueyama     return std::error_code();
103289a7a5eaSMichael J. Spencer   }
103389a7a5eaSMichael J. Spencer 
1034e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
103589a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
1036e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
103789a7a5eaSMichael J. Spencer   else
103889a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
1039e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
10407d099195SRui Ueyama   return std::error_code();
104189a7a5eaSMichael J. Spencer }
104289a7a5eaSMichael J. Spencer 
104344f51e51SDavid Majnemer ArrayRef<uint8_t>
104444f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10452617dcceSCraig Topper   const uint8_t *Aux = nullptr;
104671757ef3SMarshall Clow 
104744f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
104844f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
104971757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
105044f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
105171757ef3SMarshall Clow #ifndef NDEBUG
10528ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10538ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
105444f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
105544f51e51SDavid Majnemer         Offset >=
105644f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
105771757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
105871757ef3SMarshall Clow 
105944f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
106044f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
106171757ef3SMarshall Clow #endif
1062bfb85e67SMarshall Clow   }
106344f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
106471757ef3SMarshall Clow }
106571757ef3SMarshall Clow 
106674e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
106774e7d260SMartin Storsjo   uintptr_t Offset =
106874e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
106974e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
107074e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
107174e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
107274e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
107374e7d260SMartin Storsjo   return Index;
107474e7d260SMartin Storsjo }
107574e7d260SMartin Storsjo 
10768be28cdcSFangrui Song Expected<StringRef>
10778be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
107853c2d547SMichael J. Spencer   StringRef Name;
107944f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
108053c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
108153c2d547SMichael J. Spencer     Name = Sec->Name;
108253c2d547SMichael J. Spencer   else
108353c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
108444f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
108553c2d547SMichael J. Spencer 
108653c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10872314b3deSDavid Majnemer   if (Name.startswith("/")) {
108853c2d547SMichael J. Spencer     uint32_t Offset;
10892314b3deSDavid Majnemer     if (Name.startswith("//")) {
10909d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10918be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
10928be28cdcSFangrui Song                                  "inalid section name");
10939d2c15efSNico Rieck     } else {
109453c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
10958be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
10968be28cdcSFangrui Song                                  "invalid section name");
10979d2c15efSNico Rieck     }
1098db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10998be28cdcSFangrui Song       return errorCodeToError(EC);
110053c2d547SMichael J. Spencer   }
110153c2d547SMichael J. Spencer 
11028be28cdcSFangrui Song   return Name;
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 
1121*e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11229da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1123e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1124e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1125e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1126*e1cb2c0fSFangrui Song     return Error::success();
11279da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11289da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11299da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
11309da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1131a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1132e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
1133*e1cb2c0fSFangrui Song     return make_error<BinaryError>();
1134a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1135*e1cb2c0fSFangrui Song   return Error::success();
11369da9e693SMichael J. Spencer }
11379da9e693SMichael J. Spencer 
1138022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1139e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1140022ecdf2SBenjamin Kramer }
11418ff24d25SRui Ueyama 
11425e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1143e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1144e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1145022ecdf2SBenjamin Kramer }
11468ff24d25SRui Ueyama 
114796d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
114858323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
114996d071cdSRafael Espindola   return R->VirtualAddress;
1150cbe72fc9SDanil Malyshev }
11518ff24d25SRui Ueyama 
1152806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1153022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11548ff24d25SRui Ueyama   DataRefImpl Ref;
1155236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1156236b0ca7SDavid Majnemer     return symbol_end();
115744f51e51SDavid Majnemer   if (SymbolTable16)
115844f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
115944f51e51SDavid Majnemer   else if (SymbolTable32)
116044f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
116144f51e51SDavid Majnemer   else
1162c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11638ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1164022ecdf2SBenjamin Kramer }
11658ff24d25SRui Ueyama 
116699c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1167022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
116899c041b7SRafael Espindola   return R->Type;
1169022ecdf2SBenjamin Kramer }
1170e5fd0047SMichael J. Spencer 
117127dc8394SAlexey Samsonov const coff_section *
117227dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
117327dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
117471757ef3SMarshall Clow }
117571757ef3SMarshall Clow 
117644f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
117744f51e51SDavid Majnemer   if (SymbolTable16)
117844f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
117944f51e51SDavid Majnemer   if (SymbolTable32)
118044f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
118144f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
118244f51e51SDavid Majnemer }
118344f51e51SDavid Majnemer 
118444f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
118544f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
118671757ef3SMarshall Clow }
118771757ef3SMarshall Clow 
1188f12b8282SRafael Espindola const coff_relocation *
118927dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
119027dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1191d3e2a76cSMarshall Clow }
1192d3e2a76cSMarshall Clow 
11932f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11946a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11952f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
11962f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
11976a75acb1SRui Ueyama }
11986a75acb1SRui Ueyama 
119927dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
120027dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1201114ebf4aSMartin Storsjo     return #reloc_type;
1202e5fd0047SMichael J. Spencer 
1203114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
120444f51e51SDavid Majnemer   switch (getMachine()) {
1205e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1206114ebf4aSMartin Storsjo     switch (Type) {
1207e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1208e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1209e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1210e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1211e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1212e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1213e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1214e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1215e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1216e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1217e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1218e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1219e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1220e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1221e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1222e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1223e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1224e5fd0047SMichael J. Spencer     default:
1225114ebf4aSMartin Storsjo       return "Unknown";
1226e5fd0047SMichael J. Spencer     }
1227e5fd0047SMichael J. Spencer     break;
12285c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1229114ebf4aSMartin Storsjo     switch (Type) {
12305c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12315c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12325c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12335c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12345c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12355c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12365c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12375c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1238e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12395c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12405c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12415c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12425c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12435c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12445c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12455c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1246e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12475c503bf4SSaleem Abdulrasool     default:
1248114ebf4aSMartin Storsjo       return "Unknown";
12495c503bf4SSaleem Abdulrasool     }
12505c503bf4SSaleem Abdulrasool     break;
12510c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1252114ebf4aSMartin Storsjo     switch (Type) {
12530c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12540c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12550c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12560c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12570c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12580c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12590c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12600c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12610c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12620c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12630c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12640c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12650c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12660c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12670c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12680c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12690c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1270e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12710c72172eSMandeep Singh Grang     default:
1272114ebf4aSMartin Storsjo       return "Unknown";
12730c72172eSMandeep Singh Grang     }
12740c72172eSMandeep Singh Grang     break;
1275e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1276114ebf4aSMartin Storsjo     switch (Type) {
1277e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1278e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1279e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1280e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1281e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1282e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1283e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1284e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1285e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1286e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1287e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1288e5fd0047SMichael J. Spencer     default:
1289114ebf4aSMartin Storsjo       return "Unknown";
1290e5fd0047SMichael J. Spencer     }
1291e5fd0047SMichael J. Spencer     break;
1292e5fd0047SMichael J. Spencer   default:
1293114ebf4aSMartin Storsjo     return "Unknown";
1294e5fd0047SMichael J. Spencer   }
1295e5fd0047SMichael J. Spencer }
1296e5fd0047SMichael J. Spencer 
1297e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1298e5fd0047SMichael J. Spencer 
1299114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1300114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1301114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1302114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1303114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1304114ebf4aSMartin Storsjo }
1305114ebf4aSMartin Storsjo 
1306c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1307c66d761bSRafael Espindola   return !DataDirectory;
1308c66d761bSRafael Espindola }
1309c66d761bSRafael Espindola 
1310e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1311e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1312e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1313e3093808SMartin Storsjo       .Default(Name);
1314e3093808SMartin Storsjo }
1315e3093808SMartin Storsjo 
1316c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1317c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1318a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1319c2bed429SRui Ueyama }
1320c2bed429SRui Ueyama 
13215e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13225e812afaSRafael Espindola   ++Index;
13231c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1324ad7b7e73SDavid Majnemer     Index = -1;
1325ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1326ad7b7e73SDavid Majnemer   }
1327c2bed429SRui Ueyama }
1328c2bed429SRui Ueyama 
1329db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
13301c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1331ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1332c2bed429SRui Ueyama }
1333c2bed429SRui Ueyama 
1334861021f9SRui Ueyama static imported_symbol_iterator
133515d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1336861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
133715d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1338861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
133915d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1340861021f9SRui Ueyama   }
1341861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
134215d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1343861021f9SRui Ueyama }
1344861021f9SRui Ueyama 
134515d99359SRui Ueyama static imported_symbol_iterator
134615d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1347861021f9SRui Ueyama   uintptr_t IntPtr = 0;
134815d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
134915d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1350861021f9SRui Ueyama }
1351861021f9SRui Ueyama 
135215d99359SRui Ueyama static imported_symbol_iterator
135315d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1354861021f9SRui Ueyama   uintptr_t IntPtr = 0;
135515d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1356861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1357861021f9SRui Ueyama   int Index = 0;
135815d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1359861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1360861021f9SRui Ueyama     while (*Entry++)
1361861021f9SRui Ueyama       ++Index;
1362861021f9SRui Ueyama   } else {
1363861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1364861021f9SRui Ueyama     while (*Entry++)
1365861021f9SRui Ueyama       ++Index;
1366861021f9SRui Ueyama   }
136715d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
136815d99359SRui Ueyama }
136915d99359SRui Ueyama 
137015d99359SRui Ueyama imported_symbol_iterator
137115d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
137260049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
137315d99359SRui Ueyama                              OwningObject);
137415d99359SRui Ueyama }
137515d99359SRui Ueyama 
137615d99359SRui Ueyama imported_symbol_iterator
137715d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
137860049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
137915d99359SRui Ueyama                            OwningObject);
1380861021f9SRui Ueyama }
1381861021f9SRui Ueyama 
1382979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1383979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1384979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1385979fb40bSRui Ueyama }
1386979fb40bSRui Ueyama 
138760049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
138860049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
138960049526SDavid Majnemer                              OwningObject);
139060049526SDavid Majnemer }
139160049526SDavid Majnemer 
139260049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
139360049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
139460049526SDavid Majnemer                            OwningObject);
139560049526SDavid Majnemer }
139660049526SDavid Majnemer 
139760049526SDavid Majnemer iterator_range<imported_symbol_iterator>
139860049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
139960049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
140060049526SDavid Majnemer }
140160049526SDavid Majnemer 
1402db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1403c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1404db4ed0bdSRafael Espindola   if (std::error_code EC =
14051e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1406a045b73aSRui Ueyama     return EC;
1407a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14087d099195SRui Ueyama   return std::error_code();
1409c2bed429SRui Ueyama }
1410c2bed429SRui Ueyama 
14111e152d5eSRui Ueyama std::error_code
14121e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14131e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14147d099195SRui Ueyama   return std::error_code();
14151e152d5eSRui Ueyama }
14161e152d5eSRui Ueyama 
14171e152d5eSRui Ueyama std::error_code
14181e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
14191e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14207d099195SRui Ueyama   return std::error_code();
14211e152d5eSRui Ueyama }
14221e152d5eSRui Ueyama 
142315d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
142415d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
142515d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
142615d99359SRui Ueyama }
142715d99359SRui Ueyama 
142815d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
142915d99359SRui Ueyama   ++Index;
143015d99359SRui Ueyama }
143115d99359SRui Ueyama 
143215d99359SRui Ueyama imported_symbol_iterator
143315d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
143415d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
143515d99359SRui Ueyama                              OwningObject);
143615d99359SRui Ueyama }
143715d99359SRui Ueyama 
143815d99359SRui Ueyama imported_symbol_iterator
143915d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
144015d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
144115d99359SRui Ueyama                            OwningObject);
144215d99359SRui Ueyama }
144315d99359SRui Ueyama 
1444979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1445979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1446979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1447979fb40bSRui Ueyama }
1448979fb40bSRui Ueyama 
144915d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
145015d99359SRui Ueyama   uintptr_t IntPtr = 0;
145115d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
145215d99359SRui Ueyama     return EC;
145315d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14547d099195SRui Ueyama   return std::error_code();
145515d99359SRui Ueyama }
145615d99359SRui Ueyama 
14571af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14581af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14599f598ac7SJoseph Tremoulet   Result = &Table[Index];
14607d099195SRui Ueyama   return std::error_code();
14611af08658SRui Ueyama }
14621af08658SRui Ueyama 
1463ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1464ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1465ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1466ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1467ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1468ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1469ffa4cebeSRui Ueyama     return EC;
1470ffa4cebeSRui Ueyama   if (OwningObject->is64())
14715dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1472ffa4cebeSRui Ueyama   else
14735dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14747d099195SRui Ueyama   return std::error_code();
1475ffa4cebeSRui Ueyama }
1476ffa4cebeSRui Ueyama 
1477ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1478ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1479ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1480ad882ba8SRui Ueyama }
1481ad882ba8SRui Ueyama 
14825e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14835e812afaSRafael Espindola   ++Index;
1484ad882ba8SRui Ueyama }
1485ad882ba8SRui Ueyama 
1486da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1487da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1488db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1489da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1490db4ed0bdSRafael Espindola   if (std::error_code EC =
1491db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1492da49d0d4SRui Ueyama     return EC;
1493da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14947d099195SRui Ueyama   return std::error_code();
1495da49d0d4SRui Ueyama }
1496da49d0d4SRui Ueyama 
1497e5df6095SRui Ueyama // Returns the starting ordinal number.
1498db4ed0bdSRafael Espindola std::error_code
1499db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1500e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15017d099195SRui Ueyama   return std::error_code();
1502e5df6095SRui Ueyama }
1503e5df6095SRui Ueyama 
1504ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1505db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1506ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15077d099195SRui Ueyama   return std::error_code();
1508ad882ba8SRui Ueyama }
1509ad882ba8SRui Ueyama 
1510ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1511db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1512ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1513db4ed0bdSRafael Espindola   if (std::error_code EC =
1514db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1515ad882ba8SRui Ueyama     return EC;
151624fc2d64SRui Ueyama   const export_address_table_entry *entry =
151724fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1518ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15197d099195SRui Ueyama   return std::error_code();
1520ad882ba8SRui Ueyama }
1521ad882ba8SRui Ueyama 
1522ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1523ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1524db4ed0bdSRafael Espindola std::error_code
1525db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1526ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1527db4ed0bdSRafael Espindola   if (std::error_code EC =
1528db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1529ad882ba8SRui Ueyama     return EC;
1530ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1531ad882ba8SRui Ueyama 
1532ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1533ad882ba8SRui Ueyama   int Offset = 0;
1534ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1535ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1536ad882ba8SRui Ueyama     if (*I != Index)
1537ad882ba8SRui Ueyama       continue;
1538db4ed0bdSRafael Espindola     if (std::error_code EC =
1539db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1540ad882ba8SRui Ueyama       return EC;
1541ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1542db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1543ad882ba8SRui Ueyama       return EC;
1544ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15457d099195SRui Ueyama     return std::error_code();
1546ad882ba8SRui Ueyama   }
1547ad882ba8SRui Ueyama   Result = "";
15487d099195SRui Ueyama   return std::error_code();
1549ad882ba8SRui Ueyama }
1550ad882ba8SRui Ueyama 
15516161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15526161b38dSRui Ueyama   const data_directory *DataEntry;
15536161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15546161b38dSRui Ueyama     return EC;
15556161b38dSRui Ueyama   uint32_t RVA;
15566161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15576161b38dSRui Ueyama     return EC;
15586161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15596161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15606161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15616161b38dSRui Ueyama   return std::error_code();
15626161b38dSRui Ueyama }
15636161b38dSRui Ueyama 
15646161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15656161b38dSRui Ueyama   uint32_t RVA;
15666161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15676161b38dSRui Ueyama     return EC;
15686161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15696161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15706161b38dSRui Ueyama     return EC;
15716161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15726161b38dSRui Ueyama   return std::error_code();
15736161b38dSRui Ueyama }
15746161b38dSRui Ueyama 
1575861021f9SRui Ueyama bool ImportedSymbolRef::
1576861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1577861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1578861021f9SRui Ueyama       && Index == Other.Index;
1579861021f9SRui Ueyama }
1580861021f9SRui Ueyama 
1581861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1582861021f9SRui Ueyama   ++Index;
1583861021f9SRui Ueyama }
1584861021f9SRui Ueyama 
1585861021f9SRui Ueyama std::error_code
1586861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1587861021f9SRui Ueyama   uint32_t RVA;
1588861021f9SRui Ueyama   if (Entry32) {
1589861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1590861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15917d099195SRui Ueyama       return std::error_code();
1592861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1593861021f9SRui Ueyama   } else {
1594861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15957d099195SRui Ueyama       return std::error_code();
1596861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1597861021f9SRui Ueyama   }
1598861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1599861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1600861021f9SRui Ueyama     return EC;
1601861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1602861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16037d099195SRui Ueyama   return std::error_code();
1604861021f9SRui Ueyama }
1605861021f9SRui Ueyama 
1606ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1607ad7b7e73SDavid Majnemer   if (Entry32)
1608ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1609ad7b7e73SDavid Majnemer   else
1610ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1611ad7b7e73SDavid Majnemer   return std::error_code();
1612ad7b7e73SDavid Majnemer }
1613ad7b7e73SDavid Majnemer 
1614ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1615ad7b7e73SDavid Majnemer   if (Entry32)
1616ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1617ad7b7e73SDavid Majnemer   else
1618ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1619ad7b7e73SDavid Majnemer   return std::error_code();
1620ad7b7e73SDavid Majnemer }
1621ad7b7e73SDavid Majnemer 
1622861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1623861021f9SRui Ueyama   uint32_t RVA;
1624861021f9SRui Ueyama   if (Entry32) {
1625861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1626861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16277d099195SRui Ueyama       return std::error_code();
1628861021f9SRui Ueyama     }
1629861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1630861021f9SRui Ueyama   } else {
1631861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1632861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16337d099195SRui Ueyama       return std::error_code();
1634861021f9SRui Ueyama     }
1635861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1636861021f9SRui Ueyama   }
1637861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1638861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1639861021f9SRui Ueyama     return EC;
1640861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16417d099195SRui Ueyama   return std::error_code();
1642861021f9SRui Ueyama }
1643861021f9SRui Ueyama 
164412db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
164548af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1646db4ed0bdSRafael Espindola   std::error_code EC;
164748af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1648692410efSRafael Espindola   if (EC)
164912db383eSRafael Espindola     return errorCodeToError(EC);
1650437b0d58SRafael Espindola   return std::move(Ret);
1651686738e2SRui Ueyama }
165274e85130SRui Ueyama 
165374e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
165474e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
165574e85130SRui Ueyama }
165674e85130SRui Ueyama 
165774e85130SRui Ueyama void BaseRelocRef::moveNext() {
165874e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
165974e85130SRui Ueyama   // size of the header itself.
166074e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1661970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
166274e85130SRui Ueyama   if (Size == Header->BlockSize) {
166374e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
166474e85130SRui Ueyama     // consists of the header followed by entries. The header contains
166574e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
166674e85130SRui Ueyama     // current block, proceed to the next block.
166774e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
166874e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
166974e85130SRui Ueyama     Index = 0;
167074e85130SRui Ueyama   } else {
167174e85130SRui Ueyama     ++Index;
167274e85130SRui Ueyama   }
167374e85130SRui Ueyama }
167474e85130SRui Ueyama 
167574e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
167674e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
167774e85130SRui Ueyama   Type = Entry[Index].getType();
16787d099195SRui Ueyama   return std::error_code();
167974e85130SRui Ueyama }
168074e85130SRui Ueyama 
168174e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
168274e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
168374e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16847d099195SRui Ueyama   return std::error_code();
168574e85130SRui Ueyama }
1686efef15a0SEric Beckmann 
168787867988SRafael Espindola #define RETURN_IF_ERROR(E)                                                     \
168887867988SRafael Espindola   if (E)                                                                       \
168987867988SRafael Espindola     return E;
1690efef15a0SEric Beckmann 
169187867988SRafael Espindola Expected<ArrayRef<UTF16>>
169287867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1693efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1694efef15a0SEric Beckmann   Reader.setOffset(Offset);
1695efef15a0SEric Beckmann   uint16_t Length;
1696efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1697efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1698efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1699cd704cb6SEric Beckmann   return RawDirString;
1700efef15a0SEric Beckmann }
1701efef15a0SEric Beckmann 
1702f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1703efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1704f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1705efef15a0SEric Beckmann }
1706efef15a0SEric Beckmann 
170787867988SRafael Espindola Expected<const coff_resource_dir_table &>
1708efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1709efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1710efef15a0SEric Beckmann 
1711efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1712efef15a0SEric Beckmann   Reader.setOffset(Offset);
1713efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1714efef15a0SEric Beckmann   assert(Table != nullptr);
1715efef15a0SEric Beckmann   return *Table;
1716efef15a0SEric Beckmann }
1717efef15a0SEric Beckmann 
1718f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1719efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1720f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1721efef15a0SEric Beckmann }
1722efef15a0SEric Beckmann 
1723f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1724f3404674SRafael Espindola   return getTableAtOffset(0);
1725efef15a0SEric Beckmann }
1726