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"
150ea52537SSimon Pilgrim #include "llvm/ADT/StringSwitch.h"
168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h"
176a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h"
18264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h"
19d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
20d341c932SEugene Zelenko #include "llvm/Object/COFF.h"
21d341c932SEugene Zelenko #include "llvm/Object/Error.h"
22d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h"
23efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
24d341c932SEugene Zelenko #include "llvm/Support/Endian.h"
25d341c932SEugene Zelenko #include "llvm/Support/Error.h"
26d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
27d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h"
28e72c195fSserge-sans-paille #include "llvm/Support/MemoryBufferRef.h"
29d341c932SEugene Zelenko #include <algorithm>
30d341c932SEugene Zelenko #include <cassert>
312980ce98SHubert Tong #include <cinttypes>
32d341c932SEugene Zelenko #include <cstddef>
33d341c932SEugene Zelenko #include <cstring>
349d2c15efSNico Rieck #include <limits>
35d341c932SEugene Zelenko #include <memory>
36d341c932SEugene Zelenko #include <system_error>
378e90adafSMichael J. Spencer 
388e90adafSMichael J. Spencer using namespace llvm;
398e90adafSMichael J. Spencer using namespace object;
408e90adafSMichael J. Spencer 
418e90adafSMichael J. Spencer using support::ulittle16_t;
428e90adafSMichael J. Spencer using support::ulittle32_t;
43861021f9SRui Ueyama using support::ulittle64_t;
448e90adafSMichael J. Spencer using support::little16_t;
458e90adafSMichael J. Spencer 
461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
48c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
498ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
501d6167fdSMichael J. Spencer     return false;
511d6167fdSMichael J. Spencer   }
521d6167fdSMichael J. Spencer   return true;
538e90adafSMichael J. Spencer }
548e90adafSMichael J. Spencer 
55ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
56ed64342bSRui Ueyama // Returns unexpected_eof if error.
57ed64342bSRui Ueyama template <typename T>
581c03389cSReid Kleckner static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,
59236b0ca7SDavid Majnemer                        const uint64_t Size = sizeof(T)) {
6022cf54a7SArthur O'Dwyer   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
61e03a135bSReid Kleckner   if (Error E = Binary::checkOffset(M, Addr, Size))
621c03389cSReid Kleckner     return E;
63ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
641c03389cSReid Kleckner   return Error::success();
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 
10622cf54a7SArthur O'Dwyer   assert(!checkOffset(Data, reinterpret_cast<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.
10922cf54a7SArthur O'Dwyer   uintptr_t Offset =
11022cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base());
1111d6167fdSMichael J. Spencer 
11244f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11344f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1141d6167fdSMichael J. Spencer #endif
1151d6167fdSMichael J. Spencer 
1168ff24d25SRui Ueyama   return Addr;
1171d6167fdSMichael J. Spencer }
1181d6167fdSMichael J. Spencer 
1198ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1208ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1211d6167fdSMichael J. Spencer 
1221d6167fdSMichael J. Spencer #ifndef NDEBUG
1231d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
12444f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1251d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1261d6167fdSMichael J. Spencer 
12722cf54a7SArthur O'Dwyer   uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -
12822cf54a7SArthur O'Dwyer                      reinterpret_cast<uintptr_t>(SectionTable);
1298ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1301d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1311d6167fdSMichael J. Spencer #endif
1321d6167fdSMichael J. Spencer 
1338ff24d25SRui Ueyama   return Addr;
1341d6167fdSMichael J. Spencer }
1351d6167fdSMichael J. Spencer 
1365e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
137236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13844f51e51SDavid Majnemer   if (SymbolTable16) {
13944f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1408ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
141236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14244f51e51SDavid Majnemer   } else if (SymbolTable32) {
14344f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14444f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
145236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14644f51e51SDavid Majnemer   } else {
14744f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14844f51e51SDavid Majnemer   }
1491d6167fdSMichael J. Spencer }
1501d6167fdSMichael J. Spencer 
15181e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15277ecf90cSReid Kleckner   return getSymbolName(getCOFFSymbol(Ref));
1538e90adafSMichael J. Spencer }
1548e90adafSMichael J. Spencer 
155be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
156be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
157991af666SRafael Espindola }
158991af666SRafael Espindola 
1596b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1606b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1616b2bba14SDavide Italiano   // up to 32 bytes.
1626b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16303a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1646b2bba14SDavide Italiano }
1656b2bba14SDavide Italiano 
166931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
167ff6a0b6aSXing GUO   uint64_t Result = cantFail(getSymbolValue(Ref));
16844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
169c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
170991af666SRafael Espindola 
171991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
172991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
173ed067c45SRafael Espindola     return Result;
17454c9f3daSRafael Espindola 
17577ecf90cSReid Kleckner   Expected<const coff_section *> Section = getSection(SectionNumber);
17677ecf90cSReid Kleckner   if (!Section)
17777ecf90cSReid Kleckner     return Section.takeError();
17877ecf90cSReid Kleckner   Result += (*Section)->VirtualAddress;
17947ea9eceSReid Kleckner 
18047ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18147ea9eceSReid Kleckner   // return virtual addresses.
18221427adaSReid Kleckner   Result += getImageBase();
18347ea9eceSReid Kleckner 
184ed067c45SRafael Espindola   return Result;
185c7d7c6fbSDavid Majnemer }
186c7d7c6fbSDavid Majnemer 
1877bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
18844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
189c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
19044f51e51SDavid Majnemer 
191e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
192e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1932fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1942fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1952fa80cc5SRafael Espindola   if (Symb.isCommon())
1962fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1972fa80cc5SRafael Espindola   if (Symb.isFileRecord())
1982fa80cc5SRafael Espindola     return SymbolRef::ST_File;
1992fa80cc5SRafael Espindola 
2001a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2012fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2022fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2032fa80cc5SRafael Espindola 
2042fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2052fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2062fa80cc5SRafael Espindola 
2072fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
20875d1cf33SBenjamin Kramer }
20975d1cf33SBenjamin Kramer 
210ac00376aSvgxbj Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21220122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21375d1cf33SBenjamin Kramer 
214c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2159dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2161df4b84dSDavid Meyer 
217a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2181df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
219a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
220a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2211079ef8dSMartell Malone   }
2221df4b84dSDavid Meyer 
22344f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2241df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2251df4b84dSDavid Meyer 
226c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
227c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
228c7d7c6fbSDavid Majnemer 
229c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
230c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
231c7d7c6fbSDavid Majnemer 
232c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
233c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
234c7d7c6fbSDavid Majnemer 
235a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
236c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
237c7d7c6fbSDavid Majnemer 
23820122a43SRafael Espindola   return Result;
23901759754SMichael J. Spencer }
24001759754SMichael J. Spencer 
241d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
242c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2435eb02e45SRafael Espindola   return Symb.getValue();
2448e90adafSMichael J. Spencer }
2458e90adafSMichael J. Spencer 
2467bd8d994SKevin Enderby Expected<section_iterator>
2478bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
24844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2498bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2508bab889bSRafael Espindola     return section_end();
25177ecf90cSReid Kleckner   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
25277ecf90cSReid Kleckner   if (!Sec)
25377ecf90cSReid Kleckner     return Sec.takeError();
2548bab889bSRafael Espindola   DataRefImpl Ret;
25577ecf90cSReid Kleckner   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2568bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25732173153SMichael J. Spencer }
25832173153SMichael J. Spencer 
2596bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2606bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2616bf32210SRafael Espindola   return Symb.getSectionNumber();
2626bf32210SRafael Espindola }
2636bf32210SRafael Espindola 
2645e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2658ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2668ff24d25SRui Ueyama   Sec += 1;
2678ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2688e90adafSMichael J. Spencer }
2698e90adafSMichael J. Spencer 
2708be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2718ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2728be28cdcSFangrui Song   return getSectionName(Sec);
2738e90adafSMichael J. Spencer }
2748e90adafSMichael J. Spencer 
27580291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2768ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2777c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2787c6a071bSDavid Majnemer 
2797c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2807c6a071bSDavid Majnemer   // return virtual addresses.
28121427adaSReid Kleckner   Result += getImageBase();
2827c6a071bSDavid Majnemer   return Result;
2838e90adafSMichael J. Spencer }
2848e90adafSMichael J. Spencer 
285a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
286a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
287a25d329bSGeorge Rimar }
288a25d329bSGeorge Rimar 
28980291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
290a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2918e90adafSMichael J. Spencer }
2928e90adafSMichael J. Spencer 
293e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
294e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2958ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2969da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
297e1cb2c0fSFangrui Song   if (Error E = getSectionContents(Sec, Res))
298c55cf4afSBill Wendling     return std::move(E);
299e1cb2c0fSFangrui Song   return Res;
3008e90adafSMichael J. Spencer }
3018e90adafSMichael J. Spencer 
30280291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3038ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
304511391feSDavid Majnemer   return Sec->getAlignment();
3057989460aSMichael J. Spencer }
3067989460aSMichael J. Spencer 
307401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
308401e4e57SGeorge Rimar   return false;
309401e4e57SGeorge Rimar }
310401e4e57SGeorge Rimar 
31180291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3128ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31380291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3148e90adafSMichael J. Spencer }
3158e90adafSMichael J. Spencer 
31680291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3178ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31880291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
319800619f2SMichael J. Spencer }
320800619f2SMichael J. Spencer 
32180291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3228ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3231a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3241a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3251a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3261a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
327800619f2SMichael J. Spencer }
328800619f2SMichael J. Spencer 
32929d253c4SDjordje Todorovic // The .debug sections are the only debug sections for COFF
33029d253c4SDjordje Todorovic // (\see MCObjectFileInfo.cpp).
331bf809cd1SEsme-Yi bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {
332bf809cd1SEsme-Yi   Expected<StringRef> SectionNameOrErr = getSectionName(Ref);
333bf809cd1SEsme-Yi   if (!SectionNameOrErr) {
334bf809cd1SEsme-Yi     // TODO: Report the error message properly.
335bf809cd1SEsme-Yi     consumeError(SectionNameOrErr.takeError());
336bf809cd1SEsme-Yi     return false;
337bf809cd1SEsme-Yi   }
338bf809cd1SEsme-Yi   StringRef SectionName = SectionNameOrErr.get();
33929d253c4SDjordje Todorovic   return SectionName.startswith(".debug");
34029d253c4SDjordje Todorovic }
34129d253c4SDjordje Todorovic 
3426bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3436bf32210SRafael Espindola   uintptr_t Offset =
34422cf54a7SArthur O'Dwyer       Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3456bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3466bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3476bf32210SRafael Espindola }
3486bf32210SRafael Espindola 
34980291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3508ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3511a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3521a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3531a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3542138ef6dSPreston Gurd }
3552138ef6dSPreston Gurd 
356e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
357e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
358e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
359e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
360e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
361e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
362e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
363e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
3641c03389cSReid Kleckner     if (Error E = getObject(FirstReloc, M,
3651c03389cSReid Kleckner                             reinterpret_cast<const coff_relocation *>(
3661c03389cSReid Kleckner                                 base + Sec->PointerToRelocations))) {
3671c03389cSReid Kleckner       consumeError(std::move(E));
368e830c60dSDavid Majnemer       return 0;
3691c03389cSReid Kleckner     }
37098fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
37198fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
372e830c60dSDavid Majnemer   }
373e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
374e830c60dSDavid Majnemer }
375e830c60dSDavid Majnemer 
37694751be7SDavid Majnemer static const coff_relocation *
37794751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37894751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37994751be7SDavid Majnemer   if (!NumRelocs)
38094751be7SDavid Majnemer     return nullptr;
381827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
38294751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
383827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
384827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
385827c8a2bSRui Ueyama     // relocations.
386827c8a2bSRui Ueyama     begin++;
387827c8a2bSRui Ueyama   }
38822cf54a7SArthur O'Dwyer   if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
389e03a135bSReid Kleckner                                    sizeof(coff_relocation) * NumRelocs)) {
390e03a135bSReid Kleckner     consumeError(std::move(E));
39194751be7SDavid Majnemer     return nullptr;
392e03a135bSReid Kleckner   }
39394751be7SDavid Majnemer   return begin;
394827c8a2bSRui Ueyama }
39594751be7SDavid Majnemer 
39694751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
39794751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
39894751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
39976d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
40076d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
40194751be7SDavid Majnemer   DataRefImpl Ret;
40294751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
4038ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
404e5fd0047SMichael J. Spencer }
405e5fd0047SMichael J. Spencer 
4068ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4078ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
40894751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
40994751be7SDavid Majnemer   if (I)
41094751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4118ff24d25SRui Ueyama   DataRefImpl Ret;
41294751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4138ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
414e5fd0047SMichael J. Spencer }
415e5fd0047SMichael J. Spencer 
416c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
4171c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() {
41844f51e51SDavid Majnemer   if (COFFHeader)
4191c03389cSReid Kleckner     if (Error E = getObject(
420236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
421236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4221c03389cSReid Kleckner       return E;
42344f51e51SDavid Majnemer 
42444f51e51SDavid Majnemer   if (COFFBigObjHeader)
4251c03389cSReid Kleckner     if (Error E = getObject(
426236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
427236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4281c03389cSReid Kleckner       return E;
429c2bed429SRui Ueyama 
430c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
431c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
432c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
433f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
43444f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
435f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
436c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
4371c03389cSReid Kleckner   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4381c03389cSReid Kleckner     return E;
439c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
4401c03389cSReid Kleckner   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4411c03389cSReid Kleckner     return E;
442c2bed429SRui Ueyama 
443773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
444773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
445773a5795SNico Rieck   if (StringTableSize < 4)
446773a5795SNico Rieck     StringTableSize = 4;
447773a5795SNico Rieck 
448c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
449773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
4506ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
4516ec18aafSMartin Storsjö                              "string table missing null terminator");
4521c03389cSReid Kleckner   return Error::success();
453c2bed429SRui Ueyama }
454c2bed429SRui Ueyama 
45521427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
456e94fef7bSReid Kleckner   if (PE32Header)
45721427adaSReid Kleckner     return PE32Header->ImageBase;
458e94fef7bSReid Kleckner   else if (PE32PlusHeader)
45921427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
46021427adaSReid Kleckner   // This actually comes up in practice.
46121427adaSReid Kleckner   return 0;
462e94fef7bSReid Kleckner }
463e94fef7bSReid Kleckner 
464215a586cSRui Ueyama // Returns the file offset for the given VA.
4651c03389cSReid Kleckner Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
46621427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
467b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
468b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
469b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
470215a586cSRui Ueyama }
471215a586cSRui Ueyama 
472c2bed429SRui Ueyama // Returns the file offset for the given RVA.
4736ec18aafSMartin Storsjö Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,
4746ec18aafSMartin Storsjö                                 const char *ErrorContext) const {
47527dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
47627dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
477c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
478c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
479215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
480*bb94611dSAlvin Wong       // A table/directory entry can be pointing to somewhere in a stripped
481*bb94611dSAlvin Wong       // section, in an object that went through `objcopy --only-keep-debug`.
482*bb94611dSAlvin Wong       // In this case we don't want to cause the parsing of the object file to
483*bb94611dSAlvin Wong       // fail, otherwise it will be impossible to use this object as debug info
484*bb94611dSAlvin Wong       // in LLDB. Return SectionStrippedError here so that
485*bb94611dSAlvin Wong       // COFFObjectFile::initialize can ignore the error.
486*bb94611dSAlvin Wong       if (Section->SizeOfRawData == 0)
487*bb94611dSAlvin Wong         return make_error<SectionStrippedError>();
488*bb94611dSAlvin Wong       if (Section->SizeOfRawData < Section->VirtualSize &&
489*bb94611dSAlvin Wong           Addr >= SectionStart + Section->SizeOfRawData) {
490*bb94611dSAlvin Wong         if (ErrorContext)
491*bb94611dSAlvin Wong           return createStringError(object_error::parse_failed,
492*bb94611dSAlvin Wong                                    "RVA 0x%" PRIx32
493*bb94611dSAlvin Wong                                    " for %s found but data is incomplete",
494*bb94611dSAlvin Wong                                    Addr, ErrorContext);
495*bb94611dSAlvin Wong         return createStringError(
496*bb94611dSAlvin Wong             object_error::parse_failed,
497*bb94611dSAlvin Wong             "RVA 0x%" PRIx32 " found but data is incomplete", Addr);
498*bb94611dSAlvin Wong       }
499215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
50022cf54a7SArthur O'Dwyer       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
50122cf54a7SArthur O'Dwyer             Offset;
5021c03389cSReid Kleckner       return Error::success();
503c2bed429SRui Ueyama     }
504c2bed429SRui Ueyama   }
5056ec18aafSMartin Storsjö   if (ErrorContext)
5066ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
5076ec18aafSMartin Storsjö                              "RVA 0x%" PRIx32 " for %s not found", Addr,
5086ec18aafSMartin Storsjö                              ErrorContext);
5096ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
5106ec18aafSMartin Storsjö                            "RVA 0x%" PRIx32 " not found", Addr);
511c2bed429SRui Ueyama }
512c2bed429SRui Ueyama 
5131c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
5146ec18aafSMartin Storsjö                                            ArrayRef<uint8_t> &Contents,
5156ec18aafSMartin Storsjö                                            const char *ErrorContext) const {
5162da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
5172da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
5182da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
5192da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
5202da433eaSReid Kleckner     // overflow.
5212da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
5222da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
5232da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
52422cf54a7SArthur O'Dwyer       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
52522cf54a7SArthur O'Dwyer                         Section->PointerToRawData + OffsetIntoSection;
5262da433eaSReid Kleckner       Contents =
5272da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5281c03389cSReid Kleckner       return Error::success();
5292da433eaSReid Kleckner     }
5302da433eaSReid Kleckner   }
5316ec18aafSMartin Storsjö   if (ErrorContext)
5326ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
5336ec18aafSMartin Storsjö                              "RVA 0x%" PRIx32 " for %s not found", RVA,
5346ec18aafSMartin Storsjö                              ErrorContext);
5356ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
5366ec18aafSMartin Storsjö                            "RVA 0x%" PRIx32 " not found", RVA);
5372da433eaSReid Kleckner }
5382da433eaSReid Kleckner 
539c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
540c2bed429SRui Ueyama // table entry.
5411c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
542db4ed0bdSRafael Espindola                                   StringRef &Name) const {
543c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5441c03389cSReid Kleckner   if (Error E = getRvaPtr(Rva, IntPtr))
5451c03389cSReid Kleckner     return E;
546c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
547c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
548c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5491c03389cSReid Kleckner   return Error::success();
550c2bed429SRui Ueyama }
551c2bed429SRui Ueyama 
5521c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
55301528021SSaleem Abdulrasool                                       const codeview::DebugInfo *&PDBInfo,
5542da433eaSReid Kleckner                                       StringRef &PDBFileName) const {
5552da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5566ec18aafSMartin Storsjö   if (Error E =
5576ec18aafSMartin Storsjö           getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData,
5586ec18aafSMartin Storsjö                                InfoBytes, "PDB info"))
5591c03389cSReid Kleckner     return E;
56001528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5616ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed, "PDB info too small");
56201528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
56301528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5642da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5652da433eaSReid Kleckner                           InfoBytes.size());
5662da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5672da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5681c03389cSReid Kleckner   return Error::success();
5692da433eaSReid Kleckner }
5702da433eaSReid Kleckner 
5711c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
572f27f3f84SReid Kleckner                                       StringRef &PDBFileName) const {
573f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
574f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
575f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
576f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
577f27f3f84SReid Kleckner   PDBInfo = nullptr;
578f27f3f84SReid Kleckner   PDBFileName = StringRef();
5791c03389cSReid Kleckner   return Error::success();
580f27f3f84SReid Kleckner }
581f27f3f84SReid Kleckner 
582c2bed429SRui Ueyama // Find the import table.
5831c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() {
584c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
585c2bed429SRui Ueyama   // the import table, do nothing.
5861c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5871c03389cSReid Kleckner   if (!DataEntry)
5881c03389cSReid Kleckner     return Error::success();
589c2bed429SRui Ueyama 
590c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
591c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5921c03389cSReid Kleckner     return Error::success();
593c2bed429SRui Ueyama 
594c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
595c2bed429SRui Ueyama 
596c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
597c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
598c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5996ec18aafSMartin Storsjö   if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table"))
6001c03389cSReid Kleckner     return E;
601e03a135bSReid Kleckner   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
6021c03389cSReid Kleckner     return E;
603c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
6041c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
6051c03389cSReid Kleckner   return Error::success();
606ad882ba8SRui Ueyama }
607c2bed429SRui Ueyama 
60815d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
6091c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() {
6101c03389cSReid Kleckner   const data_directory *DataEntry =
6111c03389cSReid Kleckner       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
6121c03389cSReid Kleckner   if (!DataEntry)
6131c03389cSReid Kleckner     return Error::success();
61415d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6151c03389cSReid Kleckner     return Error::success();
61615d99359SRui Ueyama 
61715d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
61815d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
61915d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
62015d99359SRui Ueyama 
62115d99359SRui Ueyama   uintptr_t IntPtr = 0;
6226ec18aafSMartin Storsjö   if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))
6231c03389cSReid Kleckner     return E;
624*bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
625*bb94611dSAlvin Wong     return E;
626*bb94611dSAlvin Wong 
62715d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
62815d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
6291c03389cSReid Kleckner   return Error::success();
63015d99359SRui Ueyama }
63115d99359SRui Ueyama 
632ad882ba8SRui Ueyama // Find the export table.
6331c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() {
634ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
635ad882ba8SRui Ueyama   // the export table, do nothing.
6361c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6371c03389cSReid Kleckner   if (!DataEntry)
6381c03389cSReid Kleckner     return Error::success();
639ad882ba8SRui Ueyama 
640ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
641ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6421c03389cSReid Kleckner     return Error::success();
643ad882ba8SRui Ueyama 
644ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
645ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
6466ec18aafSMartin Storsjö   if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))
6471c03389cSReid Kleckner     return E;
648*bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
649*bb94611dSAlvin Wong     return E;
650*bb94611dSAlvin Wong 
65124fc2d64SRui Ueyama   ExportDirectory =
65224fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6531c03389cSReid Kleckner   return Error::success();
654c2bed429SRui Ueyama }
655c2bed429SRui Ueyama 
6561c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() {
6571c03389cSReid Kleckner   const data_directory *DataEntry =
6581c03389cSReid Kleckner       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6591c03389cSReid Kleckner   if (!DataEntry)
6601c03389cSReid Kleckner     return Error::success();
66174e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6621c03389cSReid Kleckner     return Error::success();
66374e85130SRui Ueyama 
66474e85130SRui Ueyama   uintptr_t IntPtr = 0;
6656ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
6666ec18aafSMartin Storsjö                           "base reloc table"))
6671c03389cSReid Kleckner     return E;
668*bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
669*bb94611dSAlvin Wong     return E;
670*bb94611dSAlvin Wong 
67174e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
67274e85130SRui Ueyama       IntPtr);
67374e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
67474e85130SRui Ueyama       IntPtr + DataEntry->Size);
675893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
676893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6771c03389cSReid Kleckner   return Error::success();
67874e85130SRui Ueyama }
67974e85130SRui Ueyama 
6801c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() {
6812da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6821c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6831c03389cSReid Kleckner   if (!DataEntry)
6841c03389cSReid Kleckner     return Error::success();
6852da433eaSReid Kleckner 
6862da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6872da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6881c03389cSReid Kleckner     return Error::success();
6892da433eaSReid Kleckner 
6902da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6912da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6926ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
6936ec18aafSMartin Storsjö                              "debug directory has uneven size");
6942da433eaSReid Kleckner 
6952da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6966ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
6976ec18aafSMartin Storsjö                           "debug directory"))
6981c03389cSReid Kleckner     return E;
699*bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
700*bb94611dSAlvin Wong     return E;
701*bb94611dSAlvin Wong 
7022da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
703893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
704893c6469SNico Weber       IntPtr + DataEntry->Size);
705893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
706893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
7071c03389cSReid Kleckner   return Error::success();
7082da433eaSReid Kleckner }
7092da433eaSReid Kleckner 
710568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() {
711568035acSLuqman Aden   // Get the RVA of the TLS directory. Do nothing if it does not exist.
712568035acSLuqman Aden   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
713568035acSLuqman Aden   if (!DataEntry)
714568035acSLuqman Aden     return Error::success();
715568035acSLuqman Aden 
716568035acSLuqman Aden   // Do nothing if the RVA is NULL.
717568035acSLuqman Aden   if (DataEntry->RelativeVirtualAddress == 0)
718568035acSLuqman Aden     return Error::success();
719568035acSLuqman Aden 
720568035acSLuqman Aden   uint64_t DirSize =
721568035acSLuqman Aden       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
722568035acSLuqman Aden 
723568035acSLuqman Aden   // Check that the size is correct.
724568035acSLuqman Aden   if (DataEntry->Size != DirSize)
725568035acSLuqman Aden     return createStringError(
726568035acSLuqman Aden         object_error::parse_failed,
7272980ce98SHubert Tong         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
728568035acSLuqman Aden         static_cast<uint32_t>(DataEntry->Size), DirSize);
729568035acSLuqman Aden 
730568035acSLuqman Aden   uintptr_t IntPtr = 0;
7316ec18aafSMartin Storsjö   if (Error E =
7326ec18aafSMartin Storsjö           getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))
733568035acSLuqman Aden     return E;
734*bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
735*bb94611dSAlvin Wong     return E;
736568035acSLuqman Aden 
737568035acSLuqman Aden   if (is64())
738568035acSLuqman Aden     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
739568035acSLuqman Aden   else
740568035acSLuqman Aden     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
741568035acSLuqman Aden 
742568035acSLuqman Aden   return Error::success();
743568035acSLuqman Aden }
744568035acSLuqman Aden 
7451c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() {
746b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
7471c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
7481c03389cSReid Kleckner   if (!DataEntry)
7491c03389cSReid Kleckner     return Error::success();
750b7d716c0SReid Kleckner 
751b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
752b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
7531c03389cSReid Kleckner     return Error::success();
754b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
7556ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
7566ec18aafSMartin Storsjö                           "load config table"))
7571c03389cSReid Kleckner     return E;
758*bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
759*bb94611dSAlvin Wong     return E;
760b7d716c0SReid Kleckner 
761b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
7621c03389cSReid Kleckner   return Error::success();
763b7d716c0SReid Kleckner }
764b7d716c0SReid Kleckner 
76539772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>>
76639772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) {
76739772063SReid Kleckner   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
76839772063SReid Kleckner   if (Error E = Obj->initialize())
76939772063SReid Kleckner     return std::move(E);
77039772063SReid Kleckner   return std::move(Obj);
77139772063SReid Kleckner }
77239772063SReid Kleckner 
77339772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
77448af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
77544f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
77644f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
77744f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
77839772063SReid Kleckner       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
77939772063SReid Kleckner       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
78039772063SReid Kleckner       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
781568035acSLuqman Aden       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
782568035acSLuqman Aden       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
78339772063SReid Kleckner 
784*bb94611dSAlvin Wong static Error ignoreStrippedErrors(Error E) {
785*bb94611dSAlvin Wong   if (E.isA<SectionStrippedError>()) {
786*bb94611dSAlvin Wong     consumeError(std::move(E));
787*bb94611dSAlvin Wong     return Error::success();
788*bb94611dSAlvin Wong   }
789*bb94611dSAlvin Wong   return std::move(E);
790*bb94611dSAlvin Wong }
791*bb94611dSAlvin Wong 
792101fbc01SNico Weber Error COFFObjectFile::initialize() {
7931d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
79439772063SReid Kleckner   std::error_code EC;
79548af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
79639772063SReid Kleckner     return errorCodeToError(EC);
797ee066fc4SEric Christopher 
79882ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
79982ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
80082ebd8e3SRui Ueyama 
80182ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
80282ebd8e3SRui Ueyama   // it is placed right after COFF header.
8038ff24d25SRui Ueyama   bool HasPEHeader = false;
804ee066fc4SEric Christopher 
8051d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
80650267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
807ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
808ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
80950267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
81050267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
81150267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
81282ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
81350267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
8146ec18aafSMartin Storsjö         return createStringError(object_error::parse_failed,
8156ec18aafSMartin Storsjö                                  "incorrect PE magic");
8161d6167fdSMichael J. Spencer       }
81744f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
8188ff24d25SRui Ueyama       HasPEHeader = true;
819ee066fc4SEric Christopher     }
82050267222SDavid Majnemer   }
821ee066fc4SEric Christopher 
8221c03389cSReid Kleckner   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
8231c03389cSReid Kleckner     return E;
82444f51e51SDavid Majnemer 
82544f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
82644f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
82744f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
82844f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
82944f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
8301c03389cSReid Kleckner     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
8311c03389cSReid Kleckner       return E;
83244f51e51SDavid Majnemer 
83344f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
83444f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
83544f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
83644f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
83744f51e51SDavid Majnemer       COFFHeader = nullptr;
83844f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
83944f51e51SDavid Majnemer     } else {
84044f51e51SDavid Majnemer       // It's not a bigobj.
84144f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
84244f51e51SDavid Majnemer     }
84344f51e51SDavid Majnemer   }
84444f51e51SDavid Majnemer   if (COFFHeader) {
84544f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
84644f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
8477d099195SRui Ueyama     EC = std::error_code();
84882ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
84982ebd8e3SRui Ueyama 
85044f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
85139772063SReid Kleckner       return errorCodeToError(EC);
85244f51e51SDavid Majnemer   }
85344f51e51SDavid Majnemer 
8548ff24d25SRui Ueyama   if (HasPEHeader) {
85510ed9ddcSRui Ueyama     const pe32_header *Header;
8561c03389cSReid Kleckner     if (Error E = getObject(Header, Data, base() + CurPtr))
8571c03389cSReid Kleckner       return E;
85810ed9ddcSRui Ueyama 
85910ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
86010ed9ddcSRui Ueyama     uint64_t DataDirSize;
86150267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
86210ed9ddcSRui Ueyama       PE32Header = Header;
86310ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
86410ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
86550267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
86610ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
86710ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
86810ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
86910ed9ddcSRui Ueyama     } else {
87010ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
8716ec18aafSMartin Storsjö       return createStringError(object_error::parse_failed,
8726ec18aafSMartin Storsjö                                "incorrect PE magic");
873ed64342bSRui Ueyama     }
8741c03389cSReid Kleckner     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8751c03389cSReid Kleckner       return E;
876f53c8cb4SRui Ueyama   }
877776c6828SRui Ueyama 
8788950a538SRui Ueyama   if (COFFHeader)
8798950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
8808950a538SRui Ueyama 
8811c03389cSReid Kleckner   assert(COFFHeader || COFFBigObjHeader);
8821c03389cSReid Kleckner 
8831c03389cSReid Kleckner   if (Error E =
8841c03389cSReid Kleckner           getObject(SectionTable, Data, base() + CurPtr,
8851c03389cSReid Kleckner                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8861c03389cSReid Kleckner     return E;
8871d6167fdSMichael J. Spencer 
888c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
889236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
8901c03389cSReid Kleckner     if (Error E = initSymbolTablePtr()) {
8911c03389cSReid Kleckner       // Recover from errors reading the symbol table.
8921c03389cSReid Kleckner       consumeError(std::move(E));
893ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
894ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
895ac8cfab5SDavid Majnemer       StringTable = nullptr;
896ac8cfab5SDavid Majnemer       StringTableSize = 0;
897ac8cfab5SDavid Majnemer     }
898236b0ca7SDavid Majnemer   } else {
899236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
900236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
9016ec18aafSMartin Storsjö       return createStringError(object_error::parse_failed,
9026ec18aafSMartin Storsjö                                "symbol table missing");
903236b0ca7SDavid Majnemer     }
904236b0ca7SDavid Majnemer   }
9058e90adafSMichael J. Spencer 
906c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
907*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initImportTablePtr()))
9081c03389cSReid Kleckner     return E;
909*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initDelayImportTablePtr()))
9101c03389cSReid Kleckner     return E;
9111d6167fdSMichael J. Spencer 
912ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
913*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initExportTablePtr()))
9141c03389cSReid Kleckner     return E;
915ad882ba8SRui Ueyama 
91674e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
917*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initBaseRelocPtr()))
9181c03389cSReid Kleckner     return E;
91974e85130SRui Ueyama 
920568035acSLuqman Aden   // Initialize the pointer to the debug directory.
921*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr()))
9221c03389cSReid Kleckner     return E;
9232da433eaSReid Kleckner 
924568035acSLuqman Aden   // Initialize the pointer to the TLS directory.
925*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr()))
926568035acSLuqman Aden     return E;
927568035acSLuqman Aden 
928*bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initLoadConfigPtr()))
9291c03389cSReid Kleckner     return E;
930b7d716c0SReid Kleckner 
93139772063SReid Kleckner   return Error::success();
9328e90adafSMichael J. Spencer }
9338e90adafSMichael J. Spencer 
934435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
9358ff24d25SRui Ueyama   DataRefImpl Ret;
93644f51e51SDavid Majnemer   Ret.p = getSymbolTable();
937f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
9388e90adafSMichael J. Spencer }
9398e90adafSMichael J. Spencer 
940435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
9418e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
9428ff24d25SRui Ueyama   DataRefImpl Ret;
9438ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
944f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
9458e90adafSMichael J. Spencer }
9468e90adafSMichael J. Spencer 
947bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
948ad7b7e73SDavid Majnemer   if (!ImportDirectory)
949ad7b7e73SDavid Majnemer     return import_directory_end();
9501c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
951ad7b7e73SDavid Majnemer     return import_directory_end();
952a045b73aSRui Ueyama   return import_directory_iterator(
953a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
954c2bed429SRui Ueyama }
955c2bed429SRui Ueyama 
956bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
957a045b73aSRui Ueyama   return import_directory_iterator(
958ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
959c2bed429SRui Ueyama }
960c429b80dSDavid Meyer 
96115d99359SRui Ueyama delay_import_directory_iterator
96215d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
96315d99359SRui Ueyama   return delay_import_directory_iterator(
96415d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
96515d99359SRui Ueyama }
96615d99359SRui Ueyama 
96715d99359SRui Ueyama delay_import_directory_iterator
96815d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
96915d99359SRui Ueyama   return delay_import_directory_iterator(
97015d99359SRui Ueyama       DelayImportDirectoryEntryRef(
97115d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
97215d99359SRui Ueyama }
97315d99359SRui Ueyama 
974ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
975ad882ba8SRui Ueyama   return export_directory_iterator(
976ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
977ad882ba8SRui Ueyama }
978ad882ba8SRui Ueyama 
979ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
9802617dcceSCraig Topper   if (!ExportDirectory)
9812617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9828ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
983ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
9848ff24d25SRui Ueyama   return export_directory_iterator(Ref);
985ad882ba8SRui Ueyama }
986ad882ba8SRui Ueyama 
987b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
9888ff24d25SRui Ueyama   DataRefImpl Ret;
9898ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9908ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9918e90adafSMichael J. Spencer }
9928e90adafSMichael J. Spencer 
993b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
9948ff24d25SRui Ueyama   DataRefImpl Ret;
99544f51e51SDavid Majnemer   int NumSections =
99644f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9978ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9988ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9998e90adafSMichael J. Spencer }
10008e90adafSMichael J. Spencer 
100174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
100274e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
100374e85130SRui Ueyama }
100474e85130SRui Ueyama 
100574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
100674e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
100774e85130SRui Ueyama }
100874e85130SRui Ueyama 
10098e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
101043c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
10118e90adafSMichael J. Spencer }
10128e90adafSMichael J. Spencer 
10138e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
101444f51e51SDavid Majnemer   switch(getMachine()) {
10158e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
10168e90adafSMichael J. Spencer     return "COFF-i386";
10178e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
10188e90adafSMichael J. Spencer     return "COFF-x86-64";
10199b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
10209b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
10211eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
10221eff5c9cSMartell Malone     return "COFF-ARM64";
10238e90adafSMichael J. Spencer   default:
10248e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
10258e90adafSMichael J. Spencer   }
10268e90adafSMichael J. Spencer }
10278e90adafSMichael J. Spencer 
1028260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
102944f51e51SDavid Majnemer   switch (getMachine()) {
10308e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
10318e90adafSMichael J. Spencer     return Triple::x86;
10328e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
10338e90adafSMichael J. Spencer     return Triple::x86_64;
10349b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
10359b7c0af2SSaleem Abdulrasool     return Triple::thumb;
10361eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
10371eff5c9cSMartell Malone     return Triple::aarch64;
10388e90adafSMichael J. Spencer   default:
10398e90adafSMichael J. Spencer     return Triple::UnknownArch;
10408e90adafSMichael J. Spencer   }
10418e90adafSMichael J. Spencer }
10428e90adafSMichael J. Spencer 
1043d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
1044d2af4d6fSPaul Semel   if (PE32Header)
1045d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
1046d2af4d6fSPaul Semel   return 0;
1047d2af4d6fSPaul Semel }
1048d2af4d6fSPaul Semel 
1049979fb40bSRui Ueyama iterator_range<import_directory_iterator>
1050979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
1051979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
1052979fb40bSRui Ueyama }
1053979fb40bSRui Ueyama 
1054979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
1055979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
1056979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
1057979fb40bSRui Ueyama                     delay_import_directory_end());
1058979fb40bSRui Ueyama }
1059979fb40bSRui Ueyama 
1060979fb40bSRui Ueyama iterator_range<export_directory_iterator>
1061979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
1062979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
1063979fb40bSRui Ueyama }
1064979fb40bSRui Ueyama 
106574e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
106674e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
106774e85130SRui Ueyama }
106874e85130SRui Ueyama 
10691c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
10701c03389cSReid Kleckner   if (!DataDirectory)
10711c03389cSReid Kleckner     return nullptr;
107210ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
107310ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
107410ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
10751c03389cSReid Kleckner   if (Index >= NumEnt)
10761c03389cSReid Kleckner     return nullptr;
10771c03389cSReid Kleckner   return &DataDirectory[Index];
1078ed64342bSRui Ueyama }
1079ed64342bSRui Ueyama 
108077ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
108177ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
108277ecf90cSReid Kleckner   // but callers rely on this to return null.
1083236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
108477ecf90cSReid Kleckner     return (const coff_section *)nullptr;
1085236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10861d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
108777ecf90cSReid Kleckner     return SectionTable + (Index - 1);
10888e90adafSMichael J. Spencer   }
10896ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
10906ec18aafSMartin Storsjö                            "section index out of bounds");
1091236b0ca7SDavid Majnemer }
10928e90adafSMichael J. Spencer 
109377ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10941d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10951d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
10966ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed, "string table empty");
10978ff24d25SRui Ueyama   if (Offset >= StringTableSize)
109877ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
109977ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
11008e90adafSMichael J. Spencer }
1101022ecdf2SBenjamin Kramer 
110277ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
110377ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
1104e40d30f3SRui Ueyama }
1105e40d30f3SRui Ueyama 
110677ecf90cSReid Kleckner Expected<StringRef>
110777ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
110889a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
110977ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
111077ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
111189a7a5eaSMichael J. Spencer 
111289a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
111377ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
111477ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
111577ecf90cSReid Kleckner 
111689a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
111777ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
111889a7a5eaSMichael J. Spencer }
111989a7a5eaSMichael J. Spencer 
112044f51e51SDavid Majnemer ArrayRef<uint8_t>
112144f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
11222617dcceSCraig Topper   const uint8_t *Aux = nullptr;
112371757ef3SMarshall Clow 
112444f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
112544f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
112671757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
112744f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
112871757ef3SMarshall Clow #ifndef NDEBUG
11298ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
11308ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
113144f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
113244f51e51SDavid Majnemer         Offset >=
113344f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
113471757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
113571757ef3SMarshall Clow 
113644f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
113744f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
113871757ef3SMarshall Clow #endif
1139bfb85e67SMarshall Clow   }
114044f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
114171757ef3SMarshall Clow }
114271757ef3SMarshall Clow 
114374e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
114474e7d260SMartin Storsjo   uintptr_t Offset =
114574e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
114674e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
114774e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
114874e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
114974e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
115074e7d260SMartin Storsjo   return Index;
115174e7d260SMartin Storsjo }
115274e7d260SMartin Storsjo 
11538be28cdcSFangrui Song Expected<StringRef>
11548be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
115553c2d547SMichael J. Spencer   StringRef Name;
115644f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
115753c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
115853c2d547SMichael J. Spencer     Name = Sec->Name;
115953c2d547SMichael J. Spencer   else
116053c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
116144f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
116253c2d547SMichael J. Spencer 
116353c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
11642314b3deSDavid Majnemer   if (Name.startswith("/")) {
116553c2d547SMichael J. Spencer     uint32_t Offset;
11662314b3deSDavid Majnemer     if (Name.startswith("//")) {
11679d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
11688be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1169400b6c08Sserge-sans-paille                                  "invalid section name");
11709d2c15efSNico Rieck     } else {
117153c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
11728be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
11738be28cdcSFangrui Song                                  "invalid section name");
11749d2c15efSNico Rieck     }
117577ecf90cSReid Kleckner     return getString(Offset);
117653c2d547SMichael J. Spencer   }
117753c2d547SMichael J. Spencer 
11788be28cdcSFangrui Song   return Name;
117953c2d547SMichael J. Spencer }
118053c2d547SMichael J. Spencer 
1181a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1182a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1183a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1184a9ee5c06SDavid Majnemer   //
1185a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1186d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1187a9ee5c06SDavid Majnemer   //
1188a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1189a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1190a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1191a9ee5c06SDavid Majnemer   // considered to be zero.
1192d5297ee7SRui Ueyama   if (getDOSHeader())
1193d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1194d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1195a9ee5c06SDavid Majnemer }
1196a9ee5c06SDavid Majnemer 
1197e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11989da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1199e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1200e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1201e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1202e1cb2c0fSFangrui Song     return Error::success();
12039da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
12049da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
12059da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
120622cf54a7SArthur O'Dwyer   uintptr_t ConStart =
120722cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
1208a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1209e03a135bSReid Kleckner   if (Error E = checkOffset(Data, ConStart, SectionSize))
1210e03a135bSReid Kleckner     return E;
1211a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1212e1cb2c0fSFangrui Song   return Error::success();
12139da9e693SMichael J. Spencer }
12149da9e693SMichael J. Spencer 
1215022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1216e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1217022ecdf2SBenjamin Kramer }
12188ff24d25SRui Ueyama 
12195e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1220e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1221e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1222022ecdf2SBenjamin Kramer }
12238ff24d25SRui Ueyama 
122496d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
122558323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
122696d071cdSRafael Espindola   return R->VirtualAddress;
1227cbe72fc9SDanil Malyshev }
12288ff24d25SRui Ueyama 
1229806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1230022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
12318ff24d25SRui Ueyama   DataRefImpl Ref;
1232236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1233236b0ca7SDavid Majnemer     return symbol_end();
123444f51e51SDavid Majnemer   if (SymbolTable16)
123544f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
123644f51e51SDavid Majnemer   else if (SymbolTable32)
123744f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
123844f51e51SDavid Majnemer   else
1239c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
12408ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1241022ecdf2SBenjamin Kramer }
12428ff24d25SRui Ueyama 
124399c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1244022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
124599c041b7SRafael Espindola   return R->Type;
1246022ecdf2SBenjamin Kramer }
1247e5fd0047SMichael J. Spencer 
124827dc8394SAlexey Samsonov const coff_section *
124927dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
125027dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
125171757ef3SMarshall Clow }
125271757ef3SMarshall Clow 
125344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
125444f51e51SDavid Majnemer   if (SymbolTable16)
125544f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
125644f51e51SDavid Majnemer   if (SymbolTable32)
125744f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
125844f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
125944f51e51SDavid Majnemer }
126044f51e51SDavid Majnemer 
126144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
126244f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
126371757ef3SMarshall Clow }
126471757ef3SMarshall Clow 
1265f12b8282SRafael Espindola const coff_relocation *
126627dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
126727dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1268d3e2a76cSMarshall Clow }
1269d3e2a76cSMarshall Clow 
12702f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
12716a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
12722f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
12732f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
12746a75acb1SRui Ueyama }
12756a75acb1SRui Ueyama 
127627dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
127727dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1278114ebf4aSMartin Storsjo     return #reloc_type;
1279e5fd0047SMichael J. Spencer 
1280114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
128144f51e51SDavid Majnemer   switch (getMachine()) {
1282e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1283114ebf4aSMartin Storsjo     switch (Type) {
1284e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1285e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1286e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1287e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1288e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1289e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1290e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1291e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1292e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1293e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1294e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1295e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1296e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1297e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1298e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1299e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1300e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1301e5fd0047SMichael J. Spencer     default:
1302114ebf4aSMartin Storsjo       return "Unknown";
1303e5fd0047SMichael J. Spencer     }
1304e5fd0047SMichael J. Spencer     break;
13055c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1306114ebf4aSMartin Storsjo     switch (Type) {
13075c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
13085c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
13095c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
13105c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
13115c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
13125c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
13135c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
13145c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1315e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
13165c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
13175c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
13185c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
13195c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
13205c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
13215c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
13225c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1323e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
13245c503bf4SSaleem Abdulrasool     default:
1325114ebf4aSMartin Storsjo       return "Unknown";
13265c503bf4SSaleem Abdulrasool     }
13275c503bf4SSaleem Abdulrasool     break;
13280c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1329114ebf4aSMartin Storsjo     switch (Type) {
13300c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
13310c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
13320c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
13330c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
13340c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
13350c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
13360c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
13370c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
13380c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
13390c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
13400c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
13410c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
13420c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
13430c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
13440c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
13450c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
13460c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1347e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
13480c72172eSMandeep Singh Grang     default:
1349114ebf4aSMartin Storsjo       return "Unknown";
13500c72172eSMandeep Singh Grang     }
13510c72172eSMandeep Singh Grang     break;
1352e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1353114ebf4aSMartin Storsjo     switch (Type) {
1354e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1355e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1356e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1357e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1358e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1359e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1360e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1361e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1362e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1363e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1364e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1365e5fd0047SMichael J. Spencer     default:
1366114ebf4aSMartin Storsjo       return "Unknown";
1367e5fd0047SMichael J. Spencer     }
1368e5fd0047SMichael J. Spencer     break;
1369e5fd0047SMichael J. Spencer   default:
1370114ebf4aSMartin Storsjo     return "Unknown";
1371e5fd0047SMichael J. Spencer   }
1372e5fd0047SMichael J. Spencer }
1373e5fd0047SMichael J. Spencer 
1374e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1375e5fd0047SMichael J. Spencer 
1376114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1377114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1378114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1379114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1380114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1381114ebf4aSMartin Storsjo }
1382114ebf4aSMartin Storsjo 
1383c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1384c66d761bSRafael Espindola   return !DataDirectory;
1385c66d761bSRafael Espindola }
1386c66d761bSRafael Espindola 
1387e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1388e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1389e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1390e3093808SMartin Storsjo       .Default(Name);
1391e3093808SMartin Storsjo }
1392e3093808SMartin Storsjo 
1393c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1394c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1395a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1396c2bed429SRui Ueyama }
1397c2bed429SRui Ueyama 
13985e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13995e812afaSRafael Espindola   ++Index;
14001c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1401ad7b7e73SDavid Majnemer     Index = -1;
1402ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1403ad7b7e73SDavid Majnemer   }
1404c2bed429SRui Ueyama }
1405c2bed429SRui Ueyama 
14061c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry(
14071c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1408ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1409c2bed429SRui Ueyama }
1410c2bed429SRui Ueyama 
1411861021f9SRui Ueyama static imported_symbol_iterator
141215d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1413861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
141415d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1415861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
141615d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1417861021f9SRui Ueyama   }
1418861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
141915d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1420861021f9SRui Ueyama }
1421861021f9SRui Ueyama 
142215d99359SRui Ueyama static imported_symbol_iterator
142315d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1424861021f9SRui Ueyama   uintptr_t IntPtr = 0;
14251c03389cSReid Kleckner   // FIXME: Handle errors.
14261c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
142715d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1428861021f9SRui Ueyama }
1429861021f9SRui Ueyama 
143015d99359SRui Ueyama static imported_symbol_iterator
143115d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1432861021f9SRui Ueyama   uintptr_t IntPtr = 0;
14331c03389cSReid Kleckner   // FIXME: Handle errors.
14341c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
1435861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1436861021f9SRui Ueyama   int Index = 0;
143715d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1438861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1439861021f9SRui Ueyama     while (*Entry++)
1440861021f9SRui Ueyama       ++Index;
1441861021f9SRui Ueyama   } else {
1442861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1443861021f9SRui Ueyama     while (*Entry++)
1444861021f9SRui Ueyama       ++Index;
1445861021f9SRui Ueyama   }
144615d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
144715d99359SRui Ueyama }
144815d99359SRui Ueyama 
144915d99359SRui Ueyama imported_symbol_iterator
145015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
145160049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
145215d99359SRui Ueyama                              OwningObject);
145315d99359SRui Ueyama }
145415d99359SRui Ueyama 
145515d99359SRui Ueyama imported_symbol_iterator
145615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
145760049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
145815d99359SRui Ueyama                            OwningObject);
1459861021f9SRui Ueyama }
1460861021f9SRui Ueyama 
1461979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1462979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1463979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1464979fb40bSRui Ueyama }
1465979fb40bSRui Ueyama 
146660049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
146760049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
146860049526SDavid Majnemer                              OwningObject);
146960049526SDavid Majnemer }
147060049526SDavid Majnemer 
147160049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
147260049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
147360049526SDavid Majnemer                            OwningObject);
147460049526SDavid Majnemer }
147560049526SDavid Majnemer 
147660049526SDavid Majnemer iterator_range<imported_symbol_iterator>
147760049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
147860049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
147960049526SDavid Majnemer }
148060049526SDavid Majnemer 
14811c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
1482c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
14836ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,
14846ec18aafSMartin Storsjö                                         "import directory name"))
14851c03389cSReid Kleckner     return E;
1486a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14871c03389cSReid Kleckner   return Error::success();
1488c2bed429SRui Ueyama }
1489c2bed429SRui Ueyama 
14901c03389cSReid Kleckner Error
14911e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14921e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14931c03389cSReid Kleckner   return Error::success();
14941e152d5eSRui Ueyama }
14951e152d5eSRui Ueyama 
14961c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14971c03389cSReid Kleckner     uint32_t &Result) const {
14981e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14991c03389cSReid Kleckner   return Error::success();
15001e152d5eSRui Ueyama }
15011e152d5eSRui Ueyama 
150215d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
150315d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
150415d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
150515d99359SRui Ueyama }
150615d99359SRui Ueyama 
150715d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
150815d99359SRui Ueyama   ++Index;
150915d99359SRui Ueyama }
151015d99359SRui Ueyama 
151115d99359SRui Ueyama imported_symbol_iterator
151215d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
151315d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
151415d99359SRui Ueyama                              OwningObject);
151515d99359SRui Ueyama }
151615d99359SRui Ueyama 
151715d99359SRui Ueyama imported_symbol_iterator
151815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
151915d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
152015d99359SRui Ueyama                            OwningObject);
152115d99359SRui Ueyama }
152215d99359SRui Ueyama 
1523979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1524979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1525979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1526979fb40bSRui Ueyama }
1527979fb40bSRui Ueyama 
15281c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
152915d99359SRui Ueyama   uintptr_t IntPtr = 0;
15306ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,
15316ec18aafSMartin Storsjö                                         "delay import directory name"))
15321c03389cSReid Kleckner     return E;
153315d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15341c03389cSReid Kleckner   return Error::success();
153515d99359SRui Ueyama }
153615d99359SRui Ueyama 
15371c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable(
15381c03389cSReid Kleckner     const delay_import_directory_table_entry *&Result) const {
15399f598ac7SJoseph Tremoulet   Result = &Table[Index];
15401c03389cSReid Kleckner   return Error::success();
15411af08658SRui Ueyama }
15421af08658SRui Ueyama 
15431c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
15441c03389cSReid Kleckner                                                      uint64_t &Result) const {
1545ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1546ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1547ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
15486ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address"))
15491c03389cSReid Kleckner     return E;
1550ffa4cebeSRui Ueyama   if (OwningObject->is64())
15515dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1552ffa4cebeSRui Ueyama   else
15535dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
15541c03389cSReid Kleckner   return Error::success();
1555ffa4cebeSRui Ueyama }
1556ffa4cebeSRui Ueyama 
1557ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1558ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1559ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1560ad882ba8SRui Ueyama }
1561ad882ba8SRui Ueyama 
15625e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
15635e812afaSRafael Espindola   ++Index;
1564ad882ba8SRui Ueyama }
1565ad882ba8SRui Ueyama 
1566da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1567da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
15681c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1569da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
15706ec18aafSMartin Storsjö   if (Error E =
15716ec18aafSMartin Storsjö           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name"))
15721c03389cSReid Kleckner     return E;
1573da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15741c03389cSReid Kleckner   return Error::success();
1575da49d0d4SRui Ueyama }
1576da49d0d4SRui Ueyama 
1577e5df6095SRui Ueyama // Returns the starting ordinal number.
15781c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1579e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15801c03389cSReid Kleckner   return Error::success();
1581e5df6095SRui Ueyama }
1582e5df6095SRui Ueyama 
1583ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
15841c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1585ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15861c03389cSReid Kleckner   return Error::success();
1587ad882ba8SRui Ueyama }
1588ad882ba8SRui Ueyama 
1589ad882ba8SRui Ueyama // Returns the address of the current export symbol.
15901c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1591ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15926ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,
15936ec18aafSMartin Storsjö                                          IntPtr, "export address"))
1594ad882ba8SRui Ueyama     return EC;
159524fc2d64SRui Ueyama   const export_address_table_entry *entry =
159624fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1597ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15981c03389cSReid Kleckner   return Error::success();
1599ad882ba8SRui Ueyama }
1600ad882ba8SRui Ueyama 
1601ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1602ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
16031c03389cSReid Kleckner Error
1604db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1605ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
16066ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,
16076ec18aafSMartin Storsjö                                          "export ordinal table"))
1608ad882ba8SRui Ueyama     return EC;
1609ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1610ad882ba8SRui Ueyama 
1611ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1612ad882ba8SRui Ueyama   int Offset = 0;
1613ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1614ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1615ad882ba8SRui Ueyama     if (*I != Index)
1616ad882ba8SRui Ueyama       continue;
16176ec18aafSMartin Storsjö     if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,
16186ec18aafSMartin Storsjö                                            "export table entry"))
1619ad882ba8SRui Ueyama       return EC;
1620ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
16216ec18aafSMartin Storsjö     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr,
16226ec18aafSMartin Storsjö                                            "export symbol name"))
1623ad882ba8SRui Ueyama       return EC;
1624ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16251c03389cSReid Kleckner     return Error::success();
1626ad882ba8SRui Ueyama   }
1627ad882ba8SRui Ueyama   Result = "";
16281c03389cSReid Kleckner   return Error::success();
1629ad882ba8SRui Ueyama }
1630ad882ba8SRui Ueyama 
16311c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
16321c03389cSReid Kleckner   const data_directory *DataEntry =
16331c03389cSReid Kleckner       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
16341c03389cSReid Kleckner   if (!DataEntry)
16356ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
16366ec18aafSMartin Storsjö                              "export table missing");
16376161b38dSRui Ueyama   uint32_t RVA;
16386161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
16396161b38dSRui Ueyama     return EC;
16406161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
16416161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
16426161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
16431c03389cSReid Kleckner   return Error::success();
16446161b38dSRui Ueyama }
16456161b38dSRui Ueyama 
16461c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
16476161b38dSRui Ueyama   uint32_t RVA;
16486161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
16496161b38dSRui Ueyama     return EC;
16506161b38dSRui Ueyama   uintptr_t IntPtr = 0;
16516ec18aafSMartin Storsjö   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target"))
16526161b38dSRui Ueyama     return EC;
16536161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16541c03389cSReid Kleckner   return Error::success();
16556161b38dSRui Ueyama }
16566161b38dSRui Ueyama 
1657861021f9SRui Ueyama bool ImportedSymbolRef::
1658861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1659861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1660861021f9SRui Ueyama       && Index == Other.Index;
1661861021f9SRui Ueyama }
1662861021f9SRui Ueyama 
1663861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1664861021f9SRui Ueyama   ++Index;
1665861021f9SRui Ueyama }
1666861021f9SRui Ueyama 
16671c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1668861021f9SRui Ueyama   uint32_t RVA;
1669861021f9SRui Ueyama   if (Entry32) {
1670861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1671861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
16721c03389cSReid Kleckner       return Error::success();
1673861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1674861021f9SRui Ueyama   } else {
1675861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
16761c03389cSReid Kleckner       return Error::success();
1677861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1678861021f9SRui Ueyama   }
1679861021f9SRui Ueyama   uintptr_t IntPtr = 0;
16806ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name"))
1681861021f9SRui Ueyama     return EC;
1682861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1683861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16841c03389cSReid Kleckner   return Error::success();
1685861021f9SRui Ueyama }
1686861021f9SRui Ueyama 
16871c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const {
1688ad7b7e73SDavid Majnemer   if (Entry32)
1689ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1690ad7b7e73SDavid Majnemer   else
1691ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
16921c03389cSReid Kleckner   return Error::success();
1693ad7b7e73SDavid Majnemer }
1694ad7b7e73SDavid Majnemer 
16951c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1696ad7b7e73SDavid Majnemer   if (Entry32)
1697ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1698ad7b7e73SDavid Majnemer   else
1699ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
17001c03389cSReid Kleckner   return Error::success();
1701ad7b7e73SDavid Majnemer }
1702ad7b7e73SDavid Majnemer 
17031c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1704861021f9SRui Ueyama   uint32_t RVA;
1705861021f9SRui Ueyama   if (Entry32) {
1706861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1707861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
17081c03389cSReid Kleckner       return Error::success();
1709861021f9SRui Ueyama     }
1710861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1711861021f9SRui Ueyama   } else {
1712861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1713861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
17141c03389cSReid Kleckner       return Error::success();
1715861021f9SRui Ueyama     }
1716861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1717861021f9SRui Ueyama   }
1718861021f9SRui Ueyama   uintptr_t IntPtr = 0;
17196ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal"))
1720861021f9SRui Ueyama     return EC;
1721861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
17221c03389cSReid Kleckner   return Error::success();
1723861021f9SRui Ueyama }
1724861021f9SRui Ueyama 
172512db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
172648af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
172739772063SReid Kleckner   return COFFObjectFile::create(Object);
1728686738e2SRui Ueyama }
172974e85130SRui Ueyama 
173074e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
173174e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
173274e85130SRui Ueyama }
173374e85130SRui Ueyama 
173474e85130SRui Ueyama void BaseRelocRef::moveNext() {
173574e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
173674e85130SRui Ueyama   // size of the header itself.
173774e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1738970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
173974e85130SRui Ueyama   if (Size == Header->BlockSize) {
174074e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
174174e85130SRui Ueyama     // consists of the header followed by entries. The header contains
174274e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
174374e85130SRui Ueyama     // current block, proceed to the next block.
174474e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
174574e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
174674e85130SRui Ueyama     Index = 0;
174774e85130SRui Ueyama   } else {
174874e85130SRui Ueyama     ++Index;
174974e85130SRui Ueyama   }
175074e85130SRui Ueyama }
175174e85130SRui Ueyama 
17521c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const {
175374e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
175474e85130SRui Ueyama   Type = Entry[Index].getType();
17551c03389cSReid Kleckner   return Error::success();
175674e85130SRui Ueyama }
175774e85130SRui Ueyama 
17581c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const {
175974e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
176074e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
17611c03389cSReid Kleckner   return Error::success();
176274e85130SRui Ueyama }
1763efef15a0SEric Beckmann 
1764357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1765357a40ecSMartin Storsjo   do {                                                                         \
1766357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
176787867988SRafael Espindola     if (E)                                                                     \
1768c55cf4afSBill Wendling       return std::move(E);                                                     \
1769357a40ecSMartin Storsjo   } while (0)
1770efef15a0SEric Beckmann 
177187867988SRafael Espindola Expected<ArrayRef<UTF16>>
177287867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1773efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1774efef15a0SEric Beckmann   Reader.setOffset(Offset);
1775efef15a0SEric Beckmann   uint16_t Length;
1776efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1777efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1778efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1779cd704cb6SEric Beckmann   return RawDirString;
1780efef15a0SEric Beckmann }
1781efef15a0SEric Beckmann 
1782f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1783efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1784f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1785efef15a0SEric Beckmann }
1786efef15a0SEric Beckmann 
178787867988SRafael Espindola Expected<const coff_resource_dir_table &>
1788efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1789efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1790efef15a0SEric Beckmann 
1791efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1792efef15a0SEric Beckmann   Reader.setOffset(Offset);
1793efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1794efef15a0SEric Beckmann   assert(Table != nullptr);
1795efef15a0SEric Beckmann   return *Table;
1796efef15a0SEric Beckmann }
1797efef15a0SEric Beckmann 
1798edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1799edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1800edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1801edb6ab9bSMartin Storsjo 
1802edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1803edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1804edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1805edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1806edb6ab9bSMartin Storsjo   return *Entry;
1807edb6ab9bSMartin Storsjo }
1808edb6ab9bSMartin Storsjo 
18097ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
18107ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
18117ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
18127ba81d95SMartin Storsjo 
18137ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
18147ba81d95SMartin Storsjo   Reader.setOffset(Offset);
18157ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
18167ba81d95SMartin Storsjo   assert(Entry != nullptr);
18177ba81d95SMartin Storsjo   return *Entry;
18187ba81d95SMartin Storsjo }
18197ba81d95SMartin Storsjo 
1820f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1821efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
18227ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1823f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1824efef15a0SEric Beckmann }
1825efef15a0SEric Beckmann 
18267ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
18277ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
18287ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
18297ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
18307ba81d95SMartin Storsjo }
18317ba81d95SMartin Storsjo 
1832f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1833f3404674SRafael Espindola   return getTableAtOffset(0);
1834efef15a0SEric Beckmann }
1835edb6ab9bSMartin Storsjo 
1836edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1837edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1838edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1839edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1840edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1841edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1842edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1843edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1844edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1845edb6ab9bSMartin Storsjo }
184694382217SMartin Storsjo 
184794382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
184894382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
184994382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
185094382217SMartin Storsjo     if (!Name)
185194382217SMartin Storsjo       return Name.takeError();
185294382217SMartin Storsjo 
185394382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
185494382217SMartin Storsjo       return load(O, S);
185594382217SMartin Storsjo   }
185694382217SMartin Storsjo   return createStringError(object_error::parse_failed,
185794382217SMartin Storsjo                            "no resource section found");
185894382217SMartin Storsjo }
185994382217SMartin Storsjo 
186094382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
186194382217SMartin Storsjo   Obj = O;
186294382217SMartin Storsjo   Section = S;
186394382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
186494382217SMartin Storsjo   if (!Contents)
186594382217SMartin Storsjo     return Contents.takeError();
186694382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
186794382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
186894382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
186994382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
187094382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
187194382217SMartin Storsjo     Relocs.push_back(&R);
1872352fcfc6SKazu Hirata   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
187394382217SMartin Storsjo     return A->VirtualAddress < B->VirtualAddress;
187494382217SMartin Storsjo   });
187594382217SMartin Storsjo   return Error::success();
187694382217SMartin Storsjo }
187794382217SMartin Storsjo 
187894382217SMartin Storsjo Expected<StringRef>
187994382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
188094382217SMartin Storsjo   if (!Obj)
188194382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
188294382217SMartin Storsjo 
188394382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
188494382217SMartin Storsjo   // the coff_resource_data_entry struct).
188594382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
188694382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
188794382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
188894382217SMartin Storsjo                               ulittle16_t(0)};
188994382217SMartin Storsjo   auto RelocsForOffset =
189094382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
189194382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
189294382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
189394382217SMartin Storsjo                        });
189494382217SMartin Storsjo 
189594382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
189694382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
189794382217SMartin Storsjo     // the expected type.
189894382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
189994382217SMartin Storsjo     uint16_t RVAReloc;
190094382217SMartin Storsjo     switch (Obj->getMachine()) {
190194382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
190294382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
190394382217SMartin Storsjo       break;
190494382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
190594382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
190694382217SMartin Storsjo       break;
190794382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
190894382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
190994382217SMartin Storsjo       break;
191094382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
191194382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
191294382217SMartin Storsjo       break;
191394382217SMartin Storsjo     default:
191494382217SMartin Storsjo       return createStringError(object_error::parse_failed,
191594382217SMartin Storsjo                                "unsupported architecture");
191694382217SMartin Storsjo     }
191794382217SMartin Storsjo     if (R.Type != RVAReloc)
191894382217SMartin Storsjo       return createStringError(object_error::parse_failed,
191994382217SMartin Storsjo                                "unexpected relocation type");
192094382217SMartin Storsjo     // Get the relocation's symbol
192194382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
192294382217SMartin Storsjo     if (!Sym)
192394382217SMartin Storsjo       return Sym.takeError();
192494382217SMartin Storsjo     // And the symbol's section
192577ecf90cSReid Kleckner     Expected<const coff_section *> Section =
192677ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
192777ecf90cSReid Kleckner     if (!Section)
192877ecf90cSReid Kleckner       return Section.takeError();
192994382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
193094382217SMartin Storsjo     // data it points at.
193194382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
193294382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
193377ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1934c55cf4afSBill Wendling       return std::move(E);
193594382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
193694382217SMartin Storsjo       return createStringError(object_error::parse_failed,
193794382217SMartin Storsjo                                "data outside of section");
193894382217SMartin Storsjo     // Return a reference to the data inside the section.
193994382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
194094382217SMartin Storsjo                      Entry.DataSize);
194194382217SMartin Storsjo   } else {
194294382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
194394382217SMartin Storsjo     if (Obj->isRelocatableObject())
194494382217SMartin Storsjo       return createStringError(object_error::parse_failed,
194594382217SMartin Storsjo                                "no relocation found for DataRVA");
194694382217SMartin Storsjo 
194794382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
194894382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
194994382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
195094382217SMartin Storsjo       if (VA >= S.getAddress() &&
195194382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
195294382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
195394382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
195494382217SMartin Storsjo         if (!Contents)
195594382217SMartin Storsjo           return Contents.takeError();
195694382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
195794382217SMartin Storsjo       }
195894382217SMartin Storsjo     }
195994382217SMartin Storsjo     return createStringError(object_error::parse_failed,
196094382217SMartin Storsjo                              "address not found in image");
196194382217SMartin Storsjo   }
196294382217SMartin Storsjo }
1963