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"
18264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h"
19d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
20d341c932SEugene Zelenko #include "llvm/Object/COFF.h"
21d341c932SEugene Zelenko #include "llvm/Object/Error.h"
22d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h"
23efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
24d341c932SEugene Zelenko #include "llvm/Support/Endian.h"
25d341c932SEugene Zelenko #include "llvm/Support/Error.h"
26d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
27d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h"
28d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
29d341c932SEugene Zelenko #include <algorithm>
30d341c932SEugene Zelenko #include <cassert>
31d341c932SEugene Zelenko #include <cstddef>
32d341c932SEugene Zelenko #include <cstdint>
33d341c932SEugene Zelenko #include <cstring>
349d2c15efSNico Rieck #include <limits>
35d341c932SEugene Zelenko #include <memory>
36d341c932SEugene Zelenko #include <system_error>
378e90adafSMichael J. Spencer 
388e90adafSMichael J. Spencer using namespace llvm;
398e90adafSMichael J. Spencer using namespace object;
408e90adafSMichael J. Spencer 
418e90adafSMichael J. Spencer using support::ulittle16_t;
428e90adafSMichael J. Spencer using support::ulittle32_t;
43861021f9SRui Ueyama using support::ulittle64_t;
448e90adafSMichael J. Spencer using support::little16_t;
458e90adafSMichael J. Spencer 
461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
48c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
498ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
501d6167fdSMichael J. Spencer     return false;
511d6167fdSMichael J. Spencer   }
521d6167fdSMichael J. Spencer   return true;
538e90adafSMichael J. Spencer }
548e90adafSMichael J. Spencer 
55ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
56ed64342bSRui Ueyama // Returns unexpected_eof if error.
57ed64342bSRui Ueyama template <typename T>
5848af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
5958323a97SDavid Majnemer                                  const void *Ptr,
60236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
61ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
62cbc7ee45SBenjamin Kramer   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
63e830c60dSDavid Majnemer     return EC;
64ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
657d099195SRui Ueyama   return std::error_code();
661d6167fdSMichael J. Spencer }
671d6167fdSMichael J. Spencer 
689d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
699d2c15efSNico Rieck // prefixed slashes.
709d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
719d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
729d2c15efSNico Rieck   if (Str.size() > 6)
739d2c15efSNico Rieck     return true;
749d2c15efSNico Rieck 
759d2c15efSNico Rieck   uint64_t Value = 0;
769d2c15efSNico Rieck   while (!Str.empty()) {
779d2c15efSNico Rieck     unsigned CharVal;
789d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
799d2c15efSNico Rieck       CharVal = Str[0] - 'A';
809d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
819d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
829d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
839d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
849d2c15efSNico Rieck     else if (Str[0] == '+') // 62
855500b07cSRui Ueyama       CharVal = 62;
869d2c15efSNico Rieck     else if (Str[0] == '/') // 63
875500b07cSRui Ueyama       CharVal = 63;
889d2c15efSNico Rieck     else
899d2c15efSNico Rieck       return true;
909d2c15efSNico Rieck 
919d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
929d2c15efSNico Rieck     Str = Str.substr(1);
939d2c15efSNico Rieck   }
949d2c15efSNico Rieck 
959d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
969d2c15efSNico Rieck     return true;
979d2c15efSNico Rieck 
989d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
999d2c15efSNico Rieck   return false;
1009d2c15efSNico Rieck }
1019d2c15efSNico Rieck 
10244f51e51SDavid Majnemer template <typename coff_symbol_type>
10344f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10444f51e51SDavid Majnemer   const coff_symbol_type *Addr =
10544f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1061d6167fdSMichael J. Spencer 
107236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1081d6167fdSMichael J. Spencer #ifndef NDEBUG
1091d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1108ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1111d6167fdSMichael J. Spencer 
11244f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11344f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1141d6167fdSMichael J. Spencer #endif
1151d6167fdSMichael J. Spencer 
1168ff24d25SRui Ueyama   return Addr;
1171d6167fdSMichael J. Spencer }
1181d6167fdSMichael J. Spencer 
1198ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1208ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1211d6167fdSMichael J. Spencer 
1221d6167fdSMichael J. Spencer #ifndef NDEBUG
1231d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
12444f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1251d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1261d6167fdSMichael J. Spencer 
1278ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1288ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1291d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1301d6167fdSMichael J. Spencer #endif
1311d6167fdSMichael J. Spencer 
1328ff24d25SRui Ueyama   return Addr;
1331d6167fdSMichael J. Spencer }
1341d6167fdSMichael J. Spencer 
1355e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
136236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13744f51e51SDavid Majnemer   if (SymbolTable16) {
13844f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1398ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
140236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14144f51e51SDavid Majnemer   } else if (SymbolTable32) {
14244f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14344f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
144236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14544f51e51SDavid Majnemer   } else {
14644f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14744f51e51SDavid Majnemer   }
1481d6167fdSMichael J. Spencer }
1491d6167fdSMichael J. Spencer 
15081e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1525d0c2ffaSRafael Espindola   StringRef Result;
153efef15a0SEric Beckmann   if (std::error_code EC = getSymbolName(Symb, Result))
15481e8b7d9SKevin Enderby     return errorCodeToError(EC);
1555d0c2ffaSRafael Espindola   return Result;
1568e90adafSMichael J. Spencer }
1578e90adafSMichael J. Spencer 
158be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
159be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
160991af666SRafael Espindola }
161991af666SRafael Espindola 
1626b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1636b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1646b2bba14SDavide Italiano   // up to 32 bytes.
1656b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16603a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1676b2bba14SDavide Italiano }
1686b2bba14SDavide Italiano 
169931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
170ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
17144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
172c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
173991af666SRafael Espindola 
174991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
175991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
176ed067c45SRafael Espindola     return Result;
17754c9f3daSRafael Espindola 
1782617dcceSCraig Topper   const coff_section *Section = nullptr;
179c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
180931cb65dSKevin Enderby     return errorCodeToError(EC);
181991af666SRafael Espindola   Result += Section->VirtualAddress;
18247ea9eceSReid Kleckner 
18347ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18447ea9eceSReid Kleckner   // return virtual addresses.
18521427adaSReid Kleckner   Result += getImageBase();
18647ea9eceSReid Kleckner 
187ed067c45SRafael Espindola   return Result;
188c7d7c6fbSDavid Majnemer }
189c7d7c6fbSDavid Majnemer 
1907bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
19144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
192c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
19344f51e51SDavid Majnemer 
194e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
195e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1962fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1972fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1982fa80cc5SRafael Espindola   if (Symb.isCommon())
1992fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2002fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2012fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2022fa80cc5SRafael Espindola 
2031a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2042fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2052fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2062fa80cc5SRafael Espindola 
2072fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2082fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2092fa80cc5SRafael Espindola 
2102fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
21175d1cf33SBenjamin Kramer }
21275d1cf33SBenjamin Kramer 
21320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21444f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21520122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21675d1cf33SBenjamin Kramer 
217c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2189dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2191df4b84dSDavid Meyer 
220*a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2211df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
222*a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
223*a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2241079ef8dSMartell Malone   }
2251df4b84dSDavid Meyer 
22644f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2271df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2281df4b84dSDavid Meyer 
229c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
230c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
231c7d7c6fbSDavid Majnemer 
232c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
233c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
234c7d7c6fbSDavid Majnemer 
235c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
236c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
237c7d7c6fbSDavid Majnemer 
238*a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
239c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
240c7d7c6fbSDavid Majnemer 
24120122a43SRafael Espindola   return Result;
24201759754SMichael J. Spencer }
24301759754SMichael J. Spencer 
244d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
245c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2465eb02e45SRafael Espindola   return Symb.getValue();
2478e90adafSMichael J. Spencer }
2488e90adafSMichael J. Spencer 
2497bd8d994SKevin Enderby Expected<section_iterator>
2508bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
25144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2528bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2538bab889bSRafael Espindola     return section_end();
2542617dcceSCraig Topper   const coff_section *Sec = nullptr;
25544f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2567bd8d994SKevin Enderby     return errorCodeToError(EC);
2578bab889bSRafael Espindola   DataRefImpl Ret;
2588bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2598bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
26032173153SMichael J. Spencer }
26132173153SMichael J. Spencer 
2626bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2636bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2646bf32210SRafael Espindola   return Symb.getSectionNumber();
2656bf32210SRafael Espindola }
2666bf32210SRafael Espindola 
2675e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2688ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2698ff24d25SRui Ueyama   Sec += 1;
2708ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2718e90adafSMichael J. Spencer }
2728e90adafSMichael J. Spencer 
273db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2741d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2758ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2768ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2778e90adafSMichael J. Spencer }
2788e90adafSMichael J. Spencer 
27980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2808ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2817c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2827c6a071bSDavid Majnemer 
2837c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2847c6a071bSDavid Majnemer   // return virtual addresses.
28521427adaSReid Kleckner   Result += getImageBase();
2867c6a071bSDavid Majnemer   return Result;
2878e90adafSMichael J. Spencer }
2888e90adafSMichael J. Spencer 
289a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
290a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
291a25d329bSGeorge Rimar }
292a25d329bSGeorge Rimar 
29380291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
294a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2958e90adafSMichael J. Spencer }
2968e90adafSMichael J. Spencer 
297db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
2981d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
2998ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3009da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
301db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
3029da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
3039da9e693SMichael J. Spencer   return EC;
3048e90adafSMichael J. Spencer }
3058e90adafSMichael J. Spencer 
30680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3078ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
308511391feSDavid Majnemer   return Sec->getAlignment();
3097989460aSMichael J. Spencer }
3107989460aSMichael J. Spencer 
311401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
312401e4e57SGeorge Rimar   return false;
313401e4e57SGeorge Rimar }
314401e4e57SGeorge Rimar 
31580291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3168ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31780291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3188e90adafSMichael J. Spencer }
3198e90adafSMichael J. Spencer 
32080291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3218ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32280291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
323800619f2SMichael J. Spencer }
324800619f2SMichael J. Spencer 
32580291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3268ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3271a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3281a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3291a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3301a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
331800619f2SMichael J. Spencer }
332800619f2SMichael J. Spencer 
3336bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3346bf32210SRafael Espindola   uintptr_t Offset =
3356bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3366bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3376bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3386bf32210SRafael Espindola }
3396bf32210SRafael Espindola 
34080291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3418ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3421a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3431a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3441a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3452138ef6dSPreston Gurd }
3462138ef6dSPreston Gurd 
347e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
348e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
349e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
350e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
351e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
352e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
353e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
354e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
355e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
356e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
357e830c60dSDavid Majnemer       return 0;
35898fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
35998fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
360e830c60dSDavid Majnemer   }
361e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
362e830c60dSDavid Majnemer }
363e830c60dSDavid Majnemer 
36494751be7SDavid Majnemer static const coff_relocation *
36594751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36694751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36794751be7SDavid Majnemer   if (!NumRelocs)
36894751be7SDavid Majnemer     return nullptr;
369827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37094751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
371827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
372827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
373827c8a2bSRui Ueyama     // relocations.
374827c8a2bSRui Ueyama     begin++;
375827c8a2bSRui Ueyama   }
376cbc7ee45SBenjamin Kramer   if (Binary::checkOffset(M, uintptr_t(begin),
377cbc7ee45SBenjamin Kramer                           sizeof(coff_relocation) * NumRelocs))
37894751be7SDavid Majnemer     return nullptr;
37994751be7SDavid Majnemer   return begin;
380827c8a2bSRui Ueyama }
38194751be7SDavid Majnemer 
38294751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38394751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38494751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38576d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38676d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
38794751be7SDavid Majnemer   DataRefImpl Ret;
38894751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3898ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
390e5fd0047SMichael J. Spencer }
391e5fd0047SMichael J. Spencer 
3928ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3938ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39494751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39594751be7SDavid Majnemer   if (I)
39694751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3978ff24d25SRui Ueyama   DataRefImpl Ret;
39894751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
3998ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
400e5fd0047SMichael J. Spencer }
401e5fd0047SMichael J. Spencer 
402c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
403db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40444f51e51SDavid Majnemer   if (COFFHeader)
405236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
406236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
407236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40844f51e51SDavid Majnemer       return EC;
40944f51e51SDavid Majnemer 
41044f51e51SDavid Majnemer   if (COFFBigObjHeader)
411236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
412236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
413236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4148ff24d25SRui Ueyama       return EC;
415c2bed429SRui Ueyama 
416c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
417c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
418c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
419f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42044f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
421f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
422c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42348af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4248ff24d25SRui Ueyama     return EC;
425c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
426db4ed0bdSRafael Espindola   if (std::error_code EC =
42748af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4288ff24d25SRui Ueyama     return EC;
429c2bed429SRui Ueyama 
430773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
431773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
432773a5795SNico Rieck   if (StringTableSize < 4)
433773a5795SNico Rieck       StringTableSize = 4;
434773a5795SNico Rieck 
435c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
436773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
437c2bed429SRui Ueyama     return  object_error::parse_failed;
4387d099195SRui Ueyama   return std::error_code();
439c2bed429SRui Ueyama }
440c2bed429SRui Ueyama 
44121427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
442e94fef7bSReid Kleckner   if (PE32Header)
44321427adaSReid Kleckner     return PE32Header->ImageBase;
444e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44521427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44621427adaSReid Kleckner   // This actually comes up in practice.
44721427adaSReid Kleckner   return 0;
448e94fef7bSReid Kleckner }
449e94fef7bSReid Kleckner 
450215a586cSRui Ueyama // Returns the file offset for the given VA.
451db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45221427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
453b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
454b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
455b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
456215a586cSRui Ueyama }
457215a586cSRui Ueyama 
458c2bed429SRui Ueyama // Returns the file offset for the given RVA.
459db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46027dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46127dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
462c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
463c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
464215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
465215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
466c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4677d099195SRui Ueyama       return std::error_code();
468c2bed429SRui Ueyama     }
469c2bed429SRui Ueyama   }
470c2bed429SRui Ueyama   return object_error::parse_failed;
471c2bed429SRui Ueyama }
472c2bed429SRui Ueyama 
4732da433eaSReid Kleckner std::error_code
4742da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4752da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4762da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4772da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4782da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4792da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4802da433eaSReid Kleckner     // overflow.
4812da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4822da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4832da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4842da433eaSReid Kleckner       uintptr_t Begin =
4852da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4862da433eaSReid Kleckner       Contents =
4872da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4882da433eaSReid Kleckner       return std::error_code();
4892da433eaSReid Kleckner     }
4902da433eaSReid Kleckner   }
4912da433eaSReid Kleckner   return object_error::parse_failed;
4922da433eaSReid Kleckner }
4932da433eaSReid Kleckner 
494c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
495c2bed429SRui Ueyama // table entry.
496db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
497db4ed0bdSRafael Espindola                                             StringRef &Name) const {
498c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
499db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5008ff24d25SRui Ueyama     return EC;
501c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
502c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
503c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5047d099195SRui Ueyama   return std::error_code();
505c2bed429SRui Ueyama }
506c2bed429SRui Ueyama 
50701528021SSaleem Abdulrasool std::error_code
50801528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
50901528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5102da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5112da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5122da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5132da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5142da433eaSReid Kleckner     return EC;
51501528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5162da433eaSReid Kleckner     return object_error::parse_failed;
51701528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
51801528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5192da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5202da433eaSReid Kleckner                           InfoBytes.size());
5212da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5222da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5232da433eaSReid Kleckner   return std::error_code();
5242da433eaSReid Kleckner }
5252da433eaSReid Kleckner 
52601528021SSaleem Abdulrasool std::error_code
52701528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
528f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
529f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
530f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
531f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
532f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
533f27f3f84SReid Kleckner   PDBInfo = nullptr;
534f27f3f84SReid Kleckner   PDBFileName = StringRef();
535f27f3f84SReid Kleckner   return std::error_code();
536f27f3f84SReid Kleckner }
537f27f3f84SReid Kleckner 
538c2bed429SRui Ueyama // Find the import table.
539db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
540c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
541c2bed429SRui Ueyama   // the import table, do nothing.
542c2bed429SRui Ueyama   const data_directory *DataEntry;
543c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5447d099195SRui Ueyama     return std::error_code();
545c2bed429SRui Ueyama 
546c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
547c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5487d099195SRui Ueyama     return std::error_code();
549c2bed429SRui Ueyama 
550c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
551c2bed429SRui Ueyama 
552c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
553c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
554c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
555db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5568ff24d25SRui Ueyama     return EC;
557ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
558ad7b7e73SDavid Majnemer     return EC;
559c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5601c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5617d099195SRui Ueyama   return std::error_code();
562ad882ba8SRui Ueyama }
563c2bed429SRui Ueyama 
56415d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56515d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56615d99359SRui Ueyama   const data_directory *DataEntry;
56715d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5687d099195SRui Ueyama     return std::error_code();
56915d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5707d099195SRui Ueyama     return std::error_code();
57115d99359SRui Ueyama 
57215d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57315d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57415d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57515d99359SRui Ueyama 
57615d99359SRui Ueyama   uintptr_t IntPtr = 0;
57715d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57815d99359SRui Ueyama     return EC;
57915d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58015d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5817d099195SRui Ueyama   return std::error_code();
58215d99359SRui Ueyama }
58315d99359SRui Ueyama 
584ad882ba8SRui Ueyama // Find the export table.
585db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
586ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
587ad882ba8SRui Ueyama   // the export table, do nothing.
588ad882ba8SRui Ueyama   const data_directory *DataEntry;
589ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5907d099195SRui Ueyama     return std::error_code();
591ad882ba8SRui Ueyama 
592ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
593ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5947d099195SRui Ueyama     return std::error_code();
595ad882ba8SRui Ueyama 
596ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
597ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
598db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
599ad882ba8SRui Ueyama     return EC;
60024fc2d64SRui Ueyama   ExportDirectory =
60124fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6027d099195SRui Ueyama   return std::error_code();
603c2bed429SRui Ueyama }
604c2bed429SRui Ueyama 
60574e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60674e85130SRui Ueyama   const data_directory *DataEntry;
60774e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6087d099195SRui Ueyama     return std::error_code();
60974e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6107d099195SRui Ueyama     return std::error_code();
61174e85130SRui Ueyama 
61274e85130SRui Ueyama   uintptr_t IntPtr = 0;
61374e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61474e85130SRui Ueyama     return EC;
61574e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61674e85130SRui Ueyama       IntPtr);
61774e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61874e85130SRui Ueyama       IntPtr + DataEntry->Size);
6197d099195SRui Ueyama   return std::error_code();
62074e85130SRui Ueyama }
62174e85130SRui Ueyama 
6222da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6232da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6242da433eaSReid Kleckner   const data_directory *DataEntry;
6252da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6262da433eaSReid Kleckner     return std::error_code();
6272da433eaSReid Kleckner 
6282da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6292da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6302da433eaSReid Kleckner     return std::error_code();
6312da433eaSReid Kleckner 
6322da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6332da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6342da433eaSReid Kleckner     return object_error::parse_failed;
6352da433eaSReid Kleckner 
6362da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6372da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6382da433eaSReid Kleckner     return EC;
6392da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6402da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6412da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6422da433eaSReid Kleckner     return EC;
6432da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6442da433eaSReid Kleckner   return std::error_code();
6452da433eaSReid Kleckner }
6462da433eaSReid Kleckner 
647b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
648b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
649b7d716c0SReid Kleckner   const data_directory *DataEntry;
650b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
651b7d716c0SReid Kleckner     return std::error_code();
652b7d716c0SReid Kleckner 
653b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
654b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
655b7d716c0SReid Kleckner     return std::error_code();
656b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
657b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
658b7d716c0SReid Kleckner     return EC;
659b7d716c0SReid Kleckner 
660b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
661b7d716c0SReid Kleckner   return std::error_code();
662b7d716c0SReid Kleckner }
663b7d716c0SReid Kleckner 
66448af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
66548af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
66644f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
66744f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
66844f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
669ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
67015d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6712da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6722da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6731d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
67448af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
675c3f9b5a5SRafael Espindola     return;
676ee066fc4SEric Christopher 
67782ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
67882ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
67982ebd8e3SRui Ueyama 
68082ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
68182ebd8e3SRui Ueyama   // it is placed right after COFF header.
6828ff24d25SRui Ueyama   bool HasPEHeader = false;
683ee066fc4SEric Christopher 
6841d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
68550267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
686ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
687ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
68850267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
68950267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69050267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
69182ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
69250267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6938ff24d25SRui Ueyama         EC = object_error::parse_failed;
6941d6167fdSMichael J. Spencer         return;
6951d6167fdSMichael J. Spencer       }
69644f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6978ff24d25SRui Ueyama       HasPEHeader = true;
698ee066fc4SEric Christopher     }
69950267222SDavid Majnemer   }
700ee066fc4SEric Christopher 
70148af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
7021d6167fdSMichael J. Spencer     return;
70344f51e51SDavid Majnemer 
70444f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
70544f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
70644f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
70744f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
70844f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
70944f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71044f51e51SDavid Majnemer       return;
71144f51e51SDavid Majnemer 
71244f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
71344f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
71444f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
71544f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
71644f51e51SDavid Majnemer       COFFHeader = nullptr;
71744f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
71844f51e51SDavid Majnemer     } else {
71944f51e51SDavid Majnemer       // It's not a bigobj.
72044f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
72144f51e51SDavid Majnemer     }
72244f51e51SDavid Majnemer   }
72344f51e51SDavid Majnemer   if (COFFHeader) {
72444f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
72544f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7267d099195SRui Ueyama     EC = std::error_code();
72782ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
72882ebd8e3SRui Ueyama 
72944f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
73044f51e51SDavid Majnemer       return;
73144f51e51SDavid Majnemer   }
73244f51e51SDavid Majnemer 
7338ff24d25SRui Ueyama   if (HasPEHeader) {
73410ed9ddcSRui Ueyama     const pe32_header *Header;
73548af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
73682ebd8e3SRui Ueyama       return;
73710ed9ddcSRui Ueyama 
73810ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
73910ed9ddcSRui Ueyama     uint64_t DataDirSize;
74050267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
74110ed9ddcSRui Ueyama       PE32Header = Header;
74210ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
74310ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
74450267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
74510ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
74610ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
74710ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
74810ed9ddcSRui Ueyama     } else {
74910ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
75010ed9ddcSRui Ueyama       EC = object_error::parse_failed;
751ed64342bSRui Ueyama       return;
752ed64342bSRui Ueyama     }
75348af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
75410ed9ddcSRui Ueyama       return;
755f53c8cb4SRui Ueyama   }
756776c6828SRui Ueyama 
7578950a538SRui Ueyama   if (COFFHeader)
7588950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7598950a538SRui Ueyama 
76048af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
761236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7621d6167fdSMichael J. Spencer     return;
7631d6167fdSMichael J. Spencer 
764c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
765236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
766ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
767ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
768ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
769ac8cfab5SDavid Majnemer       StringTable = nullptr;
770ac8cfab5SDavid Majnemer       StringTableSize = 0;
771ac8cfab5SDavid Majnemer     }
772236b0ca7SDavid Majnemer   } else {
773236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
774236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
775236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
776236b0ca7SDavid Majnemer       return;
777236b0ca7SDavid Majnemer     }
778236b0ca7SDavid Majnemer   }
7798e90adafSMichael J. Spencer 
780c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7818ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
782ed64342bSRui Ueyama     return;
78315d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
78415d99359SRui Ueyama     return;
7851d6167fdSMichael J. Spencer 
786ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7878ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
788ad882ba8SRui Ueyama     return;
789ad882ba8SRui Ueyama 
79074e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
79174e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
79274e85130SRui Ueyama     return;
79374e85130SRui Ueyama 
7942da433eaSReid Kleckner   // Initialize the pointer to the export table.
7952da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7962da433eaSReid Kleckner     return;
7972da433eaSReid Kleckner 
798b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
799b7d716c0SReid Kleckner     return;
800b7d716c0SReid Kleckner 
8017d099195SRui Ueyama   EC = std::error_code();
8028e90adafSMichael J. Spencer }
8038e90adafSMichael J. Spencer 
804435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8058ff24d25SRui Ueyama   DataRefImpl Ret;
80644f51e51SDavid Majnemer   Ret.p = getSymbolTable();
807f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8088e90adafSMichael J. Spencer }
8098e90adafSMichael J. Spencer 
810435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8118e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8128ff24d25SRui Ueyama   DataRefImpl Ret;
8138ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
814f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8158e90adafSMichael J. Spencer }
8168e90adafSMichael J. Spencer 
817bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
818ad7b7e73SDavid Majnemer   if (!ImportDirectory)
819ad7b7e73SDavid Majnemer     return import_directory_end();
8201c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
821ad7b7e73SDavid Majnemer     return import_directory_end();
822a045b73aSRui Ueyama   return import_directory_iterator(
823a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
824c2bed429SRui Ueyama }
825c2bed429SRui Ueyama 
826bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
827a045b73aSRui Ueyama   return import_directory_iterator(
828ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
829c2bed429SRui Ueyama }
830c429b80dSDavid Meyer 
83115d99359SRui Ueyama delay_import_directory_iterator
83215d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
83315d99359SRui Ueyama   return delay_import_directory_iterator(
83415d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
83515d99359SRui Ueyama }
83615d99359SRui Ueyama 
83715d99359SRui Ueyama delay_import_directory_iterator
83815d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
83915d99359SRui Ueyama   return delay_import_directory_iterator(
84015d99359SRui Ueyama       DelayImportDirectoryEntryRef(
84115d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
84215d99359SRui Ueyama }
84315d99359SRui Ueyama 
844ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
845ad882ba8SRui Ueyama   return export_directory_iterator(
846ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
847ad882ba8SRui Ueyama }
848ad882ba8SRui Ueyama 
849ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8502617dcceSCraig Topper   if (!ExportDirectory)
8512617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8528ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
853ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8548ff24d25SRui Ueyama   return export_directory_iterator(Ref);
855ad882ba8SRui Ueyama }
856ad882ba8SRui Ueyama 
857b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8588ff24d25SRui Ueyama   DataRefImpl Ret;
8598ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8608ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8618e90adafSMichael J. Spencer }
8628e90adafSMichael J. Spencer 
863b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8648ff24d25SRui Ueyama   DataRefImpl Ret;
86544f51e51SDavid Majnemer   int NumSections =
86644f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8678ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8688ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8698e90adafSMichael J. Spencer }
8708e90adafSMichael J. Spencer 
87174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
87274e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
87374e85130SRui Ueyama }
87474e85130SRui Ueyama 
87574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
87674e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
87774e85130SRui Ueyama }
87874e85130SRui Ueyama 
8798e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
88043c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8818e90adafSMichael J. Spencer }
8828e90adafSMichael J. Spencer 
8838e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
88444f51e51SDavid Majnemer   switch(getMachine()) {
8858e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8868e90adafSMichael J. Spencer     return "COFF-i386";
8878e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8888e90adafSMichael J. Spencer     return "COFF-x86-64";
8899b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8909b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8911eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8921eff5c9cSMartell Malone     return "COFF-ARM64";
8938e90adafSMichael J. Spencer   default:
8948e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8958e90adafSMichael J. Spencer   }
8968e90adafSMichael J. Spencer }
8978e90adafSMichael J. Spencer 
898260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
89944f51e51SDavid Majnemer   switch (getMachine()) {
9008e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9018e90adafSMichael J. Spencer     return Triple::x86;
9028e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9038e90adafSMichael J. Spencer     return Triple::x86_64;
9049b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9059b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9061eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9071eff5c9cSMartell Malone     return Triple::aarch64;
9088e90adafSMichael J. Spencer   default:
9098e90adafSMichael J. Spencer     return Triple::UnknownArch;
9108e90adafSMichael J. Spencer   }
9118e90adafSMichael J. Spencer }
9128e90adafSMichael J. Spencer 
913d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
914d2af4d6fSPaul Semel   if (PE32Header)
915d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
916d2af4d6fSPaul Semel   return 0;
917d2af4d6fSPaul Semel }
918d2af4d6fSPaul Semel 
919979fb40bSRui Ueyama iterator_range<import_directory_iterator>
920979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
921979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
922979fb40bSRui Ueyama }
923979fb40bSRui Ueyama 
924979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
925979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
926979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
927979fb40bSRui Ueyama                     delay_import_directory_end());
928979fb40bSRui Ueyama }
929979fb40bSRui Ueyama 
930979fb40bSRui Ueyama iterator_range<export_directory_iterator>
931979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
932979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
933979fb40bSRui Ueyama }
934979fb40bSRui Ueyama 
93574e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
93674e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
93774e85130SRui Ueyama }
93874e85130SRui Ueyama 
939db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
94082ebd8e3SRui Ueyama   Res = PE32Header;
9417d099195SRui Ueyama   return std::error_code();
94289a7a5eaSMichael J. Spencer }
94389a7a5eaSMichael J. Spencer 
944db4ed0bdSRafael Espindola std::error_code
94510ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
94610ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9477d099195SRui Ueyama   return std::error_code();
94810ed9ddcSRui Ueyama }
94910ed9ddcSRui Ueyama 
950db4ed0bdSRafael Espindola std::error_code
951db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
952ed64342bSRui Ueyama                                  const data_directory *&Res) const {
953bcadfee2SHiroshi Inoue   // Error if there's no data directory or the index is out of range.
954f69b0585SDavid Majnemer   if (!DataDirectory) {
955f69b0585SDavid Majnemer     Res = nullptr;
95610ed9ddcSRui Ueyama     return object_error::parse_failed;
957f69b0585SDavid Majnemer   }
95810ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
95910ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
96010ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
961f69b0585SDavid Majnemer   if (Index >= NumEnt) {
962f69b0585SDavid Majnemer     Res = nullptr;
963ed64342bSRui Ueyama     return object_error::parse_failed;
964f69b0585SDavid Majnemer   }
9658ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9667d099195SRui Ueyama   return std::error_code();
967ed64342bSRui Ueyama }
968ed64342bSRui Ueyama 
969db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9701d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9712617dcceSCraig Topper   Result = nullptr;
972236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9737d099195SRui Ueyama     return std::error_code();
974236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9751d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9768ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9777d099195SRui Ueyama     return std::error_code();
9788e90adafSMichael J. Spencer   }
979236b0ca7SDavid Majnemer   return object_error::parse_failed;
980236b0ca7SDavid Majnemer }
9818e90adafSMichael J. Spencer 
982b98f5048SPaul Semel std::error_code COFFObjectFile::getSection(StringRef SectionName,
983b98f5048SPaul Semel                                            const coff_section *&Result) const {
984b98f5048SPaul Semel   Result = nullptr;
985b98f5048SPaul Semel   StringRef SecName;
986b98f5048SPaul Semel   for (const SectionRef &Section : sections()) {
987b98f5048SPaul Semel     if (std::error_code E = Section.getName(SecName))
988b98f5048SPaul Semel       return E;
989b98f5048SPaul Semel     if (SecName == SectionName) {
990b98f5048SPaul Semel       Result = getCOFFSection(Section);
991b98f5048SPaul Semel       return std::error_code();
992b98f5048SPaul Semel     }
993b98f5048SPaul Semel   }
994b98f5048SPaul Semel   return object_error::parse_failed;
995b98f5048SPaul Semel }
996b98f5048SPaul Semel 
997db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9981d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9991d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10001d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
10011d6167fdSMichael J. Spencer     return object_error::parse_failed;
10028ff24d25SRui Ueyama   if (Offset >= StringTableSize)
10031d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
10048ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
10057d099195SRui Ueyama   return std::error_code();
10068e90adafSMichael J. Spencer }
1007022ecdf2SBenjamin Kramer 
100844f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
100989a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
1010e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
1011e40d30f3SRui Ueyama }
1012e40d30f3SRui Ueyama 
1013e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1014e40d30f3SRui Ueyama                                               StringRef &Res) const {
101589a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
1016e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
1017e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
10188ff24d25SRui Ueyama       return EC;
10197d099195SRui Ueyama     return std::error_code();
102089a7a5eaSMichael J. Spencer   }
102189a7a5eaSMichael J. Spencer 
1022e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
102389a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
1024e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
102589a7a5eaSMichael J. Spencer   else
102689a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
1027e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
10287d099195SRui Ueyama   return std::error_code();
102989a7a5eaSMichael J. Spencer }
103089a7a5eaSMichael J. Spencer 
103144f51e51SDavid Majnemer ArrayRef<uint8_t>
103244f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10332617dcceSCraig Topper   const uint8_t *Aux = nullptr;
103471757ef3SMarshall Clow 
103544f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
103644f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
103771757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
103844f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
103971757ef3SMarshall Clow #ifndef NDEBUG
10408ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10418ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
104244f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
104344f51e51SDavid Majnemer         Offset >=
104444f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
104571757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
104671757ef3SMarshall Clow 
104744f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
104844f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
104971757ef3SMarshall Clow #endif
1050bfb85e67SMarshall Clow   }
105144f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
105271757ef3SMarshall Clow }
105371757ef3SMarshall Clow 
1054db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
105553c2d547SMichael J. Spencer                                                StringRef &Res) const {
105653c2d547SMichael J. Spencer   StringRef Name;
105744f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
105853c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
105953c2d547SMichael J. Spencer     Name = Sec->Name;
106053c2d547SMichael J. Spencer   else
106153c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
106244f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
106353c2d547SMichael J. Spencer 
106453c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10652314b3deSDavid Majnemer   if (Name.startswith("/")) {
106653c2d547SMichael J. Spencer     uint32_t Offset;
10672314b3deSDavid Majnemer     if (Name.startswith("//")) {
10689d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10699d2c15efSNico Rieck         return object_error::parse_failed;
10709d2c15efSNico Rieck     } else {
107153c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
107253c2d547SMichael J. Spencer         return object_error::parse_failed;
10739d2c15efSNico Rieck     }
1074db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10758ff24d25SRui Ueyama       return EC;
107653c2d547SMichael J. Spencer   }
107753c2d547SMichael J. Spencer 
107853c2d547SMichael J. Spencer   Res = Name;
10797d099195SRui Ueyama   return std::error_code();
108053c2d547SMichael J. Spencer }
108153c2d547SMichael J. Spencer 
1082a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1083a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1084a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1085a9ee5c06SDavid Majnemer   //
1086a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1087d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1088a9ee5c06SDavid Majnemer   //
1089a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1090a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1091a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1092a9ee5c06SDavid Majnemer   // considered to be zero.
1093d5297ee7SRui Ueyama   if (getDOSHeader())
1094d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1095d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1096a9ee5c06SDavid Majnemer }
1097a9ee5c06SDavid Majnemer 
1098db4ed0bdSRafael Espindola std::error_code
1099db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
11009da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1101e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1102e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1103e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1104ee97c5f0SShoaib Meenai     return std::error_code();
11059da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11069da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11079da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
11089da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1109a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1110e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
11119da9e693SMichael J. Spencer     return object_error::parse_failed;
1112a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
11137d099195SRui Ueyama   return std::error_code();
11149da9e693SMichael J. Spencer }
11159da9e693SMichael J. Spencer 
1116022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1117e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1118022ecdf2SBenjamin Kramer }
11198ff24d25SRui Ueyama 
11205e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1121e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1122e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1123022ecdf2SBenjamin Kramer }
11248ff24d25SRui Ueyama 
112596d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
112658323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
112796d071cdSRafael Espindola   return R->VirtualAddress;
1128cbe72fc9SDanil Malyshev }
11298ff24d25SRui Ueyama 
1130806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1131022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11328ff24d25SRui Ueyama   DataRefImpl Ref;
1133236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1134236b0ca7SDavid Majnemer     return symbol_end();
113544f51e51SDavid Majnemer   if (SymbolTable16)
113644f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
113744f51e51SDavid Majnemer   else if (SymbolTable32)
113844f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
113944f51e51SDavid Majnemer   else
1140c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11418ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1142022ecdf2SBenjamin Kramer }
11438ff24d25SRui Ueyama 
114499c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1145022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
114699c041b7SRafael Espindola   return R->Type;
1147022ecdf2SBenjamin Kramer }
1148e5fd0047SMichael J. Spencer 
114927dc8394SAlexey Samsonov const coff_section *
115027dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
115127dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
115271757ef3SMarshall Clow }
115371757ef3SMarshall Clow 
115444f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
115544f51e51SDavid Majnemer   if (SymbolTable16)
115644f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
115744f51e51SDavid Majnemer   if (SymbolTable32)
115844f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
115944f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
116044f51e51SDavid Majnemer }
116144f51e51SDavid Majnemer 
116244f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
116344f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
116471757ef3SMarshall Clow }
116571757ef3SMarshall Clow 
1166f12b8282SRafael Espindola const coff_relocation *
116727dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
116827dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1169d3e2a76cSMarshall Clow }
1170d3e2a76cSMarshall Clow 
11712f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11726a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11732f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
11742f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
11756a75acb1SRui Ueyama }
11766a75acb1SRui Ueyama 
117727dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
117827dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
117927dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
118027dc8394SAlexey Samsonov     break;
1181e5fd0047SMichael J. Spencer 
118241bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
118341bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11848ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11858ff24d25SRui Ueyama   StringRef Res;
118644f51e51SDavid Majnemer   switch (getMachine()) {
1187e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11888ff24d25SRui Ueyama     switch (Reloc->Type) {
1189e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1190e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1191e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1192e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1193e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1194e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1195e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1196e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1197e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1198e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1199e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1200e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1201e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1202e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1203e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1204e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1205e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1206e5fd0047SMichael J. Spencer     default:
12078ff24d25SRui Ueyama       Res = "Unknown";
1208e5fd0047SMichael J. Spencer     }
1209e5fd0047SMichael J. Spencer     break;
12105c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
12115c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
12125c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12135c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12145c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12155c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12165c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12175c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12185c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12195c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
12205c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12215c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12225c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12235c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12245c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12255c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12265c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
12275c503bf4SSaleem Abdulrasool     default:
12285c503bf4SSaleem Abdulrasool       Res = "Unknown";
12295c503bf4SSaleem Abdulrasool     }
12305c503bf4SSaleem Abdulrasool     break;
12310c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
12320c72172eSMandeep Singh Grang     switch (Reloc->Type) {
12330c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12340c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12350c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12360c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12370c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12380c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12390c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12400c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12410c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12420c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12430c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12440c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12450c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12460c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12470c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12480c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12490c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
12500c72172eSMandeep Singh Grang     default:
12510c72172eSMandeep Singh Grang       Res = "Unknown";
12520c72172eSMandeep Singh Grang     }
12530c72172eSMandeep Singh Grang     break;
1254e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
12558ff24d25SRui Ueyama     switch (Reloc->Type) {
1256e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1257e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1258e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1259e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1260e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1261e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1262e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1263e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1264e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1265e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1266e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1267e5fd0047SMichael J. Spencer     default:
12688ff24d25SRui Ueyama       Res = "Unknown";
1269e5fd0047SMichael J. Spencer     }
1270e5fd0047SMichael J. Spencer     break;
1271e5fd0047SMichael J. Spencer   default:
12728ff24d25SRui Ueyama     Res = "Unknown";
1273e5fd0047SMichael J. Spencer   }
12748ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1275e5fd0047SMichael J. Spencer }
1276e5fd0047SMichael J. Spencer 
1277e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1278e5fd0047SMichael J. Spencer 
1279c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1280c66d761bSRafael Espindola   return !DataDirectory;
1281c66d761bSRafael Espindola }
1282c66d761bSRafael Espindola 
1283c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1284c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1285a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1286c2bed429SRui Ueyama }
1287c2bed429SRui Ueyama 
12885e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12895e812afaSRafael Espindola   ++Index;
12901c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1291ad7b7e73SDavid Majnemer     Index = -1;
1292ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1293ad7b7e73SDavid Majnemer   }
1294c2bed429SRui Ueyama }
1295c2bed429SRui Ueyama 
1296db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12971c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1298ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1299c2bed429SRui Ueyama }
1300c2bed429SRui Ueyama 
1301861021f9SRui Ueyama static imported_symbol_iterator
130215d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1303861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
130415d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1305861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
130615d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1307861021f9SRui Ueyama   }
1308861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
130915d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1310861021f9SRui Ueyama }
1311861021f9SRui Ueyama 
131215d99359SRui Ueyama static imported_symbol_iterator
131315d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1314861021f9SRui Ueyama   uintptr_t IntPtr = 0;
131515d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
131615d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1317861021f9SRui Ueyama }
1318861021f9SRui Ueyama 
131915d99359SRui Ueyama static imported_symbol_iterator
132015d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1321861021f9SRui Ueyama   uintptr_t IntPtr = 0;
132215d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1323861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1324861021f9SRui Ueyama   int Index = 0;
132515d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1326861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1327861021f9SRui Ueyama     while (*Entry++)
1328861021f9SRui Ueyama       ++Index;
1329861021f9SRui Ueyama   } else {
1330861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1331861021f9SRui Ueyama     while (*Entry++)
1332861021f9SRui Ueyama       ++Index;
1333861021f9SRui Ueyama   }
133415d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
133515d99359SRui Ueyama }
133615d99359SRui Ueyama 
133715d99359SRui Ueyama imported_symbol_iterator
133815d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
133960049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
134015d99359SRui Ueyama                              OwningObject);
134115d99359SRui Ueyama }
134215d99359SRui Ueyama 
134315d99359SRui Ueyama imported_symbol_iterator
134415d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
134560049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
134615d99359SRui Ueyama                            OwningObject);
1347861021f9SRui Ueyama }
1348861021f9SRui Ueyama 
1349979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1350979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1351979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1352979fb40bSRui Ueyama }
1353979fb40bSRui Ueyama 
135460049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
135560049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
135660049526SDavid Majnemer                              OwningObject);
135760049526SDavid Majnemer }
135860049526SDavid Majnemer 
135960049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
136060049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
136160049526SDavid Majnemer                            OwningObject);
136260049526SDavid Majnemer }
136360049526SDavid Majnemer 
136460049526SDavid Majnemer iterator_range<imported_symbol_iterator>
136560049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
136660049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
136760049526SDavid Majnemer }
136860049526SDavid Majnemer 
1369db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1370c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1371db4ed0bdSRafael Espindola   if (std::error_code EC =
13721e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1373a045b73aSRui Ueyama     return EC;
1374a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13757d099195SRui Ueyama   return std::error_code();
1376c2bed429SRui Ueyama }
1377c2bed429SRui Ueyama 
13781e152d5eSRui Ueyama std::error_code
13791e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13801e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13817d099195SRui Ueyama   return std::error_code();
13821e152d5eSRui Ueyama }
13831e152d5eSRui Ueyama 
13841e152d5eSRui Ueyama std::error_code
13851e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13861e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13877d099195SRui Ueyama   return std::error_code();
13881e152d5eSRui Ueyama }
13891e152d5eSRui Ueyama 
139015d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
139115d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
139215d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
139315d99359SRui Ueyama }
139415d99359SRui Ueyama 
139515d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
139615d99359SRui Ueyama   ++Index;
139715d99359SRui Ueyama }
139815d99359SRui Ueyama 
139915d99359SRui Ueyama imported_symbol_iterator
140015d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
140115d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
140215d99359SRui Ueyama                              OwningObject);
140315d99359SRui Ueyama }
140415d99359SRui Ueyama 
140515d99359SRui Ueyama imported_symbol_iterator
140615d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
140715d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
140815d99359SRui Ueyama                            OwningObject);
140915d99359SRui Ueyama }
141015d99359SRui Ueyama 
1411979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1412979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1413979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1414979fb40bSRui Ueyama }
1415979fb40bSRui Ueyama 
141615d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
141715d99359SRui Ueyama   uintptr_t IntPtr = 0;
141815d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
141915d99359SRui Ueyama     return EC;
142015d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14217d099195SRui Ueyama   return std::error_code();
142215d99359SRui Ueyama }
142315d99359SRui Ueyama 
14241af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14251af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14261af08658SRui Ueyama   Result = Table;
14277d099195SRui Ueyama   return std::error_code();
14281af08658SRui Ueyama }
14291af08658SRui Ueyama 
1430ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1431ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1432ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1433ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1434ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1435ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1436ffa4cebeSRui Ueyama     return EC;
1437ffa4cebeSRui Ueyama   if (OwningObject->is64())
14385dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1439ffa4cebeSRui Ueyama   else
14405dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14417d099195SRui Ueyama   return std::error_code();
1442ffa4cebeSRui Ueyama }
1443ffa4cebeSRui Ueyama 
1444ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1445ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1446ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1447ad882ba8SRui Ueyama }
1448ad882ba8SRui Ueyama 
14495e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14505e812afaSRafael Espindola   ++Index;
1451ad882ba8SRui Ueyama }
1452ad882ba8SRui Ueyama 
1453da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1454da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1455db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1456da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1457db4ed0bdSRafael Espindola   if (std::error_code EC =
1458db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1459da49d0d4SRui Ueyama     return EC;
1460da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14617d099195SRui Ueyama   return std::error_code();
1462da49d0d4SRui Ueyama }
1463da49d0d4SRui Ueyama 
1464e5df6095SRui Ueyama // Returns the starting ordinal number.
1465db4ed0bdSRafael Espindola std::error_code
1466db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1467e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14687d099195SRui Ueyama   return std::error_code();
1469e5df6095SRui Ueyama }
1470e5df6095SRui Ueyama 
1471ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1472db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1473ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14747d099195SRui Ueyama   return std::error_code();
1475ad882ba8SRui Ueyama }
1476ad882ba8SRui Ueyama 
1477ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1478db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1479ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1480db4ed0bdSRafael Espindola   if (std::error_code EC =
1481db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1482ad882ba8SRui Ueyama     return EC;
148324fc2d64SRui Ueyama   const export_address_table_entry *entry =
148424fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1485ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14867d099195SRui Ueyama   return std::error_code();
1487ad882ba8SRui Ueyama }
1488ad882ba8SRui Ueyama 
1489ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1490ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1491db4ed0bdSRafael Espindola std::error_code
1492db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1493ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1494db4ed0bdSRafael Espindola   if (std::error_code EC =
1495db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1496ad882ba8SRui Ueyama     return EC;
1497ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1498ad882ba8SRui Ueyama 
1499ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1500ad882ba8SRui Ueyama   int Offset = 0;
1501ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1502ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1503ad882ba8SRui Ueyama     if (*I != Index)
1504ad882ba8SRui Ueyama       continue;
1505db4ed0bdSRafael Espindola     if (std::error_code EC =
1506db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1507ad882ba8SRui Ueyama       return EC;
1508ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1509db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1510ad882ba8SRui Ueyama       return EC;
1511ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15127d099195SRui Ueyama     return std::error_code();
1513ad882ba8SRui Ueyama   }
1514ad882ba8SRui Ueyama   Result = "";
15157d099195SRui Ueyama   return std::error_code();
1516ad882ba8SRui Ueyama }
1517ad882ba8SRui Ueyama 
15186161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15196161b38dSRui Ueyama   const data_directory *DataEntry;
15206161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15216161b38dSRui Ueyama     return EC;
15226161b38dSRui Ueyama   uint32_t RVA;
15236161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15246161b38dSRui Ueyama     return EC;
15256161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15266161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15276161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15286161b38dSRui Ueyama   return std::error_code();
15296161b38dSRui Ueyama }
15306161b38dSRui Ueyama 
15316161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15326161b38dSRui Ueyama   uint32_t RVA;
15336161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15346161b38dSRui Ueyama     return EC;
15356161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15366161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15376161b38dSRui Ueyama     return EC;
15386161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15396161b38dSRui Ueyama   return std::error_code();
15406161b38dSRui Ueyama }
15416161b38dSRui Ueyama 
1542861021f9SRui Ueyama bool ImportedSymbolRef::
1543861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1544861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1545861021f9SRui Ueyama       && Index == Other.Index;
1546861021f9SRui Ueyama }
1547861021f9SRui Ueyama 
1548861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1549861021f9SRui Ueyama   ++Index;
1550861021f9SRui Ueyama }
1551861021f9SRui Ueyama 
1552861021f9SRui Ueyama std::error_code
1553861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1554861021f9SRui Ueyama   uint32_t RVA;
1555861021f9SRui Ueyama   if (Entry32) {
1556861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1557861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15587d099195SRui Ueyama       return std::error_code();
1559861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1560861021f9SRui Ueyama   } else {
1561861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15627d099195SRui Ueyama       return std::error_code();
1563861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1564861021f9SRui Ueyama   }
1565861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1566861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1567861021f9SRui Ueyama     return EC;
1568861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1569861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15707d099195SRui Ueyama   return std::error_code();
1571861021f9SRui Ueyama }
1572861021f9SRui Ueyama 
1573ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1574ad7b7e73SDavid Majnemer   if (Entry32)
1575ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1576ad7b7e73SDavid Majnemer   else
1577ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1578ad7b7e73SDavid Majnemer   return std::error_code();
1579ad7b7e73SDavid Majnemer }
1580ad7b7e73SDavid Majnemer 
1581ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1582ad7b7e73SDavid Majnemer   if (Entry32)
1583ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1584ad7b7e73SDavid Majnemer   else
1585ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1586ad7b7e73SDavid Majnemer   return std::error_code();
1587ad7b7e73SDavid Majnemer }
1588ad7b7e73SDavid Majnemer 
1589861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1590861021f9SRui Ueyama   uint32_t RVA;
1591861021f9SRui Ueyama   if (Entry32) {
1592861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1593861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15947d099195SRui Ueyama       return std::error_code();
1595861021f9SRui Ueyama     }
1596861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1597861021f9SRui Ueyama   } else {
1598861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1599861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16007d099195SRui Ueyama       return std::error_code();
1601861021f9SRui Ueyama     }
1602861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1603861021f9SRui Ueyama   }
1604861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1605861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1606861021f9SRui Ueyama     return EC;
1607861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16087d099195SRui Ueyama   return std::error_code();
1609861021f9SRui Ueyama }
1610861021f9SRui Ueyama 
161112db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
161248af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1613db4ed0bdSRafael Espindola   std::error_code EC;
161448af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1615692410efSRafael Espindola   if (EC)
161612db383eSRafael Espindola     return errorCodeToError(EC);
1617437b0d58SRafael Espindola   return std::move(Ret);
1618686738e2SRui Ueyama }
161974e85130SRui Ueyama 
162074e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
162174e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
162274e85130SRui Ueyama }
162374e85130SRui Ueyama 
162474e85130SRui Ueyama void BaseRelocRef::moveNext() {
162574e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
162674e85130SRui Ueyama   // size of the header itself.
162774e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1628970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
162974e85130SRui Ueyama   if (Size == Header->BlockSize) {
163074e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
163174e85130SRui Ueyama     // consists of the header followed by entries. The header contains
163274e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
163374e85130SRui Ueyama     // current block, proceed to the next block.
163474e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
163574e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
163674e85130SRui Ueyama     Index = 0;
163774e85130SRui Ueyama   } else {
163874e85130SRui Ueyama     ++Index;
163974e85130SRui Ueyama   }
164074e85130SRui Ueyama }
164174e85130SRui Ueyama 
164274e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
164374e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
164474e85130SRui Ueyama   Type = Entry[Index].getType();
16457d099195SRui Ueyama   return std::error_code();
164674e85130SRui Ueyama }
164774e85130SRui Ueyama 
164874e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
164974e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
165074e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16517d099195SRui Ueyama   return std::error_code();
165274e85130SRui Ueyama }
1653efef15a0SEric Beckmann 
165487867988SRafael Espindola #define RETURN_IF_ERROR(E)                                                     \
165587867988SRafael Espindola   if (E)                                                                       \
165687867988SRafael Espindola     return E;
1657efef15a0SEric Beckmann 
165887867988SRafael Espindola Expected<ArrayRef<UTF16>>
165987867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1660efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1661efef15a0SEric Beckmann   Reader.setOffset(Offset);
1662efef15a0SEric Beckmann   uint16_t Length;
1663efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1664efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1665efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1666cd704cb6SEric Beckmann   return RawDirString;
1667efef15a0SEric Beckmann }
1668efef15a0SEric Beckmann 
1669f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1670efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1671f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1672efef15a0SEric Beckmann }
1673efef15a0SEric Beckmann 
167487867988SRafael Espindola Expected<const coff_resource_dir_table &>
1675efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1676efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1677efef15a0SEric Beckmann 
1678efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1679efef15a0SEric Beckmann   Reader.setOffset(Offset);
1680efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1681efef15a0SEric Beckmann   assert(Table != nullptr);
1682efef15a0SEric Beckmann   return *Table;
1683efef15a0SEric Beckmann }
1684efef15a0SEric Beckmann 
1685f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1686efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1687f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1688efef15a0SEric Beckmann }
1689efef15a0SEric Beckmann 
1690f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1691f3404674SRafael Espindola   return getTableAtOffset(0);
1692efef15a0SEric Beckmann }
1693