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.
checkSize(MemoryBufferRef M,std::error_code & EC,uint64_t Size)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>
getObject(const T * & Obj,MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (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.
decodeBase64StringEntry(StringRef Str,uint32_t & Result)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>
toSymb(DataRefImpl Ref) const10244f51e51SDavid 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 
toSec(DataRefImpl Ref) const1198ff24d25SRui 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 
moveSymbolNext(DataRefImpl & Ref) const1365e812afaSRafael 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 
getSymbolName(DataRefImpl Ref) const15181e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15277ecf90cSReid Kleckner   return getSymbolName(getCOFFSymbol(Ref));
1538e90adafSMichael J. Spencer }
1548e90adafSMichael J. Spencer 
getSymbolValueImpl(DataRefImpl Ref) const155be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
156be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
157991af666SRafael Espindola }
158991af666SRafael Espindola 
getSymbolAlignment(DataRefImpl Ref) const1596b2bba14SDavide 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 
getSymbolAddress(DataRefImpl Ref) const166931cb65dSKevin 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 
getSymbolType(DataRefImpl Ref) const1877bd8d994SKevin 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 
getSymbolFlags(DataRefImpl Ref) const210ac00376aSvgxbj 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 
getCommonSymbolSizeImpl(DataRefImpl Ref) const241d7a32ea4SRafael 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>
getSymbolSection(DataRefImpl Ref) const2478bab889bSRafael 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 
getSymbolSectionID(SymbolRef Sym) const2596bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2606bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2616bf32210SRafael Espindola   return Symb.getSectionNumber();
2626bf32210SRafael Espindola }
2636bf32210SRafael Espindola 
moveSectionNext(DataRefImpl & Ref) const2645e812afaSRafael 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 
getSectionName(DataRefImpl Ref) const2708be28cdcSFangrui 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 
getSectionAddress(DataRefImpl Ref) const27580291274SRafael 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 
getSectionIndex(DataRefImpl Sec) const285a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
286a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
287a25d329bSGeorge Rimar }
288a25d329bSGeorge Rimar 
getSectionSize(DataRefImpl Ref) const28980291274SRafael 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>>
getSectionContents(DataRefImpl Ref) const294e1cb2c0fSFangrui 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 
getSectionAlignment(DataRefImpl Ref) const30280291274SRafael 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 
isSectionCompressed(DataRefImpl Sec) const307401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
308401e4e57SGeorge Rimar   return false;
309401e4e57SGeorge Rimar }
310401e4e57SGeorge Rimar 
isSectionText(DataRefImpl Ref) const31180291274SRafael 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 
isSectionData(DataRefImpl Ref) const31680291274SRafael 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 
isSectionBSS(DataRefImpl Ref) const32180291274SRafael 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).
isDebugSection(DataRefImpl Ref) const331bf809cd1SEsme-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 
getSectionID(SectionRef Sec) const3426bf32210SRafael 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 
isSectionVirtual(DataRefImpl Ref) const34980291274SRafael 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 
getNumberOfRelocations(const coff_section * Sec,MemoryBufferRef M,const uint8_t * base)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 *
getFirstReloc(const coff_section * Sec,MemoryBufferRef M,const uint8_t * Base)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 
section_rel_begin(DataRefImpl Ref) const39694751be7SDavid 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 
section_rel_end(DataRefImpl Ref) const4068ff24d25SRui 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.
initSymbolTablePtr()4171c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() {
41844f51e51SDavid Majnemer   if (COFFHeader)
4191c03389cSReid Kleckner     if (Error E = getObject(
420236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
421236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4221c03389cSReid Kleckner       return E;
42344f51e51SDavid Majnemer 
42444f51e51SDavid Majnemer   if (COFFBigObjHeader)
4251c03389cSReid Kleckner     if (Error E = getObject(
426236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
427236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4281c03389cSReid Kleckner       return E;
429c2bed429SRui Ueyama 
430c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
431c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
432c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
433f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
43444f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
435f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
436c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
4371c03389cSReid Kleckner   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4381c03389cSReid Kleckner     return E;
439c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
4401c03389cSReid Kleckner   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4411c03389cSReid Kleckner     return E;
442c2bed429SRui Ueyama 
443773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
444773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
445773a5795SNico Rieck   if (StringTableSize < 4)
446773a5795SNico Rieck     StringTableSize = 4;
447773a5795SNico Rieck 
448c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
449773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
4506ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
4516ec18aafSMartin Storsjö                              "string table missing null terminator");
4521c03389cSReid Kleckner   return Error::success();
453c2bed429SRui Ueyama }
454c2bed429SRui Ueyama 
getImageBase() const45521427adaSReid 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.
getVaPtr(uint64_t Addr,uintptr_t & Res) const4651c03389cSReid 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.
getRvaPtr(uint32_t Addr,uintptr_t & Res,const char * ErrorContext) const4736ec18aafSMartin Storsjö Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,
4746ec18aafSMartin Storsjö                                 const char *ErrorContext) const {
47527dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
47627dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
477c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
478c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
479215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
480bb94611dSAlvin Wong       // A table/directory entry can be pointing to somewhere in a stripped
481bb94611dSAlvin Wong       // section, in an object that went through `objcopy --only-keep-debug`.
482bb94611dSAlvin Wong       // In this case we don't want to cause the parsing of the object file to
483bb94611dSAlvin Wong       // fail, otherwise it will be impossible to use this object as debug info
484bb94611dSAlvin Wong       // in LLDB. Return SectionStrippedError here so that
485bb94611dSAlvin Wong       // COFFObjectFile::initialize can ignore the error.
486b209b9e1SMartin Storsjö       // Somewhat common binaries may have RVAs pointing outside of the
487b209b9e1SMartin Storsjö       // provided raw data. Instead of rejecting the binaries, just
488b209b9e1SMartin Storsjö       // treat the section as stripped for these purposes.
489bb94611dSAlvin Wong       if (Section->SizeOfRawData < Section->VirtualSize &&
490bb94611dSAlvin Wong           Addr >= SectionStart + Section->SizeOfRawData) {
491b209b9e1SMartin Storsjö         return make_error<SectionStrippedError>();
492bb94611dSAlvin Wong       }
493215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
49422cf54a7SArthur O'Dwyer       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
49522cf54a7SArthur O'Dwyer             Offset;
4961c03389cSReid Kleckner       return Error::success();
497c2bed429SRui Ueyama     }
498c2bed429SRui Ueyama   }
4996ec18aafSMartin Storsjö   if (ErrorContext)
5006ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
5016ec18aafSMartin Storsjö                              "RVA 0x%" PRIx32 " for %s not found", Addr,
5026ec18aafSMartin Storsjö                              ErrorContext);
5036ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
5046ec18aafSMartin Storsjö                            "RVA 0x%" PRIx32 " not found", Addr);
505c2bed429SRui Ueyama }
506c2bed429SRui Ueyama 
getRvaAndSizeAsBytes(uint32_t RVA,uint32_t Size,ArrayRef<uint8_t> & Contents,const char * ErrorContext) const5071c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
5086ec18aafSMartin Storsjö                                            ArrayRef<uint8_t> &Contents,
5096ec18aafSMartin Storsjö                                            const char *ErrorContext) const {
5102da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
5112da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
5122da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
5132da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
5142da433eaSReid Kleckner     // overflow.
5152da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
5162da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
5172da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
51822cf54a7SArthur O'Dwyer       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
51922cf54a7SArthur O'Dwyer                         Section->PointerToRawData + OffsetIntoSection;
5202da433eaSReid Kleckner       Contents =
5212da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5221c03389cSReid Kleckner       return Error::success();
5232da433eaSReid Kleckner     }
5242da433eaSReid Kleckner   }
5256ec18aafSMartin Storsjö   if (ErrorContext)
5266ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
5276ec18aafSMartin Storsjö                              "RVA 0x%" PRIx32 " for %s not found", RVA,
5286ec18aafSMartin Storsjö                              ErrorContext);
5296ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
5306ec18aafSMartin Storsjö                            "RVA 0x%" PRIx32 " not found", RVA);
5312da433eaSReid Kleckner }
5322da433eaSReid Kleckner 
533c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
534c2bed429SRui Ueyama // table entry.
getHintName(uint32_t Rva,uint16_t & Hint,StringRef & Name) const5351c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
536db4ed0bdSRafael Espindola                                   StringRef &Name) const {
537c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5381c03389cSReid Kleckner   if (Error E = getRvaPtr(Rva, IntPtr))
5391c03389cSReid Kleckner     return E;
540c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
541c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
542c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5431c03389cSReid Kleckner   return Error::success();
544c2bed429SRui Ueyama }
545c2bed429SRui Ueyama 
getDebugPDBInfo(const debug_directory * DebugDir,const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const5461c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
54701528021SSaleem Abdulrasool                                       const codeview::DebugInfo *&PDBInfo,
5482da433eaSReid Kleckner                                       StringRef &PDBFileName) const {
5492da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5506ec18aafSMartin Storsjö   if (Error E =
5516ec18aafSMartin Storsjö           getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData,
5526ec18aafSMartin Storsjö                                InfoBytes, "PDB info"))
5531c03389cSReid Kleckner     return E;
55401528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5556ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed, "PDB info too small");
55601528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
55701528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5582da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5592da433eaSReid Kleckner                           InfoBytes.size());
5602da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5612da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5621c03389cSReid Kleckner   return Error::success();
5632da433eaSReid Kleckner }
5642da433eaSReid Kleckner 
getDebugPDBInfo(const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const5651c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
566f27f3f84SReid Kleckner                                       StringRef &PDBFileName) const {
567f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
568f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
569f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
570f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
571f27f3f84SReid Kleckner   PDBInfo = nullptr;
572f27f3f84SReid Kleckner   PDBFileName = StringRef();
5731c03389cSReid Kleckner   return Error::success();
574f27f3f84SReid Kleckner }
575f27f3f84SReid Kleckner 
576c2bed429SRui Ueyama // Find the import table.
initImportTablePtr()5771c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() {
578c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
579c2bed429SRui Ueyama   // the import table, do nothing.
5801c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5811c03389cSReid Kleckner   if (!DataEntry)
5821c03389cSReid Kleckner     return Error::success();
583c2bed429SRui Ueyama 
584c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
585c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5861c03389cSReid Kleckner     return Error::success();
587c2bed429SRui Ueyama 
588c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
589c2bed429SRui Ueyama 
590c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
591c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
592c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5936ec18aafSMartin Storsjö   if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table"))
5941c03389cSReid Kleckner     return E;
595e03a135bSReid Kleckner   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5961c03389cSReid Kleckner     return E;
597c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5981c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5991c03389cSReid Kleckner   return Error::success();
600ad882ba8SRui Ueyama }
601c2bed429SRui Ueyama 
60215d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
initDelayImportTablePtr()6031c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() {
6041c03389cSReid Kleckner   const data_directory *DataEntry =
6051c03389cSReid Kleckner       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
6061c03389cSReid Kleckner   if (!DataEntry)
6071c03389cSReid Kleckner     return Error::success();
60815d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6091c03389cSReid Kleckner     return Error::success();
61015d99359SRui Ueyama 
61115d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
61215d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
61315d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
61415d99359SRui Ueyama 
61515d99359SRui Ueyama   uintptr_t IntPtr = 0;
6166ec18aafSMartin Storsjö   if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))
6171c03389cSReid Kleckner     return E;
618bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
619bb94611dSAlvin Wong     return E;
620bb94611dSAlvin Wong 
62115d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
62215d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
6231c03389cSReid Kleckner   return Error::success();
62415d99359SRui Ueyama }
62515d99359SRui Ueyama 
626ad882ba8SRui Ueyama // Find the export table.
initExportTablePtr()6271c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() {
628ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
629ad882ba8SRui Ueyama   // the export table, do nothing.
6301c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6311c03389cSReid Kleckner   if (!DataEntry)
6321c03389cSReid Kleckner     return Error::success();
633ad882ba8SRui Ueyama 
634ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
635ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6361c03389cSReid Kleckner     return Error::success();
637ad882ba8SRui Ueyama 
638ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
639ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
6406ec18aafSMartin Storsjö   if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))
6411c03389cSReid Kleckner     return E;
642bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
643bb94611dSAlvin Wong     return E;
644bb94611dSAlvin Wong 
64524fc2d64SRui Ueyama   ExportDirectory =
64624fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6471c03389cSReid Kleckner   return Error::success();
648c2bed429SRui Ueyama }
649c2bed429SRui Ueyama 
initBaseRelocPtr()6501c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() {
6511c03389cSReid Kleckner   const data_directory *DataEntry =
6521c03389cSReid Kleckner       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6531c03389cSReid Kleckner   if (!DataEntry)
6541c03389cSReid Kleckner     return Error::success();
65574e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6561c03389cSReid Kleckner     return Error::success();
65774e85130SRui Ueyama 
65874e85130SRui Ueyama   uintptr_t IntPtr = 0;
6596ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
6606ec18aafSMartin Storsjö                           "base reloc table"))
6611c03389cSReid Kleckner     return E;
662bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
663bb94611dSAlvin Wong     return E;
664bb94611dSAlvin Wong 
66574e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
66674e85130SRui Ueyama       IntPtr);
66774e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
66874e85130SRui Ueyama       IntPtr + DataEntry->Size);
669893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
670893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6711c03389cSReid Kleckner   return Error::success();
67274e85130SRui Ueyama }
67374e85130SRui Ueyama 
initDebugDirectoryPtr()6741c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() {
6752da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6761c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6771c03389cSReid Kleckner   if (!DataEntry)
6781c03389cSReid Kleckner     return Error::success();
6792da433eaSReid Kleckner 
6802da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6812da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6821c03389cSReid Kleckner     return Error::success();
6832da433eaSReid Kleckner 
6842da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6852da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6866ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
6876ec18aafSMartin Storsjö                              "debug directory has uneven size");
6882da433eaSReid Kleckner 
6892da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6906ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
6916ec18aafSMartin Storsjö                           "debug directory"))
6921c03389cSReid Kleckner     return E;
693bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
694bb94611dSAlvin Wong     return E;
695bb94611dSAlvin Wong 
6962da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
697893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
698893c6469SNico Weber       IntPtr + DataEntry->Size);
699893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
700893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
7011c03389cSReid Kleckner   return Error::success();
7022da433eaSReid Kleckner }
7032da433eaSReid Kleckner 
initTLSDirectoryPtr()704568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() {
705568035acSLuqman Aden   // Get the RVA of the TLS directory. Do nothing if it does not exist.
706568035acSLuqman Aden   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
707568035acSLuqman Aden   if (!DataEntry)
708568035acSLuqman Aden     return Error::success();
709568035acSLuqman Aden 
710568035acSLuqman Aden   // Do nothing if the RVA is NULL.
711568035acSLuqman Aden   if (DataEntry->RelativeVirtualAddress == 0)
712568035acSLuqman Aden     return Error::success();
713568035acSLuqman Aden 
714568035acSLuqman Aden   uint64_t DirSize =
715568035acSLuqman Aden       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
716568035acSLuqman Aden 
717568035acSLuqman Aden   // Check that the size is correct.
718568035acSLuqman Aden   if (DataEntry->Size != DirSize)
719568035acSLuqman Aden     return createStringError(
720568035acSLuqman Aden         object_error::parse_failed,
7212980ce98SHubert Tong         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
722568035acSLuqman Aden         static_cast<uint32_t>(DataEntry->Size), DirSize);
723568035acSLuqman Aden 
724568035acSLuqman Aden   uintptr_t IntPtr = 0;
7256ec18aafSMartin Storsjö   if (Error E =
7266ec18aafSMartin Storsjö           getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))
727568035acSLuqman Aden     return E;
728bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
729bb94611dSAlvin Wong     return E;
730568035acSLuqman Aden 
731568035acSLuqman Aden   if (is64())
732568035acSLuqman Aden     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
733568035acSLuqman Aden   else
734568035acSLuqman Aden     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
735568035acSLuqman Aden 
736568035acSLuqman Aden   return Error::success();
737568035acSLuqman Aden }
738568035acSLuqman Aden 
initLoadConfigPtr()7391c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() {
740b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
7411c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
7421c03389cSReid Kleckner   if (!DataEntry)
7431c03389cSReid Kleckner     return Error::success();
744b7d716c0SReid Kleckner 
745b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
746b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
7471c03389cSReid Kleckner     return Error::success();
748b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
7496ec18aafSMartin Storsjö   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
7506ec18aafSMartin Storsjö                           "load config table"))
7511c03389cSReid Kleckner     return E;
752bb94611dSAlvin Wong   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
753bb94611dSAlvin Wong     return E;
754b7d716c0SReid Kleckner 
755b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
7561c03389cSReid Kleckner   return Error::success();
757b7d716c0SReid Kleckner }
758b7d716c0SReid Kleckner 
75939772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>>
create(MemoryBufferRef Object)76039772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) {
76139772063SReid Kleckner   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
76239772063SReid Kleckner   if (Error E = Obj->initialize())
76339772063SReid Kleckner     return std::move(E);
76439772063SReid Kleckner   return std::move(Obj);
76539772063SReid Kleckner }
76639772063SReid Kleckner 
COFFObjectFile(MemoryBufferRef Object)76739772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
76848af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
76944f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
77044f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
77144f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
77239772063SReid Kleckner       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
77339772063SReid Kleckner       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
77439772063SReid Kleckner       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
775568035acSLuqman Aden       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
776568035acSLuqman Aden       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
77739772063SReid Kleckner 
ignoreStrippedErrors(Error E)778bb94611dSAlvin Wong static Error ignoreStrippedErrors(Error E) {
779bb94611dSAlvin Wong   if (E.isA<SectionStrippedError>()) {
780bb94611dSAlvin Wong     consumeError(std::move(E));
781bb94611dSAlvin Wong     return Error::success();
782bb94611dSAlvin Wong   }
7833a252806SBenjamin Kramer   return E;
784bb94611dSAlvin Wong }
785bb94611dSAlvin Wong 
initialize()786101fbc01SNico Weber Error COFFObjectFile::initialize() {
7871d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
78839772063SReid Kleckner   std::error_code EC;
78948af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
79039772063SReid Kleckner     return errorCodeToError(EC);
791ee066fc4SEric Christopher 
79282ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
79382ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
79482ebd8e3SRui Ueyama 
79582ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
79682ebd8e3SRui Ueyama   // it is placed right after COFF header.
7978ff24d25SRui Ueyama   bool HasPEHeader = false;
798ee066fc4SEric Christopher 
7991d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
80050267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
801ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
802ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
80350267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
80450267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
80550267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
80682ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
80750267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
8086ec18aafSMartin Storsjö         return createStringError(object_error::parse_failed,
8096ec18aafSMartin Storsjö                                  "incorrect PE magic");
8101d6167fdSMichael J. Spencer       }
81144f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
8128ff24d25SRui Ueyama       HasPEHeader = true;
813ee066fc4SEric Christopher     }
81450267222SDavid Majnemer   }
815ee066fc4SEric Christopher 
8161c03389cSReid Kleckner   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
8171c03389cSReid Kleckner     return E;
81844f51e51SDavid Majnemer 
81944f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
82044f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
82144f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
82244f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
82344f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
8241c03389cSReid Kleckner     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
8251c03389cSReid Kleckner       return E;
82644f51e51SDavid Majnemer 
82744f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
82844f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
82944f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
83044f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
83144f51e51SDavid Majnemer       COFFHeader = nullptr;
83244f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
83344f51e51SDavid Majnemer     } else {
83444f51e51SDavid Majnemer       // It's not a bigobj.
83544f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
83644f51e51SDavid Majnemer     }
83744f51e51SDavid Majnemer   }
83844f51e51SDavid Majnemer   if (COFFHeader) {
83944f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
84044f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
8417d099195SRui Ueyama     EC = std::error_code();
84282ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
84382ebd8e3SRui Ueyama 
84444f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
84539772063SReid Kleckner       return errorCodeToError(EC);
84644f51e51SDavid Majnemer   }
84744f51e51SDavid Majnemer 
8488ff24d25SRui Ueyama   if (HasPEHeader) {
84910ed9ddcSRui Ueyama     const pe32_header *Header;
8501c03389cSReid Kleckner     if (Error E = getObject(Header, Data, base() + CurPtr))
8511c03389cSReid Kleckner       return E;
85210ed9ddcSRui Ueyama 
85310ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
85410ed9ddcSRui Ueyama     uint64_t DataDirSize;
85550267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
85610ed9ddcSRui Ueyama       PE32Header = Header;
85710ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
85810ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
85950267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
86010ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
86110ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
86210ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
86310ed9ddcSRui Ueyama     } else {
86410ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
8656ec18aafSMartin Storsjö       return createStringError(object_error::parse_failed,
8666ec18aafSMartin Storsjö                                "incorrect PE magic");
867ed64342bSRui Ueyama     }
8681c03389cSReid Kleckner     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8691c03389cSReid Kleckner       return E;
870f53c8cb4SRui Ueyama   }
871776c6828SRui Ueyama 
8728950a538SRui Ueyama   if (COFFHeader)
8738950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
8748950a538SRui Ueyama 
8751c03389cSReid Kleckner   assert(COFFHeader || COFFBigObjHeader);
8761c03389cSReid Kleckner 
8771c03389cSReid Kleckner   if (Error E =
8781c03389cSReid Kleckner           getObject(SectionTable, Data, base() + CurPtr,
8791c03389cSReid Kleckner                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8801c03389cSReid Kleckner     return E;
8811d6167fdSMichael J. Spencer 
882c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
883236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
8841c03389cSReid Kleckner     if (Error E = initSymbolTablePtr()) {
8851c03389cSReid Kleckner       // Recover from errors reading the symbol table.
8861c03389cSReid Kleckner       consumeError(std::move(E));
887ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
888ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
889ac8cfab5SDavid Majnemer       StringTable = nullptr;
890ac8cfab5SDavid Majnemer       StringTableSize = 0;
891ac8cfab5SDavid Majnemer     }
892236b0ca7SDavid Majnemer   } else {
893236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
894236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
8956ec18aafSMartin Storsjö       return createStringError(object_error::parse_failed,
8966ec18aafSMartin Storsjö                                "symbol table missing");
897236b0ca7SDavid Majnemer     }
898236b0ca7SDavid Majnemer   }
8998e90adafSMichael J. Spencer 
900c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
901bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initImportTablePtr()))
9021c03389cSReid Kleckner     return E;
903bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initDelayImportTablePtr()))
9041c03389cSReid Kleckner     return E;
9051d6167fdSMichael J. Spencer 
906ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
907bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initExportTablePtr()))
9081c03389cSReid Kleckner     return E;
909ad882ba8SRui Ueyama 
91074e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
911bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initBaseRelocPtr()))
9121c03389cSReid Kleckner     return E;
91374e85130SRui Ueyama 
914568035acSLuqman Aden   // Initialize the pointer to the debug directory.
915bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr()))
9161c03389cSReid Kleckner     return E;
9172da433eaSReid Kleckner 
918568035acSLuqman Aden   // Initialize the pointer to the TLS directory.
919bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr()))
920568035acSLuqman Aden     return E;
921568035acSLuqman Aden 
922bb94611dSAlvin Wong   if (Error E = ignoreStrippedErrors(initLoadConfigPtr()))
9231c03389cSReid Kleckner     return E;
924b7d716c0SReid Kleckner 
92539772063SReid Kleckner   return Error::success();
9268e90adafSMichael J. Spencer }
9278e90adafSMichael J. Spencer 
symbol_begin() const928435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
9298ff24d25SRui Ueyama   DataRefImpl Ret;
93044f51e51SDavid Majnemer   Ret.p = getSymbolTable();
931f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
9328e90adafSMichael J. Spencer }
9338e90adafSMichael J. Spencer 
symbol_end() const934435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
9358e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
9368ff24d25SRui Ueyama   DataRefImpl Ret;
9378ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
938f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
9398e90adafSMichael J. Spencer }
9408e90adafSMichael J. Spencer 
import_directory_begin() const941bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
942ad7b7e73SDavid Majnemer   if (!ImportDirectory)
943ad7b7e73SDavid Majnemer     return import_directory_end();
9441c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
945ad7b7e73SDavid Majnemer     return import_directory_end();
946a045b73aSRui Ueyama   return import_directory_iterator(
947a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
948c2bed429SRui Ueyama }
949c2bed429SRui Ueyama 
import_directory_end() const950bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
951a045b73aSRui Ueyama   return import_directory_iterator(
952ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
953c2bed429SRui Ueyama }
954c429b80dSDavid Meyer 
95515d99359SRui Ueyama delay_import_directory_iterator
delay_import_directory_begin() const95615d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
95715d99359SRui Ueyama   return delay_import_directory_iterator(
95815d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
95915d99359SRui Ueyama }
96015d99359SRui Ueyama 
96115d99359SRui Ueyama delay_import_directory_iterator
delay_import_directory_end() const96215d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
96315d99359SRui Ueyama   return delay_import_directory_iterator(
96415d99359SRui Ueyama       DelayImportDirectoryEntryRef(
96515d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
96615d99359SRui Ueyama }
96715d99359SRui Ueyama 
export_directory_begin() const968ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
969ad882ba8SRui Ueyama   return export_directory_iterator(
970ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
971ad882ba8SRui Ueyama }
972ad882ba8SRui Ueyama 
export_directory_end() const973ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
9742617dcceSCraig Topper   if (!ExportDirectory)
9752617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9768ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
977ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
9788ff24d25SRui Ueyama   return export_directory_iterator(Ref);
979ad882ba8SRui Ueyama }
980ad882ba8SRui Ueyama 
section_begin() const981b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
9828ff24d25SRui Ueyama   DataRefImpl Ret;
9838ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9848ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9858e90adafSMichael J. Spencer }
9868e90adafSMichael J. Spencer 
section_end() const987b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
9888ff24d25SRui Ueyama   DataRefImpl Ret;
98944f51e51SDavid Majnemer   int NumSections =
99044f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9918ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9928ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9938e90adafSMichael J. Spencer }
9948e90adafSMichael J. Spencer 
base_reloc_begin() const99574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
99674e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
99774e85130SRui Ueyama }
99874e85130SRui Ueyama 
base_reloc_end() const99974e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
100074e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
100174e85130SRui Ueyama }
100274e85130SRui Ueyama 
getBytesInAddress() const10038e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
100443c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
10058e90adafSMichael J. Spencer }
10068e90adafSMichael J. Spencer 
getFileFormatName() const10078e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
100844f51e51SDavid Majnemer   switch(getMachine()) {
10098e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
10108e90adafSMichael J. Spencer     return "COFF-i386";
10118e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
10128e90adafSMichael J. Spencer     return "COFF-x86-64";
10139b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
10149b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
10151eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
10161eff5c9cSMartell Malone     return "COFF-ARM64";
10178e90adafSMichael J. Spencer   default:
10188e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
10198e90adafSMichael J. Spencer   }
10208e90adafSMichael J. Spencer }
10218e90adafSMichael J. Spencer 
getArch() const1022260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
102344f51e51SDavid Majnemer   switch (getMachine()) {
10248e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
10258e90adafSMichael J. Spencer     return Triple::x86;
10268e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
10278e90adafSMichael J. Spencer     return Triple::x86_64;
10289b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
10299b7c0af2SSaleem Abdulrasool     return Triple::thumb;
10301eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
10311eff5c9cSMartell Malone     return Triple::aarch64;
10328e90adafSMichael J. Spencer   default:
10338e90adafSMichael J. Spencer     return Triple::UnknownArch;
10348e90adafSMichael J. Spencer   }
10358e90adafSMichael J. Spencer }
10368e90adafSMichael J. Spencer 
getStartAddress() const1037d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
1038d2af4d6fSPaul Semel   if (PE32Header)
1039d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
1040d2af4d6fSPaul Semel   return 0;
1041d2af4d6fSPaul Semel }
1042d2af4d6fSPaul Semel 
1043979fb40bSRui Ueyama iterator_range<import_directory_iterator>
import_directories() const1044979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
1045979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
1046979fb40bSRui Ueyama }
1047979fb40bSRui Ueyama 
1048979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
delay_import_directories() const1049979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
1050979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
1051979fb40bSRui Ueyama                     delay_import_directory_end());
1052979fb40bSRui Ueyama }
1053979fb40bSRui Ueyama 
1054979fb40bSRui Ueyama iterator_range<export_directory_iterator>
export_directories() const1055979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
1056979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
1057979fb40bSRui Ueyama }
1058979fb40bSRui Ueyama 
base_relocs() const105974e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
106074e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
106174e85130SRui Ueyama }
106274e85130SRui Ueyama 
getDataDirectory(uint32_t Index) const10631c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
10641c03389cSReid Kleckner   if (!DataDirectory)
10651c03389cSReid Kleckner     return nullptr;
106610ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
106710ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
106810ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
10691c03389cSReid Kleckner   if (Index >= NumEnt)
10701c03389cSReid Kleckner     return nullptr;
10711c03389cSReid Kleckner   return &DataDirectory[Index];
1072ed64342bSRui Ueyama }
1073ed64342bSRui Ueyama 
getSection(int32_t Index) const107477ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
107577ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
107677ecf90cSReid Kleckner   // but callers rely on this to return null.
1077236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
107877ecf90cSReid Kleckner     return (const coff_section *)nullptr;
1079236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10801d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
108177ecf90cSReid Kleckner     return SectionTable + (Index - 1);
10828e90adafSMichael J. Spencer   }
10836ec18aafSMartin Storsjö   return createStringError(object_error::parse_failed,
10846ec18aafSMartin Storsjö                            "section index out of bounds");
1085236b0ca7SDavid Majnemer }
10868e90adafSMichael J. Spencer 
getString(uint32_t Offset) const108777ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10881d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10891d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
10906ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed, "string table empty");
10918ff24d25SRui Ueyama   if (Offset >= StringTableSize)
109277ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
109377ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
10948e90adafSMichael J. Spencer }
1095022ecdf2SBenjamin Kramer 
getSymbolName(COFFSymbolRef Symbol) const109677ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
109777ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
1098e40d30f3SRui Ueyama }
1099e40d30f3SRui Ueyama 
110077ecf90cSReid Kleckner Expected<StringRef>
getSymbolName(const coff_symbol_generic * Symbol) const110177ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
110289a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
110377ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
110477ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
110589a7a5eaSMichael J. Spencer 
110689a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
110777ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
110877ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
110977ecf90cSReid Kleckner 
111089a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
111177ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
111289a7a5eaSMichael J. Spencer }
111389a7a5eaSMichael J. Spencer 
111444f51e51SDavid Majnemer ArrayRef<uint8_t>
getSymbolAuxData(COFFSymbolRef Symbol) const111544f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
11162617dcceSCraig Topper   const uint8_t *Aux = nullptr;
111771757ef3SMarshall Clow 
111844f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
111944f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
112071757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
112144f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
112271757ef3SMarshall Clow #ifndef NDEBUG
11238ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
11248ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
112544f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
112644f51e51SDavid Majnemer         Offset >=
112744f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
112871757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
112971757ef3SMarshall Clow 
113044f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
113144f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
113271757ef3SMarshall Clow #endif
1133bfb85e67SMarshall Clow   }
113444f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
113571757ef3SMarshall Clow }
113671757ef3SMarshall Clow 
getSymbolIndex(COFFSymbolRef Symbol) const113774e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
113874e7d260SMartin Storsjo   uintptr_t Offset =
113974e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
114074e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
114174e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
114274e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
114374e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
114474e7d260SMartin Storsjo   return Index;
114574e7d260SMartin Storsjo }
114674e7d260SMartin Storsjo 
11478be28cdcSFangrui Song Expected<StringRef>
getSectionName(const coff_section * Sec) const11488be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
1149*2e0c4604SPengxuan Zheng   StringRef Name = StringRef(Sec->Name, COFF::NameSize).split('\0').first;
115053c2d547SMichael J. Spencer 
115153c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
11522314b3deSDavid Majnemer   if (Name.startswith("/")) {
115353c2d547SMichael J. Spencer     uint32_t Offset;
11542314b3deSDavid Majnemer     if (Name.startswith("//")) {
11559d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
11568be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1157400b6c08Sserge-sans-paille                                  "invalid section name");
11589d2c15efSNico Rieck     } else {
1159*2e0c4604SPengxuan Zheng       if (Name.substr(1).getAsInteger(10, Offset))
11608be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
11618be28cdcSFangrui Song                                  "invalid section name");
11629d2c15efSNico Rieck     }
116377ecf90cSReid Kleckner     return getString(Offset);
116453c2d547SMichael J. Spencer   }
116553c2d547SMichael J. Spencer 
11668be28cdcSFangrui Song   return Name;
116753c2d547SMichael J. Spencer }
116853c2d547SMichael J. Spencer 
getSectionSize(const coff_section * Sec) const1169a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1170a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1171a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1172a9ee5c06SDavid Majnemer   //
1173a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1174d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1175a9ee5c06SDavid Majnemer   //
1176a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1177a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1178a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1179a9ee5c06SDavid Majnemer   // considered to be zero.
1180d5297ee7SRui Ueyama   if (getDOSHeader())
1181d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1182d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1183a9ee5c06SDavid Majnemer }
1184a9ee5c06SDavid Majnemer 
getSectionContents(const coff_section * Sec,ArrayRef<uint8_t> & Res) const1185e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11869da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1187e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1188e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1189e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1190e1cb2c0fSFangrui Song     return Error::success();
11919da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11929da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11939da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
119422cf54a7SArthur O'Dwyer   uintptr_t ConStart =
119522cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
1196a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1197e03a135bSReid Kleckner   if (Error E = checkOffset(Data, ConStart, SectionSize))
1198e03a135bSReid Kleckner     return E;
1199a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1200e1cb2c0fSFangrui Song   return Error::success();
12019da9e693SMichael J. Spencer }
12029da9e693SMichael J. Spencer 
toRel(DataRefImpl Rel) const1203022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1204e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1205022ecdf2SBenjamin Kramer }
12068ff24d25SRui Ueyama 
moveRelocationNext(DataRefImpl & Rel) const12075e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1208e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1209e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1210022ecdf2SBenjamin Kramer }
12118ff24d25SRui Ueyama 
getRelocationOffset(DataRefImpl Rel) const121296d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
121358323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
121496d071cdSRafael Espindola   return R->VirtualAddress;
1215cbe72fc9SDanil Malyshev }
12168ff24d25SRui Ueyama 
getRelocationSymbol(DataRefImpl Rel) const1217806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1218022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
12198ff24d25SRui Ueyama   DataRefImpl Ref;
1220236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1221236b0ca7SDavid Majnemer     return symbol_end();
122244f51e51SDavid Majnemer   if (SymbolTable16)
122344f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
122444f51e51SDavid Majnemer   else if (SymbolTable32)
122544f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
122644f51e51SDavid Majnemer   else
1227c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
12288ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1229022ecdf2SBenjamin Kramer }
12308ff24d25SRui Ueyama 
getRelocationType(DataRefImpl Rel) const123199c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1232022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
123399c041b7SRafael Espindola   return R->Type;
1234022ecdf2SBenjamin Kramer }
1235e5fd0047SMichael J. Spencer 
123627dc8394SAlexey Samsonov const coff_section *
getCOFFSection(const SectionRef & Section) const123727dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
123827dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
123971757ef3SMarshall Clow }
124071757ef3SMarshall Clow 
getCOFFSymbol(const DataRefImpl & Ref) const124144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
124244f51e51SDavid Majnemer   if (SymbolTable16)
124344f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
124444f51e51SDavid Majnemer   if (SymbolTable32)
124544f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
124644f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
124744f51e51SDavid Majnemer }
124844f51e51SDavid Majnemer 
getCOFFSymbol(const SymbolRef & Symbol) const124944f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
125044f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
125171757ef3SMarshall Clow }
125271757ef3SMarshall Clow 
1253f12b8282SRafael Espindola const coff_relocation *
getCOFFRelocation(const RelocationRef & Reloc) const125427dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
125527dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1256d3e2a76cSMarshall Clow }
1257d3e2a76cSMarshall Clow 
12582f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
getRelocations(const coff_section * Sec) const12596a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
12602f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
12612f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
12626a75acb1SRui Ueyama }
12636a75acb1SRui Ueyama 
126427dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
126527dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1266114ebf4aSMartin Storsjo     return #reloc_type;
1267e5fd0047SMichael J. Spencer 
getRelocationTypeName(uint16_t Type) const1268114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
126944f51e51SDavid Majnemer   switch (getMachine()) {
1270e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1271114ebf4aSMartin Storsjo     switch (Type) {
1272e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1273e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1274e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1275e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1276e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1277e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1278e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1279e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1280e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1281e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1282e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1283e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1284e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1285e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1286e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1287e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1288e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1289e5fd0047SMichael J. Spencer     default:
1290114ebf4aSMartin Storsjo       return "Unknown";
1291e5fd0047SMichael J. Spencer     }
1292e5fd0047SMichael J. Spencer     break;
12935c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1294114ebf4aSMartin Storsjo     switch (Type) {
12955c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12965c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12975c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12985c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12995c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
13005c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
13015c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
13025c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1303e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
13045c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
13055c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
13065c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
13075c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
13085c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
13095c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
13105c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1311e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
13125c503bf4SSaleem Abdulrasool     default:
1313114ebf4aSMartin Storsjo       return "Unknown";
13145c503bf4SSaleem Abdulrasool     }
13155c503bf4SSaleem Abdulrasool     break;
13160c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1317114ebf4aSMartin Storsjo     switch (Type) {
13180c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
13190c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
13200c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
13210c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
13220c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
13230c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
13240c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
13250c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
13260c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
13270c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
13280c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
13290c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
13300c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
13310c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
13320c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
13330c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
13340c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1335e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
13360c72172eSMandeep Singh Grang     default:
1337114ebf4aSMartin Storsjo       return "Unknown";
13380c72172eSMandeep Singh Grang     }
13390c72172eSMandeep Singh Grang     break;
1340e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1341114ebf4aSMartin Storsjo     switch (Type) {
1342e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1343e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1344e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1345e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1346e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1347e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1348e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1349e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1350e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1351e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1352e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1353e5fd0047SMichael J. Spencer     default:
1354114ebf4aSMartin Storsjo       return "Unknown";
1355e5fd0047SMichael J. Spencer     }
1356e5fd0047SMichael J. Spencer     break;
1357e5fd0047SMichael J. Spencer   default:
1358114ebf4aSMartin Storsjo     return "Unknown";
1359e5fd0047SMichael J. Spencer   }
1360e5fd0047SMichael J. Spencer }
1361e5fd0047SMichael J. Spencer 
1362e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1363e5fd0047SMichael J. Spencer 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const1364114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1365114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1366114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1367114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1368114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1369114ebf4aSMartin Storsjo }
1370114ebf4aSMartin Storsjo 
isRelocatableObject() const1371c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1372c66d761bSRafael Espindola   return !DataDirectory;
1373c66d761bSRafael Espindola }
1374c66d761bSRafael Espindola 
mapDebugSectionName(StringRef Name) const1375e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1376e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1377e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1378e3093808SMartin Storsjo       .Default(Name);
1379e3093808SMartin Storsjo }
1380e3093808SMartin Storsjo 
1381c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
operator ==(const ImportDirectoryEntryRef & Other) const1382c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1383a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1384c2bed429SRui Ueyama }
1385c2bed429SRui Ueyama 
moveNext()13865e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13875e812afaSRafael Espindola   ++Index;
13881c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1389ad7b7e73SDavid Majnemer     Index = -1;
1390ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1391ad7b7e73SDavid Majnemer   }
1392c2bed429SRui Ueyama }
1393c2bed429SRui Ueyama 
getImportTableEntry(const coff_import_directory_table_entry * & Result) const13941c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry(
13951c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1396ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1397c2bed429SRui Ueyama }
1398c2bed429SRui Ueyama 
1399861021f9SRui Ueyama static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile * Object,uintptr_t Ptr,int Index)140015d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1401861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
140215d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1403861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
140415d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1405861021f9SRui Ueyama   }
1406861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
140715d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1408861021f9SRui Ueyama }
1409861021f9SRui Ueyama 
141015d99359SRui Ueyama static imported_symbol_iterator
importedSymbolBegin(uint32_t RVA,const COFFObjectFile * Object)141115d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1412861021f9SRui Ueyama   uintptr_t IntPtr = 0;
14131c03389cSReid Kleckner   // FIXME: Handle errors.
14141c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
141515d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1416861021f9SRui Ueyama }
1417861021f9SRui Ueyama 
141815d99359SRui Ueyama static imported_symbol_iterator
importedSymbolEnd(uint32_t RVA,const COFFObjectFile * Object)141915d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1420861021f9SRui Ueyama   uintptr_t IntPtr = 0;
14211c03389cSReid Kleckner   // FIXME: Handle errors.
14221c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
1423861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1424861021f9SRui Ueyama   int Index = 0;
142515d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1426861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1427861021f9SRui Ueyama     while (*Entry++)
1428861021f9SRui Ueyama       ++Index;
1429861021f9SRui Ueyama   } else {
1430861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1431861021f9SRui Ueyama     while (*Entry++)
1432861021f9SRui Ueyama       ++Index;
1433861021f9SRui Ueyama   }
143415d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
143515d99359SRui Ueyama }
143615d99359SRui Ueyama 
143715d99359SRui Ueyama imported_symbol_iterator
imported_symbol_begin() const143815d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
143960049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
144015d99359SRui Ueyama                              OwningObject);
144115d99359SRui Ueyama }
144215d99359SRui Ueyama 
144315d99359SRui Ueyama imported_symbol_iterator
imported_symbol_end() const144415d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
144560049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
144615d99359SRui Ueyama                            OwningObject);
1447861021f9SRui Ueyama }
1448861021f9SRui Ueyama 
1449979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
imported_symbols() const1450979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1451979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1452979fb40bSRui Ueyama }
1453979fb40bSRui Ueyama 
lookup_table_begin() const145460049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
145560049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
145660049526SDavid Majnemer                              OwningObject);
145760049526SDavid Majnemer }
145860049526SDavid Majnemer 
lookup_table_end() const145960049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
146060049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
146160049526SDavid Majnemer                            OwningObject);
146260049526SDavid Majnemer }
146360049526SDavid Majnemer 
146460049526SDavid Majnemer iterator_range<imported_symbol_iterator>
lookup_table_symbols() const146560049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
146660049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
146760049526SDavid Majnemer }
146860049526SDavid Majnemer 
getName(StringRef & Result) const14691c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
1470c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
14716ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr,
14726ec18aafSMartin Storsjö                                         "import directory name"))
14731c03389cSReid Kleckner     return E;
1474a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14751c03389cSReid Kleckner   return Error::success();
1476c2bed429SRui Ueyama }
1477c2bed429SRui Ueyama 
14781c03389cSReid Kleckner Error
getImportLookupTableRVA(uint32_t & Result) const14791e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14801e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14811c03389cSReid Kleckner   return Error::success();
14821e152d5eSRui Ueyama }
14831e152d5eSRui Ueyama 
getImportAddressTableRVA(uint32_t & Result) const14841c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14851c03389cSReid Kleckner     uint32_t &Result) const {
14861e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14871c03389cSReid Kleckner   return Error::success();
14881e152d5eSRui Ueyama }
14891e152d5eSRui Ueyama 
149015d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
operator ==(const DelayImportDirectoryEntryRef & Other) const149115d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
149215d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
149315d99359SRui Ueyama }
149415d99359SRui Ueyama 
moveNext()149515d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
149615d99359SRui Ueyama   ++Index;
149715d99359SRui Ueyama }
149815d99359SRui Ueyama 
149915d99359SRui Ueyama imported_symbol_iterator
imported_symbol_begin() const150015d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
150115d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
150215d99359SRui Ueyama                              OwningObject);
150315d99359SRui Ueyama }
150415d99359SRui Ueyama 
150515d99359SRui Ueyama imported_symbol_iterator
imported_symbol_end() const150615d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
150715d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
150815d99359SRui Ueyama                            OwningObject);
150915d99359SRui Ueyama }
151015d99359SRui Ueyama 
1511979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
imported_symbols() const1512979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1513979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1514979fb40bSRui Ueyama }
1515979fb40bSRui Ueyama 
getName(StringRef & Result) const15161c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
151715d99359SRui Ueyama   uintptr_t IntPtr = 0;
15186ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr,
15196ec18aafSMartin Storsjö                                         "delay import directory name"))
15201c03389cSReid Kleckner     return E;
152115d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15221c03389cSReid Kleckner   return Error::success();
152315d99359SRui Ueyama }
152415d99359SRui Ueyama 
getDelayImportTable(const delay_import_directory_table_entry * & Result) const15251c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable(
15261c03389cSReid Kleckner     const delay_import_directory_table_entry *&Result) const {
15279f598ac7SJoseph Tremoulet   Result = &Table[Index];
15281c03389cSReid Kleckner   return Error::success();
15291af08658SRui Ueyama }
15301af08658SRui Ueyama 
getImportAddress(int AddrIndex,uint64_t & Result) const15311c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
15321c03389cSReid Kleckner                                                      uint64_t &Result) const {
1533ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1534ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1535ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
15366ec18aafSMartin Storsjö   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address"))
15371c03389cSReid Kleckner     return E;
1538ffa4cebeSRui Ueyama   if (OwningObject->is64())
15395dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1540ffa4cebeSRui Ueyama   else
15415dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
15421c03389cSReid Kleckner   return Error::success();
1543ffa4cebeSRui Ueyama }
1544ffa4cebeSRui Ueyama 
1545ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
operator ==(const ExportDirectoryEntryRef & Other) const1546ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1547ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1548ad882ba8SRui Ueyama }
1549ad882ba8SRui Ueyama 
moveNext()15505e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
15515e812afaSRafael Espindola   ++Index;
1552ad882ba8SRui Ueyama }
1553ad882ba8SRui Ueyama 
1554da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1555da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
getDllName(StringRef & Result) const15561c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1557da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
15586ec18aafSMartin Storsjö   if (Error E =
15596ec18aafSMartin Storsjö           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name"))
15601c03389cSReid Kleckner     return E;
1561da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15621c03389cSReid Kleckner   return Error::success();
1563da49d0d4SRui Ueyama }
1564da49d0d4SRui Ueyama 
1565e5df6095SRui Ueyama // Returns the starting ordinal number.
getOrdinalBase(uint32_t & Result) const15661c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1567e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15681c03389cSReid Kleckner   return Error::success();
1569e5df6095SRui Ueyama }
1570e5df6095SRui Ueyama 
1571ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
getOrdinal(uint32_t & Result) const15721c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1573ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15741c03389cSReid Kleckner   return Error::success();
1575ad882ba8SRui Ueyama }
1576ad882ba8SRui Ueyama 
1577ad882ba8SRui Ueyama // Returns the address of the current export symbol.
getExportRVA(uint32_t & Result) const15781c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1579ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15806ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA,
15816ec18aafSMartin Storsjö                                          IntPtr, "export address"))
1582ad882ba8SRui Ueyama     return EC;
158324fc2d64SRui Ueyama   const export_address_table_entry *entry =
158424fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1585ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15861c03389cSReid Kleckner   return Error::success();
1587ad882ba8SRui Ueyama }
1588ad882ba8SRui Ueyama 
1589ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1590ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
15911c03389cSReid Kleckner Error
getSymbolName(StringRef & Result) const1592db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1593ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15946ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr,
15956ec18aafSMartin Storsjö                                          "export ordinal table"))
1596ad882ba8SRui Ueyama     return EC;
1597ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1598ad882ba8SRui Ueyama 
1599ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1600ad882ba8SRui Ueyama   int Offset = 0;
1601ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1602ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1603ad882ba8SRui Ueyama     if (*I != Index)
1604ad882ba8SRui Ueyama       continue;
16056ec18aafSMartin Storsjö     if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr,
16066ec18aafSMartin Storsjö                                            "export table entry"))
1607ad882ba8SRui Ueyama       return EC;
1608ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
16096ec18aafSMartin Storsjö     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr,
16106ec18aafSMartin Storsjö                                            "export symbol name"))
1611ad882ba8SRui Ueyama       return EC;
1612ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16131c03389cSReid Kleckner     return Error::success();
1614ad882ba8SRui Ueyama   }
1615ad882ba8SRui Ueyama   Result = "";
16161c03389cSReid Kleckner   return Error::success();
1617ad882ba8SRui Ueyama }
1618ad882ba8SRui Ueyama 
isForwarder(bool & Result) const16191c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
16201c03389cSReid Kleckner   const data_directory *DataEntry =
16211c03389cSReid Kleckner       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
16221c03389cSReid Kleckner   if (!DataEntry)
16236ec18aafSMartin Storsjö     return createStringError(object_error::parse_failed,
16246ec18aafSMartin Storsjö                              "export table missing");
16256161b38dSRui Ueyama   uint32_t RVA;
16266161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
16276161b38dSRui Ueyama     return EC;
16286161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
16296161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
16306161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
16311c03389cSReid Kleckner   return Error::success();
16326161b38dSRui Ueyama }
16336161b38dSRui Ueyama 
getForwardTo(StringRef & Result) const16341c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
16356161b38dSRui Ueyama   uint32_t RVA;
16366161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
16376161b38dSRui Ueyama     return EC;
16386161b38dSRui Ueyama   uintptr_t IntPtr = 0;
16396ec18aafSMartin Storsjö   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target"))
16406161b38dSRui Ueyama     return EC;
16416161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
16421c03389cSReid Kleckner   return Error::success();
16436161b38dSRui Ueyama }
16446161b38dSRui Ueyama 
1645861021f9SRui Ueyama bool ImportedSymbolRef::
operator ==(const ImportedSymbolRef & Other) const1646861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1647861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1648861021f9SRui Ueyama       && Index == Other.Index;
1649861021f9SRui Ueyama }
1650861021f9SRui Ueyama 
moveNext()1651861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1652861021f9SRui Ueyama   ++Index;
1653861021f9SRui Ueyama }
1654861021f9SRui Ueyama 
getSymbolName(StringRef & Result) const16551c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1656861021f9SRui Ueyama   uint32_t RVA;
1657861021f9SRui Ueyama   if (Entry32) {
1658861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1659861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
16601c03389cSReid Kleckner       return Error::success();
1661861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1662861021f9SRui Ueyama   } else {
1663861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
16641c03389cSReid Kleckner       return Error::success();
1665861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1666861021f9SRui Ueyama   }
1667861021f9SRui Ueyama   uintptr_t IntPtr = 0;
16686ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name"))
1669861021f9SRui Ueyama     return EC;
1670861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1671861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16721c03389cSReid Kleckner   return Error::success();
1673861021f9SRui Ueyama }
1674861021f9SRui Ueyama 
isOrdinal(bool & Result) const16751c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const {
1676ad7b7e73SDavid Majnemer   if (Entry32)
1677ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1678ad7b7e73SDavid Majnemer   else
1679ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
16801c03389cSReid Kleckner   return Error::success();
1681ad7b7e73SDavid Majnemer }
1682ad7b7e73SDavid Majnemer 
getHintNameRVA(uint32_t & Result) const16831c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1684ad7b7e73SDavid Majnemer   if (Entry32)
1685ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1686ad7b7e73SDavid Majnemer   else
1687ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
16881c03389cSReid Kleckner   return Error::success();
1689ad7b7e73SDavid Majnemer }
1690ad7b7e73SDavid Majnemer 
getOrdinal(uint16_t & Result) const16911c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1692861021f9SRui Ueyama   uint32_t RVA;
1693861021f9SRui Ueyama   if (Entry32) {
1694861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1695861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16961c03389cSReid Kleckner       return Error::success();
1697861021f9SRui Ueyama     }
1698861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1699861021f9SRui Ueyama   } else {
1700861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1701861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
17021c03389cSReid Kleckner       return Error::success();
1703861021f9SRui Ueyama     }
1704861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1705861021f9SRui Ueyama   }
1706861021f9SRui Ueyama   uintptr_t IntPtr = 0;
17076ec18aafSMartin Storsjö   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal"))
1708861021f9SRui Ueyama     return EC;
1709861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
17101c03389cSReid Kleckner   return Error::success();
1711861021f9SRui Ueyama }
1712861021f9SRui Ueyama 
171312db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object)171448af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
171539772063SReid Kleckner   return COFFObjectFile::create(Object);
1716686738e2SRui Ueyama }
171774e85130SRui Ueyama 
operator ==(const BaseRelocRef & Other) const171874e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
171974e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
172074e85130SRui Ueyama }
172174e85130SRui Ueyama 
moveNext()172274e85130SRui Ueyama void BaseRelocRef::moveNext() {
172374e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
172474e85130SRui Ueyama   // size of the header itself.
172574e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1726970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
172774e85130SRui Ueyama   if (Size == Header->BlockSize) {
172874e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
172974e85130SRui Ueyama     // consists of the header followed by entries. The header contains
173074e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
173174e85130SRui Ueyama     // current block, proceed to the next block.
173274e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
173374e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
173474e85130SRui Ueyama     Index = 0;
173574e85130SRui Ueyama   } else {
173674e85130SRui Ueyama     ++Index;
173774e85130SRui Ueyama   }
173874e85130SRui Ueyama }
173974e85130SRui Ueyama 
getType(uint8_t & Type) const17401c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const {
174174e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
174274e85130SRui Ueyama   Type = Entry[Index].getType();
17431c03389cSReid Kleckner   return Error::success();
174474e85130SRui Ueyama }
174574e85130SRui Ueyama 
getRVA(uint32_t & Result) const17461c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const {
174774e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
174874e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
17491c03389cSReid Kleckner   return Error::success();
175074e85130SRui Ueyama }
1751efef15a0SEric Beckmann 
1752357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1753357a40ecSMartin Storsjo   do {                                                                         \
1754357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
175587867988SRafael Espindola     if (E)                                                                     \
1756c55cf4afSBill Wendling       return std::move(E);                                                     \
1757357a40ecSMartin Storsjo   } while (0)
1758efef15a0SEric Beckmann 
175987867988SRafael Espindola Expected<ArrayRef<UTF16>>
getDirStringAtOffset(uint32_t Offset)176087867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1761efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1762efef15a0SEric Beckmann   Reader.setOffset(Offset);
1763efef15a0SEric Beckmann   uint16_t Length;
1764efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1765efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1766efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1767cd704cb6SEric Beckmann   return RawDirString;
1768efef15a0SEric Beckmann }
1769efef15a0SEric Beckmann 
1770f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
getEntryNameString(const coff_resource_dir_entry & Entry)1771efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1772f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1773efef15a0SEric Beckmann }
1774efef15a0SEric Beckmann 
177587867988SRafael Espindola Expected<const coff_resource_dir_table &>
getTableAtOffset(uint32_t Offset)1776efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1777efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1778efef15a0SEric Beckmann 
1779efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1780efef15a0SEric Beckmann   Reader.setOffset(Offset);
1781efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1782efef15a0SEric Beckmann   assert(Table != nullptr);
1783efef15a0SEric Beckmann   return *Table;
1784efef15a0SEric Beckmann }
1785efef15a0SEric Beckmann 
1786edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
getTableEntryAtOffset(uint32_t Offset)1787edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1788edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1789edb6ab9bSMartin Storsjo 
1790edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1791edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1792edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1793edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1794edb6ab9bSMartin Storsjo   return *Entry;
1795edb6ab9bSMartin Storsjo }
1796edb6ab9bSMartin Storsjo 
17977ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
getDataEntryAtOffset(uint32_t Offset)17987ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17997ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
18007ba81d95SMartin Storsjo 
18017ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
18027ba81d95SMartin Storsjo   Reader.setOffset(Offset);
18037ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
18047ba81d95SMartin Storsjo   assert(Entry != nullptr);
18057ba81d95SMartin Storsjo   return *Entry;
18067ba81d95SMartin Storsjo }
18077ba81d95SMartin Storsjo 
1808f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
getEntrySubDir(const coff_resource_dir_entry & Entry)1809efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
18107ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1811f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1812efef15a0SEric Beckmann }
1813efef15a0SEric Beckmann 
18147ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
getEntryData(const coff_resource_dir_entry & Entry)18157ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
18167ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
18177ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
18187ba81d95SMartin Storsjo }
18197ba81d95SMartin Storsjo 
getBaseTable()1820f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1821f3404674SRafael Espindola   return getTableAtOffset(0);
1822efef15a0SEric Beckmann }
1823edb6ab9bSMartin Storsjo 
1824edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
getTableEntry(const coff_resource_dir_table & Table,uint32_t Index)1825edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1826edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1827edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1828edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1829edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1830edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1831edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1832edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1833edb6ab9bSMartin Storsjo }
183494382217SMartin Storsjo 
load(const COFFObjectFile * O)183594382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
183694382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
183794382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
183894382217SMartin Storsjo     if (!Name)
183994382217SMartin Storsjo       return Name.takeError();
184094382217SMartin Storsjo 
184194382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
184294382217SMartin Storsjo       return load(O, S);
184394382217SMartin Storsjo   }
184494382217SMartin Storsjo   return createStringError(object_error::parse_failed,
184594382217SMartin Storsjo                            "no resource section found");
184694382217SMartin Storsjo }
184794382217SMartin Storsjo 
load(const COFFObjectFile * O,const SectionRef & S)184894382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
184994382217SMartin Storsjo   Obj = O;
185094382217SMartin Storsjo   Section = S;
185194382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
185294382217SMartin Storsjo   if (!Contents)
185394382217SMartin Storsjo     return Contents.takeError();
185494382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
185594382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
185694382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
185794382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
185894382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
185994382217SMartin Storsjo     Relocs.push_back(&R);
1860352fcfc6SKazu Hirata   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
186194382217SMartin Storsjo     return A->VirtualAddress < B->VirtualAddress;
186294382217SMartin Storsjo   });
186394382217SMartin Storsjo   return Error::success();
186494382217SMartin Storsjo }
186594382217SMartin Storsjo 
186694382217SMartin Storsjo Expected<StringRef>
getContents(const coff_resource_data_entry & Entry)186794382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
186894382217SMartin Storsjo   if (!Obj)
186994382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
187094382217SMartin Storsjo 
187194382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
187294382217SMartin Storsjo   // the coff_resource_data_entry struct).
187394382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
187494382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
187594382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
187694382217SMartin Storsjo                               ulittle16_t(0)};
187794382217SMartin Storsjo   auto RelocsForOffset =
187894382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
187994382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
188094382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
188194382217SMartin Storsjo                        });
188294382217SMartin Storsjo 
188394382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
188494382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
188594382217SMartin Storsjo     // the expected type.
188694382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
188794382217SMartin Storsjo     uint16_t RVAReloc;
188894382217SMartin Storsjo     switch (Obj->getMachine()) {
188994382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
189094382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
189194382217SMartin Storsjo       break;
189294382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
189394382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
189494382217SMartin Storsjo       break;
189594382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
189694382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
189794382217SMartin Storsjo       break;
189894382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
189994382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
190094382217SMartin Storsjo       break;
190194382217SMartin Storsjo     default:
190294382217SMartin Storsjo       return createStringError(object_error::parse_failed,
190394382217SMartin Storsjo                                "unsupported architecture");
190494382217SMartin Storsjo     }
190594382217SMartin Storsjo     if (R.Type != RVAReloc)
190694382217SMartin Storsjo       return createStringError(object_error::parse_failed,
190794382217SMartin Storsjo                                "unexpected relocation type");
190894382217SMartin Storsjo     // Get the relocation's symbol
190994382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
191094382217SMartin Storsjo     if (!Sym)
191194382217SMartin Storsjo       return Sym.takeError();
191294382217SMartin Storsjo     // And the symbol's section
191377ecf90cSReid Kleckner     Expected<const coff_section *> Section =
191477ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
191577ecf90cSReid Kleckner     if (!Section)
191677ecf90cSReid Kleckner       return Section.takeError();
191794382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
191894382217SMartin Storsjo     // data it points at.
191994382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
192094382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
192177ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1922c55cf4afSBill Wendling       return std::move(E);
192394382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
192494382217SMartin Storsjo       return createStringError(object_error::parse_failed,
192594382217SMartin Storsjo                                "data outside of section");
192694382217SMartin Storsjo     // Return a reference to the data inside the section.
192794382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
192894382217SMartin Storsjo                      Entry.DataSize);
192994382217SMartin Storsjo   } else {
193094382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
193194382217SMartin Storsjo     if (Obj->isRelocatableObject())
193294382217SMartin Storsjo       return createStringError(object_error::parse_failed,
193394382217SMartin Storsjo                                "no relocation found for DataRVA");
193494382217SMartin Storsjo 
193594382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
193694382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
193794382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
193894382217SMartin Storsjo       if (VA >= S.getAddress() &&
193994382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
194094382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
194194382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
194294382217SMartin Storsjo         if (!Contents)
194394382217SMartin Storsjo           return Contents.takeError();
194494382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
194594382217SMartin Storsjo       }
194694382217SMartin Storsjo     }
194794382217SMartin Storsjo     return createStringError(object_error::parse_failed,
194894382217SMartin Storsjo                              "address not found in image");
194994382217SMartin Storsjo   }
195094382217SMartin Storsjo }
1951