1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
28e90adafSMichael J. Spencer //
38e90adafSMichael J. Spencer //                     The LLVM Compiler Infrastructure
48e90adafSMichael J. Spencer //
58e90adafSMichael J. Spencer // This file is distributed under the University of Illinois Open Source
68e90adafSMichael J. Spencer // License. See LICENSE.TXT for details.
78e90adafSMichael J. Spencer //
88e90adafSMichael J. Spencer //===----------------------------------------------------------------------===//
98e90adafSMichael J. Spencer //
108e90adafSMichael J. Spencer // This file declares the COFFObjectFile class.
118e90adafSMichael J. Spencer //
128e90adafSMichael J. Spencer //===----------------------------------------------------------------------===//
138e90adafSMichael J. Spencer 
149da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h"
15d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h"
168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h"
176a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h"
18*264b5d9eSZachary 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"
28d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
29d341c932SEugene Zelenko #include <algorithm>
30d341c932SEugene Zelenko #include <cassert>
31d341c932SEugene Zelenko #include <cstddef>
32d341c932SEugene Zelenko #include <cstdint>
33d341c932SEugene Zelenko #include <cstring>
349d2c15efSNico Rieck #include <limits>
35d341c932SEugene Zelenko #include <memory>
36d341c932SEugene Zelenko #include <system_error>
378e90adafSMichael J. Spencer 
388e90adafSMichael J. Spencer using namespace llvm;
398e90adafSMichael J. Spencer using namespace object;
408e90adafSMichael J. Spencer 
418e90adafSMichael J. Spencer using support::ulittle16_t;
428e90adafSMichael J. Spencer using support::ulittle32_t;
43861021f9SRui Ueyama using support::ulittle64_t;
448e90adafSMichael J. Spencer using support::little16_t;
458e90adafSMichael J. Spencer 
461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
48c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
498ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
501d6167fdSMichael J. Spencer     return false;
511d6167fdSMichael J. Spencer   }
521d6167fdSMichael J. Spencer   return true;
538e90adafSMichael J. Spencer }
548e90adafSMichael J. Spencer 
55e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
5694751be7SDavid Majnemer                                    const uint64_t Size) {
57e830c60dSDavid Majnemer   if (Addr + Size < Addr || Addr + Size < Size ||
58e830c60dSDavid Majnemer       Addr + Size > uintptr_t(M.getBufferEnd()) ||
59e830c60dSDavid Majnemer       Addr < uintptr_t(M.getBufferStart())) {
60e830c60dSDavid Majnemer     return object_error::unexpected_eof;
61e830c60dSDavid Majnemer   }
627d099195SRui Ueyama   return std::error_code();
63e830c60dSDavid Majnemer }
64e830c60dSDavid Majnemer 
65ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
66ed64342bSRui Ueyama // Returns unexpected_eof if error.
67ed64342bSRui Ueyama template <typename T>
6848af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
6958323a97SDavid Majnemer                                  const void *Ptr,
70236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
71ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
72e830c60dSDavid Majnemer   if (std::error_code EC = checkOffset(M, Addr, Size))
73e830c60dSDavid Majnemer     return EC;
74ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
757d099195SRui Ueyama   return std::error_code();
761d6167fdSMichael J. Spencer }
771d6167fdSMichael J. Spencer 
789d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
799d2c15efSNico Rieck // prefixed slashes.
809d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
819d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
829d2c15efSNico Rieck   if (Str.size() > 6)
839d2c15efSNico Rieck     return true;
849d2c15efSNico Rieck 
859d2c15efSNico Rieck   uint64_t Value = 0;
869d2c15efSNico Rieck   while (!Str.empty()) {
879d2c15efSNico Rieck     unsigned CharVal;
889d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
899d2c15efSNico Rieck       CharVal = Str[0] - 'A';
909d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
919d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
929d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
939d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
949d2c15efSNico Rieck     else if (Str[0] == '+') // 62
955500b07cSRui Ueyama       CharVal = 62;
969d2c15efSNico Rieck     else if (Str[0] == '/') // 63
975500b07cSRui Ueyama       CharVal = 63;
989d2c15efSNico Rieck     else
999d2c15efSNico Rieck       return true;
1009d2c15efSNico Rieck 
1019d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
1029d2c15efSNico Rieck     Str = Str.substr(1);
1039d2c15efSNico Rieck   }
1049d2c15efSNico Rieck 
1059d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
1069d2c15efSNico Rieck     return true;
1079d2c15efSNico Rieck 
1089d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
1099d2c15efSNico Rieck   return false;
1109d2c15efSNico Rieck }
1119d2c15efSNico Rieck 
11244f51e51SDavid Majnemer template <typename coff_symbol_type>
11344f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
11444f51e51SDavid Majnemer   const coff_symbol_type *Addr =
11544f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1161d6167fdSMichael J. Spencer 
117236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1181d6167fdSMichael J. Spencer #ifndef NDEBUG
1191d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1208ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1211d6167fdSMichael J. Spencer 
12244f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
12344f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1241d6167fdSMichael J. Spencer #endif
1251d6167fdSMichael J. Spencer 
1268ff24d25SRui Ueyama   return Addr;
1271d6167fdSMichael J. Spencer }
1281d6167fdSMichael J. Spencer 
1298ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1308ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1311d6167fdSMichael J. Spencer 
1321d6167fdSMichael J. Spencer #ifndef NDEBUG
1331d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
13444f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1351d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1361d6167fdSMichael J. Spencer 
1378ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1388ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1391d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1401d6167fdSMichael J. Spencer #endif
1411d6167fdSMichael J. Spencer 
1428ff24d25SRui Ueyama   return Addr;
1431d6167fdSMichael J. Spencer }
1441d6167fdSMichael J. Spencer 
1455e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
146236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
14744f51e51SDavid Majnemer   if (SymbolTable16) {
14844f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1498ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
150236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
15144f51e51SDavid Majnemer   } else if (SymbolTable32) {
15244f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
15344f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
154236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
15544f51e51SDavid Majnemer   } else {
15644f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
15744f51e51SDavid Majnemer   }
1581d6167fdSMichael J. Spencer }
1591d6167fdSMichael J. Spencer 
16081e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
16144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1625d0c2ffaSRafael Espindola   StringRef Result;
163efef15a0SEric Beckmann   if (std::error_code EC = getSymbolName(Symb, Result))
16481e8b7d9SKevin Enderby     return errorCodeToError(EC);
1655d0c2ffaSRafael Espindola   return Result;
1668e90adafSMichael J. Spencer }
1678e90adafSMichael J. Spencer 
168be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
169be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
170991af666SRafael Espindola }
171991af666SRafael Espindola 
1726b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1736b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1746b2bba14SDavide Italiano   // up to 32 bytes.
1756b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
17603a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1776b2bba14SDavide Italiano }
1786b2bba14SDavide Italiano 
179931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
180ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
18144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
182c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
183991af666SRafael Espindola 
184991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
185991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
186ed067c45SRafael Espindola     return Result;
18754c9f3daSRafael Espindola 
1882617dcceSCraig Topper   const coff_section *Section = nullptr;
189c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
190931cb65dSKevin Enderby     return errorCodeToError(EC);
191991af666SRafael Espindola   Result += Section->VirtualAddress;
19247ea9eceSReid Kleckner 
19347ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
19447ea9eceSReid Kleckner   // return virtual addresses.
19521427adaSReid Kleckner   Result += getImageBase();
19647ea9eceSReid Kleckner 
197ed067c45SRafael Espindola   return Result;
198c7d7c6fbSDavid Majnemer }
199c7d7c6fbSDavid Majnemer 
2007bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
20144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
202c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
20344f51e51SDavid Majnemer 
204e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
205e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
2062fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
2072fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
2082fa80cc5SRafael Espindola   if (Symb.isCommon())
2092fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2102fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2112fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2122fa80cc5SRafael Espindola 
2131a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2142fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2152fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2162fa80cc5SRafael Espindola 
2172fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2182fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2192fa80cc5SRafael Espindola 
2202fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
22175d1cf33SBenjamin Kramer }
22275d1cf33SBenjamin Kramer 
22320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
22444f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
22520122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
22675d1cf33SBenjamin Kramer 
227c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2289dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2291df4b84dSDavid Meyer 
230c7d7c6fbSDavid Majnemer   if (Symb.isWeakExternal())
2311df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
2321df4b84dSDavid Meyer 
23344f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2341df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2351df4b84dSDavid Meyer 
236c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
237c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
238c7d7c6fbSDavid Majnemer 
239c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
240c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
241c7d7c6fbSDavid Majnemer 
242c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
243c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
244c7d7c6fbSDavid Majnemer 
245c7d7c6fbSDavid Majnemer   if (Symb.isAnyUndefined())
246c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
247c7d7c6fbSDavid Majnemer 
24820122a43SRafael Espindola   return Result;
24901759754SMichael J. Spencer }
25001759754SMichael J. Spencer 
251d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
252c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2535eb02e45SRafael Espindola   return Symb.getValue();
2548e90adafSMichael J. Spencer }
2558e90adafSMichael J. Spencer 
2567bd8d994SKevin Enderby Expected<section_iterator>
2578bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
25844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2598bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2608bab889bSRafael Espindola     return section_end();
2612617dcceSCraig Topper   const coff_section *Sec = nullptr;
26244f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2637bd8d994SKevin Enderby     return errorCodeToError(EC);
2648bab889bSRafael Espindola   DataRefImpl Ret;
2658bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2668bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
26732173153SMichael J. Spencer }
26832173153SMichael J. Spencer 
2696bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2706bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2716bf32210SRafael Espindola   return Symb.getSectionNumber();
2726bf32210SRafael Espindola }
2736bf32210SRafael Espindola 
2745e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2758ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2768ff24d25SRui Ueyama   Sec += 1;
2778ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2788e90adafSMichael J. Spencer }
2798e90adafSMichael J. Spencer 
280db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2811d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2828ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2838ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2848e90adafSMichael J. Spencer }
2858e90adafSMichael J. Spencer 
28680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2878ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2887c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2897c6a071bSDavid Majnemer 
2907c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2917c6a071bSDavid Majnemer   // return virtual addresses.
29221427adaSReid Kleckner   Result += getImageBase();
2937c6a071bSDavid Majnemer   return Result;
2948e90adafSMichael J. Spencer }
2958e90adafSMichael J. Spencer 
296a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
297a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
298a25d329bSGeorge Rimar }
299a25d329bSGeorge Rimar 
30080291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
301a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
3028e90adafSMichael J. Spencer }
3038e90adafSMichael J. Spencer 
304db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
3051d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
3068ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3079da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
308db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
3099da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
3109da9e693SMichael J. Spencer   return EC;
3118e90adafSMichael J. Spencer }
3128e90adafSMichael J. Spencer 
31380291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3148ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
315511391feSDavid Majnemer   return Sec->getAlignment();
3167989460aSMichael J. Spencer }
3177989460aSMichael J. Spencer 
318401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
319401e4e57SGeorge Rimar   return false;
320401e4e57SGeorge Rimar }
321401e4e57SGeorge Rimar 
32280291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3238ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32480291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3258e90adafSMichael J. Spencer }
3268e90adafSMichael J. Spencer 
32780291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3288ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32980291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
330800619f2SMichael J. Spencer }
331800619f2SMichael J. Spencer 
33280291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3338ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3341a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3351a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3361a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3371a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
338800619f2SMichael J. Spencer }
339800619f2SMichael J. Spencer 
3406bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3416bf32210SRafael Espindola   uintptr_t Offset =
3426bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3436bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3446bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3456bf32210SRafael Espindola }
3466bf32210SRafael Espindola 
34780291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3488ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3491a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3501a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3511a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3522138ef6dSPreston Gurd }
3532138ef6dSPreston Gurd 
354e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
355e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
356e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
357e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
358e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
359e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
360e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
361e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
362e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
363e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
364e830c60dSDavid Majnemer       return 0;
36598fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36698fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
367e830c60dSDavid Majnemer   }
368e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
369e830c60dSDavid Majnemer }
370e830c60dSDavid Majnemer 
37194751be7SDavid Majnemer static const coff_relocation *
37294751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37394751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37494751be7SDavid Majnemer   if (!NumRelocs)
37594751be7SDavid Majnemer     return nullptr;
376827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37794751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
378827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
379827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
380827c8a2bSRui Ueyama     // relocations.
381827c8a2bSRui Ueyama     begin++;
382827c8a2bSRui Ueyama   }
38394751be7SDavid Majnemer   if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
38494751be7SDavid Majnemer     return nullptr;
38594751be7SDavid Majnemer   return begin;
386827c8a2bSRui Ueyama }
38794751be7SDavid Majnemer 
38894751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38994751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
39094751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
39176d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
39276d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
39394751be7SDavid Majnemer   DataRefImpl Ret;
39494751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3958ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
396e5fd0047SMichael J. Spencer }
397e5fd0047SMichael J. Spencer 
3988ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3998ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
40094751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
40194751be7SDavid Majnemer   if (I)
40294751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4038ff24d25SRui Ueyama   DataRefImpl Ret;
40494751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4058ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
406e5fd0047SMichael J. Spencer }
407e5fd0047SMichael J. Spencer 
408c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
409db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
41044f51e51SDavid Majnemer   if (COFFHeader)
411236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
412236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
413236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
41444f51e51SDavid Majnemer       return EC;
41544f51e51SDavid Majnemer 
41644f51e51SDavid Majnemer   if (COFFBigObjHeader)
417236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
418236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
419236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4208ff24d25SRui Ueyama       return EC;
421c2bed429SRui Ueyama 
422c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
423c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
424c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
425f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42644f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
427f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
428c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42948af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4308ff24d25SRui Ueyama     return EC;
431c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
432db4ed0bdSRafael Espindola   if (std::error_code EC =
43348af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4348ff24d25SRui Ueyama     return EC;
435c2bed429SRui Ueyama 
436773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
437773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
438773a5795SNico Rieck   if (StringTableSize < 4)
439773a5795SNico Rieck       StringTableSize = 4;
440773a5795SNico Rieck 
441c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
442773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
443c2bed429SRui Ueyama     return  object_error::parse_failed;
4447d099195SRui Ueyama   return std::error_code();
445c2bed429SRui Ueyama }
446c2bed429SRui Ueyama 
44721427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
448e94fef7bSReid Kleckner   if (PE32Header)
44921427adaSReid Kleckner     return PE32Header->ImageBase;
450e94fef7bSReid Kleckner   else if (PE32PlusHeader)
45121427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
45221427adaSReid Kleckner   // This actually comes up in practice.
45321427adaSReid Kleckner   return 0;
454e94fef7bSReid Kleckner }
455e94fef7bSReid Kleckner 
456215a586cSRui Ueyama // Returns the file offset for the given VA.
457db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45821427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
459b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
460b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
461b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
462215a586cSRui Ueyama }
463215a586cSRui Ueyama 
464c2bed429SRui Ueyama // Returns the file offset for the given RVA.
465db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46627dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46727dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
468c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
469c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
470215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
471215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
472c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4737d099195SRui Ueyama       return std::error_code();
474c2bed429SRui Ueyama     }
475c2bed429SRui Ueyama   }
476c2bed429SRui Ueyama   return object_error::parse_failed;
477c2bed429SRui Ueyama }
478c2bed429SRui Ueyama 
4792da433eaSReid Kleckner std::error_code
4802da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4812da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4822da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4832da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4842da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4852da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4862da433eaSReid Kleckner     // overflow.
4872da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4882da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4892da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4902da433eaSReid Kleckner       uintptr_t Begin =
4912da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4922da433eaSReid Kleckner       Contents =
4932da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4942da433eaSReid Kleckner       return std::error_code();
4952da433eaSReid Kleckner     }
4962da433eaSReid Kleckner   }
4972da433eaSReid Kleckner   return object_error::parse_failed;
4982da433eaSReid Kleckner }
4992da433eaSReid Kleckner 
500c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
501c2bed429SRui Ueyama // table entry.
502db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
503db4ed0bdSRafael Espindola                                             StringRef &Name) const {
504c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
505db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5068ff24d25SRui Ueyama     return EC;
507c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
508c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
509c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5107d099195SRui Ueyama   return std::error_code();
511c2bed429SRui Ueyama }
512c2bed429SRui Ueyama 
51301528021SSaleem Abdulrasool std::error_code
51401528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51501528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5162da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5172da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5182da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5192da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5202da433eaSReid Kleckner     return EC;
52101528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5222da433eaSReid Kleckner     return object_error::parse_failed;
52301528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
52401528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5252da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5262da433eaSReid Kleckner                           InfoBytes.size());
5272da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5282da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5292da433eaSReid Kleckner   return std::error_code();
5302da433eaSReid Kleckner }
5312da433eaSReid Kleckner 
53201528021SSaleem Abdulrasool std::error_code
53301528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
534f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
535f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
536f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
537f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
538f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
539f27f3f84SReid Kleckner   PDBInfo = nullptr;
540f27f3f84SReid Kleckner   PDBFileName = StringRef();
541f27f3f84SReid Kleckner   return std::error_code();
542f27f3f84SReid Kleckner }
543f27f3f84SReid Kleckner 
544c2bed429SRui Ueyama // Find the import table.
545db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
546c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
547c2bed429SRui Ueyama   // the import table, do nothing.
548c2bed429SRui Ueyama   const data_directory *DataEntry;
549c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5507d099195SRui Ueyama     return std::error_code();
551c2bed429SRui Ueyama 
552c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
553c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5547d099195SRui Ueyama     return std::error_code();
555c2bed429SRui Ueyama 
556c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
557c2bed429SRui Ueyama 
558c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
559c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
560c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
561db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5628ff24d25SRui Ueyama     return EC;
563ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
564ad7b7e73SDavid Majnemer     return EC;
565c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5661c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5677d099195SRui Ueyama   return std::error_code();
568ad882ba8SRui Ueyama }
569c2bed429SRui Ueyama 
57015d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
57115d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
57215d99359SRui Ueyama   const data_directory *DataEntry;
57315d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5747d099195SRui Ueyama     return std::error_code();
57515d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5767d099195SRui Ueyama     return std::error_code();
57715d99359SRui Ueyama 
57815d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57915d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
58015d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
58115d99359SRui Ueyama 
58215d99359SRui Ueyama   uintptr_t IntPtr = 0;
58315d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
58415d99359SRui Ueyama     return EC;
58515d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58615d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5877d099195SRui Ueyama   return std::error_code();
58815d99359SRui Ueyama }
58915d99359SRui Ueyama 
590ad882ba8SRui Ueyama // Find the export table.
591db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
592ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
593ad882ba8SRui Ueyama   // the export table, do nothing.
594ad882ba8SRui Ueyama   const data_directory *DataEntry;
595ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5967d099195SRui Ueyama     return std::error_code();
597ad882ba8SRui Ueyama 
598ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
599ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6007d099195SRui Ueyama     return std::error_code();
601ad882ba8SRui Ueyama 
602ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
603ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
604db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
605ad882ba8SRui Ueyama     return EC;
60624fc2d64SRui Ueyama   ExportDirectory =
60724fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6087d099195SRui Ueyama   return std::error_code();
609c2bed429SRui Ueyama }
610c2bed429SRui Ueyama 
61174e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
61274e85130SRui Ueyama   const data_directory *DataEntry;
61374e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6147d099195SRui Ueyama     return std::error_code();
61574e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6167d099195SRui Ueyama     return std::error_code();
61774e85130SRui Ueyama 
61874e85130SRui Ueyama   uintptr_t IntPtr = 0;
61974e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
62074e85130SRui Ueyama     return EC;
62174e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
62274e85130SRui Ueyama       IntPtr);
62374e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
62474e85130SRui Ueyama       IntPtr + DataEntry->Size);
6257d099195SRui Ueyama   return std::error_code();
62674e85130SRui Ueyama }
62774e85130SRui Ueyama 
6282da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6292da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6302da433eaSReid Kleckner   const data_directory *DataEntry;
6312da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6322da433eaSReid Kleckner     return std::error_code();
6332da433eaSReid Kleckner 
6342da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6352da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6362da433eaSReid Kleckner     return std::error_code();
6372da433eaSReid Kleckner 
6382da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6392da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6402da433eaSReid Kleckner     return object_error::parse_failed;
6412da433eaSReid Kleckner 
6422da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6432da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6442da433eaSReid Kleckner     return EC;
6452da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6462da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6472da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6482da433eaSReid Kleckner     return EC;
6492da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6502da433eaSReid Kleckner   return std::error_code();
6512da433eaSReid Kleckner }
6522da433eaSReid Kleckner 
65348af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
65448af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
65544f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
65644f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
65744f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
658ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
65915d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6602da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6612da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6621d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
66348af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
664c3f9b5a5SRafael Espindola     return;
665ee066fc4SEric Christopher 
66682ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
66782ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
66882ebd8e3SRui Ueyama 
66982ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
67082ebd8e3SRui Ueyama   // it is placed right after COFF header.
6718ff24d25SRui Ueyama   bool HasPEHeader = false;
672ee066fc4SEric Christopher 
6731d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
67450267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
675ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
676ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
67750267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
67850267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
67950267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
68082ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
68150267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6828ff24d25SRui Ueyama         EC = object_error::parse_failed;
6831d6167fdSMichael J. Spencer         return;
6841d6167fdSMichael J. Spencer       }
68544f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6868ff24d25SRui Ueyama       HasPEHeader = true;
687ee066fc4SEric Christopher     }
68850267222SDavid Majnemer   }
689ee066fc4SEric Christopher 
69048af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
6911d6167fdSMichael J. Spencer     return;
69244f51e51SDavid Majnemer 
69344f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
69444f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
69544f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
69644f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
69744f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
69844f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
69944f51e51SDavid Majnemer       return;
70044f51e51SDavid Majnemer 
70144f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
70244f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
70344f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
70444f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
70544f51e51SDavid Majnemer       COFFHeader = nullptr;
70644f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
70744f51e51SDavid Majnemer     } else {
70844f51e51SDavid Majnemer       // It's not a bigobj.
70944f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
71044f51e51SDavid Majnemer     }
71144f51e51SDavid Majnemer   }
71244f51e51SDavid Majnemer   if (COFFHeader) {
71344f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
71444f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7157d099195SRui Ueyama     EC = std::error_code();
71682ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
71782ebd8e3SRui Ueyama 
71844f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
71944f51e51SDavid Majnemer       return;
72044f51e51SDavid Majnemer   }
72144f51e51SDavid Majnemer 
7228ff24d25SRui Ueyama   if (HasPEHeader) {
72310ed9ddcSRui Ueyama     const pe32_header *Header;
72448af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
72582ebd8e3SRui Ueyama       return;
72610ed9ddcSRui Ueyama 
72710ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
72810ed9ddcSRui Ueyama     uint64_t DataDirSize;
72950267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
73010ed9ddcSRui Ueyama       PE32Header = Header;
73110ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
73210ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
73350267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
73410ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
73510ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
73610ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
73710ed9ddcSRui Ueyama     } else {
73810ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
73910ed9ddcSRui Ueyama       EC = object_error::parse_failed;
740ed64342bSRui Ueyama       return;
741ed64342bSRui Ueyama     }
74248af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
74310ed9ddcSRui Ueyama       return;
744f53c8cb4SRui Ueyama   }
745776c6828SRui Ueyama 
7468950a538SRui Ueyama   if (COFFHeader)
7478950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7488950a538SRui Ueyama 
74948af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
750236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7511d6167fdSMichael J. Spencer     return;
7521d6167fdSMichael J. Spencer 
753c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
754236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
755ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
756ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
757ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
758ac8cfab5SDavid Majnemer       StringTable = nullptr;
759ac8cfab5SDavid Majnemer       StringTableSize = 0;
760ac8cfab5SDavid Majnemer     }
761236b0ca7SDavid Majnemer   } else {
762236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
763236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
764236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
765236b0ca7SDavid Majnemer       return;
766236b0ca7SDavid Majnemer     }
767236b0ca7SDavid Majnemer   }
7688e90adafSMichael J. Spencer 
769c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7708ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
771ed64342bSRui Ueyama     return;
77215d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
77315d99359SRui Ueyama     return;
7741d6167fdSMichael J. Spencer 
775ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7768ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
777ad882ba8SRui Ueyama     return;
778ad882ba8SRui Ueyama 
77974e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
78074e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
78174e85130SRui Ueyama     return;
78274e85130SRui Ueyama 
7832da433eaSReid Kleckner   // Initialize the pointer to the export table.
7842da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7852da433eaSReid Kleckner     return;
7862da433eaSReid Kleckner 
7877d099195SRui Ueyama   EC = std::error_code();
7888e90adafSMichael J. Spencer }
7898e90adafSMichael J. Spencer 
790435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
7918ff24d25SRui Ueyama   DataRefImpl Ret;
79244f51e51SDavid Majnemer   Ret.p = getSymbolTable();
793f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7948e90adafSMichael J. Spencer }
7958e90adafSMichael J. Spencer 
796435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
7978e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
7988ff24d25SRui Ueyama   DataRefImpl Ret;
7998ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
800f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8018e90adafSMichael J. Spencer }
8028e90adafSMichael J. Spencer 
803bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
804ad7b7e73SDavid Majnemer   if (!ImportDirectory)
805ad7b7e73SDavid Majnemer     return import_directory_end();
8061c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
807ad7b7e73SDavid Majnemer     return import_directory_end();
808a045b73aSRui Ueyama   return import_directory_iterator(
809a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
810c2bed429SRui Ueyama }
811c2bed429SRui Ueyama 
812bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
813a045b73aSRui Ueyama   return import_directory_iterator(
814ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
815c2bed429SRui Ueyama }
816c429b80dSDavid Meyer 
81715d99359SRui Ueyama delay_import_directory_iterator
81815d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
81915d99359SRui Ueyama   return delay_import_directory_iterator(
82015d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
82115d99359SRui Ueyama }
82215d99359SRui Ueyama 
82315d99359SRui Ueyama delay_import_directory_iterator
82415d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
82515d99359SRui Ueyama   return delay_import_directory_iterator(
82615d99359SRui Ueyama       DelayImportDirectoryEntryRef(
82715d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
82815d99359SRui Ueyama }
82915d99359SRui Ueyama 
830ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
831ad882ba8SRui Ueyama   return export_directory_iterator(
832ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
833ad882ba8SRui Ueyama }
834ad882ba8SRui Ueyama 
835ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8362617dcceSCraig Topper   if (!ExportDirectory)
8372617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8388ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
839ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8408ff24d25SRui Ueyama   return export_directory_iterator(Ref);
841ad882ba8SRui Ueyama }
842ad882ba8SRui Ueyama 
843b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8448ff24d25SRui Ueyama   DataRefImpl Ret;
8458ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8468ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8478e90adafSMichael J. Spencer }
8488e90adafSMichael J. Spencer 
849b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8508ff24d25SRui Ueyama   DataRefImpl Ret;
85144f51e51SDavid Majnemer   int NumSections =
85244f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8538ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8548ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8558e90adafSMichael J. Spencer }
8568e90adafSMichael J. Spencer 
85774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
85874e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
85974e85130SRui Ueyama }
86074e85130SRui Ueyama 
86174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
86274e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
86374e85130SRui Ueyama }
86474e85130SRui Ueyama 
8658e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
8660324b672SMichael J. Spencer   return getArch() == Triple::x86_64 ? 8 : 4;
8678e90adafSMichael J. Spencer }
8688e90adafSMichael J. Spencer 
8698e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
87044f51e51SDavid Majnemer   switch(getMachine()) {
8718e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8728e90adafSMichael J. Spencer     return "COFF-i386";
8738e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8748e90adafSMichael J. Spencer     return "COFF-x86-64";
8759b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8769b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8771eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8781eff5c9cSMartell Malone     return "COFF-ARM64";
8798e90adafSMichael J. Spencer   default:
8808e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8818e90adafSMichael J. Spencer   }
8828e90adafSMichael J. Spencer }
8838e90adafSMichael J. Spencer 
8848e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const {
88544f51e51SDavid Majnemer   switch (getMachine()) {
8868e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8878e90adafSMichael J. Spencer     return Triple::x86;
8888e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8898e90adafSMichael J. Spencer     return Triple::x86_64;
8909b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8919b7c0af2SSaleem Abdulrasool     return Triple::thumb;
8921eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8931eff5c9cSMartell Malone     return Triple::aarch64;
8948e90adafSMichael J. Spencer   default:
8958e90adafSMichael J. Spencer     return Triple::UnknownArch;
8968e90adafSMichael J. Spencer   }
8978e90adafSMichael J. Spencer }
8988e90adafSMichael J. Spencer 
899979fb40bSRui Ueyama iterator_range<import_directory_iterator>
900979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
901979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
902979fb40bSRui Ueyama }
903979fb40bSRui Ueyama 
904979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
905979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
906979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
907979fb40bSRui Ueyama                     delay_import_directory_end());
908979fb40bSRui Ueyama }
909979fb40bSRui Ueyama 
910979fb40bSRui Ueyama iterator_range<export_directory_iterator>
911979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
912979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
913979fb40bSRui Ueyama }
914979fb40bSRui Ueyama 
91574e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
91674e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
91774e85130SRui Ueyama }
91874e85130SRui Ueyama 
919db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
92082ebd8e3SRui Ueyama   Res = PE32Header;
9217d099195SRui Ueyama   return std::error_code();
92289a7a5eaSMichael J. Spencer }
92389a7a5eaSMichael J. Spencer 
924db4ed0bdSRafael Espindola std::error_code
92510ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
92610ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9277d099195SRui Ueyama   return std::error_code();
92810ed9ddcSRui Ueyama }
92910ed9ddcSRui Ueyama 
930db4ed0bdSRafael Espindola std::error_code
931db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
932ed64342bSRui Ueyama                                  const data_directory *&Res) const {
933ed64342bSRui Ueyama   // Error if if there's no data directory or the index is out of range.
934f69b0585SDavid Majnemer   if (!DataDirectory) {
935f69b0585SDavid Majnemer     Res = nullptr;
93610ed9ddcSRui Ueyama     return object_error::parse_failed;
937f69b0585SDavid Majnemer   }
93810ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
93910ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
94010ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
941f69b0585SDavid Majnemer   if (Index >= NumEnt) {
942f69b0585SDavid Majnemer     Res = nullptr;
943ed64342bSRui Ueyama     return object_error::parse_failed;
944f69b0585SDavid Majnemer   }
9458ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9467d099195SRui Ueyama   return std::error_code();
947ed64342bSRui Ueyama }
948ed64342bSRui Ueyama 
949db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9501d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9512617dcceSCraig Topper   Result = nullptr;
952236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9537d099195SRui Ueyama     return std::error_code();
954236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9551d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9568ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9577d099195SRui Ueyama     return std::error_code();
9588e90adafSMichael J. Spencer   }
959236b0ca7SDavid Majnemer   return object_error::parse_failed;
960236b0ca7SDavid Majnemer }
9618e90adafSMichael J. Spencer 
962db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9631d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9641d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9651d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9661d6167fdSMichael J. Spencer     return object_error::parse_failed;
9678ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9681d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
9698ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
9707d099195SRui Ueyama   return std::error_code();
9718e90adafSMichael J. Spencer }
972022ecdf2SBenjamin Kramer 
97344f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
97489a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
975e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
976e40d30f3SRui Ueyama }
977e40d30f3SRui Ueyama 
978e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
979e40d30f3SRui Ueyama                                               StringRef &Res) const {
98089a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
981e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
982e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
9838ff24d25SRui Ueyama       return EC;
9847d099195SRui Ueyama     return std::error_code();
98589a7a5eaSMichael J. Spencer   }
98689a7a5eaSMichael J. Spencer 
987e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
98889a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
989e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
99089a7a5eaSMichael J. Spencer   else
99189a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
992e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
9937d099195SRui Ueyama   return std::error_code();
99489a7a5eaSMichael J. Spencer }
99589a7a5eaSMichael J. Spencer 
99644f51e51SDavid Majnemer ArrayRef<uint8_t>
99744f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
9982617dcceSCraig Topper   const uint8_t *Aux = nullptr;
99971757ef3SMarshall Clow 
100044f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
100144f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
100271757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
100344f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
100471757ef3SMarshall Clow #ifndef NDEBUG
10058ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10068ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
100744f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
100844f51e51SDavid Majnemer         Offset >=
100944f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
101071757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
101171757ef3SMarshall Clow 
101244f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
101344f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
101471757ef3SMarshall Clow #endif
1015bfb85e67SMarshall Clow   }
101644f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
101771757ef3SMarshall Clow }
101871757ef3SMarshall Clow 
1019db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
102053c2d547SMichael J. Spencer                                                StringRef &Res) const {
102153c2d547SMichael J. Spencer   StringRef Name;
102244f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
102353c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
102453c2d547SMichael J. Spencer     Name = Sec->Name;
102553c2d547SMichael J. Spencer   else
102653c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
102744f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
102853c2d547SMichael J. Spencer 
102953c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10302314b3deSDavid Majnemer   if (Name.startswith("/")) {
103153c2d547SMichael J. Spencer     uint32_t Offset;
10322314b3deSDavid Majnemer     if (Name.startswith("//")) {
10339d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10349d2c15efSNico Rieck         return object_error::parse_failed;
10359d2c15efSNico Rieck     } else {
103653c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
103753c2d547SMichael J. Spencer         return object_error::parse_failed;
10389d2c15efSNico Rieck     }
1039db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10408ff24d25SRui Ueyama       return EC;
104153c2d547SMichael J. Spencer   }
104253c2d547SMichael J. Spencer 
104353c2d547SMichael J. Spencer   Res = Name;
10447d099195SRui Ueyama   return std::error_code();
104553c2d547SMichael J. Spencer }
104653c2d547SMichael J. Spencer 
1047a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1048a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1049a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1050a9ee5c06SDavid Majnemer   //
1051a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1052d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1053a9ee5c06SDavid Majnemer   //
1054a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1055a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1056a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1057a9ee5c06SDavid Majnemer   // considered to be zero.
1058d5297ee7SRui Ueyama   if (getDOSHeader())
1059d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1060d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1061a9ee5c06SDavid Majnemer }
1062a9ee5c06SDavid Majnemer 
1063db4ed0bdSRafael Espindola std::error_code
1064db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
10659da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1066e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1067e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1068e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1069ee97c5f0SShoaib Meenai     return std::error_code();
10709da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10719da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10729da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10739da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1074a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1075e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
10769da9e693SMichael J. Spencer     return object_error::parse_failed;
1077a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
10787d099195SRui Ueyama   return std::error_code();
10799da9e693SMichael J. Spencer }
10809da9e693SMichael J. Spencer 
1081022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1082e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1083022ecdf2SBenjamin Kramer }
10848ff24d25SRui Ueyama 
10855e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1086e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1087e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1088022ecdf2SBenjamin Kramer }
10898ff24d25SRui Ueyama 
109096d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
109158323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
109296d071cdSRafael Espindola   return R->VirtualAddress;
1093cbe72fc9SDanil Malyshev }
10948ff24d25SRui Ueyama 
1095806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1096022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
10978ff24d25SRui Ueyama   DataRefImpl Ref;
1098236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1099236b0ca7SDavid Majnemer     return symbol_end();
110044f51e51SDavid Majnemer   if (SymbolTable16)
110144f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
110244f51e51SDavid Majnemer   else if (SymbolTable32)
110344f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
110444f51e51SDavid Majnemer   else
1105c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11068ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1107022ecdf2SBenjamin Kramer }
11088ff24d25SRui Ueyama 
110999c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1110022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
111199c041b7SRafael Espindola   return R->Type;
1112022ecdf2SBenjamin Kramer }
1113e5fd0047SMichael J. Spencer 
111427dc8394SAlexey Samsonov const coff_section *
111527dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
111627dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
111771757ef3SMarshall Clow }
111871757ef3SMarshall Clow 
111944f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
112044f51e51SDavid Majnemer   if (SymbolTable16)
112144f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
112244f51e51SDavid Majnemer   if (SymbolTable32)
112344f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
112444f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
112544f51e51SDavid Majnemer }
112644f51e51SDavid Majnemer 
112744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
112844f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
112971757ef3SMarshall Clow }
113071757ef3SMarshall Clow 
1131f12b8282SRafael Espindola const coff_relocation *
113227dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
113327dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1134d3e2a76cSMarshall Clow }
1135d3e2a76cSMarshall Clow 
11366a75acb1SRui Ueyama iterator_range<const coff_relocation *>
11376a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11386a75acb1SRui Ueyama   const coff_relocation *I = getFirstReloc(Sec, Data, base());
11396a75acb1SRui Ueyama   const coff_relocation *E = I;
11406a75acb1SRui Ueyama   if (I)
11416a75acb1SRui Ueyama     E += getNumberOfRelocations(Sec, Data, base());
11426a75acb1SRui Ueyama   return make_range(I, E);
11436a75acb1SRui Ueyama }
11446a75acb1SRui Ueyama 
114527dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
114627dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
114727dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
114827dc8394SAlexey Samsonov     break;
1149e5fd0047SMichael J. Spencer 
115041bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
115141bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11528ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11538ff24d25SRui Ueyama   StringRef Res;
115444f51e51SDavid Majnemer   switch (getMachine()) {
1155e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11568ff24d25SRui Ueyama     switch (Reloc->Type) {
1157e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1158e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1159e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1160e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1161e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1162e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1163e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1164e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1165e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1166e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1167e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1168e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1169e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1170e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1171e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1172e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1173e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1174e5fd0047SMichael J. Spencer     default:
11758ff24d25SRui Ueyama       Res = "Unknown";
1176e5fd0047SMichael J. Spencer     }
1177e5fd0047SMichael J. Spencer     break;
11785c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
11795c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
11805c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11815c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11825c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11835c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11845c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11855c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
11865c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
11875c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
11885c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
11895c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
11905c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
11915c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
11925c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
11935c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
11945c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
11955c503bf4SSaleem Abdulrasool     default:
11965c503bf4SSaleem Abdulrasool       Res = "Unknown";
11975c503bf4SSaleem Abdulrasool     }
11985c503bf4SSaleem Abdulrasool     break;
1199e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
12008ff24d25SRui Ueyama     switch (Reloc->Type) {
1201e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1202e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1203e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1204e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1205e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1206e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1207e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1208e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1209e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1210e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1211e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1212e5fd0047SMichael J. Spencer     default:
12138ff24d25SRui Ueyama       Res = "Unknown";
1214e5fd0047SMichael J. Spencer     }
1215e5fd0047SMichael J. Spencer     break;
1216e5fd0047SMichael J. Spencer   default:
12178ff24d25SRui Ueyama     Res = "Unknown";
1218e5fd0047SMichael J. Spencer   }
12198ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1220e5fd0047SMichael J. Spencer }
1221e5fd0047SMichael J. Spencer 
1222e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1223e5fd0047SMichael J. Spencer 
1224c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1225c66d761bSRafael Espindola   return !DataDirectory;
1226c66d761bSRafael Espindola }
1227c66d761bSRafael Espindola 
1228c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1229c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1230a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1231c2bed429SRui Ueyama }
1232c2bed429SRui Ueyama 
12335e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12345e812afaSRafael Espindola   ++Index;
12351c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1236ad7b7e73SDavid Majnemer     Index = -1;
1237ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1238ad7b7e73SDavid Majnemer   }
1239c2bed429SRui Ueyama }
1240c2bed429SRui Ueyama 
1241db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12421c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1243ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1244c2bed429SRui Ueyama }
1245c2bed429SRui Ueyama 
1246861021f9SRui Ueyama static imported_symbol_iterator
124715d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1248861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
124915d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1250861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
125115d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1252861021f9SRui Ueyama   }
1253861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
125415d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1255861021f9SRui Ueyama }
1256861021f9SRui Ueyama 
125715d99359SRui Ueyama static imported_symbol_iterator
125815d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1259861021f9SRui Ueyama   uintptr_t IntPtr = 0;
126015d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
126115d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1262861021f9SRui Ueyama }
1263861021f9SRui Ueyama 
126415d99359SRui Ueyama static imported_symbol_iterator
126515d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1266861021f9SRui Ueyama   uintptr_t IntPtr = 0;
126715d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1268861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1269861021f9SRui Ueyama   int Index = 0;
127015d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1271861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1272861021f9SRui Ueyama     while (*Entry++)
1273861021f9SRui Ueyama       ++Index;
1274861021f9SRui Ueyama   } else {
1275861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1276861021f9SRui Ueyama     while (*Entry++)
1277861021f9SRui Ueyama       ++Index;
1278861021f9SRui Ueyama   }
127915d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
128015d99359SRui Ueyama }
128115d99359SRui Ueyama 
128215d99359SRui Ueyama imported_symbol_iterator
128315d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
128460049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
128515d99359SRui Ueyama                              OwningObject);
128615d99359SRui Ueyama }
128715d99359SRui Ueyama 
128815d99359SRui Ueyama imported_symbol_iterator
128915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
129060049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
129115d99359SRui Ueyama                            OwningObject);
1292861021f9SRui Ueyama }
1293861021f9SRui Ueyama 
1294979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1295979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1296979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1297979fb40bSRui Ueyama }
1298979fb40bSRui Ueyama 
129960049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
130060049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
130160049526SDavid Majnemer                              OwningObject);
130260049526SDavid Majnemer }
130360049526SDavid Majnemer 
130460049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
130560049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
130660049526SDavid Majnemer                            OwningObject);
130760049526SDavid Majnemer }
130860049526SDavid Majnemer 
130960049526SDavid Majnemer iterator_range<imported_symbol_iterator>
131060049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
131160049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
131260049526SDavid Majnemer }
131360049526SDavid Majnemer 
1314db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1315c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1316db4ed0bdSRafael Espindola   if (std::error_code EC =
13171e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1318a045b73aSRui Ueyama     return EC;
1319a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13207d099195SRui Ueyama   return std::error_code();
1321c2bed429SRui Ueyama }
1322c2bed429SRui Ueyama 
13231e152d5eSRui Ueyama std::error_code
13241e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13251e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13267d099195SRui Ueyama   return std::error_code();
13271e152d5eSRui Ueyama }
13281e152d5eSRui Ueyama 
13291e152d5eSRui Ueyama std::error_code
13301e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13311e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13327d099195SRui Ueyama   return std::error_code();
13331e152d5eSRui Ueyama }
13341e152d5eSRui Ueyama 
133515d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
133615d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
133715d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
133815d99359SRui Ueyama }
133915d99359SRui Ueyama 
134015d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
134115d99359SRui Ueyama   ++Index;
134215d99359SRui Ueyama }
134315d99359SRui Ueyama 
134415d99359SRui Ueyama imported_symbol_iterator
134515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
134615d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
134715d99359SRui Ueyama                              OwningObject);
134815d99359SRui Ueyama }
134915d99359SRui Ueyama 
135015d99359SRui Ueyama imported_symbol_iterator
135115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
135215d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
135315d99359SRui Ueyama                            OwningObject);
135415d99359SRui Ueyama }
135515d99359SRui Ueyama 
1356979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1357979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1358979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1359979fb40bSRui Ueyama }
1360979fb40bSRui Ueyama 
136115d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
136215d99359SRui Ueyama   uintptr_t IntPtr = 0;
136315d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
136415d99359SRui Ueyama     return EC;
136515d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13667d099195SRui Ueyama   return std::error_code();
136715d99359SRui Ueyama }
136815d99359SRui Ueyama 
13691af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
13701af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
13711af08658SRui Ueyama   Result = Table;
13727d099195SRui Ueyama   return std::error_code();
13731af08658SRui Ueyama }
13741af08658SRui Ueyama 
1375ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1376ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1377ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1378ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1379ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1380ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1381ffa4cebeSRui Ueyama     return EC;
1382ffa4cebeSRui Ueyama   if (OwningObject->is64())
13835dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1384ffa4cebeSRui Ueyama   else
13855dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
13867d099195SRui Ueyama   return std::error_code();
1387ffa4cebeSRui Ueyama }
1388ffa4cebeSRui Ueyama 
1389ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1390ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1391ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1392ad882ba8SRui Ueyama }
1393ad882ba8SRui Ueyama 
13945e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
13955e812afaSRafael Espindola   ++Index;
1396ad882ba8SRui Ueyama }
1397ad882ba8SRui Ueyama 
1398da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1399da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1400db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1401da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1402db4ed0bdSRafael Espindola   if (std::error_code EC =
1403db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1404da49d0d4SRui Ueyama     return EC;
1405da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14067d099195SRui Ueyama   return std::error_code();
1407da49d0d4SRui Ueyama }
1408da49d0d4SRui Ueyama 
1409e5df6095SRui Ueyama // Returns the starting ordinal number.
1410db4ed0bdSRafael Espindola std::error_code
1411db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1412e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14137d099195SRui Ueyama   return std::error_code();
1414e5df6095SRui Ueyama }
1415e5df6095SRui Ueyama 
1416ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1417db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1418ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14197d099195SRui Ueyama   return std::error_code();
1420ad882ba8SRui Ueyama }
1421ad882ba8SRui Ueyama 
1422ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1423db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1424ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1425db4ed0bdSRafael Espindola   if (std::error_code EC =
1426db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1427ad882ba8SRui Ueyama     return EC;
142824fc2d64SRui Ueyama   const export_address_table_entry *entry =
142924fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1430ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14317d099195SRui Ueyama   return std::error_code();
1432ad882ba8SRui Ueyama }
1433ad882ba8SRui Ueyama 
1434ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1435ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1436db4ed0bdSRafael Espindola std::error_code
1437db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1438ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1439db4ed0bdSRafael Espindola   if (std::error_code EC =
1440db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1441ad882ba8SRui Ueyama     return EC;
1442ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1443ad882ba8SRui Ueyama 
1444ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1445ad882ba8SRui Ueyama   int Offset = 0;
1446ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1447ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1448ad882ba8SRui Ueyama     if (*I != Index)
1449ad882ba8SRui Ueyama       continue;
1450db4ed0bdSRafael Espindola     if (std::error_code EC =
1451db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1452ad882ba8SRui Ueyama       return EC;
1453ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1454db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1455ad882ba8SRui Ueyama       return EC;
1456ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14577d099195SRui Ueyama     return std::error_code();
1458ad882ba8SRui Ueyama   }
1459ad882ba8SRui Ueyama   Result = "";
14607d099195SRui Ueyama   return std::error_code();
1461ad882ba8SRui Ueyama }
1462ad882ba8SRui Ueyama 
14636161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
14646161b38dSRui Ueyama   const data_directory *DataEntry;
14656161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
14666161b38dSRui Ueyama     return EC;
14676161b38dSRui Ueyama   uint32_t RVA;
14686161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14696161b38dSRui Ueyama     return EC;
14706161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
14716161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
14726161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
14736161b38dSRui Ueyama   return std::error_code();
14746161b38dSRui Ueyama }
14756161b38dSRui Ueyama 
14766161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
14776161b38dSRui Ueyama   uint32_t RVA;
14786161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14796161b38dSRui Ueyama     return EC;
14806161b38dSRui Ueyama   uintptr_t IntPtr = 0;
14816161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
14826161b38dSRui Ueyama     return EC;
14836161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14846161b38dSRui Ueyama   return std::error_code();
14856161b38dSRui Ueyama }
14866161b38dSRui Ueyama 
1487861021f9SRui Ueyama bool ImportedSymbolRef::
1488861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1489861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1490861021f9SRui Ueyama       && Index == Other.Index;
1491861021f9SRui Ueyama }
1492861021f9SRui Ueyama 
1493861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1494861021f9SRui Ueyama   ++Index;
1495861021f9SRui Ueyama }
1496861021f9SRui Ueyama 
1497861021f9SRui Ueyama std::error_code
1498861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1499861021f9SRui Ueyama   uint32_t RVA;
1500861021f9SRui Ueyama   if (Entry32) {
1501861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1502861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15037d099195SRui Ueyama       return std::error_code();
1504861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1505861021f9SRui Ueyama   } else {
1506861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15077d099195SRui Ueyama       return std::error_code();
1508861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1509861021f9SRui Ueyama   }
1510861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1511861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1512861021f9SRui Ueyama     return EC;
1513861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1514861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15157d099195SRui Ueyama   return std::error_code();
1516861021f9SRui Ueyama }
1517861021f9SRui Ueyama 
1518ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1519ad7b7e73SDavid Majnemer   if (Entry32)
1520ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1521ad7b7e73SDavid Majnemer   else
1522ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1523ad7b7e73SDavid Majnemer   return std::error_code();
1524ad7b7e73SDavid Majnemer }
1525ad7b7e73SDavid Majnemer 
1526ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1527ad7b7e73SDavid Majnemer   if (Entry32)
1528ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1529ad7b7e73SDavid Majnemer   else
1530ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1531ad7b7e73SDavid Majnemer   return std::error_code();
1532ad7b7e73SDavid Majnemer }
1533ad7b7e73SDavid Majnemer 
1534861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1535861021f9SRui Ueyama   uint32_t RVA;
1536861021f9SRui Ueyama   if (Entry32) {
1537861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1538861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15397d099195SRui Ueyama       return std::error_code();
1540861021f9SRui Ueyama     }
1541861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1542861021f9SRui Ueyama   } else {
1543861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1544861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15457d099195SRui Ueyama       return std::error_code();
1546861021f9SRui Ueyama     }
1547861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1548861021f9SRui Ueyama   }
1549861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1550861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1551861021f9SRui Ueyama     return EC;
1552861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15537d099195SRui Ueyama   return std::error_code();
1554861021f9SRui Ueyama }
1555861021f9SRui Ueyama 
1556437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>>
155748af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1558db4ed0bdSRafael Espindola   std::error_code EC;
155948af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1560692410efSRafael Espindola   if (EC)
1561692410efSRafael Espindola     return EC;
1562437b0d58SRafael Espindola   return std::move(Ret);
1563686738e2SRui Ueyama }
156474e85130SRui Ueyama 
156574e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
156674e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
156774e85130SRui Ueyama }
156874e85130SRui Ueyama 
156974e85130SRui Ueyama void BaseRelocRef::moveNext() {
157074e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
157174e85130SRui Ueyama   // size of the header itself.
157274e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1573970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
157474e85130SRui Ueyama   if (Size == Header->BlockSize) {
157574e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
157674e85130SRui Ueyama     // consists of the header followed by entries. The header contains
157774e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
157874e85130SRui Ueyama     // current block, proceed to the next block.
157974e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
158074e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
158174e85130SRui Ueyama     Index = 0;
158274e85130SRui Ueyama   } else {
158374e85130SRui Ueyama     ++Index;
158474e85130SRui Ueyama   }
158574e85130SRui Ueyama }
158674e85130SRui Ueyama 
158774e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
158874e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
158974e85130SRui Ueyama   Type = Entry[Index].getType();
15907d099195SRui Ueyama   return std::error_code();
159174e85130SRui Ueyama }
159274e85130SRui Ueyama 
159374e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
159474e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
159574e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
15967d099195SRui Ueyama   return std::error_code();
159774e85130SRui Ueyama }
1598efef15a0SEric Beckmann 
1599efef15a0SEric Beckmann #define RETURN_IF_ERROR(X)                                                     \
1600efef15a0SEric Beckmann   if (auto EC = errorToErrorCode(X))                                           \
1601efef15a0SEric Beckmann     return EC;
1602efef15a0SEric Beckmann 
1603cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1604efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1605efef15a0SEric Beckmann   Reader.setOffset(Offset);
1606efef15a0SEric Beckmann   uint16_t Length;
1607efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1608efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1609efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1610cd704cb6SEric Beckmann   return RawDirString;
1611efef15a0SEric Beckmann }
1612efef15a0SEric Beckmann 
1613cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>>
1614efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1615efef15a0SEric Beckmann   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1616efef15a0SEric Beckmann }
1617efef15a0SEric Beckmann 
1618efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1619efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1620efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1621efef15a0SEric Beckmann 
1622efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1623efef15a0SEric Beckmann   Reader.setOffset(Offset);
1624efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1625efef15a0SEric Beckmann   assert(Table != nullptr);
1626efef15a0SEric Beckmann   return *Table;
1627efef15a0SEric Beckmann }
1628efef15a0SEric Beckmann 
1629efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1630efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1631efef15a0SEric Beckmann   return getTableAtOffset(Entry.Offset.value());
1632efef15a0SEric Beckmann }
1633efef15a0SEric Beckmann 
1634efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1635efef15a0SEric Beckmann   return getTableAtOffset(0);
1636efef15a0SEric Beckmann }
1637