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"
18d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
19d341c932SEugene Zelenko #include "llvm/Object/COFF.h"
20d341c932SEugene Zelenko #include "llvm/Object/Error.h"
21d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h"
22efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
23f078eff3SRui Ueyama #include "llvm/Support/COFF.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 
29680291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
297a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2988e90adafSMichael J. Spencer }
2998e90adafSMichael J. Spencer 
300db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
3011d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
3028ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3039da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
304db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
3059da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
3069da9e693SMichael J. Spencer   return EC;
3078e90adafSMichael J. Spencer }
3088e90adafSMichael J. Spencer 
30980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3108ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
311511391feSDavid Majnemer   return Sec->getAlignment();
3127989460aSMichael J. Spencer }
3137989460aSMichael J. Spencer 
314401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
315401e4e57SGeorge Rimar   return false;
316401e4e57SGeorge Rimar }
317401e4e57SGeorge Rimar 
31880291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3198ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32080291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3218e90adafSMichael J. Spencer }
3228e90adafSMichael J. Spencer 
32380291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3248ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32580291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
326800619f2SMichael J. Spencer }
327800619f2SMichael J. Spencer 
32880291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3298ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3301a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3311a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3321a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3331a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
334800619f2SMichael J. Spencer }
335800619f2SMichael J. Spencer 
3366bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3376bf32210SRafael Espindola   uintptr_t Offset =
3386bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3396bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3406bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3416bf32210SRafael Espindola }
3426bf32210SRafael Espindola 
34380291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3448ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3451a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3461a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3471a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3482138ef6dSPreston Gurd }
3492138ef6dSPreston Gurd 
350e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
351e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
352e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
353e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
354e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
355e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
356e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
357e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
358e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
359e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
360e830c60dSDavid Majnemer       return 0;
36198fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36298fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
363e830c60dSDavid Majnemer   }
364e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
365e830c60dSDavid Majnemer }
366e830c60dSDavid Majnemer 
36794751be7SDavid Majnemer static const coff_relocation *
36894751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36994751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37094751be7SDavid Majnemer   if (!NumRelocs)
37194751be7SDavid Majnemer     return nullptr;
372827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37394751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
374827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
375827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
376827c8a2bSRui Ueyama     // relocations.
377827c8a2bSRui Ueyama     begin++;
378827c8a2bSRui Ueyama   }
37994751be7SDavid Majnemer   if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
38094751be7SDavid Majnemer     return nullptr;
38194751be7SDavid Majnemer   return begin;
382827c8a2bSRui Ueyama }
38394751be7SDavid Majnemer 
38494751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38594751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38694751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38776d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38876d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
38994751be7SDavid Majnemer   DataRefImpl Ret;
39094751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3918ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
392e5fd0047SMichael J. Spencer }
393e5fd0047SMichael J. Spencer 
3948ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3958ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39694751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39794751be7SDavid Majnemer   if (I)
39894751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3998ff24d25SRui Ueyama   DataRefImpl Ret;
40094751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4018ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
402e5fd0047SMichael J. Spencer }
403e5fd0047SMichael J. Spencer 
404c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
405db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40644f51e51SDavid Majnemer   if (COFFHeader)
407236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
408236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
409236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
41044f51e51SDavid Majnemer       return EC;
41144f51e51SDavid Majnemer 
41244f51e51SDavid Majnemer   if (COFFBigObjHeader)
413236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
414236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
415236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4168ff24d25SRui Ueyama       return EC;
417c2bed429SRui Ueyama 
418c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
419c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
420c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
421f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42244f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
423f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
424c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42548af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4268ff24d25SRui Ueyama     return EC;
427c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
428db4ed0bdSRafael Espindola   if (std::error_code EC =
42948af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4308ff24d25SRui Ueyama     return EC;
431c2bed429SRui Ueyama 
432773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
433773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
434773a5795SNico Rieck   if (StringTableSize < 4)
435773a5795SNico Rieck       StringTableSize = 4;
436773a5795SNico Rieck 
437c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
438773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
439c2bed429SRui Ueyama     return  object_error::parse_failed;
4407d099195SRui Ueyama   return std::error_code();
441c2bed429SRui Ueyama }
442c2bed429SRui Ueyama 
44321427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
444e94fef7bSReid Kleckner   if (PE32Header)
44521427adaSReid Kleckner     return PE32Header->ImageBase;
446e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44721427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44821427adaSReid Kleckner   // This actually comes up in practice.
44921427adaSReid Kleckner   return 0;
450e94fef7bSReid Kleckner }
451e94fef7bSReid Kleckner 
452215a586cSRui Ueyama // Returns the file offset for the given VA.
453db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45421427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
455b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
456b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
457b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
458215a586cSRui Ueyama }
459215a586cSRui Ueyama 
460c2bed429SRui Ueyama // Returns the file offset for the given RVA.
461db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46227dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46327dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
464c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
465c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
466215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
467215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
468c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4697d099195SRui Ueyama       return std::error_code();
470c2bed429SRui Ueyama     }
471c2bed429SRui Ueyama   }
472c2bed429SRui Ueyama   return object_error::parse_failed;
473c2bed429SRui Ueyama }
474c2bed429SRui Ueyama 
4752da433eaSReid Kleckner std::error_code
4762da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4772da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4782da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4792da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4802da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4812da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4822da433eaSReid Kleckner     // overflow.
4832da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4842da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4852da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4862da433eaSReid Kleckner       uintptr_t Begin =
4872da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4882da433eaSReid Kleckner       Contents =
4892da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4902da433eaSReid Kleckner       return std::error_code();
4912da433eaSReid Kleckner     }
4922da433eaSReid Kleckner   }
4932da433eaSReid Kleckner   return object_error::parse_failed;
4942da433eaSReid Kleckner }
4952da433eaSReid Kleckner 
496c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
497c2bed429SRui Ueyama // table entry.
498db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
499db4ed0bdSRafael Espindola                                             StringRef &Name) const {
500c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
501db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5028ff24d25SRui Ueyama     return EC;
503c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
504c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
505c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5067d099195SRui Ueyama   return std::error_code();
507c2bed429SRui Ueyama }
508c2bed429SRui Ueyama 
50901528021SSaleem Abdulrasool std::error_code
51001528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51101528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5122da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5132da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5142da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5152da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5162da433eaSReid Kleckner     return EC;
51701528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5182da433eaSReid Kleckner     return object_error::parse_failed;
51901528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
52001528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5212da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5222da433eaSReid Kleckner                           InfoBytes.size());
5232da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5242da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5252da433eaSReid Kleckner   return std::error_code();
5262da433eaSReid Kleckner }
5272da433eaSReid Kleckner 
52801528021SSaleem Abdulrasool std::error_code
52901528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
530f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
531f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
532f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
533f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
534f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
535f27f3f84SReid Kleckner   PDBInfo = nullptr;
536f27f3f84SReid Kleckner   PDBFileName = StringRef();
537f27f3f84SReid Kleckner   return std::error_code();
538f27f3f84SReid Kleckner }
539f27f3f84SReid Kleckner 
540c2bed429SRui Ueyama // Find the import table.
541db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
542c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
543c2bed429SRui Ueyama   // the import table, do nothing.
544c2bed429SRui Ueyama   const data_directory *DataEntry;
545c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5467d099195SRui Ueyama     return std::error_code();
547c2bed429SRui Ueyama 
548c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
549c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5507d099195SRui Ueyama     return std::error_code();
551c2bed429SRui Ueyama 
552c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
553c2bed429SRui Ueyama 
554c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
555c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
556c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
557db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5588ff24d25SRui Ueyama     return EC;
559ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
560ad7b7e73SDavid Majnemer     return EC;
561c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5621c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5637d099195SRui Ueyama   return std::error_code();
564ad882ba8SRui Ueyama }
565c2bed429SRui Ueyama 
56615d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56715d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56815d99359SRui Ueyama   const data_directory *DataEntry;
56915d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5707d099195SRui Ueyama     return std::error_code();
57115d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5727d099195SRui Ueyama     return std::error_code();
57315d99359SRui Ueyama 
57415d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57515d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57615d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57715d99359SRui Ueyama 
57815d99359SRui Ueyama   uintptr_t IntPtr = 0;
57915d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
58015d99359SRui Ueyama     return EC;
58115d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58215d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5837d099195SRui Ueyama   return std::error_code();
58415d99359SRui Ueyama }
58515d99359SRui Ueyama 
586ad882ba8SRui Ueyama // Find the export table.
587db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
588ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
589ad882ba8SRui Ueyama   // the export table, do nothing.
590ad882ba8SRui Ueyama   const data_directory *DataEntry;
591ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5927d099195SRui Ueyama     return std::error_code();
593ad882ba8SRui Ueyama 
594ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
595ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5967d099195SRui Ueyama     return std::error_code();
597ad882ba8SRui Ueyama 
598ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
599ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
600db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
601ad882ba8SRui Ueyama     return EC;
60224fc2d64SRui Ueyama   ExportDirectory =
60324fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6047d099195SRui Ueyama   return std::error_code();
605c2bed429SRui Ueyama }
606c2bed429SRui Ueyama 
60774e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60874e85130SRui Ueyama   const data_directory *DataEntry;
60974e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6107d099195SRui Ueyama     return std::error_code();
61174e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6127d099195SRui Ueyama     return std::error_code();
61374e85130SRui Ueyama 
61474e85130SRui Ueyama   uintptr_t IntPtr = 0;
61574e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61674e85130SRui Ueyama     return EC;
61774e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61874e85130SRui Ueyama       IntPtr);
61974e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
62074e85130SRui Ueyama       IntPtr + DataEntry->Size);
6217d099195SRui Ueyama   return std::error_code();
62274e85130SRui Ueyama }
62374e85130SRui Ueyama 
6242da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6252da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6262da433eaSReid Kleckner   const data_directory *DataEntry;
6272da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6282da433eaSReid Kleckner     return std::error_code();
6292da433eaSReid Kleckner 
6302da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6312da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6322da433eaSReid Kleckner     return std::error_code();
6332da433eaSReid Kleckner 
6342da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6352da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6362da433eaSReid Kleckner     return object_error::parse_failed;
6372da433eaSReid Kleckner 
6382da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6392da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6402da433eaSReid Kleckner     return EC;
6412da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6422da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6432da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6442da433eaSReid Kleckner     return EC;
6452da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6462da433eaSReid Kleckner   return std::error_code();
6472da433eaSReid Kleckner }
6482da433eaSReid Kleckner 
64948af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
65048af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
65144f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
65244f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
65344f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
654ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
65515d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6562da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6572da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6581d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
65948af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
660c3f9b5a5SRafael Espindola     return;
661ee066fc4SEric Christopher 
66282ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
66382ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
66482ebd8e3SRui Ueyama 
66582ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
66682ebd8e3SRui Ueyama   // it is placed right after COFF header.
6678ff24d25SRui Ueyama   bool HasPEHeader = false;
668ee066fc4SEric Christopher 
6691d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
67050267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
671ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
672ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
67350267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
67450267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
67550267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
67682ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
67750267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6788ff24d25SRui Ueyama         EC = object_error::parse_failed;
6791d6167fdSMichael J. Spencer         return;
6801d6167fdSMichael J. Spencer       }
68144f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6828ff24d25SRui Ueyama       HasPEHeader = true;
683ee066fc4SEric Christopher     }
68450267222SDavid Majnemer   }
685ee066fc4SEric Christopher 
68648af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
6871d6167fdSMichael J. Spencer     return;
68844f51e51SDavid Majnemer 
68944f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
69044f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
69144f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
69244f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
69344f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
69444f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
69544f51e51SDavid Majnemer       return;
69644f51e51SDavid Majnemer 
69744f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
69844f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
69944f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
70044f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
70144f51e51SDavid Majnemer       COFFHeader = nullptr;
70244f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
70344f51e51SDavid Majnemer     } else {
70444f51e51SDavid Majnemer       // It's not a bigobj.
70544f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
70644f51e51SDavid Majnemer     }
70744f51e51SDavid Majnemer   }
70844f51e51SDavid Majnemer   if (COFFHeader) {
70944f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
71044f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7117d099195SRui Ueyama     EC = std::error_code();
71282ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
71382ebd8e3SRui Ueyama 
71444f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
71544f51e51SDavid Majnemer       return;
71644f51e51SDavid Majnemer   }
71744f51e51SDavid Majnemer 
7188ff24d25SRui Ueyama   if (HasPEHeader) {
71910ed9ddcSRui Ueyama     const pe32_header *Header;
72048af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
72182ebd8e3SRui Ueyama       return;
72210ed9ddcSRui Ueyama 
72310ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
72410ed9ddcSRui Ueyama     uint64_t DataDirSize;
72550267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
72610ed9ddcSRui Ueyama       PE32Header = Header;
72710ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
72810ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
72950267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
73010ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
73110ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
73210ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
73310ed9ddcSRui Ueyama     } else {
73410ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
73510ed9ddcSRui Ueyama       EC = object_error::parse_failed;
736ed64342bSRui Ueyama       return;
737ed64342bSRui Ueyama     }
73848af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
73910ed9ddcSRui Ueyama       return;
740f53c8cb4SRui Ueyama   }
741776c6828SRui Ueyama 
7428950a538SRui Ueyama   if (COFFHeader)
7438950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7448950a538SRui Ueyama 
74548af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
746236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7471d6167fdSMichael J. Spencer     return;
7481d6167fdSMichael J. Spencer 
749c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
750236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
751ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
752ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
753ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
754ac8cfab5SDavid Majnemer       StringTable = nullptr;
755ac8cfab5SDavid Majnemer       StringTableSize = 0;
756ac8cfab5SDavid Majnemer     }
757236b0ca7SDavid Majnemer   } else {
758236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
759236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
760236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
761236b0ca7SDavid Majnemer       return;
762236b0ca7SDavid Majnemer     }
763236b0ca7SDavid Majnemer   }
7648e90adafSMichael J. Spencer 
765c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7668ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
767ed64342bSRui Ueyama     return;
76815d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
76915d99359SRui Ueyama     return;
7701d6167fdSMichael J. Spencer 
771ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7728ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
773ad882ba8SRui Ueyama     return;
774ad882ba8SRui Ueyama 
77574e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
77674e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
77774e85130SRui Ueyama     return;
77874e85130SRui Ueyama 
7792da433eaSReid Kleckner   // Initialize the pointer to the export table.
7802da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7812da433eaSReid Kleckner     return;
7822da433eaSReid Kleckner 
7837d099195SRui Ueyama   EC = std::error_code();
7848e90adafSMichael J. Spencer }
7858e90adafSMichael J. Spencer 
786435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
7878ff24d25SRui Ueyama   DataRefImpl Ret;
78844f51e51SDavid Majnemer   Ret.p = getSymbolTable();
789f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7908e90adafSMichael J. Spencer }
7918e90adafSMichael J. Spencer 
792435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
7938e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
7948ff24d25SRui Ueyama   DataRefImpl Ret;
7958ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
796f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7978e90adafSMichael J. Spencer }
7988e90adafSMichael J. Spencer 
799bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
800ad7b7e73SDavid Majnemer   if (!ImportDirectory)
801ad7b7e73SDavid Majnemer     return import_directory_end();
8021c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
803ad7b7e73SDavid Majnemer     return import_directory_end();
804a045b73aSRui Ueyama   return import_directory_iterator(
805a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
806c2bed429SRui Ueyama }
807c2bed429SRui Ueyama 
808bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
809a045b73aSRui Ueyama   return import_directory_iterator(
810ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
811c2bed429SRui Ueyama }
812c429b80dSDavid Meyer 
81315d99359SRui Ueyama delay_import_directory_iterator
81415d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
81515d99359SRui Ueyama   return delay_import_directory_iterator(
81615d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
81715d99359SRui Ueyama }
81815d99359SRui Ueyama 
81915d99359SRui Ueyama delay_import_directory_iterator
82015d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
82115d99359SRui Ueyama   return delay_import_directory_iterator(
82215d99359SRui Ueyama       DelayImportDirectoryEntryRef(
82315d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
82415d99359SRui Ueyama }
82515d99359SRui Ueyama 
826ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
827ad882ba8SRui Ueyama   return export_directory_iterator(
828ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
829ad882ba8SRui Ueyama }
830ad882ba8SRui Ueyama 
831ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8322617dcceSCraig Topper   if (!ExportDirectory)
8332617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8348ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
835ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8368ff24d25SRui Ueyama   return export_directory_iterator(Ref);
837ad882ba8SRui Ueyama }
838ad882ba8SRui Ueyama 
839b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8408ff24d25SRui Ueyama   DataRefImpl Ret;
8418ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8428ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8438e90adafSMichael J. Spencer }
8448e90adafSMichael J. Spencer 
845b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8468ff24d25SRui Ueyama   DataRefImpl Ret;
84744f51e51SDavid Majnemer   int NumSections =
84844f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8498ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8508ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8518e90adafSMichael J. Spencer }
8528e90adafSMichael J. Spencer 
85374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
85474e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
85574e85130SRui Ueyama }
85674e85130SRui Ueyama 
85774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
85874e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
85974e85130SRui Ueyama }
86074e85130SRui Ueyama 
8618e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
8620324b672SMichael J. Spencer   return getArch() == Triple::x86_64 ? 8 : 4;
8638e90adafSMichael J. Spencer }
8648e90adafSMichael J. Spencer 
8658e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
86644f51e51SDavid Majnemer   switch(getMachine()) {
8678e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8688e90adafSMichael J. Spencer     return "COFF-i386";
8698e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8708e90adafSMichael J. Spencer     return "COFF-x86-64";
8719b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8729b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8731eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8741eff5c9cSMartell Malone     return "COFF-ARM64";
8758e90adafSMichael J. Spencer   default:
8768e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8778e90adafSMichael J. Spencer   }
8788e90adafSMichael J. Spencer }
8798e90adafSMichael J. Spencer 
8808e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const {
88144f51e51SDavid Majnemer   switch (getMachine()) {
8828e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8838e90adafSMichael J. Spencer     return Triple::x86;
8848e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8858e90adafSMichael J. Spencer     return Triple::x86_64;
8869b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8879b7c0af2SSaleem Abdulrasool     return Triple::thumb;
8881eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8891eff5c9cSMartell Malone     return Triple::aarch64;
8908e90adafSMichael J. Spencer   default:
8918e90adafSMichael J. Spencer     return Triple::UnknownArch;
8928e90adafSMichael J. Spencer   }
8938e90adafSMichael J. Spencer }
8948e90adafSMichael J. Spencer 
895979fb40bSRui Ueyama iterator_range<import_directory_iterator>
896979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
897979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
898979fb40bSRui Ueyama }
899979fb40bSRui Ueyama 
900979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
901979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
902979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
903979fb40bSRui Ueyama                     delay_import_directory_end());
904979fb40bSRui Ueyama }
905979fb40bSRui Ueyama 
906979fb40bSRui Ueyama iterator_range<export_directory_iterator>
907979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
908979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
909979fb40bSRui Ueyama }
910979fb40bSRui Ueyama 
91174e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
91274e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
91374e85130SRui Ueyama }
91474e85130SRui Ueyama 
915db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
91682ebd8e3SRui Ueyama   Res = PE32Header;
9177d099195SRui Ueyama   return std::error_code();
91889a7a5eaSMichael J. Spencer }
91989a7a5eaSMichael J. Spencer 
920db4ed0bdSRafael Espindola std::error_code
92110ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
92210ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9237d099195SRui Ueyama   return std::error_code();
92410ed9ddcSRui Ueyama }
92510ed9ddcSRui Ueyama 
926db4ed0bdSRafael Espindola std::error_code
927db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
928ed64342bSRui Ueyama                                  const data_directory *&Res) const {
929ed64342bSRui Ueyama   // Error if if there's no data directory or the index is out of range.
930f69b0585SDavid Majnemer   if (!DataDirectory) {
931f69b0585SDavid Majnemer     Res = nullptr;
93210ed9ddcSRui Ueyama     return object_error::parse_failed;
933f69b0585SDavid Majnemer   }
93410ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
93510ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
93610ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
937f69b0585SDavid Majnemer   if (Index >= NumEnt) {
938f69b0585SDavid Majnemer     Res = nullptr;
939ed64342bSRui Ueyama     return object_error::parse_failed;
940f69b0585SDavid Majnemer   }
9418ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9427d099195SRui Ueyama   return std::error_code();
943ed64342bSRui Ueyama }
944ed64342bSRui Ueyama 
945db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9461d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9472617dcceSCraig Topper   Result = nullptr;
948236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9497d099195SRui Ueyama     return std::error_code();
950236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9511d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9528ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9537d099195SRui Ueyama     return std::error_code();
9548e90adafSMichael J. Spencer   }
955236b0ca7SDavid Majnemer   return object_error::parse_failed;
956236b0ca7SDavid Majnemer }
9578e90adafSMichael J. Spencer 
958db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9591d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9601d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9611d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9621d6167fdSMichael J. Spencer     return object_error::parse_failed;
9638ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9641d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
9658ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
9667d099195SRui Ueyama   return std::error_code();
9678e90adafSMichael J. Spencer }
968022ecdf2SBenjamin Kramer 
96944f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
97089a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
971e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
972e40d30f3SRui Ueyama }
973e40d30f3SRui Ueyama 
974e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
975e40d30f3SRui Ueyama                                               StringRef &Res) const {
97689a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
977e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
978e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
9798ff24d25SRui Ueyama       return EC;
9807d099195SRui Ueyama     return std::error_code();
98189a7a5eaSMichael J. Spencer   }
98289a7a5eaSMichael J. Spencer 
983e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
98489a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
985e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
98689a7a5eaSMichael J. Spencer   else
98789a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
988e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
9897d099195SRui Ueyama   return std::error_code();
99089a7a5eaSMichael J. Spencer }
99189a7a5eaSMichael J. Spencer 
99244f51e51SDavid Majnemer ArrayRef<uint8_t>
99344f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
9942617dcceSCraig Topper   const uint8_t *Aux = nullptr;
99571757ef3SMarshall Clow 
99644f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
99744f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
99871757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
99944f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
100071757ef3SMarshall Clow #ifndef NDEBUG
10018ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10028ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
100344f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
100444f51e51SDavid Majnemer         Offset >=
100544f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
100671757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
100771757ef3SMarshall Clow 
100844f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
100944f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
101071757ef3SMarshall Clow #endif
1011bfb85e67SMarshall Clow   }
101244f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
101371757ef3SMarshall Clow }
101471757ef3SMarshall Clow 
1015db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
101653c2d547SMichael J. Spencer                                                StringRef &Res) const {
101753c2d547SMichael J. Spencer   StringRef Name;
101844f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
101953c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
102053c2d547SMichael J. Spencer     Name = Sec->Name;
102153c2d547SMichael J. Spencer   else
102253c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
102344f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
102453c2d547SMichael J. Spencer 
102553c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10262314b3deSDavid Majnemer   if (Name.startswith("/")) {
102753c2d547SMichael J. Spencer     uint32_t Offset;
10282314b3deSDavid Majnemer     if (Name.startswith("//")) {
10299d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10309d2c15efSNico Rieck         return object_error::parse_failed;
10319d2c15efSNico Rieck     } else {
103253c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
103353c2d547SMichael J. Spencer         return object_error::parse_failed;
10349d2c15efSNico Rieck     }
1035db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10368ff24d25SRui Ueyama       return EC;
103753c2d547SMichael J. Spencer   }
103853c2d547SMichael J. Spencer 
103953c2d547SMichael J. Spencer   Res = Name;
10407d099195SRui Ueyama   return std::error_code();
104153c2d547SMichael J. Spencer }
104253c2d547SMichael J. Spencer 
1043a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1044a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1045a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1046a9ee5c06SDavid Majnemer   //
1047a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1048d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1049a9ee5c06SDavid Majnemer   //
1050a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1051a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1052a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1053a9ee5c06SDavid Majnemer   // considered to be zero.
1054d5297ee7SRui Ueyama   if (getDOSHeader())
1055d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1056d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1057a9ee5c06SDavid Majnemer }
1058a9ee5c06SDavid Majnemer 
1059db4ed0bdSRafael Espindola std::error_code
1060db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
10619da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1062e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1063e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1064e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1065*ee97c5f0SShoaib Meenai     return std::error_code();
10669da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10679da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10689da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10699da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1070a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1071e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
10729da9e693SMichael J. Spencer     return object_error::parse_failed;
1073a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
10747d099195SRui Ueyama   return std::error_code();
10759da9e693SMichael J. Spencer }
10769da9e693SMichael J. Spencer 
1077022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1078e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1079022ecdf2SBenjamin Kramer }
10808ff24d25SRui Ueyama 
10815e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1082e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1083e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1084022ecdf2SBenjamin Kramer }
10858ff24d25SRui Ueyama 
108696d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
108758323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
108896d071cdSRafael Espindola   return R->VirtualAddress;
1089cbe72fc9SDanil Malyshev }
10908ff24d25SRui Ueyama 
1091806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1092022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
10938ff24d25SRui Ueyama   DataRefImpl Ref;
1094236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1095236b0ca7SDavid Majnemer     return symbol_end();
109644f51e51SDavid Majnemer   if (SymbolTable16)
109744f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
109844f51e51SDavid Majnemer   else if (SymbolTable32)
109944f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
110044f51e51SDavid Majnemer   else
1101c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11028ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1103022ecdf2SBenjamin Kramer }
11048ff24d25SRui Ueyama 
110599c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1106022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
110799c041b7SRafael Espindola   return R->Type;
1108022ecdf2SBenjamin Kramer }
1109e5fd0047SMichael J. Spencer 
111027dc8394SAlexey Samsonov const coff_section *
111127dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
111227dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
111371757ef3SMarshall Clow }
111471757ef3SMarshall Clow 
111544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
111644f51e51SDavid Majnemer   if (SymbolTable16)
111744f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
111844f51e51SDavid Majnemer   if (SymbolTable32)
111944f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
112044f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
112144f51e51SDavid Majnemer }
112244f51e51SDavid Majnemer 
112344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
112444f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
112571757ef3SMarshall Clow }
112671757ef3SMarshall Clow 
1127f12b8282SRafael Espindola const coff_relocation *
112827dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
112927dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1130d3e2a76cSMarshall Clow }
1131d3e2a76cSMarshall Clow 
11326a75acb1SRui Ueyama iterator_range<const coff_relocation *>
11336a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11346a75acb1SRui Ueyama   const coff_relocation *I = getFirstReloc(Sec, Data, base());
11356a75acb1SRui Ueyama   const coff_relocation *E = I;
11366a75acb1SRui Ueyama   if (I)
11376a75acb1SRui Ueyama     E += getNumberOfRelocations(Sec, Data, base());
11386a75acb1SRui Ueyama   return make_range(I, E);
11396a75acb1SRui Ueyama }
11406a75acb1SRui Ueyama 
114127dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
114227dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
114327dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
114427dc8394SAlexey Samsonov     break;
1145e5fd0047SMichael J. Spencer 
114641bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
114741bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11488ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11498ff24d25SRui Ueyama   StringRef Res;
115044f51e51SDavid Majnemer   switch (getMachine()) {
1151e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11528ff24d25SRui Ueyama     switch (Reloc->Type) {
1153e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1154e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1155e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1156e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1157e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1158e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1159e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1160e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1161e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1162e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1163e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1164e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1165e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1166e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1167e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1168e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1169e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1170e5fd0047SMichael J. Spencer     default:
11718ff24d25SRui Ueyama       Res = "Unknown";
1172e5fd0047SMichael J. Spencer     }
1173e5fd0047SMichael J. Spencer     break;
11745c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
11755c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
11765c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11775c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11785c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11795c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11805c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11815c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
11825c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
11835c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
11845c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
11855c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
11865c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
11875c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
11885c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
11895c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
11905c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
11915c503bf4SSaleem Abdulrasool     default:
11925c503bf4SSaleem Abdulrasool       Res = "Unknown";
11935c503bf4SSaleem Abdulrasool     }
11945c503bf4SSaleem Abdulrasool     break;
1195e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
11968ff24d25SRui Ueyama     switch (Reloc->Type) {
1197e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1198e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1199e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1200e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1201e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1202e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1203e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1204e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1205e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1206e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1207e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1208e5fd0047SMichael J. Spencer     default:
12098ff24d25SRui Ueyama       Res = "Unknown";
1210e5fd0047SMichael J. Spencer     }
1211e5fd0047SMichael J. Spencer     break;
1212e5fd0047SMichael J. Spencer   default:
12138ff24d25SRui Ueyama     Res = "Unknown";
1214e5fd0047SMichael J. Spencer   }
12158ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1216e5fd0047SMichael J. Spencer }
1217e5fd0047SMichael J. Spencer 
1218e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1219e5fd0047SMichael J. Spencer 
1220c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1221c66d761bSRafael Espindola   return !DataDirectory;
1222c66d761bSRafael Espindola }
1223c66d761bSRafael Espindola 
1224c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1225c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1226a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1227c2bed429SRui Ueyama }
1228c2bed429SRui Ueyama 
12295e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12305e812afaSRafael Espindola   ++Index;
12311c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1232ad7b7e73SDavid Majnemer     Index = -1;
1233ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1234ad7b7e73SDavid Majnemer   }
1235c2bed429SRui Ueyama }
1236c2bed429SRui Ueyama 
1237db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12381c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1239ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1240c2bed429SRui Ueyama }
1241c2bed429SRui Ueyama 
1242861021f9SRui Ueyama static imported_symbol_iterator
124315d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1244861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
124515d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1246861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
124715d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1248861021f9SRui Ueyama   }
1249861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
125015d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1251861021f9SRui Ueyama }
1252861021f9SRui Ueyama 
125315d99359SRui Ueyama static imported_symbol_iterator
125415d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1255861021f9SRui Ueyama   uintptr_t IntPtr = 0;
125615d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
125715d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1258861021f9SRui Ueyama }
1259861021f9SRui Ueyama 
126015d99359SRui Ueyama static imported_symbol_iterator
126115d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1262861021f9SRui Ueyama   uintptr_t IntPtr = 0;
126315d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1264861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1265861021f9SRui Ueyama   int Index = 0;
126615d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1267861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1268861021f9SRui Ueyama     while (*Entry++)
1269861021f9SRui Ueyama       ++Index;
1270861021f9SRui Ueyama   } else {
1271861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1272861021f9SRui Ueyama     while (*Entry++)
1273861021f9SRui Ueyama       ++Index;
1274861021f9SRui Ueyama   }
127515d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
127615d99359SRui Ueyama }
127715d99359SRui Ueyama 
127815d99359SRui Ueyama imported_symbol_iterator
127915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
128060049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
128115d99359SRui Ueyama                              OwningObject);
128215d99359SRui Ueyama }
128315d99359SRui Ueyama 
128415d99359SRui Ueyama imported_symbol_iterator
128515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
128660049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
128715d99359SRui Ueyama                            OwningObject);
1288861021f9SRui Ueyama }
1289861021f9SRui Ueyama 
1290979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1291979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1292979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1293979fb40bSRui Ueyama }
1294979fb40bSRui Ueyama 
129560049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
129660049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
129760049526SDavid Majnemer                              OwningObject);
129860049526SDavid Majnemer }
129960049526SDavid Majnemer 
130060049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
130160049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
130260049526SDavid Majnemer                            OwningObject);
130360049526SDavid Majnemer }
130460049526SDavid Majnemer 
130560049526SDavid Majnemer iterator_range<imported_symbol_iterator>
130660049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
130760049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
130860049526SDavid Majnemer }
130960049526SDavid Majnemer 
1310db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1311c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1312db4ed0bdSRafael Espindola   if (std::error_code EC =
13131e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1314a045b73aSRui Ueyama     return EC;
1315a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13167d099195SRui Ueyama   return std::error_code();
1317c2bed429SRui Ueyama }
1318c2bed429SRui Ueyama 
13191e152d5eSRui Ueyama std::error_code
13201e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13211e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13227d099195SRui Ueyama   return std::error_code();
13231e152d5eSRui Ueyama }
13241e152d5eSRui Ueyama 
13251e152d5eSRui Ueyama std::error_code
13261e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13271e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13287d099195SRui Ueyama   return std::error_code();
13291e152d5eSRui Ueyama }
13301e152d5eSRui Ueyama 
133115d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
133215d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
133315d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
133415d99359SRui Ueyama }
133515d99359SRui Ueyama 
133615d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
133715d99359SRui Ueyama   ++Index;
133815d99359SRui Ueyama }
133915d99359SRui Ueyama 
134015d99359SRui Ueyama imported_symbol_iterator
134115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
134215d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
134315d99359SRui Ueyama                              OwningObject);
134415d99359SRui Ueyama }
134515d99359SRui Ueyama 
134615d99359SRui Ueyama imported_symbol_iterator
134715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
134815d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
134915d99359SRui Ueyama                            OwningObject);
135015d99359SRui Ueyama }
135115d99359SRui Ueyama 
1352979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1353979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1354979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1355979fb40bSRui Ueyama }
1356979fb40bSRui Ueyama 
135715d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
135815d99359SRui Ueyama   uintptr_t IntPtr = 0;
135915d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
136015d99359SRui Ueyama     return EC;
136115d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13627d099195SRui Ueyama   return std::error_code();
136315d99359SRui Ueyama }
136415d99359SRui Ueyama 
13651af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
13661af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
13671af08658SRui Ueyama   Result = Table;
13687d099195SRui Ueyama   return std::error_code();
13691af08658SRui Ueyama }
13701af08658SRui Ueyama 
1371ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1372ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1373ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1374ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1375ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1376ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1377ffa4cebeSRui Ueyama     return EC;
1378ffa4cebeSRui Ueyama   if (OwningObject->is64())
13795dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1380ffa4cebeSRui Ueyama   else
13815dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
13827d099195SRui Ueyama   return std::error_code();
1383ffa4cebeSRui Ueyama }
1384ffa4cebeSRui Ueyama 
1385ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1386ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1387ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1388ad882ba8SRui Ueyama }
1389ad882ba8SRui Ueyama 
13905e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
13915e812afaSRafael Espindola   ++Index;
1392ad882ba8SRui Ueyama }
1393ad882ba8SRui Ueyama 
1394da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1395da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1396db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1397da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1398db4ed0bdSRafael Espindola   if (std::error_code EC =
1399db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1400da49d0d4SRui Ueyama     return EC;
1401da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14027d099195SRui Ueyama   return std::error_code();
1403da49d0d4SRui Ueyama }
1404da49d0d4SRui Ueyama 
1405e5df6095SRui Ueyama // Returns the starting ordinal number.
1406db4ed0bdSRafael Espindola std::error_code
1407db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1408e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14097d099195SRui Ueyama   return std::error_code();
1410e5df6095SRui Ueyama }
1411e5df6095SRui Ueyama 
1412ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1413db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1414ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14157d099195SRui Ueyama   return std::error_code();
1416ad882ba8SRui Ueyama }
1417ad882ba8SRui Ueyama 
1418ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1419db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1420ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1421db4ed0bdSRafael Espindola   if (std::error_code EC =
1422db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1423ad882ba8SRui Ueyama     return EC;
142424fc2d64SRui Ueyama   const export_address_table_entry *entry =
142524fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1426ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14277d099195SRui Ueyama   return std::error_code();
1428ad882ba8SRui Ueyama }
1429ad882ba8SRui Ueyama 
1430ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1431ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1432db4ed0bdSRafael Espindola std::error_code
1433db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1434ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1435db4ed0bdSRafael Espindola   if (std::error_code EC =
1436db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1437ad882ba8SRui Ueyama     return EC;
1438ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1439ad882ba8SRui Ueyama 
1440ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1441ad882ba8SRui Ueyama   int Offset = 0;
1442ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1443ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1444ad882ba8SRui Ueyama     if (*I != Index)
1445ad882ba8SRui Ueyama       continue;
1446db4ed0bdSRafael Espindola     if (std::error_code EC =
1447db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1448ad882ba8SRui Ueyama       return EC;
1449ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1450db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1451ad882ba8SRui Ueyama       return EC;
1452ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14537d099195SRui Ueyama     return std::error_code();
1454ad882ba8SRui Ueyama   }
1455ad882ba8SRui Ueyama   Result = "";
14567d099195SRui Ueyama   return std::error_code();
1457ad882ba8SRui Ueyama }
1458ad882ba8SRui Ueyama 
14596161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
14606161b38dSRui Ueyama   const data_directory *DataEntry;
14616161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
14626161b38dSRui Ueyama     return EC;
14636161b38dSRui Ueyama   uint32_t RVA;
14646161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14656161b38dSRui Ueyama     return EC;
14666161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
14676161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
14686161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
14696161b38dSRui Ueyama   return std::error_code();
14706161b38dSRui Ueyama }
14716161b38dSRui Ueyama 
14726161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
14736161b38dSRui Ueyama   uint32_t RVA;
14746161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14756161b38dSRui Ueyama     return EC;
14766161b38dSRui Ueyama   uintptr_t IntPtr = 0;
14776161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
14786161b38dSRui Ueyama     return EC;
14796161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14806161b38dSRui Ueyama   return std::error_code();
14816161b38dSRui Ueyama }
14826161b38dSRui Ueyama 
1483861021f9SRui Ueyama bool ImportedSymbolRef::
1484861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1485861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1486861021f9SRui Ueyama       && Index == Other.Index;
1487861021f9SRui Ueyama }
1488861021f9SRui Ueyama 
1489861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1490861021f9SRui Ueyama   ++Index;
1491861021f9SRui Ueyama }
1492861021f9SRui Ueyama 
1493861021f9SRui Ueyama std::error_code
1494861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1495861021f9SRui Ueyama   uint32_t RVA;
1496861021f9SRui Ueyama   if (Entry32) {
1497861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1498861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
14997d099195SRui Ueyama       return std::error_code();
1500861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1501861021f9SRui Ueyama   } else {
1502861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15037d099195SRui Ueyama       return std::error_code();
1504861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1505861021f9SRui Ueyama   }
1506861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1507861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1508861021f9SRui Ueyama     return EC;
1509861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1510861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15117d099195SRui Ueyama   return std::error_code();
1512861021f9SRui Ueyama }
1513861021f9SRui Ueyama 
1514ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1515ad7b7e73SDavid Majnemer   if (Entry32)
1516ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1517ad7b7e73SDavid Majnemer   else
1518ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1519ad7b7e73SDavid Majnemer   return std::error_code();
1520ad7b7e73SDavid Majnemer }
1521ad7b7e73SDavid Majnemer 
1522ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1523ad7b7e73SDavid Majnemer   if (Entry32)
1524ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1525ad7b7e73SDavid Majnemer   else
1526ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1527ad7b7e73SDavid Majnemer   return std::error_code();
1528ad7b7e73SDavid Majnemer }
1529ad7b7e73SDavid Majnemer 
1530861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1531861021f9SRui Ueyama   uint32_t RVA;
1532861021f9SRui Ueyama   if (Entry32) {
1533861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1534861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15357d099195SRui Ueyama       return std::error_code();
1536861021f9SRui Ueyama     }
1537861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1538861021f9SRui Ueyama   } else {
1539861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1540861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15417d099195SRui Ueyama       return std::error_code();
1542861021f9SRui Ueyama     }
1543861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1544861021f9SRui Ueyama   }
1545861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1546861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1547861021f9SRui Ueyama     return EC;
1548861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15497d099195SRui Ueyama   return std::error_code();
1550861021f9SRui Ueyama }
1551861021f9SRui Ueyama 
1552437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>>
155348af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1554db4ed0bdSRafael Espindola   std::error_code EC;
155548af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1556692410efSRafael Espindola   if (EC)
1557692410efSRafael Espindola     return EC;
1558437b0d58SRafael Espindola   return std::move(Ret);
1559686738e2SRui Ueyama }
156074e85130SRui Ueyama 
156174e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
156274e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
156374e85130SRui Ueyama }
156474e85130SRui Ueyama 
156574e85130SRui Ueyama void BaseRelocRef::moveNext() {
156674e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
156774e85130SRui Ueyama   // size of the header itself.
156874e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1569970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
157074e85130SRui Ueyama   if (Size == Header->BlockSize) {
157174e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
157274e85130SRui Ueyama     // consists of the header followed by entries. The header contains
157374e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
157474e85130SRui Ueyama     // current block, proceed to the next block.
157574e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
157674e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
157774e85130SRui Ueyama     Index = 0;
157874e85130SRui Ueyama   } else {
157974e85130SRui Ueyama     ++Index;
158074e85130SRui Ueyama   }
158174e85130SRui Ueyama }
158274e85130SRui Ueyama 
158374e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
158474e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
158574e85130SRui Ueyama   Type = Entry[Index].getType();
15867d099195SRui Ueyama   return std::error_code();
158774e85130SRui Ueyama }
158874e85130SRui Ueyama 
158974e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
159074e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
159174e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
15927d099195SRui Ueyama   return std::error_code();
159374e85130SRui Ueyama }
1594efef15a0SEric Beckmann 
1595efef15a0SEric Beckmann #define RETURN_IF_ERROR(X)                                                     \
1596efef15a0SEric Beckmann   if (auto EC = errorToErrorCode(X))                                           \
1597efef15a0SEric Beckmann     return EC;
1598efef15a0SEric Beckmann 
1599cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1600efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1601efef15a0SEric Beckmann   Reader.setOffset(Offset);
1602efef15a0SEric Beckmann   uint16_t Length;
1603efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1604efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1605efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1606cd704cb6SEric Beckmann   return RawDirString;
1607efef15a0SEric Beckmann }
1608efef15a0SEric Beckmann 
1609cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>>
1610efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1611efef15a0SEric Beckmann   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1612efef15a0SEric Beckmann }
1613efef15a0SEric Beckmann 
1614efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1615efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1616efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1617efef15a0SEric Beckmann 
1618efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1619efef15a0SEric Beckmann   Reader.setOffset(Offset);
1620efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1621efef15a0SEric Beckmann   assert(Table != nullptr);
1622efef15a0SEric Beckmann   return *Table;
1623efef15a0SEric Beckmann }
1624efef15a0SEric Beckmann 
1625efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1626efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1627efef15a0SEric Beckmann   return getTableAtOffset(Entry.Offset.value());
1628efef15a0SEric Beckmann }
1629efef15a0SEric Beckmann 
1630efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1631efef15a0SEric Beckmann   return getTableAtOffset(0);
1632efef15a0SEric Beckmann }
1633