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 
55e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
5694751be7SDavid Majnemer                                    const uint64_t Size) {
57e830c60dSDavid Majnemer   if (Addr + Size < Addr || Addr + Size < Size ||
58e830c60dSDavid Majnemer       Addr + Size > uintptr_t(M.getBufferEnd()) ||
59e830c60dSDavid Majnemer       Addr < uintptr_t(M.getBufferStart())) {
60e830c60dSDavid Majnemer     return object_error::unexpected_eof;
61e830c60dSDavid Majnemer   }
627d099195SRui Ueyama   return std::error_code();
63e830c60dSDavid Majnemer }
64e830c60dSDavid Majnemer 
65ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
66ed64342bSRui Ueyama // Returns unexpected_eof if error.
67ed64342bSRui Ueyama template <typename T>
6848af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
6958323a97SDavid Majnemer                                  const void *Ptr,
70236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
71ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
72e830c60dSDavid Majnemer   if (std::error_code EC = checkOffset(M, Addr, Size))
73e830c60dSDavid Majnemer     return EC;
74ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
757d099195SRui Ueyama   return std::error_code();
761d6167fdSMichael J. Spencer }
771d6167fdSMichael J. Spencer 
789d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
799d2c15efSNico Rieck // prefixed slashes.
809d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
819d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
829d2c15efSNico Rieck   if (Str.size() > 6)
839d2c15efSNico Rieck     return true;
849d2c15efSNico Rieck 
859d2c15efSNico Rieck   uint64_t Value = 0;
869d2c15efSNico Rieck   while (!Str.empty()) {
879d2c15efSNico Rieck     unsigned CharVal;
889d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
899d2c15efSNico Rieck       CharVal = Str[0] - 'A';
909d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
919d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
929d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
939d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
949d2c15efSNico Rieck     else if (Str[0] == '+') // 62
955500b07cSRui Ueyama       CharVal = 62;
969d2c15efSNico Rieck     else if (Str[0] == '/') // 63
975500b07cSRui Ueyama       CharVal = 63;
989d2c15efSNico Rieck     else
999d2c15efSNico Rieck       return true;
1009d2c15efSNico Rieck 
1019d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
1029d2c15efSNico Rieck     Str = Str.substr(1);
1039d2c15efSNico Rieck   }
1049d2c15efSNico Rieck 
1059d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
1069d2c15efSNico Rieck     return true;
1079d2c15efSNico Rieck 
1089d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
1099d2c15efSNico Rieck   return false;
1109d2c15efSNico Rieck }
1119d2c15efSNico Rieck 
11244f51e51SDavid Majnemer template <typename coff_symbol_type>
11344f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
11444f51e51SDavid Majnemer   const coff_symbol_type *Addr =
11544f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1161d6167fdSMichael J. Spencer 
117236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1181d6167fdSMichael J. Spencer #ifndef NDEBUG
1191d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1208ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1211d6167fdSMichael J. Spencer 
12244f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
12344f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1241d6167fdSMichael J. Spencer #endif
1251d6167fdSMichael J. Spencer 
1268ff24d25SRui Ueyama   return Addr;
1271d6167fdSMichael J. Spencer }
1281d6167fdSMichael J. Spencer 
1298ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1308ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1311d6167fdSMichael J. Spencer 
1321d6167fdSMichael J. Spencer #ifndef NDEBUG
1331d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
13444f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1351d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1361d6167fdSMichael J. Spencer 
1378ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1388ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1391d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1401d6167fdSMichael J. Spencer #endif
1411d6167fdSMichael J. Spencer 
1428ff24d25SRui Ueyama   return Addr;
1431d6167fdSMichael J. Spencer }
1441d6167fdSMichael J. Spencer 
1455e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
146236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
14744f51e51SDavid Majnemer   if (SymbolTable16) {
14844f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1498ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
150236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
15144f51e51SDavid Majnemer   } else if (SymbolTable32) {
15244f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
15344f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
154236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
15544f51e51SDavid Majnemer   } else {
15644f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
15744f51e51SDavid Majnemer   }
1581d6167fdSMichael J. Spencer }
1591d6167fdSMichael J. Spencer 
16081e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
16144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1625d0c2ffaSRafael Espindola   StringRef Result;
163efef15a0SEric Beckmann   if (std::error_code EC = getSymbolName(Symb, Result))
16481e8b7d9SKevin Enderby     return errorCodeToError(EC);
1655d0c2ffaSRafael Espindola   return Result;
1668e90adafSMichael J. Spencer }
1678e90adafSMichael J. Spencer 
168be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
169be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
170991af666SRafael Espindola }
171991af666SRafael Espindola 
1726b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1736b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1746b2bba14SDavide Italiano   // up to 32 bytes.
1756b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
17603a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1776b2bba14SDavide Italiano }
1786b2bba14SDavide Italiano 
179931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
180ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
18144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
182c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
183991af666SRafael Espindola 
184991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
185991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
186ed067c45SRafael Espindola     return Result;
18754c9f3daSRafael Espindola 
1882617dcceSCraig Topper   const coff_section *Section = nullptr;
189c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
190931cb65dSKevin Enderby     return errorCodeToError(EC);
191991af666SRafael Espindola   Result += Section->VirtualAddress;
19247ea9eceSReid Kleckner 
19347ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
19447ea9eceSReid Kleckner   // return virtual addresses.
19521427adaSReid Kleckner   Result += getImageBase();
19647ea9eceSReid Kleckner 
197ed067c45SRafael Espindola   return Result;
198c7d7c6fbSDavid Majnemer }
199c7d7c6fbSDavid Majnemer 
2007bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
20144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
202c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
20344f51e51SDavid Majnemer 
204e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
205e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
2062fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
2072fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
2082fa80cc5SRafael Espindola   if (Symb.isCommon())
2092fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2102fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2112fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2122fa80cc5SRafael Espindola 
2131a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2142fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2152fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2162fa80cc5SRafael Espindola 
2172fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2182fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2192fa80cc5SRafael Espindola 
2202fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
22175d1cf33SBenjamin Kramer }
22275d1cf33SBenjamin Kramer 
22320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
22444f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
22520122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
22675d1cf33SBenjamin Kramer 
227c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2289dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2291df4b84dSDavid Meyer 
230*1079ef8dSMartell Malone   if (Symb.isWeakExternal()) {
2311df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
232*1079ef8dSMartell Malone     // We use indirect to allow the archiver to write weak externs
233*1079ef8dSMartell Malone     Result |= SymbolRef::SF_Indirect;
234*1079ef8dSMartell Malone   }
2351df4b84dSDavid Meyer 
23644f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2371df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2381df4b84dSDavid Meyer 
239c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
240c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
241c7d7c6fbSDavid Majnemer 
242c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
243c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
244c7d7c6fbSDavid Majnemer 
245c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
246c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
247c7d7c6fbSDavid Majnemer 
248c7d7c6fbSDavid Majnemer   if (Symb.isAnyUndefined())
249c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
250c7d7c6fbSDavid Majnemer 
25120122a43SRafael Espindola   return Result;
25201759754SMichael J. Spencer }
25301759754SMichael J. Spencer 
254d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
255c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2565eb02e45SRafael Espindola   return Symb.getValue();
2578e90adafSMichael J. Spencer }
2588e90adafSMichael J. Spencer 
2597bd8d994SKevin Enderby Expected<section_iterator>
2608bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
26144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2628bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2638bab889bSRafael Espindola     return section_end();
2642617dcceSCraig Topper   const coff_section *Sec = nullptr;
26544f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2667bd8d994SKevin Enderby     return errorCodeToError(EC);
2678bab889bSRafael Espindola   DataRefImpl Ret;
2688bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2698bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
27032173153SMichael J. Spencer }
27132173153SMichael J. Spencer 
2726bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2736bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2746bf32210SRafael Espindola   return Symb.getSectionNumber();
2756bf32210SRafael Espindola }
2766bf32210SRafael Espindola 
2775e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2788ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2798ff24d25SRui Ueyama   Sec += 1;
2808ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2818e90adafSMichael J. Spencer }
2828e90adafSMichael J. Spencer 
283db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2841d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2858ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2868ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2878e90adafSMichael J. Spencer }
2888e90adafSMichael J. Spencer 
28980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2908ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2917c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2927c6a071bSDavid Majnemer 
2937c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2947c6a071bSDavid Majnemer   // return virtual addresses.
29521427adaSReid Kleckner   Result += getImageBase();
2967c6a071bSDavid Majnemer   return Result;
2978e90adafSMichael J. Spencer }
2988e90adafSMichael J. Spencer 
299a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
300a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
301a25d329bSGeorge Rimar }
302a25d329bSGeorge Rimar 
30380291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
304a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
3058e90adafSMichael J. Spencer }
3068e90adafSMichael J. Spencer 
307db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
3081d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
3098ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3109da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
311db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
3129da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
3139da9e693SMichael J. Spencer   return EC;
3148e90adafSMichael J. Spencer }
3158e90adafSMichael J. Spencer 
31680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3178ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
318511391feSDavid Majnemer   return Sec->getAlignment();
3197989460aSMichael J. Spencer }
3207989460aSMichael J. Spencer 
321401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
322401e4e57SGeorge Rimar   return false;
323401e4e57SGeorge Rimar }
324401e4e57SGeorge Rimar 
32580291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3268ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32780291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3288e90adafSMichael J. Spencer }
3298e90adafSMichael J. Spencer 
33080291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3318ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
33280291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
333800619f2SMichael J. Spencer }
334800619f2SMichael J. Spencer 
33580291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3368ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3371a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3381a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3391a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3401a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
341800619f2SMichael J. Spencer }
342800619f2SMichael J. Spencer 
3436bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3446bf32210SRafael Espindola   uintptr_t Offset =
3456bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3466bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3476bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3486bf32210SRafael Espindola }
3496bf32210SRafael Espindola 
35080291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3518ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3521a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3531a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3541a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3552138ef6dSPreston Gurd }
3562138ef6dSPreston Gurd 
357e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
358e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
359e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
360e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
361e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
362e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
363e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
364e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
365e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
366e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
367e830c60dSDavid Majnemer       return 0;
36898fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36998fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
370e830c60dSDavid Majnemer   }
371e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
372e830c60dSDavid Majnemer }
373e830c60dSDavid Majnemer 
37494751be7SDavid Majnemer static const coff_relocation *
37594751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37694751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37794751be7SDavid Majnemer   if (!NumRelocs)
37894751be7SDavid Majnemer     return nullptr;
379827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
38094751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
381827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
382827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
383827c8a2bSRui Ueyama     // relocations.
384827c8a2bSRui Ueyama     begin++;
385827c8a2bSRui Ueyama   }
38694751be7SDavid Majnemer   if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
38794751be7SDavid Majnemer     return nullptr;
38894751be7SDavid Majnemer   return begin;
389827c8a2bSRui Ueyama }
39094751be7SDavid Majnemer 
39194751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
39294751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
39394751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
39476d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
39576d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
39694751be7SDavid Majnemer   DataRefImpl Ret;
39794751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3988ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
399e5fd0047SMichael J. Spencer }
400e5fd0047SMichael J. Spencer 
4018ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4028ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
40394751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
40494751be7SDavid Majnemer   if (I)
40594751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4068ff24d25SRui Ueyama   DataRefImpl Ret;
40794751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4088ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
409e5fd0047SMichael J. Spencer }
410e5fd0047SMichael J. Spencer 
411c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
412db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
41344f51e51SDavid Majnemer   if (COFFHeader)
414236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
415236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
416236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
41744f51e51SDavid Majnemer       return EC;
41844f51e51SDavid Majnemer 
41944f51e51SDavid Majnemer   if (COFFBigObjHeader)
420236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
421236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
422236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4238ff24d25SRui Ueyama       return EC;
424c2bed429SRui Ueyama 
425c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
426c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
427c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
428f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42944f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
430f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
431c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
43248af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4338ff24d25SRui Ueyama     return EC;
434c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
435db4ed0bdSRafael Espindola   if (std::error_code EC =
43648af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4378ff24d25SRui Ueyama     return EC;
438c2bed429SRui Ueyama 
439773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
440773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
441773a5795SNico Rieck   if (StringTableSize < 4)
442773a5795SNico Rieck       StringTableSize = 4;
443773a5795SNico Rieck 
444c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
445773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
446c2bed429SRui Ueyama     return  object_error::parse_failed;
4477d099195SRui Ueyama   return std::error_code();
448c2bed429SRui Ueyama }
449c2bed429SRui Ueyama 
45021427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
451e94fef7bSReid Kleckner   if (PE32Header)
45221427adaSReid Kleckner     return PE32Header->ImageBase;
453e94fef7bSReid Kleckner   else if (PE32PlusHeader)
45421427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
45521427adaSReid Kleckner   // This actually comes up in practice.
45621427adaSReid Kleckner   return 0;
457e94fef7bSReid Kleckner }
458e94fef7bSReid Kleckner 
459215a586cSRui Ueyama // Returns the file offset for the given VA.
460db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
46121427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
462b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
463b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
464b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
465215a586cSRui Ueyama }
466215a586cSRui Ueyama 
467c2bed429SRui Ueyama // Returns the file offset for the given RVA.
468db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46927dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
47027dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
471c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
472c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
473215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
474215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
475c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4767d099195SRui Ueyama       return std::error_code();
477c2bed429SRui Ueyama     }
478c2bed429SRui Ueyama   }
479c2bed429SRui Ueyama   return object_error::parse_failed;
480c2bed429SRui Ueyama }
481c2bed429SRui Ueyama 
4822da433eaSReid Kleckner std::error_code
4832da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4842da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4852da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4862da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4872da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4882da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4892da433eaSReid Kleckner     // overflow.
4902da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4912da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4922da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4932da433eaSReid Kleckner       uintptr_t Begin =
4942da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4952da433eaSReid Kleckner       Contents =
4962da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4972da433eaSReid Kleckner       return std::error_code();
4982da433eaSReid Kleckner     }
4992da433eaSReid Kleckner   }
5002da433eaSReid Kleckner   return object_error::parse_failed;
5012da433eaSReid Kleckner }
5022da433eaSReid Kleckner 
503c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
504c2bed429SRui Ueyama // table entry.
505db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
506db4ed0bdSRafael Espindola                                             StringRef &Name) const {
507c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
508db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5098ff24d25SRui Ueyama     return EC;
510c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
511c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
512c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5137d099195SRui Ueyama   return std::error_code();
514c2bed429SRui Ueyama }
515c2bed429SRui Ueyama 
51601528021SSaleem Abdulrasool std::error_code
51701528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51801528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5192da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5202da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5212da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5222da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5232da433eaSReid Kleckner     return EC;
52401528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5252da433eaSReid Kleckner     return object_error::parse_failed;
52601528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
52701528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5282da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5292da433eaSReid Kleckner                           InfoBytes.size());
5302da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5312da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5322da433eaSReid Kleckner   return std::error_code();
5332da433eaSReid Kleckner }
5342da433eaSReid Kleckner 
53501528021SSaleem Abdulrasool std::error_code
53601528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
537f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
538f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
539f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
540f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
541f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
542f27f3f84SReid Kleckner   PDBInfo = nullptr;
543f27f3f84SReid Kleckner   PDBFileName = StringRef();
544f27f3f84SReid Kleckner   return std::error_code();
545f27f3f84SReid Kleckner }
546f27f3f84SReid Kleckner 
547c2bed429SRui Ueyama // Find the import table.
548db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
549c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
550c2bed429SRui Ueyama   // the import table, do nothing.
551c2bed429SRui Ueyama   const data_directory *DataEntry;
552c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5537d099195SRui Ueyama     return std::error_code();
554c2bed429SRui Ueyama 
555c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
556c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5577d099195SRui Ueyama     return std::error_code();
558c2bed429SRui Ueyama 
559c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
560c2bed429SRui Ueyama 
561c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
562c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
563c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
564db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5658ff24d25SRui Ueyama     return EC;
566ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
567ad7b7e73SDavid Majnemer     return EC;
568c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5691c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5707d099195SRui Ueyama   return std::error_code();
571ad882ba8SRui Ueyama }
572c2bed429SRui Ueyama 
57315d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
57415d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
57515d99359SRui Ueyama   const data_directory *DataEntry;
57615d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5777d099195SRui Ueyama     return std::error_code();
57815d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5797d099195SRui Ueyama     return std::error_code();
58015d99359SRui Ueyama 
58115d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
58215d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
58315d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
58415d99359SRui Ueyama 
58515d99359SRui Ueyama   uintptr_t IntPtr = 0;
58615d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
58715d99359SRui Ueyama     return EC;
58815d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58915d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5907d099195SRui Ueyama   return std::error_code();
59115d99359SRui Ueyama }
59215d99359SRui Ueyama 
593ad882ba8SRui Ueyama // Find the export table.
594db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
595ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
596ad882ba8SRui Ueyama   // the export table, do nothing.
597ad882ba8SRui Ueyama   const data_directory *DataEntry;
598ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5997d099195SRui Ueyama     return std::error_code();
600ad882ba8SRui Ueyama 
601ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
602ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6037d099195SRui Ueyama     return std::error_code();
604ad882ba8SRui Ueyama 
605ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
606ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
607db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
608ad882ba8SRui Ueyama     return EC;
60924fc2d64SRui Ueyama   ExportDirectory =
61024fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6117d099195SRui Ueyama   return std::error_code();
612c2bed429SRui Ueyama }
613c2bed429SRui Ueyama 
61474e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
61574e85130SRui Ueyama   const data_directory *DataEntry;
61674e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6177d099195SRui Ueyama     return std::error_code();
61874e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6197d099195SRui Ueyama     return std::error_code();
62074e85130SRui Ueyama 
62174e85130SRui Ueyama   uintptr_t IntPtr = 0;
62274e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
62374e85130SRui Ueyama     return EC;
62474e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
62574e85130SRui Ueyama       IntPtr);
62674e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
62774e85130SRui Ueyama       IntPtr + DataEntry->Size);
6287d099195SRui Ueyama   return std::error_code();
62974e85130SRui Ueyama }
63074e85130SRui Ueyama 
6312da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6322da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6332da433eaSReid Kleckner   const data_directory *DataEntry;
6342da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6352da433eaSReid Kleckner     return std::error_code();
6362da433eaSReid Kleckner 
6372da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6382da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6392da433eaSReid Kleckner     return std::error_code();
6402da433eaSReid Kleckner 
6412da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6422da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6432da433eaSReid Kleckner     return object_error::parse_failed;
6442da433eaSReid Kleckner 
6452da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6462da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6472da433eaSReid Kleckner     return EC;
6482da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6492da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6502da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6512da433eaSReid Kleckner     return EC;
6522da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6532da433eaSReid Kleckner   return std::error_code();
6542da433eaSReid Kleckner }
6552da433eaSReid Kleckner 
656b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
657b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
658b7d716c0SReid Kleckner   const data_directory *DataEntry;
659b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
660b7d716c0SReid Kleckner     return std::error_code();
661b7d716c0SReid Kleckner 
662b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
663b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
664b7d716c0SReid Kleckner     return std::error_code();
665b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
666b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
667b7d716c0SReid Kleckner     return EC;
668b7d716c0SReid Kleckner 
669b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
670b7d716c0SReid Kleckner   return std::error_code();
671b7d716c0SReid Kleckner }
672b7d716c0SReid Kleckner 
67348af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
67448af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
67544f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
67644f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
67744f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
678ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
67915d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6802da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6812da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6821d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
68348af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
684c3f9b5a5SRafael Espindola     return;
685ee066fc4SEric Christopher 
68682ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
68782ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
68882ebd8e3SRui Ueyama 
68982ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
69082ebd8e3SRui Ueyama   // it is placed right after COFF header.
6918ff24d25SRui Ueyama   bool HasPEHeader = false;
692ee066fc4SEric Christopher 
6931d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
69450267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
695ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
696ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
69750267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
69850267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69950267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
70082ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
70150267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
7028ff24d25SRui Ueyama         EC = object_error::parse_failed;
7031d6167fdSMichael J. Spencer         return;
7041d6167fdSMichael J. Spencer       }
70544f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7068ff24d25SRui Ueyama       HasPEHeader = true;
707ee066fc4SEric Christopher     }
70850267222SDavid Majnemer   }
709ee066fc4SEric Christopher 
71048af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
7111d6167fdSMichael J. Spencer     return;
71244f51e51SDavid Majnemer 
71344f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
71444f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
71544f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
71644f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
71744f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
71844f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71944f51e51SDavid Majnemer       return;
72044f51e51SDavid Majnemer 
72144f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
72244f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
72344f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
72444f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
72544f51e51SDavid Majnemer       COFFHeader = nullptr;
72644f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
72744f51e51SDavid Majnemer     } else {
72844f51e51SDavid Majnemer       // It's not a bigobj.
72944f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
73044f51e51SDavid Majnemer     }
73144f51e51SDavid Majnemer   }
73244f51e51SDavid Majnemer   if (COFFHeader) {
73344f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
73444f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7357d099195SRui Ueyama     EC = std::error_code();
73682ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
73782ebd8e3SRui Ueyama 
73844f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
73944f51e51SDavid Majnemer       return;
74044f51e51SDavid Majnemer   }
74144f51e51SDavid Majnemer 
7428ff24d25SRui Ueyama   if (HasPEHeader) {
74310ed9ddcSRui Ueyama     const pe32_header *Header;
74448af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
74582ebd8e3SRui Ueyama       return;
74610ed9ddcSRui Ueyama 
74710ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
74810ed9ddcSRui Ueyama     uint64_t DataDirSize;
74950267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
75010ed9ddcSRui Ueyama       PE32Header = Header;
75110ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
75210ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
75350267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
75410ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
75510ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
75610ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
75710ed9ddcSRui Ueyama     } else {
75810ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
75910ed9ddcSRui Ueyama       EC = object_error::parse_failed;
760ed64342bSRui Ueyama       return;
761ed64342bSRui Ueyama     }
76248af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
76310ed9ddcSRui Ueyama       return;
764f53c8cb4SRui Ueyama   }
765776c6828SRui Ueyama 
7668950a538SRui Ueyama   if (COFFHeader)
7678950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7688950a538SRui Ueyama 
76948af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
770236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7711d6167fdSMichael J. Spencer     return;
7721d6167fdSMichael J. Spencer 
773c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
774236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
775ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
776ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
777ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
778ac8cfab5SDavid Majnemer       StringTable = nullptr;
779ac8cfab5SDavid Majnemer       StringTableSize = 0;
780ac8cfab5SDavid Majnemer     }
781236b0ca7SDavid Majnemer   } else {
782236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
783236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
784236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
785236b0ca7SDavid Majnemer       return;
786236b0ca7SDavid Majnemer     }
787236b0ca7SDavid Majnemer   }
7888e90adafSMichael J. Spencer 
789c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7908ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
791ed64342bSRui Ueyama     return;
79215d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
79315d99359SRui Ueyama     return;
7941d6167fdSMichael J. Spencer 
795ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7968ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
797ad882ba8SRui Ueyama     return;
798ad882ba8SRui Ueyama 
79974e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
80074e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
80174e85130SRui Ueyama     return;
80274e85130SRui Ueyama 
8032da433eaSReid Kleckner   // Initialize the pointer to the export table.
8042da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
8052da433eaSReid Kleckner     return;
8062da433eaSReid Kleckner 
807b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
808b7d716c0SReid Kleckner     return;
809b7d716c0SReid Kleckner 
8107d099195SRui Ueyama   EC = std::error_code();
8118e90adafSMichael J. Spencer }
8128e90adafSMichael J. Spencer 
813435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8148ff24d25SRui Ueyama   DataRefImpl Ret;
81544f51e51SDavid Majnemer   Ret.p = getSymbolTable();
816f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8178e90adafSMichael J. Spencer }
8188e90adafSMichael J. Spencer 
819435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8208e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8218ff24d25SRui Ueyama   DataRefImpl Ret;
8228ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
823f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8248e90adafSMichael J. Spencer }
8258e90adafSMichael J. Spencer 
826bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
827ad7b7e73SDavid Majnemer   if (!ImportDirectory)
828ad7b7e73SDavid Majnemer     return import_directory_end();
8291c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
830ad7b7e73SDavid Majnemer     return import_directory_end();
831a045b73aSRui Ueyama   return import_directory_iterator(
832a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
833c2bed429SRui Ueyama }
834c2bed429SRui Ueyama 
835bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
836a045b73aSRui Ueyama   return import_directory_iterator(
837ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
838c2bed429SRui Ueyama }
839c429b80dSDavid Meyer 
84015d99359SRui Ueyama delay_import_directory_iterator
84115d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
84215d99359SRui Ueyama   return delay_import_directory_iterator(
84315d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
84415d99359SRui Ueyama }
84515d99359SRui Ueyama 
84615d99359SRui Ueyama delay_import_directory_iterator
84715d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
84815d99359SRui Ueyama   return delay_import_directory_iterator(
84915d99359SRui Ueyama       DelayImportDirectoryEntryRef(
85015d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
85115d99359SRui Ueyama }
85215d99359SRui Ueyama 
853ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
854ad882ba8SRui Ueyama   return export_directory_iterator(
855ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
856ad882ba8SRui Ueyama }
857ad882ba8SRui Ueyama 
858ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8592617dcceSCraig Topper   if (!ExportDirectory)
8602617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8618ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
862ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8638ff24d25SRui Ueyama   return export_directory_iterator(Ref);
864ad882ba8SRui Ueyama }
865ad882ba8SRui Ueyama 
866b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8678ff24d25SRui Ueyama   DataRefImpl Ret;
8688ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8698ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8708e90adafSMichael J. Spencer }
8718e90adafSMichael J. Spencer 
872b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8738ff24d25SRui Ueyama   DataRefImpl Ret;
87444f51e51SDavid Majnemer   int NumSections =
87544f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8768ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8778ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8788e90adafSMichael J. Spencer }
8798e90adafSMichael J. Spencer 
88074e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
88174e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
88274e85130SRui Ueyama }
88374e85130SRui Ueyama 
88474e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
88574e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
88674e85130SRui Ueyama }
88774e85130SRui Ueyama 
8888e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
88943c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8908e90adafSMichael J. Spencer }
8918e90adafSMichael J. Spencer 
8928e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
89344f51e51SDavid Majnemer   switch(getMachine()) {
8948e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8958e90adafSMichael J. Spencer     return "COFF-i386";
8968e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8978e90adafSMichael J. Spencer     return "COFF-x86-64";
8989b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8999b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
9001eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9011eff5c9cSMartell Malone     return "COFF-ARM64";
9028e90adafSMichael J. Spencer   default:
9038e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
9048e90adafSMichael J. Spencer   }
9058e90adafSMichael J. Spencer }
9068e90adafSMichael J. Spencer 
9078e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const {
90844f51e51SDavid Majnemer   switch (getMachine()) {
9098e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9108e90adafSMichael J. Spencer     return Triple::x86;
9118e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9128e90adafSMichael J. Spencer     return Triple::x86_64;
9139b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9149b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9151eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9161eff5c9cSMartell Malone     return Triple::aarch64;
9178e90adafSMichael J. Spencer   default:
9188e90adafSMichael J. Spencer     return Triple::UnknownArch;
9198e90adafSMichael J. Spencer   }
9208e90adafSMichael J. Spencer }
9218e90adafSMichael J. Spencer 
922979fb40bSRui Ueyama iterator_range<import_directory_iterator>
923979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
924979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
925979fb40bSRui Ueyama }
926979fb40bSRui Ueyama 
927979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
928979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
929979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
930979fb40bSRui Ueyama                     delay_import_directory_end());
931979fb40bSRui Ueyama }
932979fb40bSRui Ueyama 
933979fb40bSRui Ueyama iterator_range<export_directory_iterator>
934979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
935979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
936979fb40bSRui Ueyama }
937979fb40bSRui Ueyama 
93874e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
93974e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
94074e85130SRui Ueyama }
94174e85130SRui Ueyama 
942db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
94382ebd8e3SRui Ueyama   Res = PE32Header;
9447d099195SRui Ueyama   return std::error_code();
94589a7a5eaSMichael J. Spencer }
94689a7a5eaSMichael J. Spencer 
947db4ed0bdSRafael Espindola std::error_code
94810ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
94910ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9507d099195SRui Ueyama   return std::error_code();
95110ed9ddcSRui Ueyama }
95210ed9ddcSRui Ueyama 
953db4ed0bdSRafael Espindola std::error_code
954db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
955ed64342bSRui Ueyama                                  const data_directory *&Res) const {
956ed64342bSRui Ueyama   // Error if if there's no data directory or the index is out of range.
957f69b0585SDavid Majnemer   if (!DataDirectory) {
958f69b0585SDavid Majnemer     Res = nullptr;
95910ed9ddcSRui Ueyama     return object_error::parse_failed;
960f69b0585SDavid Majnemer   }
96110ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
96210ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
96310ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
964f69b0585SDavid Majnemer   if (Index >= NumEnt) {
965f69b0585SDavid Majnemer     Res = nullptr;
966ed64342bSRui Ueyama     return object_error::parse_failed;
967f69b0585SDavid Majnemer   }
9688ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9697d099195SRui Ueyama   return std::error_code();
970ed64342bSRui Ueyama }
971ed64342bSRui Ueyama 
972db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9731d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9742617dcceSCraig Topper   Result = nullptr;
975236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9767d099195SRui Ueyama     return std::error_code();
977236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9781d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9798ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9807d099195SRui Ueyama     return std::error_code();
9818e90adafSMichael J. Spencer   }
982236b0ca7SDavid Majnemer   return object_error::parse_failed;
983236b0ca7SDavid Majnemer }
9848e90adafSMichael J. Spencer 
985db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9861d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9871d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9881d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9891d6167fdSMichael J. Spencer     return object_error::parse_failed;
9908ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9911d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
9928ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
9937d099195SRui Ueyama   return std::error_code();
9948e90adafSMichael J. Spencer }
995022ecdf2SBenjamin Kramer 
99644f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
99789a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
998e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
999e40d30f3SRui Ueyama }
1000e40d30f3SRui Ueyama 
1001e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1002e40d30f3SRui Ueyama                                               StringRef &Res) const {
100389a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
1004e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
1005e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
10068ff24d25SRui Ueyama       return EC;
10077d099195SRui Ueyama     return std::error_code();
100889a7a5eaSMichael J. Spencer   }
100989a7a5eaSMichael J. Spencer 
1010e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
101189a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
1012e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
101389a7a5eaSMichael J. Spencer   else
101489a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
1015e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
10167d099195SRui Ueyama   return std::error_code();
101789a7a5eaSMichael J. Spencer }
101889a7a5eaSMichael J. Spencer 
101944f51e51SDavid Majnemer ArrayRef<uint8_t>
102044f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10212617dcceSCraig Topper   const uint8_t *Aux = nullptr;
102271757ef3SMarshall Clow 
102344f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
102444f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
102571757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
102644f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
102771757ef3SMarshall Clow #ifndef NDEBUG
10288ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10298ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
103044f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
103144f51e51SDavid Majnemer         Offset >=
103244f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
103371757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
103471757ef3SMarshall Clow 
103544f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
103644f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
103771757ef3SMarshall Clow #endif
1038bfb85e67SMarshall Clow   }
103944f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
104071757ef3SMarshall Clow }
104171757ef3SMarshall Clow 
1042db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
104353c2d547SMichael J. Spencer                                                StringRef &Res) const {
104453c2d547SMichael J. Spencer   StringRef Name;
104544f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
104653c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
104753c2d547SMichael J. Spencer     Name = Sec->Name;
104853c2d547SMichael J. Spencer   else
104953c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
105044f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
105153c2d547SMichael J. Spencer 
105253c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10532314b3deSDavid Majnemer   if (Name.startswith("/")) {
105453c2d547SMichael J. Spencer     uint32_t Offset;
10552314b3deSDavid Majnemer     if (Name.startswith("//")) {
10569d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10579d2c15efSNico Rieck         return object_error::parse_failed;
10589d2c15efSNico Rieck     } else {
105953c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
106053c2d547SMichael J. Spencer         return object_error::parse_failed;
10619d2c15efSNico Rieck     }
1062db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10638ff24d25SRui Ueyama       return EC;
106453c2d547SMichael J. Spencer   }
106553c2d547SMichael J. Spencer 
106653c2d547SMichael J. Spencer   Res = Name;
10677d099195SRui Ueyama   return std::error_code();
106853c2d547SMichael J. Spencer }
106953c2d547SMichael J. Spencer 
1070a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1071a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1072a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1073a9ee5c06SDavid Majnemer   //
1074a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1075d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1076a9ee5c06SDavid Majnemer   //
1077a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1078a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1079a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1080a9ee5c06SDavid Majnemer   // considered to be zero.
1081d5297ee7SRui Ueyama   if (getDOSHeader())
1082d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1083d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1084a9ee5c06SDavid Majnemer }
1085a9ee5c06SDavid Majnemer 
1086db4ed0bdSRafael Espindola std::error_code
1087db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
10889da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1089e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1090e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1091e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1092ee97c5f0SShoaib Meenai     return std::error_code();
10939da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10949da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10959da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10969da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1097a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1098e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
10999da9e693SMichael J. Spencer     return object_error::parse_failed;
1100a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
11017d099195SRui Ueyama   return std::error_code();
11029da9e693SMichael J. Spencer }
11039da9e693SMichael J. Spencer 
1104022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1105e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1106022ecdf2SBenjamin Kramer }
11078ff24d25SRui Ueyama 
11085e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1109e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1110e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1111022ecdf2SBenjamin Kramer }
11128ff24d25SRui Ueyama 
111396d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
111458323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
111596d071cdSRafael Espindola   return R->VirtualAddress;
1116cbe72fc9SDanil Malyshev }
11178ff24d25SRui Ueyama 
1118806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1119022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11208ff24d25SRui Ueyama   DataRefImpl Ref;
1121236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1122236b0ca7SDavid Majnemer     return symbol_end();
112344f51e51SDavid Majnemer   if (SymbolTable16)
112444f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
112544f51e51SDavid Majnemer   else if (SymbolTable32)
112644f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
112744f51e51SDavid Majnemer   else
1128c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11298ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1130022ecdf2SBenjamin Kramer }
11318ff24d25SRui Ueyama 
113299c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1133022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
113499c041b7SRafael Espindola   return R->Type;
1135022ecdf2SBenjamin Kramer }
1136e5fd0047SMichael J. Spencer 
113727dc8394SAlexey Samsonov const coff_section *
113827dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
113927dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
114071757ef3SMarshall Clow }
114171757ef3SMarshall Clow 
114244f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
114344f51e51SDavid Majnemer   if (SymbolTable16)
114444f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
114544f51e51SDavid Majnemer   if (SymbolTable32)
114644f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
114744f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
114844f51e51SDavid Majnemer }
114944f51e51SDavid Majnemer 
115044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
115144f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
115271757ef3SMarshall Clow }
115371757ef3SMarshall Clow 
1154f12b8282SRafael Espindola const coff_relocation *
115527dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
115627dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1157d3e2a76cSMarshall Clow }
1158d3e2a76cSMarshall Clow 
11596a75acb1SRui Ueyama iterator_range<const coff_relocation *>
11606a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11616a75acb1SRui Ueyama   const coff_relocation *I = getFirstReloc(Sec, Data, base());
11626a75acb1SRui Ueyama   const coff_relocation *E = I;
11636a75acb1SRui Ueyama   if (I)
11646a75acb1SRui Ueyama     E += getNumberOfRelocations(Sec, Data, base());
11656a75acb1SRui Ueyama   return make_range(I, E);
11666a75acb1SRui Ueyama }
11676a75acb1SRui Ueyama 
116827dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
116927dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
117027dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
117127dc8394SAlexey Samsonov     break;
1172e5fd0047SMichael J. Spencer 
117341bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
117441bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11758ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11768ff24d25SRui Ueyama   StringRef Res;
117744f51e51SDavid Majnemer   switch (getMachine()) {
1178e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11798ff24d25SRui Ueyama     switch (Reloc->Type) {
1180e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1181e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1182e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1183e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1184e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1185e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1186e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1187e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1188e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1189e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1190e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1191e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1192e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1193e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1194e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1195e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1196e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1197e5fd0047SMichael J. Spencer     default:
11988ff24d25SRui Ueyama       Res = "Unknown";
1199e5fd0047SMichael J. Spencer     }
1200e5fd0047SMichael J. Spencer     break;
12015c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
12025c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
12035c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12045c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12055c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12065c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12075c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12085c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12095c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12105c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
12115c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12125c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12135c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12145c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12155c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12165c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12175c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
12185c503bf4SSaleem Abdulrasool     default:
12195c503bf4SSaleem Abdulrasool       Res = "Unknown";
12205c503bf4SSaleem Abdulrasool     }
12215c503bf4SSaleem Abdulrasool     break;
12220c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
12230c72172eSMandeep Singh Grang     switch (Reloc->Type) {
12240c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12250c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12260c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12270c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12280c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12290c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12300c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12310c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12320c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12330c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12340c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12350c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12360c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12370c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12380c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12390c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12400c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
12410c72172eSMandeep Singh Grang     default:
12420c72172eSMandeep Singh Grang       Res = "Unknown";
12430c72172eSMandeep Singh Grang     }
12440c72172eSMandeep Singh Grang     break;
1245e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
12468ff24d25SRui Ueyama     switch (Reloc->Type) {
1247e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1248e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1249e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1250e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1251e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1252e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1253e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1254e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1255e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1256e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1257e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1258e5fd0047SMichael J. Spencer     default:
12598ff24d25SRui Ueyama       Res = "Unknown";
1260e5fd0047SMichael J. Spencer     }
1261e5fd0047SMichael J. Spencer     break;
1262e5fd0047SMichael J. Spencer   default:
12638ff24d25SRui Ueyama     Res = "Unknown";
1264e5fd0047SMichael J. Spencer   }
12658ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1266e5fd0047SMichael J. Spencer }
1267e5fd0047SMichael J. Spencer 
1268e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1269e5fd0047SMichael J. Spencer 
1270c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1271c66d761bSRafael Espindola   return !DataDirectory;
1272c66d761bSRafael Espindola }
1273c66d761bSRafael Espindola 
1274c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1275c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1276a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1277c2bed429SRui Ueyama }
1278c2bed429SRui Ueyama 
12795e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12805e812afaSRafael Espindola   ++Index;
12811c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1282ad7b7e73SDavid Majnemer     Index = -1;
1283ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1284ad7b7e73SDavid Majnemer   }
1285c2bed429SRui Ueyama }
1286c2bed429SRui Ueyama 
1287db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12881c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1289ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1290c2bed429SRui Ueyama }
1291c2bed429SRui Ueyama 
1292861021f9SRui Ueyama static imported_symbol_iterator
129315d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1294861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
129515d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1296861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
129715d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1298861021f9SRui Ueyama   }
1299861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
130015d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1301861021f9SRui Ueyama }
1302861021f9SRui Ueyama 
130315d99359SRui Ueyama static imported_symbol_iterator
130415d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1305861021f9SRui Ueyama   uintptr_t IntPtr = 0;
130615d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
130715d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1308861021f9SRui Ueyama }
1309861021f9SRui Ueyama 
131015d99359SRui Ueyama static imported_symbol_iterator
131115d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1312861021f9SRui Ueyama   uintptr_t IntPtr = 0;
131315d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1314861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1315861021f9SRui Ueyama   int Index = 0;
131615d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1317861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1318861021f9SRui Ueyama     while (*Entry++)
1319861021f9SRui Ueyama       ++Index;
1320861021f9SRui Ueyama   } else {
1321861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1322861021f9SRui Ueyama     while (*Entry++)
1323861021f9SRui Ueyama       ++Index;
1324861021f9SRui Ueyama   }
132515d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
132615d99359SRui Ueyama }
132715d99359SRui Ueyama 
132815d99359SRui Ueyama imported_symbol_iterator
132915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
133060049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
133115d99359SRui Ueyama                              OwningObject);
133215d99359SRui Ueyama }
133315d99359SRui Ueyama 
133415d99359SRui Ueyama imported_symbol_iterator
133515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
133660049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
133715d99359SRui Ueyama                            OwningObject);
1338861021f9SRui Ueyama }
1339861021f9SRui Ueyama 
1340979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1341979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1342979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1343979fb40bSRui Ueyama }
1344979fb40bSRui Ueyama 
134560049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
134660049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
134760049526SDavid Majnemer                              OwningObject);
134860049526SDavid Majnemer }
134960049526SDavid Majnemer 
135060049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
135160049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
135260049526SDavid Majnemer                            OwningObject);
135360049526SDavid Majnemer }
135460049526SDavid Majnemer 
135560049526SDavid Majnemer iterator_range<imported_symbol_iterator>
135660049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
135760049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
135860049526SDavid Majnemer }
135960049526SDavid Majnemer 
1360db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1361c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1362db4ed0bdSRafael Espindola   if (std::error_code EC =
13631e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1364a045b73aSRui Ueyama     return EC;
1365a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13667d099195SRui Ueyama   return std::error_code();
1367c2bed429SRui Ueyama }
1368c2bed429SRui Ueyama 
13691e152d5eSRui Ueyama std::error_code
13701e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13711e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13727d099195SRui Ueyama   return std::error_code();
13731e152d5eSRui Ueyama }
13741e152d5eSRui Ueyama 
13751e152d5eSRui Ueyama std::error_code
13761e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13771e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13787d099195SRui Ueyama   return std::error_code();
13791e152d5eSRui Ueyama }
13801e152d5eSRui Ueyama 
138115d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
138215d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
138315d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
138415d99359SRui Ueyama }
138515d99359SRui Ueyama 
138615d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
138715d99359SRui Ueyama   ++Index;
138815d99359SRui Ueyama }
138915d99359SRui Ueyama 
139015d99359SRui Ueyama imported_symbol_iterator
139115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
139215d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
139315d99359SRui Ueyama                              OwningObject);
139415d99359SRui Ueyama }
139515d99359SRui Ueyama 
139615d99359SRui Ueyama imported_symbol_iterator
139715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
139815d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
139915d99359SRui Ueyama                            OwningObject);
140015d99359SRui Ueyama }
140115d99359SRui Ueyama 
1402979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1403979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1404979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1405979fb40bSRui Ueyama }
1406979fb40bSRui Ueyama 
140715d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
140815d99359SRui Ueyama   uintptr_t IntPtr = 0;
140915d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
141015d99359SRui Ueyama     return EC;
141115d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14127d099195SRui Ueyama   return std::error_code();
141315d99359SRui Ueyama }
141415d99359SRui Ueyama 
14151af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14161af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14171af08658SRui Ueyama   Result = Table;
14187d099195SRui Ueyama   return std::error_code();
14191af08658SRui Ueyama }
14201af08658SRui Ueyama 
1421ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1422ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1423ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1424ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1425ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1426ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1427ffa4cebeSRui Ueyama     return EC;
1428ffa4cebeSRui Ueyama   if (OwningObject->is64())
14295dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1430ffa4cebeSRui Ueyama   else
14315dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14327d099195SRui Ueyama   return std::error_code();
1433ffa4cebeSRui Ueyama }
1434ffa4cebeSRui Ueyama 
1435ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1436ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1437ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1438ad882ba8SRui Ueyama }
1439ad882ba8SRui Ueyama 
14405e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14415e812afaSRafael Espindola   ++Index;
1442ad882ba8SRui Ueyama }
1443ad882ba8SRui Ueyama 
1444da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1445da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1446db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1447da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1448db4ed0bdSRafael Espindola   if (std::error_code EC =
1449db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1450da49d0d4SRui Ueyama     return EC;
1451da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14527d099195SRui Ueyama   return std::error_code();
1453da49d0d4SRui Ueyama }
1454da49d0d4SRui Ueyama 
1455e5df6095SRui Ueyama // Returns the starting ordinal number.
1456db4ed0bdSRafael Espindola std::error_code
1457db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1458e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14597d099195SRui Ueyama   return std::error_code();
1460e5df6095SRui Ueyama }
1461e5df6095SRui Ueyama 
1462ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1463db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1464ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14657d099195SRui Ueyama   return std::error_code();
1466ad882ba8SRui Ueyama }
1467ad882ba8SRui Ueyama 
1468ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1469db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1470ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1471db4ed0bdSRafael Espindola   if (std::error_code EC =
1472db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1473ad882ba8SRui Ueyama     return EC;
147424fc2d64SRui Ueyama   const export_address_table_entry *entry =
147524fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1476ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14777d099195SRui Ueyama   return std::error_code();
1478ad882ba8SRui Ueyama }
1479ad882ba8SRui Ueyama 
1480ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1481ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1482db4ed0bdSRafael Espindola std::error_code
1483db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1484ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1485db4ed0bdSRafael Espindola   if (std::error_code EC =
1486db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1487ad882ba8SRui Ueyama     return EC;
1488ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1489ad882ba8SRui Ueyama 
1490ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1491ad882ba8SRui Ueyama   int Offset = 0;
1492ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1493ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1494ad882ba8SRui Ueyama     if (*I != Index)
1495ad882ba8SRui Ueyama       continue;
1496db4ed0bdSRafael Espindola     if (std::error_code EC =
1497db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1498ad882ba8SRui Ueyama       return EC;
1499ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1500db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1501ad882ba8SRui Ueyama       return EC;
1502ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15037d099195SRui Ueyama     return std::error_code();
1504ad882ba8SRui Ueyama   }
1505ad882ba8SRui Ueyama   Result = "";
15067d099195SRui Ueyama   return std::error_code();
1507ad882ba8SRui Ueyama }
1508ad882ba8SRui Ueyama 
15096161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15106161b38dSRui Ueyama   const data_directory *DataEntry;
15116161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15126161b38dSRui Ueyama     return EC;
15136161b38dSRui Ueyama   uint32_t RVA;
15146161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15156161b38dSRui Ueyama     return EC;
15166161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15176161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15186161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15196161b38dSRui Ueyama   return std::error_code();
15206161b38dSRui Ueyama }
15216161b38dSRui Ueyama 
15226161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15236161b38dSRui Ueyama   uint32_t RVA;
15246161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15256161b38dSRui Ueyama     return EC;
15266161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15276161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15286161b38dSRui Ueyama     return EC;
15296161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15306161b38dSRui Ueyama   return std::error_code();
15316161b38dSRui Ueyama }
15326161b38dSRui Ueyama 
1533861021f9SRui Ueyama bool ImportedSymbolRef::
1534861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1535861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1536861021f9SRui Ueyama       && Index == Other.Index;
1537861021f9SRui Ueyama }
1538861021f9SRui Ueyama 
1539861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1540861021f9SRui Ueyama   ++Index;
1541861021f9SRui Ueyama }
1542861021f9SRui Ueyama 
1543861021f9SRui Ueyama std::error_code
1544861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1545861021f9SRui Ueyama   uint32_t RVA;
1546861021f9SRui Ueyama   if (Entry32) {
1547861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1548861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15497d099195SRui Ueyama       return std::error_code();
1550861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1551861021f9SRui Ueyama   } else {
1552861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15537d099195SRui Ueyama       return std::error_code();
1554861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1555861021f9SRui Ueyama   }
1556861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1557861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1558861021f9SRui Ueyama     return EC;
1559861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1560861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15617d099195SRui Ueyama   return std::error_code();
1562861021f9SRui Ueyama }
1563861021f9SRui Ueyama 
1564ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1565ad7b7e73SDavid Majnemer   if (Entry32)
1566ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1567ad7b7e73SDavid Majnemer   else
1568ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1569ad7b7e73SDavid Majnemer   return std::error_code();
1570ad7b7e73SDavid Majnemer }
1571ad7b7e73SDavid Majnemer 
1572ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1573ad7b7e73SDavid Majnemer   if (Entry32)
1574ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1575ad7b7e73SDavid Majnemer   else
1576ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1577ad7b7e73SDavid Majnemer   return std::error_code();
1578ad7b7e73SDavid Majnemer }
1579ad7b7e73SDavid Majnemer 
1580861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1581861021f9SRui Ueyama   uint32_t RVA;
1582861021f9SRui Ueyama   if (Entry32) {
1583861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1584861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15857d099195SRui Ueyama       return std::error_code();
1586861021f9SRui Ueyama     }
1587861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1588861021f9SRui Ueyama   } else {
1589861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1590861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15917d099195SRui Ueyama       return std::error_code();
1592861021f9SRui Ueyama     }
1593861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1594861021f9SRui Ueyama   }
1595861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1596861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1597861021f9SRui Ueyama     return EC;
1598861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15997d099195SRui Ueyama   return std::error_code();
1600861021f9SRui Ueyama }
1601861021f9SRui Ueyama 
1602437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>>
160348af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1604db4ed0bdSRafael Espindola   std::error_code EC;
160548af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1606692410efSRafael Espindola   if (EC)
1607692410efSRafael Espindola     return EC;
1608437b0d58SRafael Espindola   return std::move(Ret);
1609686738e2SRui Ueyama }
161074e85130SRui Ueyama 
161174e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
161274e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
161374e85130SRui Ueyama }
161474e85130SRui Ueyama 
161574e85130SRui Ueyama void BaseRelocRef::moveNext() {
161674e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
161774e85130SRui Ueyama   // size of the header itself.
161874e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1619970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
162074e85130SRui Ueyama   if (Size == Header->BlockSize) {
162174e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
162274e85130SRui Ueyama     // consists of the header followed by entries. The header contains
162374e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
162474e85130SRui Ueyama     // current block, proceed to the next block.
162574e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
162674e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
162774e85130SRui Ueyama     Index = 0;
162874e85130SRui Ueyama   } else {
162974e85130SRui Ueyama     ++Index;
163074e85130SRui Ueyama   }
163174e85130SRui Ueyama }
163274e85130SRui Ueyama 
163374e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
163474e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
163574e85130SRui Ueyama   Type = Entry[Index].getType();
16367d099195SRui Ueyama   return std::error_code();
163774e85130SRui Ueyama }
163874e85130SRui Ueyama 
163974e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
164074e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
164174e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16427d099195SRui Ueyama   return std::error_code();
164374e85130SRui Ueyama }
1644efef15a0SEric Beckmann 
1645efef15a0SEric Beckmann #define RETURN_IF_ERROR(X)                                                     \
1646efef15a0SEric Beckmann   if (auto EC = errorToErrorCode(X))                                           \
1647efef15a0SEric Beckmann     return EC;
1648efef15a0SEric Beckmann 
1649cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1650efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1651efef15a0SEric Beckmann   Reader.setOffset(Offset);
1652efef15a0SEric Beckmann   uint16_t Length;
1653efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1654efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1655efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1656cd704cb6SEric Beckmann   return RawDirString;
1657efef15a0SEric Beckmann }
1658efef15a0SEric Beckmann 
1659cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>>
1660efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1661efef15a0SEric Beckmann   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1662efef15a0SEric Beckmann }
1663efef15a0SEric Beckmann 
1664efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1665efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1666efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1667efef15a0SEric Beckmann 
1668efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1669efef15a0SEric Beckmann   Reader.setOffset(Offset);
1670efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1671efef15a0SEric Beckmann   assert(Table != nullptr);
1672efef15a0SEric Beckmann   return *Table;
1673efef15a0SEric Beckmann }
1674efef15a0SEric Beckmann 
1675efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &>
1676efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
1677efef15a0SEric Beckmann   return getTableAtOffset(Entry.Offset.value());
1678efef15a0SEric Beckmann }
1679efef15a0SEric Beckmann 
1680efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1681efef15a0SEric Beckmann   return getTableAtOffset(0);
1682efef15a0SEric Beckmann }
1683