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"
22*efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
23f078eff3SRui Ueyama #include "llvm/Support/COFF.h"
24*efef15a0SEric Beckmann #include "llvm/Support/ConvertUTF.h"
25d341c932SEugene Zelenko #include "llvm/Support/Endian.h"
26d341c932SEugene Zelenko #include "llvm/Support/Error.h"
27d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
28d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h"
29d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
30d341c932SEugene Zelenko #include <algorithm>
31d341c932SEugene Zelenko #include <cassert>
32d341c932SEugene Zelenko #include <cstddef>
33d341c932SEugene Zelenko #include <cstdint>
34d341c932SEugene Zelenko #include <cstring>
359d2c15efSNico Rieck #include <limits>
36d341c932SEugene Zelenko #include <memory>
37d341c932SEugene Zelenko #include <system_error>
388e90adafSMichael J. Spencer 
398e90adafSMichael J. Spencer using namespace llvm;
408e90adafSMichael J. Spencer using namespace object;
418e90adafSMichael J. Spencer 
428e90adafSMichael J. Spencer using support::ulittle16_t;
438e90adafSMichael J. Spencer using support::ulittle32_t;
44861021f9SRui Ueyama using support::ulittle64_t;
458e90adafSMichael J. Spencer using support::little16_t;
468e90adafSMichael J. Spencer 
471d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4848af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
49c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
508ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
511d6167fdSMichael J. Spencer     return false;
521d6167fdSMichael J. Spencer   }
531d6167fdSMichael J. Spencer   return true;
548e90adafSMichael J. Spencer }
558e90adafSMichael J. Spencer 
56e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
5794751be7SDavid Majnemer                                    const uint64_t Size) {
58e830c60dSDavid Majnemer   if (Addr + Size < Addr || Addr + Size < Size ||
59e830c60dSDavid Majnemer       Addr + Size > uintptr_t(M.getBufferEnd()) ||
60e830c60dSDavid Majnemer       Addr < uintptr_t(M.getBufferStart())) {
61e830c60dSDavid Majnemer     return object_error::unexpected_eof;
62e830c60dSDavid Majnemer   }
637d099195SRui Ueyama   return std::error_code();
64e830c60dSDavid Majnemer }
65e830c60dSDavid Majnemer 
66ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
67ed64342bSRui Ueyama // Returns unexpected_eof if error.
68ed64342bSRui Ueyama template <typename T>
6948af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
7058323a97SDavid Majnemer                                  const void *Ptr,
71236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
72ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
73e830c60dSDavid Majnemer   if (std::error_code EC = checkOffset(M, Addr, Size))
74e830c60dSDavid Majnemer     return EC;
75ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
767d099195SRui Ueyama   return std::error_code();
771d6167fdSMichael J. Spencer }
781d6167fdSMichael J. Spencer 
799d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
809d2c15efSNico Rieck // prefixed slashes.
819d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
829d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
839d2c15efSNico Rieck   if (Str.size() > 6)
849d2c15efSNico Rieck     return true;
859d2c15efSNico Rieck 
869d2c15efSNico Rieck   uint64_t Value = 0;
879d2c15efSNico Rieck   while (!Str.empty()) {
889d2c15efSNico Rieck     unsigned CharVal;
899d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
909d2c15efSNico Rieck       CharVal = Str[0] - 'A';
919d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
929d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
939d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
949d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
959d2c15efSNico Rieck     else if (Str[0] == '+') // 62
965500b07cSRui Ueyama       CharVal = 62;
979d2c15efSNico Rieck     else if (Str[0] == '/') // 63
985500b07cSRui Ueyama       CharVal = 63;
999d2c15efSNico Rieck     else
1009d2c15efSNico Rieck       return true;
1019d2c15efSNico Rieck 
1029d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
1039d2c15efSNico Rieck     Str = Str.substr(1);
1049d2c15efSNico Rieck   }
1059d2c15efSNico Rieck 
1069d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
1079d2c15efSNico Rieck     return true;
1089d2c15efSNico Rieck 
1099d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
1109d2c15efSNico Rieck   return false;
1119d2c15efSNico Rieck }
1129d2c15efSNico Rieck 
11344f51e51SDavid Majnemer template <typename coff_symbol_type>
11444f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
11544f51e51SDavid Majnemer   const coff_symbol_type *Addr =
11644f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1171d6167fdSMichael J. Spencer 
118236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1191d6167fdSMichael J. Spencer #ifndef NDEBUG
1201d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1218ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1221d6167fdSMichael J. Spencer 
12344f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
12444f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1251d6167fdSMichael J. Spencer #endif
1261d6167fdSMichael J. Spencer 
1278ff24d25SRui Ueyama   return Addr;
1281d6167fdSMichael J. Spencer }
1291d6167fdSMichael J. Spencer 
1308ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1318ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1321d6167fdSMichael J. Spencer 
1331d6167fdSMichael J. Spencer #ifndef NDEBUG
1341d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
13544f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1361d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1371d6167fdSMichael J. Spencer 
1388ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1398ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1401d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1411d6167fdSMichael J. Spencer #endif
1421d6167fdSMichael J. Spencer 
1438ff24d25SRui Ueyama   return Addr;
1441d6167fdSMichael J. Spencer }
1451d6167fdSMichael J. Spencer 
1465e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
147236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
14844f51e51SDavid Majnemer   if (SymbolTable16) {
14944f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1508ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
151236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
15244f51e51SDavid Majnemer   } else if (SymbolTable32) {
15344f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
15444f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
155236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
15644f51e51SDavid Majnemer   } else {
15744f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
15844f51e51SDavid Majnemer   }
1591d6167fdSMichael J. Spencer }
1601d6167fdSMichael J. Spencer 
16181e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
16244f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1635d0c2ffaSRafael Espindola   StringRef Result;
164*efef15a0SEric Beckmann   if (std::error_code EC = getSymbolName(Symb, Result))
16581e8b7d9SKevin Enderby     return errorCodeToError(EC);
1665d0c2ffaSRafael Espindola   return Result;
1678e90adafSMichael J. Spencer }
1688e90adafSMichael J. Spencer 
169be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
170be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
171991af666SRafael Espindola }
172991af666SRafael Espindola 
1736b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1746b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1756b2bba14SDavide Italiano   // up to 32 bytes.
1766b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
17703a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1786b2bba14SDavide Italiano }
1796b2bba14SDavide Italiano 
180931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
181ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
18244f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
183c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
184991af666SRafael Espindola 
185991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
186991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
187ed067c45SRafael Espindola     return Result;
18854c9f3daSRafael Espindola 
1892617dcceSCraig Topper   const coff_section *Section = nullptr;
190c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
191931cb65dSKevin Enderby     return errorCodeToError(EC);
192991af666SRafael Espindola   Result += Section->VirtualAddress;
19347ea9eceSReid Kleckner 
19447ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
19547ea9eceSReid Kleckner   // return virtual addresses.
19621427adaSReid Kleckner   Result += getImageBase();
19747ea9eceSReid Kleckner 
198ed067c45SRafael Espindola   return Result;
199c7d7c6fbSDavid Majnemer }
200c7d7c6fbSDavid Majnemer 
2017bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
20244f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
203c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
20444f51e51SDavid Majnemer 
205e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
206e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
2072fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
2082fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
2092fa80cc5SRafael Espindola   if (Symb.isCommon())
2102fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2112fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2122fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2132fa80cc5SRafael Espindola 
2141a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2152fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2162fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2172fa80cc5SRafael Espindola 
2182fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2192fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2202fa80cc5SRafael Espindola 
2212fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
22275d1cf33SBenjamin Kramer }
22375d1cf33SBenjamin Kramer 
22420122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
22544f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
22620122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
22775d1cf33SBenjamin Kramer 
228c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2299dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2301df4b84dSDavid Meyer 
231c7d7c6fbSDavid Majnemer   if (Symb.isWeakExternal())
2321df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
2331df4b84dSDavid Meyer 
23444f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2351df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2361df4b84dSDavid Meyer 
237c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
238c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
239c7d7c6fbSDavid Majnemer 
240c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
241c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
242c7d7c6fbSDavid Majnemer 
243c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
244c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
245c7d7c6fbSDavid Majnemer 
246c7d7c6fbSDavid Majnemer   if (Symb.isAnyUndefined())
247c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
248c7d7c6fbSDavid Majnemer 
24920122a43SRafael Espindola   return Result;
25001759754SMichael J. Spencer }
25101759754SMichael J. Spencer 
252d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
253c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2545eb02e45SRafael Espindola   return Symb.getValue();
2558e90adafSMichael J. Spencer }
2568e90adafSMichael J. Spencer 
2577bd8d994SKevin Enderby Expected<section_iterator>
2588bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
25944f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2608bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2618bab889bSRafael Espindola     return section_end();
2622617dcceSCraig Topper   const coff_section *Sec = nullptr;
26344f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2647bd8d994SKevin Enderby     return errorCodeToError(EC);
2658bab889bSRafael Espindola   DataRefImpl Ret;
2668bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2678bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
26832173153SMichael J. Spencer }
26932173153SMichael J. Spencer 
2706bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2716bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2726bf32210SRafael Espindola   return Symb.getSectionNumber();
2736bf32210SRafael Espindola }
2746bf32210SRafael Espindola 
2755e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2768ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2778ff24d25SRui Ueyama   Sec += 1;
2788ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2798e90adafSMichael J. Spencer }
2808e90adafSMichael J. Spencer 
281db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2821d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2838ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2848ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2858e90adafSMichael J. Spencer }
2868e90adafSMichael J. Spencer 
28780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2888ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2897c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2907c6a071bSDavid Majnemer 
2917c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2927c6a071bSDavid Majnemer   // return virtual addresses.
29321427adaSReid Kleckner   Result += getImageBase();
2947c6a071bSDavid Majnemer   return Result;
2958e90adafSMichael J. Spencer }
2968e90adafSMichael J. Spencer 
29780291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
298a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2998e90adafSMichael J. Spencer }
3008e90adafSMichael J. Spencer 
301db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
3021d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
3038ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3049da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
305db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
3069da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
3079da9e693SMichael J. Spencer   return EC;
3088e90adafSMichael J. Spencer }
3098e90adafSMichael J. Spencer 
31080291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3118ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
312511391feSDavid Majnemer   return Sec->getAlignment();
3137989460aSMichael J. Spencer }
3147989460aSMichael J. Spencer 
315401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
316401e4e57SGeorge Rimar   return false;
317401e4e57SGeorge Rimar }
318401e4e57SGeorge Rimar 
31980291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3208ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32180291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3228e90adafSMichael J. Spencer }
3238e90adafSMichael J. Spencer 
32480291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3258ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32680291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
327800619f2SMichael J. Spencer }
328800619f2SMichael J. Spencer 
32980291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3308ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3311a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3321a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3331a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3341a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
335800619f2SMichael J. Spencer }
336800619f2SMichael J. Spencer 
3376bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3386bf32210SRafael Espindola   uintptr_t Offset =
3396bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3406bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3416bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3426bf32210SRafael Espindola }
3436bf32210SRafael Espindola 
34480291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3458ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3461a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3471a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3481a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3492138ef6dSPreston Gurd }
3502138ef6dSPreston Gurd 
351e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
352e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
353e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
354e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
355e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
356e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
357e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
358e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
359e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
360e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
361e830c60dSDavid Majnemer       return 0;
36298fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36398fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
364e830c60dSDavid Majnemer   }
365e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
366e830c60dSDavid Majnemer }
367e830c60dSDavid Majnemer 
36894751be7SDavid Majnemer static const coff_relocation *
36994751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37094751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37194751be7SDavid Majnemer   if (!NumRelocs)
37294751be7SDavid Majnemer     return nullptr;
373827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37494751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
375827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
376827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
377827c8a2bSRui Ueyama     // relocations.
378827c8a2bSRui Ueyama     begin++;
379827c8a2bSRui Ueyama   }
38094751be7SDavid Majnemer   if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
38194751be7SDavid Majnemer     return nullptr;
38294751be7SDavid Majnemer   return begin;
383827c8a2bSRui Ueyama }
38494751be7SDavid Majnemer 
38594751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38694751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38794751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38876d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38976d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
39094751be7SDavid Majnemer   DataRefImpl Ret;
39194751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3928ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
393e5fd0047SMichael J. Spencer }
394e5fd0047SMichael J. Spencer 
3958ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3968ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39794751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39894751be7SDavid Majnemer   if (I)
39994751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4008ff24d25SRui Ueyama   DataRefImpl Ret;
40194751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4028ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
403e5fd0047SMichael J. Spencer }
404e5fd0047SMichael J. Spencer 
405c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
406db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40744f51e51SDavid Majnemer   if (COFFHeader)
408236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
409236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
410236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
41144f51e51SDavid Majnemer       return EC;
41244f51e51SDavid Majnemer 
41344f51e51SDavid Majnemer   if (COFFBigObjHeader)
414236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
415236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
416236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4178ff24d25SRui Ueyama       return EC;
418c2bed429SRui Ueyama 
419c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
420c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
421c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
422f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42344f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
424f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
425c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42648af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4278ff24d25SRui Ueyama     return EC;
428c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
429db4ed0bdSRafael Espindola   if (std::error_code EC =
43048af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4318ff24d25SRui Ueyama     return EC;
432c2bed429SRui Ueyama 
433773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
434773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
435773a5795SNico Rieck   if (StringTableSize < 4)
436773a5795SNico Rieck       StringTableSize = 4;
437773a5795SNico Rieck 
438c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
439773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
440c2bed429SRui Ueyama     return  object_error::parse_failed;
4417d099195SRui Ueyama   return std::error_code();
442c2bed429SRui Ueyama }
443c2bed429SRui Ueyama 
44421427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
445e94fef7bSReid Kleckner   if (PE32Header)
44621427adaSReid Kleckner     return PE32Header->ImageBase;
447e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44821427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44921427adaSReid Kleckner   // This actually comes up in practice.
45021427adaSReid Kleckner   return 0;
451e94fef7bSReid Kleckner }
452e94fef7bSReid Kleckner 
453215a586cSRui Ueyama // Returns the file offset for the given VA.
454db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45521427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
456b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
457b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
458b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
459215a586cSRui Ueyama }
460215a586cSRui Ueyama 
461c2bed429SRui Ueyama // Returns the file offset for the given RVA.
462db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46327dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46427dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
465c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
466c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
467215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
468215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
469c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4707d099195SRui Ueyama       return std::error_code();
471c2bed429SRui Ueyama     }
472c2bed429SRui Ueyama   }
473c2bed429SRui Ueyama   return object_error::parse_failed;
474c2bed429SRui Ueyama }
475c2bed429SRui Ueyama 
4762da433eaSReid Kleckner std::error_code
4772da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4782da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4792da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4802da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4812da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4822da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4832da433eaSReid Kleckner     // overflow.
4842da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4852da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4862da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4872da433eaSReid Kleckner       uintptr_t Begin =
4882da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4892da433eaSReid Kleckner       Contents =
4902da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4912da433eaSReid Kleckner       return std::error_code();
4922da433eaSReid Kleckner     }
4932da433eaSReid Kleckner   }
4942da433eaSReid Kleckner   return object_error::parse_failed;
4952da433eaSReid Kleckner }
4962da433eaSReid Kleckner 
497c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
498c2bed429SRui Ueyama // table entry.
499db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
500db4ed0bdSRafael Espindola                                             StringRef &Name) const {
501c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
502db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5038ff24d25SRui Ueyama     return EC;
504c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
505c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
506c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5077d099195SRui Ueyama   return std::error_code();
508c2bed429SRui Ueyama }
509c2bed429SRui Ueyama 
51001528021SSaleem Abdulrasool std::error_code
51101528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51201528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5132da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5142da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5152da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5162da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5172da433eaSReid Kleckner     return EC;
51801528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5192da433eaSReid Kleckner     return object_error::parse_failed;
52001528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
52101528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5222da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5232da433eaSReid Kleckner                           InfoBytes.size());
5242da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5252da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5262da433eaSReid Kleckner   return std::error_code();
5272da433eaSReid Kleckner }
5282da433eaSReid Kleckner 
52901528021SSaleem Abdulrasool std::error_code
53001528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
531f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
532f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
533f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
534f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
535f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
536f27f3f84SReid Kleckner   PDBInfo = nullptr;
537f27f3f84SReid Kleckner   PDBFileName = StringRef();
538f27f3f84SReid Kleckner   return std::error_code();
539f27f3f84SReid Kleckner }
540f27f3f84SReid Kleckner 
541c2bed429SRui Ueyama // Find the import table.
542db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
543c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
544c2bed429SRui Ueyama   // the import table, do nothing.
545c2bed429SRui Ueyama   const data_directory *DataEntry;
546c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5477d099195SRui Ueyama     return std::error_code();
548c2bed429SRui Ueyama 
549c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
550c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5517d099195SRui Ueyama     return std::error_code();
552c2bed429SRui Ueyama 
553c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
554c2bed429SRui Ueyama 
555c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
556c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
557c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
558db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5598ff24d25SRui Ueyama     return EC;
560ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
561ad7b7e73SDavid Majnemer     return EC;
562c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5631c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5647d099195SRui Ueyama   return std::error_code();
565ad882ba8SRui Ueyama }
566c2bed429SRui Ueyama 
56715d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56815d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56915d99359SRui Ueyama   const data_directory *DataEntry;
57015d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5717d099195SRui Ueyama     return std::error_code();
57215d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5737d099195SRui Ueyama     return std::error_code();
57415d99359SRui Ueyama 
57515d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57615d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57715d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57815d99359SRui Ueyama 
57915d99359SRui Ueyama   uintptr_t IntPtr = 0;
58015d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
58115d99359SRui Ueyama     return EC;
58215d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58315d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5847d099195SRui Ueyama   return std::error_code();
58515d99359SRui Ueyama }
58615d99359SRui Ueyama 
587ad882ba8SRui Ueyama // Find the export table.
588db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
589ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
590ad882ba8SRui Ueyama   // the export table, do nothing.
591ad882ba8SRui Ueyama   const data_directory *DataEntry;
592ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5937d099195SRui Ueyama     return std::error_code();
594ad882ba8SRui Ueyama 
595ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
596ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5977d099195SRui Ueyama     return std::error_code();
598ad882ba8SRui Ueyama 
599ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
600ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
601db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
602ad882ba8SRui Ueyama     return EC;
60324fc2d64SRui Ueyama   ExportDirectory =
60424fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6057d099195SRui Ueyama   return std::error_code();
606c2bed429SRui Ueyama }
607c2bed429SRui Ueyama 
60874e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60974e85130SRui Ueyama   const data_directory *DataEntry;
61074e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6117d099195SRui Ueyama     return std::error_code();
61274e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6137d099195SRui Ueyama     return std::error_code();
61474e85130SRui Ueyama 
61574e85130SRui Ueyama   uintptr_t IntPtr = 0;
61674e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61774e85130SRui Ueyama     return EC;
61874e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61974e85130SRui Ueyama       IntPtr);
62074e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
62174e85130SRui Ueyama       IntPtr + DataEntry->Size);
6227d099195SRui Ueyama   return std::error_code();
62374e85130SRui Ueyama }
62474e85130SRui Ueyama 
6252da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6262da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6272da433eaSReid Kleckner   const data_directory *DataEntry;
6282da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6292da433eaSReid Kleckner     return std::error_code();
6302da433eaSReid Kleckner 
6312da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6322da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6332da433eaSReid Kleckner     return std::error_code();
6342da433eaSReid Kleckner 
6352da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6362da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6372da433eaSReid Kleckner     return object_error::parse_failed;
6382da433eaSReid Kleckner 
6392da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6402da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6412da433eaSReid Kleckner     return EC;
6422da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6432da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6442da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6452da433eaSReid Kleckner     return EC;
6462da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6472da433eaSReid Kleckner   return std::error_code();
6482da433eaSReid Kleckner }
6492da433eaSReid Kleckner 
65048af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
65148af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
65244f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
65344f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
65444f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
655ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
65615d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6572da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6582da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6591d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
66048af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
661c3f9b5a5SRafael Espindola     return;
662ee066fc4SEric Christopher 
66382ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
66482ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
66582ebd8e3SRui Ueyama 
66682ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
66782ebd8e3SRui Ueyama   // it is placed right after COFF header.
6688ff24d25SRui Ueyama   bool HasPEHeader = false;
669ee066fc4SEric Christopher 
6701d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
67150267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
672ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
673ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
67450267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
67550267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
67650267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
67782ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
67850267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6798ff24d25SRui Ueyama         EC = object_error::parse_failed;
6801d6167fdSMichael J. Spencer         return;
6811d6167fdSMichael J. Spencer       }
68244f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6838ff24d25SRui Ueyama       HasPEHeader = true;
684ee066fc4SEric Christopher     }
68550267222SDavid Majnemer   }
686ee066fc4SEric Christopher 
68748af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
6881d6167fdSMichael J. Spencer     return;
68944f51e51SDavid Majnemer 
69044f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
69144f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
69244f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
69344f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
69444f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
69544f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
69644f51e51SDavid Majnemer       return;
69744f51e51SDavid Majnemer 
69844f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
69944f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
70044f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
70144f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
70244f51e51SDavid Majnemer       COFFHeader = nullptr;
70344f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
70444f51e51SDavid Majnemer     } else {
70544f51e51SDavid Majnemer       // It's not a bigobj.
70644f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
70744f51e51SDavid Majnemer     }
70844f51e51SDavid Majnemer   }
70944f51e51SDavid Majnemer   if (COFFHeader) {
71044f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
71144f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7127d099195SRui Ueyama     EC = std::error_code();
71382ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
71482ebd8e3SRui Ueyama 
71544f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
71644f51e51SDavid Majnemer       return;
71744f51e51SDavid Majnemer   }
71844f51e51SDavid Majnemer 
7198ff24d25SRui Ueyama   if (HasPEHeader) {
72010ed9ddcSRui Ueyama     const pe32_header *Header;
72148af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
72282ebd8e3SRui Ueyama       return;
72310ed9ddcSRui Ueyama 
72410ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
72510ed9ddcSRui Ueyama     uint64_t DataDirSize;
72650267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
72710ed9ddcSRui Ueyama       PE32Header = Header;
72810ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
72910ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
73050267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
73110ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
73210ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
73310ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
73410ed9ddcSRui Ueyama     } else {
73510ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
73610ed9ddcSRui Ueyama       EC = object_error::parse_failed;
737ed64342bSRui Ueyama       return;
738ed64342bSRui Ueyama     }
73948af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
74010ed9ddcSRui Ueyama       return;
741f53c8cb4SRui Ueyama   }
742776c6828SRui Ueyama 
7438950a538SRui Ueyama   if (COFFHeader)
7448950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7458950a538SRui Ueyama 
74648af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
747236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7481d6167fdSMichael J. Spencer     return;
7491d6167fdSMichael J. Spencer 
750c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
751236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
752ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
753ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
754ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
755ac8cfab5SDavid Majnemer       StringTable = nullptr;
756ac8cfab5SDavid Majnemer       StringTableSize = 0;
757ac8cfab5SDavid Majnemer     }
758236b0ca7SDavid Majnemer   } else {
759236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
760236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
761236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
762236b0ca7SDavid Majnemer       return;
763236b0ca7SDavid Majnemer     }
764236b0ca7SDavid Majnemer   }
7658e90adafSMichael J. Spencer 
766c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7678ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
768ed64342bSRui Ueyama     return;
76915d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
77015d99359SRui Ueyama     return;
7711d6167fdSMichael J. Spencer 
772ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7738ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
774ad882ba8SRui Ueyama     return;
775ad882ba8SRui Ueyama 
77674e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
77774e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
77874e85130SRui Ueyama     return;
77974e85130SRui Ueyama 
7802da433eaSReid Kleckner   // Initialize the pointer to the export table.
7812da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7822da433eaSReid Kleckner     return;
7832da433eaSReid Kleckner 
7847d099195SRui Ueyama   EC = std::error_code();
7858e90adafSMichael J. Spencer }
7868e90adafSMichael J. Spencer 
787435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
7888ff24d25SRui Ueyama   DataRefImpl Ret;
78944f51e51SDavid Majnemer   Ret.p = getSymbolTable();
790f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7918e90adafSMichael J. Spencer }
7928e90adafSMichael J. Spencer 
793435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
7948e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
7958ff24d25SRui Ueyama   DataRefImpl Ret;
7968ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
797f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7988e90adafSMichael J. Spencer }
7998e90adafSMichael J. Spencer 
800bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
801ad7b7e73SDavid Majnemer   if (!ImportDirectory)
802ad7b7e73SDavid Majnemer     return import_directory_end();
8031c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
804ad7b7e73SDavid Majnemer     return import_directory_end();
805a045b73aSRui Ueyama   return import_directory_iterator(
806a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
807c2bed429SRui Ueyama }
808c2bed429SRui Ueyama 
809bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
810a045b73aSRui Ueyama   return import_directory_iterator(
811ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
812c2bed429SRui Ueyama }
813c429b80dSDavid Meyer 
81415d99359SRui Ueyama delay_import_directory_iterator
81515d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
81615d99359SRui Ueyama   return delay_import_directory_iterator(
81715d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
81815d99359SRui Ueyama }
81915d99359SRui Ueyama 
82015d99359SRui Ueyama delay_import_directory_iterator
82115d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
82215d99359SRui Ueyama   return delay_import_directory_iterator(
82315d99359SRui Ueyama       DelayImportDirectoryEntryRef(
82415d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
82515d99359SRui Ueyama }
82615d99359SRui Ueyama 
827ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
828ad882ba8SRui Ueyama   return export_directory_iterator(
829ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
830ad882ba8SRui Ueyama }
831ad882ba8SRui Ueyama 
832ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8332617dcceSCraig Topper   if (!ExportDirectory)
8342617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8358ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
836ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8378ff24d25SRui Ueyama   return export_directory_iterator(Ref);
838ad882ba8SRui Ueyama }
839ad882ba8SRui Ueyama 
840b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8418ff24d25SRui Ueyama   DataRefImpl Ret;
8428ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8438ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8448e90adafSMichael J. Spencer }
8458e90adafSMichael J. Spencer 
846b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8478ff24d25SRui Ueyama   DataRefImpl Ret;
84844f51e51SDavid Majnemer   int NumSections =
84944f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8508ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8518ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8528e90adafSMichael J. Spencer }
8538e90adafSMichael J. Spencer 
85474e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
85574e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
85674e85130SRui Ueyama }
85774e85130SRui Ueyama 
85874e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
85974e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
86074e85130SRui Ueyama }
86174e85130SRui Ueyama 
8628e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
8630324b672SMichael J. Spencer   return getArch() == Triple::x86_64 ? 8 : 4;
8648e90adafSMichael J. Spencer }
8658e90adafSMichael J. Spencer 
8668e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
86744f51e51SDavid Majnemer   switch(getMachine()) {
8688e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8698e90adafSMichael J. Spencer     return "COFF-i386";
8708e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8718e90adafSMichael J. Spencer     return "COFF-x86-64";
8729b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8739b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8741eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8751eff5c9cSMartell Malone     return "COFF-ARM64";
8768e90adafSMichael J. Spencer   default:
8778e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8788e90adafSMichael J. Spencer   }
8798e90adafSMichael J. Spencer }
8808e90adafSMichael J. Spencer 
8818e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const {
88244f51e51SDavid Majnemer   switch (getMachine()) {
8838e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8848e90adafSMichael J. Spencer     return Triple::x86;
8858e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8868e90adafSMichael J. Spencer     return Triple::x86_64;
8879b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8889b7c0af2SSaleem Abdulrasool     return Triple::thumb;
8891eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8901eff5c9cSMartell Malone     return Triple::aarch64;
8918e90adafSMichael J. Spencer   default:
8928e90adafSMichael J. Spencer     return Triple::UnknownArch;
8938e90adafSMichael J. Spencer   }
8948e90adafSMichael J. Spencer }
8958e90adafSMichael J. Spencer 
896979fb40bSRui Ueyama iterator_range<import_directory_iterator>
897979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
898979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
899979fb40bSRui Ueyama }
900979fb40bSRui Ueyama 
901979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
902979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
903979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
904979fb40bSRui Ueyama                     delay_import_directory_end());
905979fb40bSRui Ueyama }
906979fb40bSRui Ueyama 
907979fb40bSRui Ueyama iterator_range<export_directory_iterator>
908979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
909979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
910979fb40bSRui Ueyama }
911979fb40bSRui Ueyama 
91274e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
91374e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
91474e85130SRui Ueyama }
91574e85130SRui Ueyama 
916db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
91782ebd8e3SRui Ueyama   Res = PE32Header;
9187d099195SRui Ueyama   return std::error_code();
91989a7a5eaSMichael J. Spencer }
92089a7a5eaSMichael J. Spencer 
921db4ed0bdSRafael Espindola std::error_code
92210ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
92310ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9247d099195SRui Ueyama   return std::error_code();
92510ed9ddcSRui Ueyama }
92610ed9ddcSRui Ueyama 
927db4ed0bdSRafael Espindola std::error_code
928db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
929ed64342bSRui Ueyama                                  const data_directory *&Res) const {
930ed64342bSRui Ueyama   // Error if if there's no data directory or the index is out of range.
931f69b0585SDavid Majnemer   if (!DataDirectory) {
932f69b0585SDavid Majnemer     Res = nullptr;
93310ed9ddcSRui Ueyama     return object_error::parse_failed;
934f69b0585SDavid Majnemer   }
93510ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
93610ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
93710ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
938f69b0585SDavid Majnemer   if (Index >= NumEnt) {
939f69b0585SDavid Majnemer     Res = nullptr;
940ed64342bSRui Ueyama     return object_error::parse_failed;
941f69b0585SDavid Majnemer   }
9428ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9437d099195SRui Ueyama   return std::error_code();
944ed64342bSRui Ueyama }
945ed64342bSRui Ueyama 
946db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9471d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9482617dcceSCraig Topper   Result = nullptr;
949236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9507d099195SRui Ueyama     return std::error_code();
951236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9521d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9538ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9547d099195SRui Ueyama     return std::error_code();
9558e90adafSMichael J. Spencer   }
956236b0ca7SDavid Majnemer   return object_error::parse_failed;
957236b0ca7SDavid Majnemer }
9588e90adafSMichael J. Spencer 
959db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9601d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9611d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9621d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9631d6167fdSMichael J. Spencer     return object_error::parse_failed;
9648ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9651d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
9668ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
9677d099195SRui Ueyama   return std::error_code();
9688e90adafSMichael J. Spencer }
969022ecdf2SBenjamin Kramer 
97044f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
97189a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
972e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
973e40d30f3SRui Ueyama }
974e40d30f3SRui Ueyama 
975e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
976e40d30f3SRui Ueyama                                               StringRef &Res) const {
97789a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
978e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
979e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
9808ff24d25SRui Ueyama       return EC;
9817d099195SRui Ueyama     return std::error_code();
98289a7a5eaSMichael J. Spencer   }
98389a7a5eaSMichael J. Spencer 
984e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
98589a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
986e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
98789a7a5eaSMichael J. Spencer   else
98889a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
989e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
9907d099195SRui Ueyama   return std::error_code();
99189a7a5eaSMichael J. Spencer }
99289a7a5eaSMichael J. Spencer 
99344f51e51SDavid Majnemer ArrayRef<uint8_t>
99444f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
9952617dcceSCraig Topper   const uint8_t *Aux = nullptr;
99671757ef3SMarshall Clow 
99744f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
99844f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
99971757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
100044f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
100171757ef3SMarshall Clow #ifndef NDEBUG
10028ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10038ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
100444f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
100544f51e51SDavid Majnemer         Offset >=
100644f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
100771757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
100871757ef3SMarshall Clow 
100944f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
101044f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
101171757ef3SMarshall Clow #endif
1012bfb85e67SMarshall Clow   }
101344f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
101471757ef3SMarshall Clow }
101571757ef3SMarshall Clow 
1016db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
101753c2d547SMichael J. Spencer                                                StringRef &Res) const {
101853c2d547SMichael J. Spencer   StringRef Name;
101944f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
102053c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
102153c2d547SMichael J. Spencer     Name = Sec->Name;
102253c2d547SMichael J. Spencer   else
102353c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
102444f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
102553c2d547SMichael J. Spencer 
102653c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10272314b3deSDavid Majnemer   if (Name.startswith("/")) {
102853c2d547SMichael J. Spencer     uint32_t Offset;
10292314b3deSDavid Majnemer     if (Name.startswith("//")) {
10309d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10319d2c15efSNico Rieck         return object_error::parse_failed;
10329d2c15efSNico Rieck     } else {
103353c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
103453c2d547SMichael J. Spencer         return object_error::parse_failed;
10359d2c15efSNico Rieck     }
1036db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10378ff24d25SRui Ueyama       return EC;
103853c2d547SMichael J. Spencer   }
103953c2d547SMichael J. Spencer 
104053c2d547SMichael J. Spencer   Res = Name;
10417d099195SRui Ueyama   return std::error_code();
104253c2d547SMichael J. Spencer }
104353c2d547SMichael J. Spencer 
1044a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1045a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1046a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1047a9ee5c06SDavid Majnemer   //
1048a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1049d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1050a9ee5c06SDavid Majnemer   //
1051a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1052a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1053a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1054a9ee5c06SDavid Majnemer   // considered to be zero.
1055d5297ee7SRui Ueyama   if (getDOSHeader())
1056d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1057d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1058a9ee5c06SDavid Majnemer }
1059a9ee5c06SDavid Majnemer 
1060db4ed0bdSRafael Espindola std::error_code
1061db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
10629da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1063e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1064e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1065e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1066e2129662SDavid Majnemer     return object_error::parse_failed;
10679da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10689da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10699da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10709da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1071a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1072e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
10739da9e693SMichael J. Spencer     return object_error::parse_failed;
1074a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
10757d099195SRui Ueyama   return std::error_code();
10769da9e693SMichael J. Spencer }
10779da9e693SMichael J. Spencer 
1078022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1079e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1080022ecdf2SBenjamin Kramer }
10818ff24d25SRui Ueyama 
10825e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1083e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1084e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1085022ecdf2SBenjamin Kramer }
10868ff24d25SRui Ueyama 
108796d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
108858323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
108996d071cdSRafael Espindola   return R->VirtualAddress;
1090cbe72fc9SDanil Malyshev }
10918ff24d25SRui Ueyama 
1092806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1093022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
10948ff24d25SRui Ueyama   DataRefImpl Ref;
1095236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1096236b0ca7SDavid Majnemer     return symbol_end();
109744f51e51SDavid Majnemer   if (SymbolTable16)
109844f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
109944f51e51SDavid Majnemer   else if (SymbolTable32)
110044f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
110144f51e51SDavid Majnemer   else
1102c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11038ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1104022ecdf2SBenjamin Kramer }
11058ff24d25SRui Ueyama 
110699c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1107022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
110899c041b7SRafael Espindola   return R->Type;
1109022ecdf2SBenjamin Kramer }
1110e5fd0047SMichael J. Spencer 
111127dc8394SAlexey Samsonov const coff_section *
111227dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
111327dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
111471757ef3SMarshall Clow }
111571757ef3SMarshall Clow 
111644f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
111744f51e51SDavid Majnemer   if (SymbolTable16)
111844f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
111944f51e51SDavid Majnemer   if (SymbolTable32)
112044f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
112144f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
112244f51e51SDavid Majnemer }
112344f51e51SDavid Majnemer 
112444f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
112544f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
112671757ef3SMarshall Clow }
112771757ef3SMarshall Clow 
1128f12b8282SRafael Espindola const coff_relocation *
112927dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
113027dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1131d3e2a76cSMarshall Clow }
1132d3e2a76cSMarshall Clow 
11336a75acb1SRui Ueyama iterator_range<const coff_relocation *>
11346a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11356a75acb1SRui Ueyama   const coff_relocation *I = getFirstReloc(Sec, Data, base());
11366a75acb1SRui Ueyama   const coff_relocation *E = I;
11376a75acb1SRui Ueyama   if (I)
11386a75acb1SRui Ueyama     E += getNumberOfRelocations(Sec, Data, base());
11396a75acb1SRui Ueyama   return make_range(I, E);
11406a75acb1SRui Ueyama }
11416a75acb1SRui Ueyama 
114227dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
114327dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
114427dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
114527dc8394SAlexey Samsonov     break;
1146e5fd0047SMichael J. Spencer 
114741bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
114841bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11498ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11508ff24d25SRui Ueyama   StringRef Res;
115144f51e51SDavid Majnemer   switch (getMachine()) {
1152e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11538ff24d25SRui Ueyama     switch (Reloc->Type) {
1154e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1155e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1156e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1157e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1158e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1159e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1160e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1161e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1162e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1163e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1164e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1165e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1166e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1167e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1168e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1169e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1170e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1171e5fd0047SMichael J. Spencer     default:
11728ff24d25SRui Ueyama       Res = "Unknown";
1173e5fd0047SMichael J. Spencer     }
1174e5fd0047SMichael J. Spencer     break;
11755c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
11765c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
11775c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11785c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11795c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11805c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11815c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11825c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
11835c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
11845c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
11855c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
11865c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
11875c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
11885c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
11895c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
11905c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
11915c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
11925c503bf4SSaleem Abdulrasool     default:
11935c503bf4SSaleem Abdulrasool       Res = "Unknown";
11945c503bf4SSaleem Abdulrasool     }
11955c503bf4SSaleem Abdulrasool     break;
1196e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
11978ff24d25SRui Ueyama     switch (Reloc->Type) {
1198e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1199e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1200e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1201e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1202e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1203e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1204e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1205e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1206e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1207e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1208e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1209e5fd0047SMichael J. Spencer     default:
12108ff24d25SRui Ueyama       Res = "Unknown";
1211e5fd0047SMichael J. Spencer     }
1212e5fd0047SMichael J. Spencer     break;
1213e5fd0047SMichael J. Spencer   default:
12148ff24d25SRui Ueyama     Res = "Unknown";
1215e5fd0047SMichael J. Spencer   }
12168ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1217e5fd0047SMichael J. Spencer }
1218e5fd0047SMichael J. Spencer 
1219e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1220e5fd0047SMichael J. Spencer 
1221c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1222c66d761bSRafael Espindola   return !DataDirectory;
1223c66d761bSRafael Espindola }
1224c66d761bSRafael Espindola 
1225c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1226c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1227a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1228c2bed429SRui Ueyama }
1229c2bed429SRui Ueyama 
12305e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12315e812afaSRafael Espindola   ++Index;
12321c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1233ad7b7e73SDavid Majnemer     Index = -1;
1234ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1235ad7b7e73SDavid Majnemer   }
1236c2bed429SRui Ueyama }
1237c2bed429SRui Ueyama 
1238db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12391c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1240ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1241c2bed429SRui Ueyama }
1242c2bed429SRui Ueyama 
1243861021f9SRui Ueyama static imported_symbol_iterator
124415d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1245861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
124615d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1247861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
124815d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1249861021f9SRui Ueyama   }
1250861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
125115d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1252861021f9SRui Ueyama }
1253861021f9SRui Ueyama 
125415d99359SRui Ueyama static imported_symbol_iterator
125515d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1256861021f9SRui Ueyama   uintptr_t IntPtr = 0;
125715d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
125815d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1259861021f9SRui Ueyama }
1260861021f9SRui Ueyama 
126115d99359SRui Ueyama static imported_symbol_iterator
126215d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1263861021f9SRui Ueyama   uintptr_t IntPtr = 0;
126415d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1265861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1266861021f9SRui Ueyama   int Index = 0;
126715d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1268861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1269861021f9SRui Ueyama     while (*Entry++)
1270861021f9SRui Ueyama       ++Index;
1271861021f9SRui Ueyama   } else {
1272861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1273861021f9SRui Ueyama     while (*Entry++)
1274861021f9SRui Ueyama       ++Index;
1275861021f9SRui Ueyama   }
127615d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
127715d99359SRui Ueyama }
127815d99359SRui Ueyama 
127915d99359SRui Ueyama imported_symbol_iterator
128015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
128160049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
128215d99359SRui Ueyama                              OwningObject);
128315d99359SRui Ueyama }
128415d99359SRui Ueyama 
128515d99359SRui Ueyama imported_symbol_iterator
128615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
128760049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
128815d99359SRui Ueyama                            OwningObject);
1289861021f9SRui Ueyama }
1290861021f9SRui Ueyama 
1291979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1292979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1293979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1294979fb40bSRui Ueyama }
1295979fb40bSRui Ueyama 
129660049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
129760049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
129860049526SDavid Majnemer                              OwningObject);
129960049526SDavid Majnemer }
130060049526SDavid Majnemer 
130160049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
130260049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
130360049526SDavid Majnemer                            OwningObject);
130460049526SDavid Majnemer }
130560049526SDavid Majnemer 
130660049526SDavid Majnemer iterator_range<imported_symbol_iterator>
130760049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
130860049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
130960049526SDavid Majnemer }
131060049526SDavid Majnemer 
1311db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1312c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1313db4ed0bdSRafael Espindola   if (std::error_code EC =
13141e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1315a045b73aSRui Ueyama     return EC;
1316a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13177d099195SRui Ueyama   return std::error_code();
1318c2bed429SRui Ueyama }
1319c2bed429SRui Ueyama 
13201e152d5eSRui Ueyama std::error_code
13211e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13221e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13237d099195SRui Ueyama   return std::error_code();
13241e152d5eSRui Ueyama }
13251e152d5eSRui Ueyama 
13261e152d5eSRui Ueyama std::error_code
13271e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13281e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13297d099195SRui Ueyama   return std::error_code();
13301e152d5eSRui Ueyama }
13311e152d5eSRui Ueyama 
133215d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
133315d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
133415d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
133515d99359SRui Ueyama }
133615d99359SRui Ueyama 
133715d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
133815d99359SRui Ueyama   ++Index;
133915d99359SRui Ueyama }
134015d99359SRui Ueyama 
134115d99359SRui Ueyama imported_symbol_iterator
134215d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
134315d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
134415d99359SRui Ueyama                              OwningObject);
134515d99359SRui Ueyama }
134615d99359SRui Ueyama 
134715d99359SRui Ueyama imported_symbol_iterator
134815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
134915d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
135015d99359SRui Ueyama                            OwningObject);
135115d99359SRui Ueyama }
135215d99359SRui Ueyama 
1353979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1354979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1355979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1356979fb40bSRui Ueyama }
1357979fb40bSRui Ueyama 
135815d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
135915d99359SRui Ueyama   uintptr_t IntPtr = 0;
136015d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
136115d99359SRui Ueyama     return EC;
136215d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13637d099195SRui Ueyama   return std::error_code();
136415d99359SRui Ueyama }
136515d99359SRui Ueyama 
13661af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
13671af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
13681af08658SRui Ueyama   Result = Table;
13697d099195SRui Ueyama   return std::error_code();
13701af08658SRui Ueyama }
13711af08658SRui Ueyama 
1372ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1373ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1374ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1375ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1376ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1377ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1378ffa4cebeSRui Ueyama     return EC;
1379ffa4cebeSRui Ueyama   if (OwningObject->is64())
13805dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1381ffa4cebeSRui Ueyama   else
13825dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
13837d099195SRui Ueyama   return std::error_code();
1384ffa4cebeSRui Ueyama }
1385ffa4cebeSRui Ueyama 
1386ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1387ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1388ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1389ad882ba8SRui Ueyama }
1390ad882ba8SRui Ueyama 
13915e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
13925e812afaSRafael Espindola   ++Index;
1393ad882ba8SRui Ueyama }
1394ad882ba8SRui Ueyama 
1395da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1396da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1397db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1398da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1399db4ed0bdSRafael Espindola   if (std::error_code EC =
1400db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1401da49d0d4SRui Ueyama     return EC;
1402da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14037d099195SRui Ueyama   return std::error_code();
1404da49d0d4SRui Ueyama }
1405da49d0d4SRui Ueyama 
1406e5df6095SRui Ueyama // Returns the starting ordinal number.
1407db4ed0bdSRafael Espindola std::error_code
1408db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1409e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14107d099195SRui Ueyama   return std::error_code();
1411e5df6095SRui Ueyama }
1412e5df6095SRui Ueyama 
1413ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1414db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1415ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14167d099195SRui Ueyama   return std::error_code();
1417ad882ba8SRui Ueyama }
1418ad882ba8SRui Ueyama 
1419ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1420db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1421ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1422db4ed0bdSRafael Espindola   if (std::error_code EC =
1423db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1424ad882ba8SRui Ueyama     return EC;
142524fc2d64SRui Ueyama   const export_address_table_entry *entry =
142624fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1427ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14287d099195SRui Ueyama   return std::error_code();
1429ad882ba8SRui Ueyama }
1430ad882ba8SRui Ueyama 
1431ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1432ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1433db4ed0bdSRafael Espindola std::error_code
1434db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1435ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1436db4ed0bdSRafael Espindola   if (std::error_code EC =
1437db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1438ad882ba8SRui Ueyama     return EC;
1439ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1440ad882ba8SRui Ueyama 
1441ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1442ad882ba8SRui Ueyama   int Offset = 0;
1443ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1444ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1445ad882ba8SRui Ueyama     if (*I != Index)
1446ad882ba8SRui Ueyama       continue;
1447db4ed0bdSRafael Espindola     if (std::error_code EC =
1448db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1449ad882ba8SRui Ueyama       return EC;
1450ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1451db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1452ad882ba8SRui Ueyama       return EC;
1453ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14547d099195SRui Ueyama     return std::error_code();
1455ad882ba8SRui Ueyama   }
1456ad882ba8SRui Ueyama   Result = "";
14577d099195SRui Ueyama   return std::error_code();
1458ad882ba8SRui Ueyama }
1459ad882ba8SRui Ueyama 
14606161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
14616161b38dSRui Ueyama   const data_directory *DataEntry;
14626161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
14636161b38dSRui Ueyama     return EC;
14646161b38dSRui Ueyama   uint32_t RVA;
14656161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14666161b38dSRui Ueyama     return EC;
14676161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
14686161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
14696161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
14706161b38dSRui Ueyama   return std::error_code();
14716161b38dSRui Ueyama }
14726161b38dSRui Ueyama 
14736161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
14746161b38dSRui Ueyama   uint32_t RVA;
14756161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14766161b38dSRui Ueyama     return EC;
14776161b38dSRui Ueyama   uintptr_t IntPtr = 0;
14786161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
14796161b38dSRui Ueyama     return EC;
14806161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14816161b38dSRui Ueyama   return std::error_code();
14826161b38dSRui Ueyama }
14836161b38dSRui Ueyama 
1484861021f9SRui Ueyama bool ImportedSymbolRef::
1485861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1486861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1487861021f9SRui Ueyama       && Index == Other.Index;
1488861021f9SRui Ueyama }
1489861021f9SRui Ueyama 
1490861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1491861021f9SRui Ueyama   ++Index;
1492861021f9SRui Ueyama }
1493861021f9SRui Ueyama 
1494861021f9SRui Ueyama std::error_code
1495861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1496861021f9SRui Ueyama   uint32_t RVA;
1497861021f9SRui Ueyama   if (Entry32) {
1498861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1499861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15007d099195SRui Ueyama       return std::error_code();
1501861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1502861021f9SRui Ueyama   } else {
1503861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15047d099195SRui Ueyama       return std::error_code();
1505861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1506861021f9SRui Ueyama   }
1507861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1508861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1509861021f9SRui Ueyama     return EC;
1510861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1511861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15127d099195SRui Ueyama   return std::error_code();
1513861021f9SRui Ueyama }
1514861021f9SRui Ueyama 
1515ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1516ad7b7e73SDavid Majnemer   if (Entry32)
1517ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1518ad7b7e73SDavid Majnemer   else
1519ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1520ad7b7e73SDavid Majnemer   return std::error_code();
1521ad7b7e73SDavid Majnemer }
1522ad7b7e73SDavid Majnemer 
1523ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1524ad7b7e73SDavid Majnemer   if (Entry32)
1525ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1526ad7b7e73SDavid Majnemer   else
1527ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1528ad7b7e73SDavid Majnemer   return std::error_code();
1529ad7b7e73SDavid Majnemer }
1530ad7b7e73SDavid Majnemer 
1531861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1532861021f9SRui Ueyama   uint32_t RVA;
1533861021f9SRui Ueyama   if (Entry32) {
1534861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1535861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15367d099195SRui Ueyama       return std::error_code();
1537861021f9SRui Ueyama     }
1538861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1539861021f9SRui Ueyama   } else {
1540861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1541861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15427d099195SRui Ueyama       return std::error_code();
1543861021f9SRui Ueyama     }
1544861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1545861021f9SRui Ueyama   }
1546861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1547861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1548861021f9SRui Ueyama     return EC;
1549861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15507d099195SRui Ueyama   return std::error_code();
1551861021f9SRui Ueyama }
1552861021f9SRui Ueyama 
1553437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>>
155448af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1555db4ed0bdSRafael Espindola   std::error_code EC;
155648af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1557692410efSRafael Espindola   if (EC)
1558692410efSRafael Espindola     return EC;
1559437b0d58SRafael Espindola   return std::move(Ret);
1560686738e2SRui Ueyama }
156174e85130SRui Ueyama 
156274e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
156374e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
156474e85130SRui Ueyama }
156574e85130SRui Ueyama 
156674e85130SRui Ueyama void BaseRelocRef::moveNext() {
156774e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
156874e85130SRui Ueyama   // size of the header itself.
156974e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1570970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
157174e85130SRui Ueyama   if (Size == Header->BlockSize) {
157274e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
157374e85130SRui Ueyama     // consists of the header followed by entries. The header contains
157474e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
157574e85130SRui Ueyama     // current block, proceed to the next block.
157674e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
157774e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
157874e85130SRui Ueyama     Index = 0;
157974e85130SRui Ueyama   } else {
158074e85130SRui Ueyama     ++Index;
158174e85130SRui Ueyama   }
158274e85130SRui Ueyama }
158374e85130SRui Ueyama 
158474e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
158574e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
158674e85130SRui Ueyama   Type = Entry[Index].getType();
15877d099195SRui Ueyama   return std::error_code();
158874e85130SRui Ueyama }
158974e85130SRui Ueyama 
159074e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
159174e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
159274e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
15937d099195SRui Ueyama   return std::error_code();
159474e85130SRui Ueyama }
1595*efef15a0SEric Beckmann 
1596*efef15a0SEric Beckmann #define RETURN_IF_ERROR(X)                                                     \
1597*efef15a0SEric Beckmann   if (auto EC = errorToErrorCode(X))                                           \
1598*efef15a0SEric Beckmann     return EC;
1599*efef15a0SEric Beckmann 
1600*efef15a0SEric Beckmann ErrorOr<StringRef> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1601*efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1602*efef15a0SEric Beckmann   Reader.setOffset(Offset);
1603*efef15a0SEric Beckmann   uint16_t Length;
1604*efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1605*efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1606*efef15a0SEric Beckmann   // Strings are stored as 2-byte aligned unicode characters but readFixedString
1607*efef15a0SEric Beckmann   // assumes byte string, so we double length.
1608*efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1609*efef15a0SEric Beckmann   std::string DirString;
1610*efef15a0SEric Beckmann   if (!llvm::convertUTF16ToUTF8String(RawDirString, DirString))
1611*efef15a0SEric Beckmann     return object_error::parse_failed;
1612*efef15a0SEric Beckmann   return DirString;
1613*efef15a0SEric Beckmann }
1614*efef15a0SEric Beckmann 
1615*efef15a0SEric Beckmann ErrorOr<StringRef>
1616*efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1617*efef15a0SEric Beckmann   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1618*efef15a0SEric Beckmann }
1619*efef15a0SEric Beckmann 
1620*efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1621*efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1622*efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1623*efef15a0SEric Beckmann 
1624*efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1625*efef15a0SEric Beckmann   Reader.setOffset(Offset);
1626*efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1627*efef15a0SEric Beckmann   assert(Table != nullptr);
1628*efef15a0SEric Beckmann   return *Table;
1629*efef15a0SEric Beckmann }
1630*efef15a0SEric Beckmann 
1631*efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1632*efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1633*efef15a0SEric Beckmann   return getTableAtOffset(Entry.Offset.value());
1634*efef15a0SEric Beckmann }
1635*efef15a0SEric Beckmann 
1636*efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1637*efef15a0SEric Beckmann   return getTableAtOffset(0);
1638*efef15a0SEric Beckmann }
1639