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)
450*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
451*6ec18aafSMartin 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.
473*6ec18aafSMartin Storsjö Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,
474*6ec18aafSMartin 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) {
480215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
48122cf54a7SArthur O'Dwyer       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
48222cf54a7SArthur O'Dwyer             Offset;
4831c03389cSReid Kleckner       return Error::success();
484c2bed429SRui Ueyama     }
485c2bed429SRui Ueyama   }
486*6ec18aafSMartin Storsjö   if (ErrorContext)
487*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
488*6ec18aafSMartin Storsjö                              "RVA 0x%" PRIx32 " for %s not found", Addr,
489*6ec18aafSMartin Storsjö                              ErrorContext);
490*6ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
491*6ec18aafSMartin Storsjö                            "RVA 0x%" PRIx32 " not found", Addr);
492c2bed429SRui Ueyama }
493c2bed429SRui Ueyama 
4941c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
495*6ec18aafSMartin Storsjö                                            ArrayRef<uint8_t> &Contents,
496*6ec18aafSMartin Storsjö                                            const char *ErrorContext) const {
4972da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4982da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4992da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
5002da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
5012da433eaSReid Kleckner     // overflow.
5022da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
5032da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
5042da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
50522cf54a7SArthur O'Dwyer       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
50622cf54a7SArthur O'Dwyer                         Section->PointerToRawData + OffsetIntoSection;
5072da433eaSReid Kleckner       Contents =
5082da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5091c03389cSReid Kleckner       return Error::success();
5102da433eaSReid Kleckner     }
5112da433eaSReid Kleckner   }
512*6ec18aafSMartin Storsjö   if (ErrorContext)
513*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
514*6ec18aafSMartin Storsjö                              "RVA 0x%" PRIx32 " for %s not found", RVA,
515*6ec18aafSMartin Storsjö                              ErrorContext);
516*6ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
517*6ec18aafSMartin Storsjö                            "RVA 0x%" PRIx32 " not found", RVA);
5182da433eaSReid Kleckner }
5192da433eaSReid Kleckner 
520c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
521c2bed429SRui Ueyama // table entry.
5221c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
523db4ed0bdSRafael Espindola                                   StringRef &Name) const {
524c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5251c03389cSReid Kleckner   if (Error E = getRvaPtr(Rva, IntPtr))
5261c03389cSReid Kleckner     return E;
527c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
528c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
529c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5301c03389cSReid Kleckner   return Error::success();
531c2bed429SRui Ueyama }
532c2bed429SRui Ueyama 
5331c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
53401528021SSaleem Abdulrasool                                       const codeview::DebugInfo *&PDBInfo,
5352da433eaSReid Kleckner                                       StringRef &PDBFileName) const {
5362da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
537*6ec18aafSMartin Storsjö   if (Error E =
538*6ec18aafSMartin Storsjö           getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData,
539*6ec18aafSMartin Storsjö                                InfoBytes, "PDB info"))
5401c03389cSReid Kleckner     return E;
54101528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
542*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed, "PDB info too small");
54301528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
54401528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5452da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5462da433eaSReid Kleckner                           InfoBytes.size());
5472da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5482da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5491c03389cSReid Kleckner   return Error::success();
5502da433eaSReid Kleckner }
5512da433eaSReid Kleckner 
5521c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
553f27f3f84SReid Kleckner                                       StringRef &PDBFileName) const {
554f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
555f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
556f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
557f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
558f27f3f84SReid Kleckner   PDBInfo = nullptr;
559f27f3f84SReid Kleckner   PDBFileName = StringRef();
5601c03389cSReid Kleckner   return Error::success();
561f27f3f84SReid Kleckner }
562f27f3f84SReid Kleckner 
563c2bed429SRui Ueyama // Find the import table.
5641c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() {
565c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
566c2bed429SRui Ueyama   // the import table, do nothing.
5671c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5681c03389cSReid Kleckner   if (!DataEntry)
5691c03389cSReid Kleckner     return Error::success();
570c2bed429SRui Ueyama 
571c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
572c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5731c03389cSReid Kleckner     return Error::success();
574c2bed429SRui Ueyama 
575c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
576c2bed429SRui Ueyama 
577c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
578c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
579c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
580*6ec18aafSMartin Storsjö   if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table"))
5811c03389cSReid Kleckner     return E;
582e03a135bSReid Kleckner   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5831c03389cSReid Kleckner     return E;
584c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5851c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5861c03389cSReid Kleckner   return Error::success();
587ad882ba8SRui Ueyama }
588c2bed429SRui Ueyama 
58915d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
5901c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() {
5911c03389cSReid Kleckner   const data_directory *DataEntry =
5921c03389cSReid Kleckner       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
5931c03389cSReid Kleckner   if (!DataEntry)
5941c03389cSReid Kleckner     return Error::success();
59515d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5961c03389cSReid Kleckner     return Error::success();
59715d99359SRui Ueyama 
59815d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
59915d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
60015d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
60115d99359SRui Ueyama 
60215d99359SRui Ueyama   uintptr_t IntPtr = 0;
603*6ec18aafSMartin Storsjö   if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))
6041c03389cSReid Kleckner     return E;
60515d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
60615d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
6071c03389cSReid Kleckner   return Error::success();
60815d99359SRui Ueyama }
60915d99359SRui Ueyama 
610ad882ba8SRui Ueyama // Find the export table.
6111c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() {
612ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
613ad882ba8SRui Ueyama   // the export table, do nothing.
6141c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6151c03389cSReid Kleckner   if (!DataEntry)
6161c03389cSReid Kleckner     return Error::success();
617ad882ba8SRui Ueyama 
618ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
619ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6201c03389cSReid Kleckner     return Error::success();
621ad882ba8SRui Ueyama 
622ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
623ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
624*6ec18aafSMartin Storsjö   if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))
6251c03389cSReid Kleckner     return E;
62624fc2d64SRui Ueyama   ExportDirectory =
62724fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6281c03389cSReid Kleckner   return Error::success();
629c2bed429SRui Ueyama }
630c2bed429SRui Ueyama 
6311c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() {
6321c03389cSReid Kleckner   const data_directory *DataEntry =
6331c03389cSReid Kleckner       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6341c03389cSReid Kleckner   if (!DataEntry)
6351c03389cSReid Kleckner     return Error::success();
63674e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6371c03389cSReid Kleckner     return Error::success();
63874e85130SRui Ueyama 
63974e85130SRui Ueyama   uintptr_t IntPtr = 0;
640*6ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
641*6ec18aafSMartin Storsjö                           "base reloc table"))
6421c03389cSReid Kleckner     return E;
64374e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
64474e85130SRui Ueyama       IntPtr);
64574e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
64674e85130SRui Ueyama       IntPtr + DataEntry->Size);
647893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
648893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6491c03389cSReid Kleckner   return Error::success();
65074e85130SRui Ueyama }
65174e85130SRui Ueyama 
6521c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() {
6532da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6541c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6551c03389cSReid Kleckner   if (!DataEntry)
6561c03389cSReid Kleckner     return Error::success();
6572da433eaSReid Kleckner 
6582da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6592da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6601c03389cSReid Kleckner     return Error::success();
6612da433eaSReid Kleckner 
6622da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6632da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
664*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
665*6ec18aafSMartin Storsjö                              "debug directory has uneven size");
6662da433eaSReid Kleckner 
6672da433eaSReid Kleckner   uintptr_t IntPtr = 0;
668*6ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
669*6ec18aafSMartin Storsjö                           "debug directory"))
6701c03389cSReid Kleckner     return E;
6712da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
672893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
673893c6469SNico Weber       IntPtr + DataEntry->Size);
674893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
675893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6761c03389cSReid Kleckner   return Error::success();
6772da433eaSReid Kleckner }
6782da433eaSReid Kleckner 
679568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() {
680568035acSLuqman Aden   // Get the RVA of the TLS directory. Do nothing if it does not exist.
681568035acSLuqman Aden   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
682568035acSLuqman Aden   if (!DataEntry)
683568035acSLuqman Aden     return Error::success();
684568035acSLuqman Aden 
685568035acSLuqman Aden   // Do nothing if the RVA is NULL.
686568035acSLuqman Aden   if (DataEntry->RelativeVirtualAddress == 0)
687568035acSLuqman Aden     return Error::success();
688568035acSLuqman Aden 
689568035acSLuqman Aden   uint64_t DirSize =
690568035acSLuqman Aden       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
691568035acSLuqman Aden 
692568035acSLuqman Aden   // Check that the size is correct.
693568035acSLuqman Aden   if (DataEntry->Size != DirSize)
694568035acSLuqman Aden     return createStringError(
695568035acSLuqman Aden         object_error::parse_failed,
6962980ce98SHubert Tong         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
697568035acSLuqman Aden         static_cast<uint32_t>(DataEntry->Size), DirSize);
698568035acSLuqman Aden 
699568035acSLuqman Aden   uintptr_t IntPtr = 0;
700*6ec18aafSMartin Storsjö   if (Error E =
701*6ec18aafSMartin Storsjö           getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))
702568035acSLuqman Aden     return E;
703568035acSLuqman Aden 
704568035acSLuqman Aden   if (is64())
705568035acSLuqman Aden     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
706568035acSLuqman Aden   else
707568035acSLuqman Aden     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
708568035acSLuqman Aden 
709568035acSLuqman Aden   return Error::success();
710568035acSLuqman Aden }
711568035acSLuqman Aden 
7121c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() {
713b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
7141c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
7151c03389cSReid Kleckner   if (!DataEntry)
7161c03389cSReid Kleckner     return Error::success();
717b7d716c0SReid Kleckner 
718b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
719b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
7201c03389cSReid Kleckner     return Error::success();
721b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
722*6ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
723*6ec18aafSMartin Storsjö                           "load config table"))
7241c03389cSReid Kleckner     return E;
725b7d716c0SReid Kleckner 
726b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
7271c03389cSReid Kleckner   return Error::success();
728b7d716c0SReid Kleckner }
729b7d716c0SReid Kleckner 
73039772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>>
73139772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) {
73239772063SReid Kleckner   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
73339772063SReid Kleckner   if (Error E = Obj->initialize())
73439772063SReid Kleckner     return std::move(E);
73539772063SReid Kleckner   return std::move(Obj);
73639772063SReid Kleckner }
73739772063SReid Kleckner 
73839772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
73948af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
74044f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
74144f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
74244f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
74339772063SReid Kleckner       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
74439772063SReid Kleckner       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
74539772063SReid Kleckner       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
746568035acSLuqman Aden       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
747568035acSLuqman Aden       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
74839772063SReid Kleckner 
749101fbc01SNico Weber Error COFFObjectFile::initialize() {
7501d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
75139772063SReid Kleckner   std::error_code EC;
75248af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
75339772063SReid Kleckner     return errorCodeToError(EC);
754ee066fc4SEric Christopher 
75582ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
75682ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
75782ebd8e3SRui Ueyama 
75882ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
75982ebd8e3SRui Ueyama   // it is placed right after COFF header.
7608ff24d25SRui Ueyama   bool HasPEHeader = false;
761ee066fc4SEric Christopher 
7621d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
76350267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
764ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
765ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
76650267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
76750267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
76850267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
76982ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
77050267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
771*6ec18aafSMartin Storsjö         return createStringError(object_error::parse_failed,
772*6ec18aafSMartin Storsjö                                  "incorrect PE magic");
7731d6167fdSMichael J. Spencer       }
77444f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7758ff24d25SRui Ueyama       HasPEHeader = true;
776ee066fc4SEric Christopher     }
77750267222SDavid Majnemer   }
778ee066fc4SEric Christopher 
7791c03389cSReid Kleckner   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
7801c03389cSReid Kleckner     return E;
78144f51e51SDavid Majnemer 
78244f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
78344f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
78444f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
78544f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
78644f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
7871c03389cSReid Kleckner     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
7881c03389cSReid Kleckner       return E;
78944f51e51SDavid Majnemer 
79044f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
79144f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
79244f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
79344f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
79444f51e51SDavid Majnemer       COFFHeader = nullptr;
79544f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
79644f51e51SDavid Majnemer     } else {
79744f51e51SDavid Majnemer       // It's not a bigobj.
79844f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
79944f51e51SDavid Majnemer     }
80044f51e51SDavid Majnemer   }
80144f51e51SDavid Majnemer   if (COFFHeader) {
80244f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
80344f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
8047d099195SRui Ueyama     EC = std::error_code();
80582ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
80682ebd8e3SRui Ueyama 
80744f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
80839772063SReid Kleckner       return errorCodeToError(EC);
80944f51e51SDavid Majnemer   }
81044f51e51SDavid Majnemer 
8118ff24d25SRui Ueyama   if (HasPEHeader) {
81210ed9ddcSRui Ueyama     const pe32_header *Header;
8131c03389cSReid Kleckner     if (Error E = getObject(Header, Data, base() + CurPtr))
8141c03389cSReid Kleckner       return E;
81510ed9ddcSRui Ueyama 
81610ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
81710ed9ddcSRui Ueyama     uint64_t DataDirSize;
81850267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
81910ed9ddcSRui Ueyama       PE32Header = Header;
82010ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
82110ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
82250267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
82310ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
82410ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
82510ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
82610ed9ddcSRui Ueyama     } else {
82710ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
828*6ec18aafSMartin Storsjö       return createStringError(object_error::parse_failed,
829*6ec18aafSMartin Storsjö                                "incorrect PE magic");
830ed64342bSRui Ueyama     }
8311c03389cSReid Kleckner     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8321c03389cSReid Kleckner       return E;
833f53c8cb4SRui Ueyama   }
834776c6828SRui Ueyama 
8358950a538SRui Ueyama   if (COFFHeader)
8368950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
8378950a538SRui Ueyama 
8381c03389cSReid Kleckner   assert(COFFHeader || COFFBigObjHeader);
8391c03389cSReid Kleckner 
8401c03389cSReid Kleckner   if (Error E =
8411c03389cSReid Kleckner           getObject(SectionTable, Data, base() + CurPtr,
8421c03389cSReid Kleckner                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8431c03389cSReid Kleckner     return E;
8441d6167fdSMichael J. Spencer 
845c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
846236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
8471c03389cSReid Kleckner     if (Error E = initSymbolTablePtr()) {
8481c03389cSReid Kleckner       // Recover from errors reading the symbol table.
8491c03389cSReid Kleckner       consumeError(std::move(E));
850ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
851ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
852ac8cfab5SDavid Majnemer       StringTable = nullptr;
853ac8cfab5SDavid Majnemer       StringTableSize = 0;
854ac8cfab5SDavid Majnemer     }
855236b0ca7SDavid Majnemer   } else {
856236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
857236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
858*6ec18aafSMartin Storsjö       return createStringError(object_error::parse_failed,
859*6ec18aafSMartin Storsjö                                "symbol table missing");
860236b0ca7SDavid Majnemer     }
861236b0ca7SDavid Majnemer   }
8628e90adafSMichael J. Spencer 
863c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
8641c03389cSReid Kleckner   if (Error E = initImportTablePtr())
8651c03389cSReid Kleckner     return E;
8661c03389cSReid Kleckner   if (Error E = initDelayImportTablePtr())
8671c03389cSReid Kleckner     return E;
8681d6167fdSMichael J. Spencer 
869ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
8701c03389cSReid Kleckner   if (Error E = initExportTablePtr())
8711c03389cSReid Kleckner     return E;
872ad882ba8SRui Ueyama 
87374e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
8741c03389cSReid Kleckner   if (Error E = initBaseRelocPtr())
8751c03389cSReid Kleckner     return E;
87674e85130SRui Ueyama 
877568035acSLuqman Aden   // Initialize the pointer to the debug directory.
8781c03389cSReid Kleckner   if (Error E = initDebugDirectoryPtr())
8791c03389cSReid Kleckner     return E;
8802da433eaSReid Kleckner 
881568035acSLuqman Aden   // Initialize the pointer to the TLS directory.
882568035acSLuqman Aden   if (Error E = initTLSDirectoryPtr())
883568035acSLuqman Aden     return E;
884568035acSLuqman Aden 
8851c03389cSReid Kleckner   if (Error E = initLoadConfigPtr())
8861c03389cSReid Kleckner     return E;
887b7d716c0SReid Kleckner 
88839772063SReid Kleckner   return Error::success();
8898e90adafSMichael J. Spencer }
8908e90adafSMichael J. Spencer 
891435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8928ff24d25SRui Ueyama   DataRefImpl Ret;
89344f51e51SDavid Majnemer   Ret.p = getSymbolTable();
894f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8958e90adafSMichael J. Spencer }
8968e90adafSMichael J. Spencer 
897435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8988e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8998ff24d25SRui Ueyama   DataRefImpl Ret;
9008ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
901f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
9028e90adafSMichael J. Spencer }
9038e90adafSMichael J. Spencer 
904bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
905ad7b7e73SDavid Majnemer   if (!ImportDirectory)
906ad7b7e73SDavid Majnemer     return import_directory_end();
9071c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
908ad7b7e73SDavid Majnemer     return import_directory_end();
909a045b73aSRui Ueyama   return import_directory_iterator(
910a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
911c2bed429SRui Ueyama }
912c2bed429SRui Ueyama 
913bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
914a045b73aSRui Ueyama   return import_directory_iterator(
915ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
916c2bed429SRui Ueyama }
917c429b80dSDavid Meyer 
91815d99359SRui Ueyama delay_import_directory_iterator
91915d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
92015d99359SRui Ueyama   return delay_import_directory_iterator(
92115d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
92215d99359SRui Ueyama }
92315d99359SRui Ueyama 
92415d99359SRui Ueyama delay_import_directory_iterator
92515d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
92615d99359SRui Ueyama   return delay_import_directory_iterator(
92715d99359SRui Ueyama       DelayImportDirectoryEntryRef(
92815d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
92915d99359SRui Ueyama }
93015d99359SRui Ueyama 
931ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
932ad882ba8SRui Ueyama   return export_directory_iterator(
933ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
934ad882ba8SRui Ueyama }
935ad882ba8SRui Ueyama 
936ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
9372617dcceSCraig Topper   if (!ExportDirectory)
9382617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9398ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
940ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
9418ff24d25SRui Ueyama   return export_directory_iterator(Ref);
942ad882ba8SRui Ueyama }
943ad882ba8SRui Ueyama 
944b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
9458ff24d25SRui Ueyama   DataRefImpl Ret;
9468ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9478ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9488e90adafSMichael J. Spencer }
9498e90adafSMichael J. Spencer 
950b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
9518ff24d25SRui Ueyama   DataRefImpl Ret;
95244f51e51SDavid Majnemer   int NumSections =
95344f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9548ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9558ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9568e90adafSMichael J. Spencer }
9578e90adafSMichael J. Spencer 
95874e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
95974e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
96074e85130SRui Ueyama }
96174e85130SRui Ueyama 
96274e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
96374e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
96474e85130SRui Ueyama }
96574e85130SRui Ueyama 
9668e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
96743c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
9688e90adafSMichael J. Spencer }
9698e90adafSMichael J. Spencer 
9708e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
97144f51e51SDavid Majnemer   switch(getMachine()) {
9728e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9738e90adafSMichael J. Spencer     return "COFF-i386";
9748e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9758e90adafSMichael J. Spencer     return "COFF-x86-64";
9769b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9779b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
9781eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9791eff5c9cSMartell Malone     return "COFF-ARM64";
9808e90adafSMichael J. Spencer   default:
9818e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
9828e90adafSMichael J. Spencer   }
9838e90adafSMichael J. Spencer }
9848e90adafSMichael J. Spencer 
985260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
98644f51e51SDavid Majnemer   switch (getMachine()) {
9878e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9888e90adafSMichael J. Spencer     return Triple::x86;
9898e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9908e90adafSMichael J. Spencer     return Triple::x86_64;
9919b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9929b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9931eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9941eff5c9cSMartell Malone     return Triple::aarch64;
9958e90adafSMichael J. Spencer   default:
9968e90adafSMichael J. Spencer     return Triple::UnknownArch;
9978e90adafSMichael J. Spencer   }
9988e90adafSMichael J. Spencer }
9998e90adafSMichael J. Spencer 
1000d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
1001d2af4d6fSPaul Semel   if (PE32Header)
1002d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
1003d2af4d6fSPaul Semel   return 0;
1004d2af4d6fSPaul Semel }
1005d2af4d6fSPaul Semel 
1006979fb40bSRui Ueyama iterator_range<import_directory_iterator>
1007979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
1008979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
1009979fb40bSRui Ueyama }
1010979fb40bSRui Ueyama 
1011979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
1012979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
1013979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
1014979fb40bSRui Ueyama                     delay_import_directory_end());
1015979fb40bSRui Ueyama }
1016979fb40bSRui Ueyama 
1017979fb40bSRui Ueyama iterator_range<export_directory_iterator>
1018979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
1019979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
1020979fb40bSRui Ueyama }
1021979fb40bSRui Ueyama 
102274e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
102374e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
102474e85130SRui Ueyama }
102574e85130SRui Ueyama 
10261c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
10271c03389cSReid Kleckner   if (!DataDirectory)
10281c03389cSReid Kleckner     return nullptr;
102910ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
103010ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
103110ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
10321c03389cSReid Kleckner   if (Index >= NumEnt)
10331c03389cSReid Kleckner     return nullptr;
10341c03389cSReid Kleckner   return &DataDirectory[Index];
1035ed64342bSRui Ueyama }
1036ed64342bSRui Ueyama 
103777ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
103877ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
103977ecf90cSReid Kleckner   // but callers rely on this to return null.
1040236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
104177ecf90cSReid Kleckner     return (const coff_section *)nullptr;
1042236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10431d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
104477ecf90cSReid Kleckner     return SectionTable + (Index - 1);
10458e90adafSMichael J. Spencer   }
1046*6ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
1047*6ec18aafSMartin Storsjö                            "section index out of bounds");
1048236b0ca7SDavid Majnemer }
10498e90adafSMichael J. Spencer 
105077ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10511d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10521d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
1053*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed, "string table empty");
10548ff24d25SRui Ueyama   if (Offset >= StringTableSize)
105577ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
105677ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
10578e90adafSMichael J. Spencer }
1058022ecdf2SBenjamin Kramer 
105977ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
106077ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
1061e40d30f3SRui Ueyama }
1062e40d30f3SRui Ueyama 
106377ecf90cSReid Kleckner Expected<StringRef>
106477ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
106589a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
106677ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
106777ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
106889a7a5eaSMichael J. Spencer 
106989a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
107077ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
107177ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
107277ecf90cSReid Kleckner 
107389a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
107477ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
107589a7a5eaSMichael J. Spencer }
107689a7a5eaSMichael J. Spencer 
107744f51e51SDavid Majnemer ArrayRef<uint8_t>
107844f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10792617dcceSCraig Topper   const uint8_t *Aux = nullptr;
108071757ef3SMarshall Clow 
108144f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
108244f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
108371757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
108444f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
108571757ef3SMarshall Clow #ifndef NDEBUG
10868ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10878ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
108844f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
108944f51e51SDavid Majnemer         Offset >=
109044f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
109171757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
109271757ef3SMarshall Clow 
109344f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
109444f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
109571757ef3SMarshall Clow #endif
1096bfb85e67SMarshall Clow   }
109744f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
109871757ef3SMarshall Clow }
109971757ef3SMarshall Clow 
110074e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
110174e7d260SMartin Storsjo   uintptr_t Offset =
110274e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
110374e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
110474e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
110574e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
110674e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
110774e7d260SMartin Storsjo   return Index;
110874e7d260SMartin Storsjo }
110974e7d260SMartin Storsjo 
11108be28cdcSFangrui Song Expected<StringRef>
11118be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
111253c2d547SMichael J. Spencer   StringRef Name;
111344f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
111453c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
111553c2d547SMichael J. Spencer     Name = Sec->Name;
111653c2d547SMichael J. Spencer   else
111753c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
111844f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
111953c2d547SMichael J. Spencer 
112053c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
11212314b3deSDavid Majnemer   if (Name.startswith("/")) {
112253c2d547SMichael J. Spencer     uint32_t Offset;
11232314b3deSDavid Majnemer     if (Name.startswith("//")) {
11249d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
11258be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1126400b6c08Sserge-sans-paille                                  "invalid section name");
11279d2c15efSNico Rieck     } else {
112853c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
11298be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
11308be28cdcSFangrui Song                                  "invalid section name");
11319d2c15efSNico Rieck     }
113277ecf90cSReid Kleckner     return getString(Offset);
113353c2d547SMichael J. Spencer   }
113453c2d547SMichael J. Spencer 
11358be28cdcSFangrui Song   return Name;
113653c2d547SMichael J. Spencer }
113753c2d547SMichael J. Spencer 
1138a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1139a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1140a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1141a9ee5c06SDavid Majnemer   //
1142a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1143d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1144a9ee5c06SDavid Majnemer   //
1145a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1146a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1147a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1148a9ee5c06SDavid Majnemer   // considered to be zero.
1149d5297ee7SRui Ueyama   if (getDOSHeader())
1150d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1151d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1152a9ee5c06SDavid Majnemer }
1153a9ee5c06SDavid Majnemer 
1154e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11559da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1156e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1157e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1158e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1159e1cb2c0fSFangrui Song     return Error::success();
11609da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11619da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11629da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
116322cf54a7SArthur O'Dwyer   uintptr_t ConStart =
116422cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
1165a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1166e03a135bSReid Kleckner   if (Error E = checkOffset(Data, ConStart, SectionSize))
1167e03a135bSReid Kleckner     return E;
1168a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1169e1cb2c0fSFangrui Song   return Error::success();
11709da9e693SMichael J. Spencer }
11719da9e693SMichael J. Spencer 
1172022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1173e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1174022ecdf2SBenjamin Kramer }
11758ff24d25SRui Ueyama 
11765e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1177e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1178e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1179022ecdf2SBenjamin Kramer }
11808ff24d25SRui Ueyama 
118196d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
118258323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
118396d071cdSRafael Espindola   return R->VirtualAddress;
1184cbe72fc9SDanil Malyshev }
11858ff24d25SRui Ueyama 
1186806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1187022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11888ff24d25SRui Ueyama   DataRefImpl Ref;
1189236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1190236b0ca7SDavid Majnemer     return symbol_end();
119144f51e51SDavid Majnemer   if (SymbolTable16)
119244f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
119344f51e51SDavid Majnemer   else if (SymbolTable32)
119444f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
119544f51e51SDavid Majnemer   else
1196c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11978ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1198022ecdf2SBenjamin Kramer }
11998ff24d25SRui Ueyama 
120099c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1201022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
120299c041b7SRafael Espindola   return R->Type;
1203022ecdf2SBenjamin Kramer }
1204e5fd0047SMichael J. Spencer 
120527dc8394SAlexey Samsonov const coff_section *
120627dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
120727dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
120871757ef3SMarshall Clow }
120971757ef3SMarshall Clow 
121044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
121144f51e51SDavid Majnemer   if (SymbolTable16)
121244f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
121344f51e51SDavid Majnemer   if (SymbolTable32)
121444f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
121544f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
121644f51e51SDavid Majnemer }
121744f51e51SDavid Majnemer 
121844f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
121944f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
122071757ef3SMarshall Clow }
122171757ef3SMarshall Clow 
1222f12b8282SRafael Espindola const coff_relocation *
122327dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
122427dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1225d3e2a76cSMarshall Clow }
1226d3e2a76cSMarshall Clow 
12272f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
12286a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
12292f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
12302f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
12316a75acb1SRui Ueyama }
12326a75acb1SRui Ueyama 
123327dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
123427dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1235114ebf4aSMartin Storsjo     return #reloc_type;
1236e5fd0047SMichael J. Spencer 
1237114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
123844f51e51SDavid Majnemer   switch (getMachine()) {
1239e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1240114ebf4aSMartin Storsjo     switch (Type) {
1241e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1242e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1243e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1244e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1245e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1246e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1247e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1248e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1249e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1250e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1251e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1252e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1253e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1254e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1255e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1256e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1257e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1258e5fd0047SMichael J. Spencer     default:
1259114ebf4aSMartin Storsjo       return "Unknown";
1260e5fd0047SMichael J. Spencer     }
1261e5fd0047SMichael J. Spencer     break;
12625c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1263114ebf4aSMartin Storsjo     switch (Type) {
12645c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12655c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12665c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12675c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12685c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12695c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12705c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12715c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1272e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12735c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12745c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12755c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12765c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12775c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12785c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12795c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1280e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12815c503bf4SSaleem Abdulrasool     default:
1282114ebf4aSMartin Storsjo       return "Unknown";
12835c503bf4SSaleem Abdulrasool     }
12845c503bf4SSaleem Abdulrasool     break;
12850c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1286114ebf4aSMartin Storsjo     switch (Type) {
12870c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12880c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12890c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12900c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12910c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12920c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12930c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12940c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12950c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12960c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12970c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12980c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12990c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
13000c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
13010c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
13020c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
13030c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1304e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
13050c72172eSMandeep Singh Grang     default:
1306114ebf4aSMartin Storsjo       return "Unknown";
13070c72172eSMandeep Singh Grang     }
13080c72172eSMandeep Singh Grang     break;
1309e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1310114ebf4aSMartin Storsjo     switch (Type) {
1311e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1312e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1313e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1314e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1315e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1316e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1317e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1318e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1319e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1320e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1321e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1322e5fd0047SMichael J. Spencer     default:
1323114ebf4aSMartin Storsjo       return "Unknown";
1324e5fd0047SMichael J. Spencer     }
1325e5fd0047SMichael J. Spencer     break;
1326e5fd0047SMichael J. Spencer   default:
1327114ebf4aSMartin Storsjo     return "Unknown";
1328e5fd0047SMichael J. Spencer   }
1329e5fd0047SMichael J. Spencer }
1330e5fd0047SMichael J. Spencer 
1331e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1332e5fd0047SMichael J. Spencer 
1333114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1334114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1335114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1336114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1337114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1338114ebf4aSMartin Storsjo }
1339114ebf4aSMartin Storsjo 
1340c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1341c66d761bSRafael Espindola   return !DataDirectory;
1342c66d761bSRafael Espindola }
1343c66d761bSRafael Espindola 
1344e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1345e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1346e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1347e3093808SMartin Storsjo       .Default(Name);
1348e3093808SMartin Storsjo }
1349e3093808SMartin Storsjo 
1350c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1351c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1352a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1353c2bed429SRui Ueyama }
1354c2bed429SRui Ueyama 
13555e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13565e812afaSRafael Espindola   ++Index;
13571c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1358ad7b7e73SDavid Majnemer     Index = -1;
1359ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1360ad7b7e73SDavid Majnemer   }
1361c2bed429SRui Ueyama }
1362c2bed429SRui Ueyama 
13631c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry(
13641c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1365ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1366c2bed429SRui Ueyama }
1367c2bed429SRui Ueyama 
1368861021f9SRui Ueyama static imported_symbol_iterator
136915d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1370861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
137115d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1372861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
137315d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1374861021f9SRui Ueyama   }
1375861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
137615d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1377861021f9SRui Ueyama }
1378861021f9SRui Ueyama 
137915d99359SRui Ueyama static imported_symbol_iterator
138015d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1381861021f9SRui Ueyama   uintptr_t IntPtr = 0;
13821c03389cSReid Kleckner   // FIXME: Handle errors.
13831c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
138415d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1385861021f9SRui Ueyama }
1386861021f9SRui Ueyama 
138715d99359SRui Ueyama static imported_symbol_iterator
138815d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1389861021f9SRui Ueyama   uintptr_t IntPtr = 0;
13901c03389cSReid Kleckner   // FIXME: Handle errors.
13911c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
1392861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1393861021f9SRui Ueyama   int Index = 0;
139415d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1395861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1396861021f9SRui Ueyama     while (*Entry++)
1397861021f9SRui Ueyama       ++Index;
1398861021f9SRui Ueyama   } else {
1399861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1400861021f9SRui Ueyama     while (*Entry++)
1401861021f9SRui Ueyama       ++Index;
1402861021f9SRui Ueyama   }
140315d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
140415d99359SRui Ueyama }
140515d99359SRui Ueyama 
140615d99359SRui Ueyama imported_symbol_iterator
140715d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
140860049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
140915d99359SRui Ueyama                              OwningObject);
141015d99359SRui Ueyama }
141115d99359SRui Ueyama 
141215d99359SRui Ueyama imported_symbol_iterator
141315d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
141460049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
141515d99359SRui Ueyama                            OwningObject);
1416861021f9SRui Ueyama }
1417861021f9SRui Ueyama 
1418979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1419979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1420979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1421979fb40bSRui Ueyama }
1422979fb40bSRui Ueyama 
142360049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
142460049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
142560049526SDavid Majnemer                              OwningObject);
142660049526SDavid Majnemer }
142760049526SDavid Majnemer 
142860049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
142960049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
143060049526SDavid Majnemer                            OwningObject);
143160049526SDavid Majnemer }
143260049526SDavid Majnemer 
143360049526SDavid Majnemer iterator_range<imported_symbol_iterator>
143460049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
143560049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
143660049526SDavid Majnemer }
143760049526SDavid Majnemer 
14381c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
1439c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1440*6ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,
1441*6ec18aafSMartin Storsjö                                         "import directory name"))
14421c03389cSReid Kleckner     return E;
1443a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14441c03389cSReid Kleckner   return Error::success();
1445c2bed429SRui Ueyama }
1446c2bed429SRui Ueyama 
14471c03389cSReid Kleckner Error
14481e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14491e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14501c03389cSReid Kleckner   return Error::success();
14511e152d5eSRui Ueyama }
14521e152d5eSRui Ueyama 
14531c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14541c03389cSReid Kleckner     uint32_t &Result) const {
14551e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14561c03389cSReid Kleckner   return Error::success();
14571e152d5eSRui Ueyama }
14581e152d5eSRui Ueyama 
145915d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
146015d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
146115d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
146215d99359SRui Ueyama }
146315d99359SRui Ueyama 
146415d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
146515d99359SRui Ueyama   ++Index;
146615d99359SRui Ueyama }
146715d99359SRui Ueyama 
146815d99359SRui Ueyama imported_symbol_iterator
146915d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
147015d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
147115d99359SRui Ueyama                              OwningObject);
147215d99359SRui Ueyama }
147315d99359SRui Ueyama 
147415d99359SRui Ueyama imported_symbol_iterator
147515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
147615d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
147715d99359SRui Ueyama                            OwningObject);
147815d99359SRui Ueyama }
147915d99359SRui Ueyama 
1480979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1481979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1482979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1483979fb40bSRui Ueyama }
1484979fb40bSRui Ueyama 
14851c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
148615d99359SRui Ueyama   uintptr_t IntPtr = 0;
1487*6ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,
1488*6ec18aafSMartin Storsjö                                         "delay import directory name"))
14891c03389cSReid Kleckner     return E;
149015d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14911c03389cSReid Kleckner   return Error::success();
149215d99359SRui Ueyama }
149315d99359SRui Ueyama 
14941c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable(
14951c03389cSReid Kleckner     const delay_import_directory_table_entry *&Result) const {
14969f598ac7SJoseph Tremoulet   Result = &Table[Index];
14971c03389cSReid Kleckner   return Error::success();
14981af08658SRui Ueyama }
14991af08658SRui Ueyama 
15001c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
15011c03389cSReid Kleckner                                                      uint64_t &Result) const {
1502ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1503ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1504ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1505*6ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address"))
15061c03389cSReid Kleckner     return E;
1507ffa4cebeSRui Ueyama   if (OwningObject->is64())
15085dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1509ffa4cebeSRui Ueyama   else
15105dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
15111c03389cSReid Kleckner   return Error::success();
1512ffa4cebeSRui Ueyama }
1513ffa4cebeSRui Ueyama 
1514ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1515ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1516ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1517ad882ba8SRui Ueyama }
1518ad882ba8SRui Ueyama 
15195e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
15205e812afaSRafael Espindola   ++Index;
1521ad882ba8SRui Ueyama }
1522ad882ba8SRui Ueyama 
1523da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1524da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
15251c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1526da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1527*6ec18aafSMartin Storsjö   if (Error E =
1528*6ec18aafSMartin Storsjö           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name"))
15291c03389cSReid Kleckner     return E;
1530da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15311c03389cSReid Kleckner   return Error::success();
1532da49d0d4SRui Ueyama }
1533da49d0d4SRui Ueyama 
1534e5df6095SRui Ueyama // Returns the starting ordinal number.
15351c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1536e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15371c03389cSReid Kleckner   return Error::success();
1538e5df6095SRui Ueyama }
1539e5df6095SRui Ueyama 
1540ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
15411c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1542ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15431c03389cSReid Kleckner   return Error::success();
1544ad882ba8SRui Ueyama }
1545ad882ba8SRui Ueyama 
1546ad882ba8SRui Ueyama // Returns the address of the current export symbol.
15471c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1548ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1549*6ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,
1550*6ec18aafSMartin Storsjö                                          IntPtr, "export address"))
1551ad882ba8SRui Ueyama     return EC;
155224fc2d64SRui Ueyama   const export_address_table_entry *entry =
155324fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1554ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15551c03389cSReid Kleckner   return Error::success();
1556ad882ba8SRui Ueyama }
1557ad882ba8SRui Ueyama 
1558ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1559ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
15601c03389cSReid Kleckner Error
1561db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1562ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1563*6ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,
1564*6ec18aafSMartin Storsjö                                          "export ordinal table"))
1565ad882ba8SRui Ueyama     return EC;
1566ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1567ad882ba8SRui Ueyama 
1568ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1569ad882ba8SRui Ueyama   int Offset = 0;
1570ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1571ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1572ad882ba8SRui Ueyama     if (*I != Index)
1573ad882ba8SRui Ueyama       continue;
1574*6ec18aafSMartin Storsjö     if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,
1575*6ec18aafSMartin Storsjö                                            "export table entry"))
1576ad882ba8SRui Ueyama       return EC;
1577ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1578*6ec18aafSMartin Storsjö     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr,
1579*6ec18aafSMartin Storsjö                                            "export symbol name"))
1580ad882ba8SRui Ueyama       return EC;
1581ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15821c03389cSReid Kleckner     return Error::success();
1583ad882ba8SRui Ueyama   }
1584ad882ba8SRui Ueyama   Result = "";
15851c03389cSReid Kleckner   return Error::success();
1586ad882ba8SRui Ueyama }
1587ad882ba8SRui Ueyama 
15881c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15891c03389cSReid Kleckner   const data_directory *DataEntry =
15901c03389cSReid Kleckner       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
15911c03389cSReid Kleckner   if (!DataEntry)
1592*6ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
1593*6ec18aafSMartin Storsjö                              "export table missing");
15946161b38dSRui Ueyama   uint32_t RVA;
15956161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15966161b38dSRui Ueyama     return EC;
15976161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15986161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15996161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
16001c03389cSReid Kleckner   return Error::success();
16016161b38dSRui Ueyama }
16026161b38dSRui Ueyama 
16031c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
16046161b38dSRui Ueyama   uint32_t RVA;
16056161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
16066161b38dSRui Ueyama     return EC;
16076161b38dSRui Ueyama   uintptr_t IntPtr = 0;
1608*6ec18aafSMartin Storsjö   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target"))
16096161b38dSRui Ueyama     return EC;
16106161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16111c03389cSReid Kleckner   return Error::success();
16126161b38dSRui Ueyama }
16136161b38dSRui Ueyama 
1614861021f9SRui Ueyama bool ImportedSymbolRef::
1615861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1616861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1617861021f9SRui Ueyama       && Index == Other.Index;
1618861021f9SRui Ueyama }
1619861021f9SRui Ueyama 
1620861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1621861021f9SRui Ueyama   ++Index;
1622861021f9SRui Ueyama }
1623861021f9SRui Ueyama 
16241c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1625861021f9SRui Ueyama   uint32_t RVA;
1626861021f9SRui Ueyama   if (Entry32) {
1627861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1628861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
16291c03389cSReid Kleckner       return Error::success();
1630861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1631861021f9SRui Ueyama   } else {
1632861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
16331c03389cSReid Kleckner       return Error::success();
1634861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1635861021f9SRui Ueyama   }
1636861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1637*6ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name"))
1638861021f9SRui Ueyama     return EC;
1639861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1640861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16411c03389cSReid Kleckner   return Error::success();
1642861021f9SRui Ueyama }
1643861021f9SRui Ueyama 
16441c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const {
1645ad7b7e73SDavid Majnemer   if (Entry32)
1646ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1647ad7b7e73SDavid Majnemer   else
1648ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
16491c03389cSReid Kleckner   return Error::success();
1650ad7b7e73SDavid Majnemer }
1651ad7b7e73SDavid Majnemer 
16521c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1653ad7b7e73SDavid Majnemer   if (Entry32)
1654ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1655ad7b7e73SDavid Majnemer   else
1656ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
16571c03389cSReid Kleckner   return Error::success();
1658ad7b7e73SDavid Majnemer }
1659ad7b7e73SDavid Majnemer 
16601c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1661861021f9SRui Ueyama   uint32_t RVA;
1662861021f9SRui Ueyama   if (Entry32) {
1663861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1664861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16651c03389cSReid Kleckner       return Error::success();
1666861021f9SRui Ueyama     }
1667861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1668861021f9SRui Ueyama   } else {
1669861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1670861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16711c03389cSReid Kleckner       return Error::success();
1672861021f9SRui Ueyama     }
1673861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1674861021f9SRui Ueyama   }
1675861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1676*6ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal"))
1677861021f9SRui Ueyama     return EC;
1678861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16791c03389cSReid Kleckner   return Error::success();
1680861021f9SRui Ueyama }
1681861021f9SRui Ueyama 
168212db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
168348af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
168439772063SReid Kleckner   return COFFObjectFile::create(Object);
1685686738e2SRui Ueyama }
168674e85130SRui Ueyama 
168774e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
168874e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
168974e85130SRui Ueyama }
169074e85130SRui Ueyama 
169174e85130SRui Ueyama void BaseRelocRef::moveNext() {
169274e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
169374e85130SRui Ueyama   // size of the header itself.
169474e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1695970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
169674e85130SRui Ueyama   if (Size == Header->BlockSize) {
169774e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
169874e85130SRui Ueyama     // consists of the header followed by entries. The header contains
169974e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
170074e85130SRui Ueyama     // current block, proceed to the next block.
170174e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
170274e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
170374e85130SRui Ueyama     Index = 0;
170474e85130SRui Ueyama   } else {
170574e85130SRui Ueyama     ++Index;
170674e85130SRui Ueyama   }
170774e85130SRui Ueyama }
170874e85130SRui Ueyama 
17091c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const {
171074e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
171174e85130SRui Ueyama   Type = Entry[Index].getType();
17121c03389cSReid Kleckner   return Error::success();
171374e85130SRui Ueyama }
171474e85130SRui Ueyama 
17151c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const {
171674e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
171774e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
17181c03389cSReid Kleckner   return Error::success();
171974e85130SRui Ueyama }
1720efef15a0SEric Beckmann 
1721357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1722357a40ecSMartin Storsjo   do {                                                                         \
1723357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
172487867988SRafael Espindola     if (E)                                                                     \
1725c55cf4afSBill Wendling       return std::move(E);                                                     \
1726357a40ecSMartin Storsjo   } while (0)
1727efef15a0SEric Beckmann 
172887867988SRafael Espindola Expected<ArrayRef<UTF16>>
172987867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1730efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1731efef15a0SEric Beckmann   Reader.setOffset(Offset);
1732efef15a0SEric Beckmann   uint16_t Length;
1733efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1734efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1735efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1736cd704cb6SEric Beckmann   return RawDirString;
1737efef15a0SEric Beckmann }
1738efef15a0SEric Beckmann 
1739f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1740efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1741f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1742efef15a0SEric Beckmann }
1743efef15a0SEric Beckmann 
174487867988SRafael Espindola Expected<const coff_resource_dir_table &>
1745efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1746efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1747efef15a0SEric Beckmann 
1748efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1749efef15a0SEric Beckmann   Reader.setOffset(Offset);
1750efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1751efef15a0SEric Beckmann   assert(Table != nullptr);
1752efef15a0SEric Beckmann   return *Table;
1753efef15a0SEric Beckmann }
1754efef15a0SEric Beckmann 
1755edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1756edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1757edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1758edb6ab9bSMartin Storsjo 
1759edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1760edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1761edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1762edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1763edb6ab9bSMartin Storsjo   return *Entry;
1764edb6ab9bSMartin Storsjo }
1765edb6ab9bSMartin Storsjo 
17667ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17677ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17687ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
17697ba81d95SMartin Storsjo 
17707ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
17717ba81d95SMartin Storsjo   Reader.setOffset(Offset);
17727ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
17737ba81d95SMartin Storsjo   assert(Entry != nullptr);
17747ba81d95SMartin Storsjo   return *Entry;
17757ba81d95SMartin Storsjo }
17767ba81d95SMartin Storsjo 
1777f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1778efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17797ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1780f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1781efef15a0SEric Beckmann }
1782efef15a0SEric Beckmann 
17837ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17847ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17857ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
17867ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
17877ba81d95SMartin Storsjo }
17887ba81d95SMartin Storsjo 
1789f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1790f3404674SRafael Espindola   return getTableAtOffset(0);
1791efef15a0SEric Beckmann }
1792edb6ab9bSMartin Storsjo 
1793edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1794edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1795edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1796edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1797edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1798edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1799edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1800edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1801edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1802edb6ab9bSMartin Storsjo }
180394382217SMartin Storsjo 
180494382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
180594382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
180694382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
180794382217SMartin Storsjo     if (!Name)
180894382217SMartin Storsjo       return Name.takeError();
180994382217SMartin Storsjo 
181094382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
181194382217SMartin Storsjo       return load(O, S);
181294382217SMartin Storsjo   }
181394382217SMartin Storsjo   return createStringError(object_error::parse_failed,
181494382217SMartin Storsjo                            "no resource section found");
181594382217SMartin Storsjo }
181694382217SMartin Storsjo 
181794382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
181894382217SMartin Storsjo   Obj = O;
181994382217SMartin Storsjo   Section = S;
182094382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
182194382217SMartin Storsjo   if (!Contents)
182294382217SMartin Storsjo     return Contents.takeError();
182394382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
182494382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
182594382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
182694382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
182794382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
182894382217SMartin Storsjo     Relocs.push_back(&R);
1829352fcfc6SKazu Hirata   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
183094382217SMartin Storsjo     return A->VirtualAddress < B->VirtualAddress;
183194382217SMartin Storsjo   });
183294382217SMartin Storsjo   return Error::success();
183394382217SMartin Storsjo }
183494382217SMartin Storsjo 
183594382217SMartin Storsjo Expected<StringRef>
183694382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
183794382217SMartin Storsjo   if (!Obj)
183894382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
183994382217SMartin Storsjo 
184094382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
184194382217SMartin Storsjo   // the coff_resource_data_entry struct).
184294382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
184394382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
184494382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
184594382217SMartin Storsjo                               ulittle16_t(0)};
184694382217SMartin Storsjo   auto RelocsForOffset =
184794382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
184894382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
184994382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
185094382217SMartin Storsjo                        });
185194382217SMartin Storsjo 
185294382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
185394382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
185494382217SMartin Storsjo     // the expected type.
185594382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
185694382217SMartin Storsjo     uint16_t RVAReloc;
185794382217SMartin Storsjo     switch (Obj->getMachine()) {
185894382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
185994382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
186094382217SMartin Storsjo       break;
186194382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
186294382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
186394382217SMartin Storsjo       break;
186494382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
186594382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
186694382217SMartin Storsjo       break;
186794382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
186894382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
186994382217SMartin Storsjo       break;
187094382217SMartin Storsjo     default:
187194382217SMartin Storsjo       return createStringError(object_error::parse_failed,
187294382217SMartin Storsjo                                "unsupported architecture");
187394382217SMartin Storsjo     }
187494382217SMartin Storsjo     if (R.Type != RVAReloc)
187594382217SMartin Storsjo       return createStringError(object_error::parse_failed,
187694382217SMartin Storsjo                                "unexpected relocation type");
187794382217SMartin Storsjo     // Get the relocation's symbol
187894382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
187994382217SMartin Storsjo     if (!Sym)
188094382217SMartin Storsjo       return Sym.takeError();
188194382217SMartin Storsjo     // And the symbol's section
188277ecf90cSReid Kleckner     Expected<const coff_section *> Section =
188377ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
188477ecf90cSReid Kleckner     if (!Section)
188577ecf90cSReid Kleckner       return Section.takeError();
188694382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
188794382217SMartin Storsjo     // data it points at.
188894382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
188994382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
189077ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1891c55cf4afSBill Wendling       return std::move(E);
189294382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
189394382217SMartin Storsjo       return createStringError(object_error::parse_failed,
189494382217SMartin Storsjo                                "data outside of section");
189594382217SMartin Storsjo     // Return a reference to the data inside the section.
189694382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
189794382217SMartin Storsjo                      Entry.DataSize);
189894382217SMartin Storsjo   } else {
189994382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
190094382217SMartin Storsjo     if (Obj->isRelocatableObject())
190194382217SMartin Storsjo       return createStringError(object_error::parse_failed,
190294382217SMartin Storsjo                                "no relocation found for DataRVA");
190394382217SMartin Storsjo 
190494382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
190594382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
190694382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
190794382217SMartin Storsjo       if (VA >= S.getAddress() &&
190894382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
190994382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
191094382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
191194382217SMartin Storsjo         if (!Contents)
191294382217SMartin Storsjo           return Contents.takeError();
191394382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
191494382217SMartin Storsjo       }
191594382217SMartin Storsjo     }
191694382217SMartin Storsjo     return createStringError(object_error::parse_failed,
191794382217SMartin Storsjo                              "address not found in image");
191894382217SMartin Storsjo   }
191994382217SMartin Storsjo }
1920