18e90adafSMichael J. Spencer //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
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 
14ec29b121SMichael J. Spencer #include "llvm/Object/COFF.h"
159da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h"
168e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h"
178e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h"
186a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h"
19f078eff3SRui Ueyama #include "llvm/Support/COFF.h"
20c2bed429SRui Ueyama #include "llvm/Support/Debug.h"
21c2bed429SRui Ueyama #include "llvm/Support/raw_ostream.h"
22981af002SWill Dietz #include <cctype>
239d2c15efSNico Rieck #include <limits>
248e90adafSMichael J. Spencer 
258e90adafSMichael J. Spencer using namespace llvm;
268e90adafSMichael J. Spencer using namespace object;
278e90adafSMichael J. Spencer 
288e90adafSMichael J. Spencer using support::ulittle16_t;
298e90adafSMichael J. Spencer using support::ulittle32_t;
30861021f9SRui Ueyama using support::ulittle64_t;
318e90adafSMichael J. Spencer using support::little16_t;
328e90adafSMichael J. Spencer 
331d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
3448af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
35c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
368ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
371d6167fdSMichael J. Spencer     return false;
381d6167fdSMichael J. Spencer   }
391d6167fdSMichael J. Spencer   return true;
408e90adafSMichael J. Spencer }
418e90adafSMichael J. Spencer 
42e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
4394751be7SDavid Majnemer                                    const uint64_t Size) {
44e830c60dSDavid Majnemer   if (Addr + Size < Addr || Addr + Size < Size ||
45e830c60dSDavid Majnemer       Addr + Size > uintptr_t(M.getBufferEnd()) ||
46e830c60dSDavid Majnemer       Addr < uintptr_t(M.getBufferStart())) {
47e830c60dSDavid Majnemer     return object_error::unexpected_eof;
48e830c60dSDavid Majnemer   }
497d099195SRui Ueyama   return std::error_code();
50e830c60dSDavid Majnemer }
51e830c60dSDavid Majnemer 
52ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
53ed64342bSRui Ueyama // Returns unexpected_eof if error.
54ed64342bSRui Ueyama template <typename T>
5548af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
5658323a97SDavid Majnemer                                  const void *Ptr,
57236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
58ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
59e830c60dSDavid Majnemer   if (std::error_code EC = checkOffset(M, Addr, Size))
60e830c60dSDavid Majnemer     return EC;
61ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
627d099195SRui Ueyama   return std::error_code();
631d6167fdSMichael J. Spencer }
641d6167fdSMichael J. Spencer 
659d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
669d2c15efSNico Rieck // prefixed slashes.
679d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
689d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
699d2c15efSNico Rieck   if (Str.size() > 6)
709d2c15efSNico Rieck     return true;
719d2c15efSNico Rieck 
729d2c15efSNico Rieck   uint64_t Value = 0;
739d2c15efSNico Rieck   while (!Str.empty()) {
749d2c15efSNico Rieck     unsigned CharVal;
759d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
769d2c15efSNico Rieck       CharVal = Str[0] - 'A';
779d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
789d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
799d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
809d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
819d2c15efSNico Rieck     else if (Str[0] == '+') // 62
825500b07cSRui Ueyama       CharVal = 62;
839d2c15efSNico Rieck     else if (Str[0] == '/') // 63
845500b07cSRui Ueyama       CharVal = 63;
859d2c15efSNico Rieck     else
869d2c15efSNico Rieck       return true;
879d2c15efSNico Rieck 
889d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
899d2c15efSNico Rieck     Str = Str.substr(1);
909d2c15efSNico Rieck   }
919d2c15efSNico Rieck 
929d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
939d2c15efSNico Rieck     return true;
949d2c15efSNico Rieck 
959d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
969d2c15efSNico Rieck   return false;
979d2c15efSNico Rieck }
989d2c15efSNico Rieck 
9944f51e51SDavid Majnemer template <typename coff_symbol_type>
10044f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10144f51e51SDavid Majnemer   const coff_symbol_type *Addr =
10244f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1031d6167fdSMichael J. Spencer 
104236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1051d6167fdSMichael J. Spencer #ifndef NDEBUG
1061d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1078ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1081d6167fdSMichael J. Spencer 
10944f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11044f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1111d6167fdSMichael J. Spencer #endif
1121d6167fdSMichael J. Spencer 
1138ff24d25SRui Ueyama   return Addr;
1141d6167fdSMichael J. Spencer }
1151d6167fdSMichael J. Spencer 
1168ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1178ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1181d6167fdSMichael J. Spencer 
1191d6167fdSMichael J. Spencer # ifndef NDEBUG
1201d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
12144f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1221d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1231d6167fdSMichael J. Spencer 
1248ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1258ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1261d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1271d6167fdSMichael J. Spencer # endif
1281d6167fdSMichael J. Spencer 
1298ff24d25SRui Ueyama   return Addr;
1301d6167fdSMichael J. Spencer }
1311d6167fdSMichael J. Spencer 
1325e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
133236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13444f51e51SDavid Majnemer   if (SymbolTable16) {
13544f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1368ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
137236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
13844f51e51SDavid Majnemer   } else if (SymbolTable32) {
13944f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14044f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
141236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14244f51e51SDavid Majnemer   } else {
14344f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14444f51e51SDavid Majnemer   }
1451d6167fdSMichael J. Spencer }
1461d6167fdSMichael J. Spencer 
14781e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
14844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1495d0c2ffaSRafael Espindola   StringRef Result;
1505d0c2ffaSRafael Espindola   std::error_code EC = getSymbolName(Symb, Result);
1515d0c2ffaSRafael Espindola   if (EC)
15281e8b7d9SKevin Enderby     return errorCodeToError(EC);
1535d0c2ffaSRafael Espindola   return Result;
1548e90adafSMichael J. Spencer }
1558e90adafSMichael J. Spencer 
156be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
157be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
158991af666SRafael Espindola }
159991af666SRafael Espindola 
160931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
161ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
16244f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
163c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
164991af666SRafael Espindola 
165991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
166991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
167ed067c45SRafael Espindola     return Result;
16854c9f3daSRafael Espindola 
1692617dcceSCraig Topper   const coff_section *Section = nullptr;
170c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
171931cb65dSKevin Enderby     return errorCodeToError(EC);
172991af666SRafael Espindola   Result += Section->VirtualAddress;
17347ea9eceSReid Kleckner 
17447ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
17547ea9eceSReid Kleckner   // return virtual addresses.
17621427adaSReid Kleckner   Result += getImageBase();
17747ea9eceSReid Kleckner 
178ed067c45SRafael Espindola   return Result;
179c7d7c6fbSDavid Majnemer }
180c7d7c6fbSDavid Majnemer 
1817bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
18244f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
183c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
18444f51e51SDavid Majnemer 
185e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
186e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1872fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1882fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1892fa80cc5SRafael Espindola   if (Symb.isCommon())
1902fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1912fa80cc5SRafael Espindola   if (Symb.isFileRecord())
1922fa80cc5SRafael Espindola     return SymbolRef::ST_File;
1932fa80cc5SRafael Espindola 
1941a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
1952fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
1962fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
1972fa80cc5SRafael Espindola 
1982fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
1992fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2002fa80cc5SRafael Espindola 
2012fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
20275d1cf33SBenjamin Kramer }
20375d1cf33SBenjamin Kramer 
20420122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
20544f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
20620122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
20775d1cf33SBenjamin Kramer 
208c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2099dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2101df4b84dSDavid Meyer 
211c7d7c6fbSDavid Majnemer   if (Symb.isWeakExternal())
2121df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
2131df4b84dSDavid Meyer 
21444f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2151df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2161df4b84dSDavid Meyer 
217c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
218c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
219c7d7c6fbSDavid Majnemer 
220c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
221c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
222c7d7c6fbSDavid Majnemer 
223c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
224c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
225c7d7c6fbSDavid Majnemer 
226c7d7c6fbSDavid Majnemer   if (Symb.isAnyUndefined())
227c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
228c7d7c6fbSDavid Majnemer 
22920122a43SRafael Espindola   return Result;
23001759754SMichael J. Spencer }
23101759754SMichael J. Spencer 
232d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
233c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2345eb02e45SRafael Espindola   return Symb.getValue();
2358e90adafSMichael J. Spencer }
2368e90adafSMichael J. Spencer 
2377bd8d994SKevin Enderby Expected<section_iterator>
2388bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
23944f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2408bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2418bab889bSRafael Espindola     return section_end();
2422617dcceSCraig Topper   const coff_section *Sec = nullptr;
24344f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2447bd8d994SKevin Enderby     return errorCodeToError(EC);
2458bab889bSRafael Espindola   DataRefImpl Ret;
2468bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2478bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
24832173153SMichael J. Spencer }
24932173153SMichael J. Spencer 
2506bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2516bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2526bf32210SRafael Espindola   return Symb.getSectionNumber();
2536bf32210SRafael Espindola }
2546bf32210SRafael Espindola 
2555e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2568ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2578ff24d25SRui Ueyama   Sec += 1;
2588ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2598e90adafSMichael J. Spencer }
2608e90adafSMichael J. Spencer 
261db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2621d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2638ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2648ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2658e90adafSMichael J. Spencer }
2668e90adafSMichael J. Spencer 
26780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2688ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2697c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2707c6a071bSDavid Majnemer 
2717c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2727c6a071bSDavid Majnemer   // return virtual addresses.
27321427adaSReid Kleckner   Result += getImageBase();
2747c6a071bSDavid Majnemer   return Result;
2758e90adafSMichael J. Spencer }
2768e90adafSMichael J. Spencer 
27780291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
278a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2798e90adafSMichael J. Spencer }
2808e90adafSMichael J. Spencer 
281db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
2821d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
2838ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2849da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
285db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
2869da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
2879da9e693SMichael J. Spencer   return EC;
2888e90adafSMichael J. Spencer }
2898e90adafSMichael J. Spencer 
29080291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
2918ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
292511391feSDavid Majnemer   return Sec->getAlignment();
2937989460aSMichael J. Spencer }
2947989460aSMichael J. Spencer 
295401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
296401e4e57SGeorge Rimar   return false;
297401e4e57SGeorge Rimar }
298401e4e57SGeorge Rimar 
29980291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3008ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
30180291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3028e90adafSMichael J. Spencer }
3038e90adafSMichael J. Spencer 
30480291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3058ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
30680291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
307800619f2SMichael J. Spencer }
308800619f2SMichael J. Spencer 
30980291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3108ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3111a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3121a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3131a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3141a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
315800619f2SMichael J. Spencer }
316800619f2SMichael J. Spencer 
3176bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3186bf32210SRafael Espindola   uintptr_t Offset =
3196bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3206bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3216bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3226bf32210SRafael Espindola }
3236bf32210SRafael Espindola 
32480291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3258ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3261a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3271a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3281a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3292138ef6dSPreston Gurd }
3302138ef6dSPreston Gurd 
331e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
332e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
333e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
334e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
335e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
336e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
337e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
338e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
339e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
340e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
341e830c60dSDavid Majnemer       return 0;
34298fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
34398fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
344e830c60dSDavid Majnemer   }
345e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
346e830c60dSDavid Majnemer }
347e830c60dSDavid Majnemer 
34894751be7SDavid Majnemer static const coff_relocation *
34994751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
35094751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
35194751be7SDavid Majnemer   if (!NumRelocs)
35294751be7SDavid Majnemer     return nullptr;
353827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
35494751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
355827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
356827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
357827c8a2bSRui Ueyama     // relocations.
358827c8a2bSRui Ueyama     begin++;
359827c8a2bSRui Ueyama   }
36094751be7SDavid Majnemer   if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
36194751be7SDavid Majnemer     return nullptr;
36294751be7SDavid Majnemer   return begin;
363827c8a2bSRui Ueyama }
36494751be7SDavid Majnemer 
36594751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
36694751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
36794751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
36876d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
36976d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
37094751be7SDavid Majnemer   DataRefImpl Ret;
37194751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3728ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
373e5fd0047SMichael J. Spencer }
374e5fd0047SMichael J. Spencer 
3758ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3768ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
37794751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
37894751be7SDavid Majnemer   if (I)
37994751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3808ff24d25SRui Ueyama   DataRefImpl Ret;
38194751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
3828ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
383e5fd0047SMichael J. Spencer }
384e5fd0047SMichael J. Spencer 
385c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
386db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
38744f51e51SDavid Majnemer   if (COFFHeader)
388236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
389236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
390236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
39144f51e51SDavid Majnemer       return EC;
39244f51e51SDavid Majnemer 
39344f51e51SDavid Majnemer   if (COFFBigObjHeader)
394236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
395236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
396236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
3978ff24d25SRui Ueyama       return EC;
398c2bed429SRui Ueyama 
399c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
400c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
401c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
402f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
40344f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
404f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
405c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
40648af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4078ff24d25SRui Ueyama     return EC;
408c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
409db4ed0bdSRafael Espindola   if (std::error_code EC =
41048af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4118ff24d25SRui Ueyama     return EC;
412c2bed429SRui Ueyama 
413773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
414773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
415773a5795SNico Rieck   if (StringTableSize < 4)
416773a5795SNico Rieck       StringTableSize = 4;
417773a5795SNico Rieck 
418c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
419773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
420c2bed429SRui Ueyama     return  object_error::parse_failed;
4217d099195SRui Ueyama   return std::error_code();
422c2bed429SRui Ueyama }
423c2bed429SRui Ueyama 
42421427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
425e94fef7bSReid Kleckner   if (PE32Header)
42621427adaSReid Kleckner     return PE32Header->ImageBase;
427e94fef7bSReid Kleckner   else if (PE32PlusHeader)
42821427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
42921427adaSReid Kleckner   // This actually comes up in practice.
43021427adaSReid Kleckner   return 0;
431e94fef7bSReid Kleckner }
432e94fef7bSReid Kleckner 
433215a586cSRui Ueyama // Returns the file offset for the given VA.
434db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
43521427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
436b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
437b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
438b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
439215a586cSRui Ueyama }
440215a586cSRui Ueyama 
441c2bed429SRui Ueyama // Returns the file offset for the given RVA.
442db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
44327dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
44427dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
445c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
446c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
447215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
448215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
449c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4507d099195SRui Ueyama       return std::error_code();
451c2bed429SRui Ueyama     }
452c2bed429SRui Ueyama   }
453c2bed429SRui Ueyama   return object_error::parse_failed;
454c2bed429SRui Ueyama }
455c2bed429SRui Ueyama 
4562da433eaSReid Kleckner std::error_code
4572da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4582da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4592da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4602da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4612da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4622da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4632da433eaSReid Kleckner     // overflow.
4642da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4652da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4662da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4672da433eaSReid Kleckner       uintptr_t Begin =
4682da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4692da433eaSReid Kleckner       Contents =
4702da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4712da433eaSReid Kleckner       return std::error_code();
4722da433eaSReid Kleckner     }
4732da433eaSReid Kleckner   }
4742da433eaSReid Kleckner   return object_error::parse_failed;
4752da433eaSReid Kleckner }
4762da433eaSReid Kleckner 
477c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
478c2bed429SRui Ueyama // table entry.
479db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
480db4ed0bdSRafael Espindola                                             StringRef &Name) const {
481c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
482db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
4838ff24d25SRui Ueyama     return EC;
484c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
485c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
486c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
4877d099195SRui Ueyama   return std::error_code();
488c2bed429SRui Ueyama }
489c2bed429SRui Ueyama 
49001528021SSaleem Abdulrasool std::error_code
49101528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
49201528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
4932da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
4942da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
4952da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
4962da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
4972da433eaSReid Kleckner     return EC;
49801528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
4992da433eaSReid Kleckner     return object_error::parse_failed;
50001528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
50101528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5022da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5032da433eaSReid Kleckner                           InfoBytes.size());
5042da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5052da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5062da433eaSReid Kleckner   return std::error_code();
5072da433eaSReid Kleckner }
5082da433eaSReid Kleckner 
50901528021SSaleem Abdulrasool std::error_code
51001528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
511f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
512f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
513f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
514f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
515f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
516f27f3f84SReid Kleckner   PDBInfo = nullptr;
517f27f3f84SReid Kleckner   PDBFileName = StringRef();
518f27f3f84SReid Kleckner   return std::error_code();
519f27f3f84SReid Kleckner }
520f27f3f84SReid Kleckner 
521c2bed429SRui Ueyama // Find the import table.
522db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
523c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
524c2bed429SRui Ueyama   // the import table, do nothing.
525c2bed429SRui Ueyama   const data_directory *DataEntry;
526c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5277d099195SRui Ueyama     return std::error_code();
528c2bed429SRui Ueyama 
529c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
530c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5317d099195SRui Ueyama     return std::error_code();
532c2bed429SRui Ueyama 
533c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
534c2bed429SRui Ueyama 
535c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
536c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
537c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
538db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5398ff24d25SRui Ueyama     return EC;
540ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
541ad7b7e73SDavid Majnemer     return EC;
542c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5431c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5447d099195SRui Ueyama   return std::error_code();
545ad882ba8SRui Ueyama }
546c2bed429SRui Ueyama 
54715d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
54815d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
54915d99359SRui Ueyama   const data_directory *DataEntry;
55015d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5517d099195SRui Ueyama     return std::error_code();
55215d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5537d099195SRui Ueyama     return std::error_code();
55415d99359SRui Ueyama 
55515d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
55615d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
55715d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
55815d99359SRui Ueyama 
55915d99359SRui Ueyama   uintptr_t IntPtr = 0;
56015d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
56115d99359SRui Ueyama     return EC;
56215d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
56315d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5647d099195SRui Ueyama   return std::error_code();
56515d99359SRui Ueyama }
56615d99359SRui Ueyama 
567ad882ba8SRui Ueyama // Find the export table.
568db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
569ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
570ad882ba8SRui Ueyama   // the export table, do nothing.
571ad882ba8SRui Ueyama   const data_directory *DataEntry;
572ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5737d099195SRui Ueyama     return std::error_code();
574ad882ba8SRui Ueyama 
575ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
576ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5777d099195SRui Ueyama     return std::error_code();
578ad882ba8SRui Ueyama 
579ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
580ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
581db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
582ad882ba8SRui Ueyama     return EC;
58324fc2d64SRui Ueyama   ExportDirectory =
58424fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
5857d099195SRui Ueyama   return std::error_code();
586c2bed429SRui Ueyama }
587c2bed429SRui Ueyama 
58874e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
58974e85130SRui Ueyama   const data_directory *DataEntry;
59074e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
5917d099195SRui Ueyama     return std::error_code();
59274e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5937d099195SRui Ueyama     return std::error_code();
59474e85130SRui Ueyama 
59574e85130SRui Ueyama   uintptr_t IntPtr = 0;
59674e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
59774e85130SRui Ueyama     return EC;
59874e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
59974e85130SRui Ueyama       IntPtr);
60074e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
60174e85130SRui Ueyama       IntPtr + DataEntry->Size);
6027d099195SRui Ueyama   return std::error_code();
60374e85130SRui Ueyama }
60474e85130SRui Ueyama 
6052da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6062da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6072da433eaSReid Kleckner   const data_directory *DataEntry;
6082da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6092da433eaSReid Kleckner     return std::error_code();
6102da433eaSReid Kleckner 
6112da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6122da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6132da433eaSReid Kleckner     return std::error_code();
6142da433eaSReid Kleckner 
6152da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6162da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6172da433eaSReid Kleckner     return object_error::parse_failed;
6182da433eaSReid Kleckner 
6192da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6202da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6212da433eaSReid Kleckner     return EC;
6222da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6232da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6242da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6252da433eaSReid Kleckner     return EC;
6262da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6272da433eaSReid Kleckner   return std::error_code();
6282da433eaSReid Kleckner }
6292da433eaSReid Kleckner 
63048af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
63148af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
63244f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
63344f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
63444f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
635ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
63615d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6372da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6382da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6391d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
64048af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
641c3f9b5a5SRafael Espindola     return;
642ee066fc4SEric Christopher 
64382ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
64482ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
64582ebd8e3SRui Ueyama 
64682ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
64782ebd8e3SRui Ueyama   // it is placed right after COFF header.
6488ff24d25SRui Ueyama   bool HasPEHeader = false;
649ee066fc4SEric Christopher 
6501d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
65150267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
652ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
653ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
65450267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
65550267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
65650267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
65782ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
65850267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6598ff24d25SRui Ueyama         EC = object_error::parse_failed;
6601d6167fdSMichael J. Spencer         return;
6611d6167fdSMichael J. Spencer       }
66244f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6638ff24d25SRui Ueyama       HasPEHeader = true;
664ee066fc4SEric Christopher     }
66550267222SDavid Majnemer   }
666ee066fc4SEric Christopher 
66748af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
6681d6167fdSMichael J. Spencer     return;
66944f51e51SDavid Majnemer 
67044f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
67144f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
67244f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
67344f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
67444f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
67544f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
67644f51e51SDavid Majnemer       return;
67744f51e51SDavid Majnemer 
67844f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
67944f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
68044f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
68144f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
68244f51e51SDavid Majnemer       COFFHeader = nullptr;
68344f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
68444f51e51SDavid Majnemer     } else {
68544f51e51SDavid Majnemer       // It's not a bigobj.
68644f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
68744f51e51SDavid Majnemer     }
68844f51e51SDavid Majnemer   }
68944f51e51SDavid Majnemer   if (COFFHeader) {
69044f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
69144f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
6927d099195SRui Ueyama     EC = std::error_code();
69382ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
69482ebd8e3SRui Ueyama 
69544f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
69644f51e51SDavid Majnemer       return;
69744f51e51SDavid Majnemer   }
69844f51e51SDavid Majnemer 
6998ff24d25SRui Ueyama   if (HasPEHeader) {
70010ed9ddcSRui Ueyama     const pe32_header *Header;
70148af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
70282ebd8e3SRui Ueyama       return;
70310ed9ddcSRui Ueyama 
70410ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
70510ed9ddcSRui Ueyama     uint64_t DataDirSize;
70650267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
70710ed9ddcSRui Ueyama       PE32Header = Header;
70810ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
70910ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
71050267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
71110ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
71210ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
71310ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
71410ed9ddcSRui Ueyama     } else {
71510ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
71610ed9ddcSRui Ueyama       EC = object_error::parse_failed;
717ed64342bSRui Ueyama       return;
718ed64342bSRui Ueyama     }
71948af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
72010ed9ddcSRui Ueyama       return;
721f53c8cb4SRui Ueyama   }
722776c6828SRui Ueyama 
7238950a538SRui Ueyama   if (COFFHeader)
7248950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7258950a538SRui Ueyama 
72648af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
727236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7281d6167fdSMichael J. Spencer     return;
7291d6167fdSMichael J. Spencer 
730c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
731236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
732*ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
733*ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
734*ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
735*ac8cfab5SDavid Majnemer       StringTable = nullptr;
736*ac8cfab5SDavid Majnemer       StringTableSize = 0;
737*ac8cfab5SDavid Majnemer     }
738236b0ca7SDavid Majnemer   } else {
739236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
740236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
741236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
742236b0ca7SDavid Majnemer       return;
743236b0ca7SDavid Majnemer     }
744236b0ca7SDavid Majnemer   }
7458e90adafSMichael J. Spencer 
746c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7478ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
748ed64342bSRui Ueyama     return;
74915d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
75015d99359SRui Ueyama     return;
7511d6167fdSMichael J. Spencer 
752ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7538ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
754ad882ba8SRui Ueyama     return;
755ad882ba8SRui Ueyama 
75674e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
75774e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
75874e85130SRui Ueyama     return;
75974e85130SRui Ueyama 
7602da433eaSReid Kleckner   // Initialize the pointer to the export table.
7612da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7622da433eaSReid Kleckner     return;
7632da433eaSReid Kleckner 
7647d099195SRui Ueyama   EC = std::error_code();
7658e90adafSMichael J. Spencer }
7668e90adafSMichael J. Spencer 
767f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const {
7688ff24d25SRui Ueyama   DataRefImpl Ret;
76944f51e51SDavid Majnemer   Ret.p = getSymbolTable();
770f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7718e90adafSMichael J. Spencer }
7728e90adafSMichael J. Spencer 
773f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const {
7748e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
7758ff24d25SRui Ueyama   DataRefImpl Ret;
7768ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
777f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7788e90adafSMichael J. Spencer }
7798e90adafSMichael J. Spencer 
780bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
781ad7b7e73SDavid Majnemer   if (!ImportDirectory)
782ad7b7e73SDavid Majnemer     return import_directory_end();
7831c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
784ad7b7e73SDavid Majnemer     return import_directory_end();
785a045b73aSRui Ueyama   return import_directory_iterator(
786a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
787c2bed429SRui Ueyama }
788c2bed429SRui Ueyama 
789bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
790a045b73aSRui Ueyama   return import_directory_iterator(
791ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
792c2bed429SRui Ueyama }
793c429b80dSDavid Meyer 
79415d99359SRui Ueyama delay_import_directory_iterator
79515d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
79615d99359SRui Ueyama   return delay_import_directory_iterator(
79715d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
79815d99359SRui Ueyama }
79915d99359SRui Ueyama 
80015d99359SRui Ueyama delay_import_directory_iterator
80115d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
80215d99359SRui Ueyama   return delay_import_directory_iterator(
80315d99359SRui Ueyama       DelayImportDirectoryEntryRef(
80415d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
80515d99359SRui Ueyama }
80615d99359SRui Ueyama 
807ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
808ad882ba8SRui Ueyama   return export_directory_iterator(
809ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
810ad882ba8SRui Ueyama }
811ad882ba8SRui Ueyama 
812ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8132617dcceSCraig Topper   if (!ExportDirectory)
8142617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8158ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
816ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8178ff24d25SRui Ueyama   return export_directory_iterator(Ref);
818ad882ba8SRui Ueyama }
819ad882ba8SRui Ueyama 
820b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8218ff24d25SRui Ueyama   DataRefImpl Ret;
8228ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8238ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8248e90adafSMichael J. Spencer }
8258e90adafSMichael J. Spencer 
826b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8278ff24d25SRui Ueyama   DataRefImpl Ret;
82844f51e51SDavid Majnemer   int NumSections =
82944f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8308ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8318ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8328e90adafSMichael J. Spencer }
8338e90adafSMichael J. Spencer 
83474e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
83574e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
83674e85130SRui Ueyama }
83774e85130SRui Ueyama 
83874e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
83974e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
84074e85130SRui Ueyama }
84174e85130SRui Ueyama 
8428e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
8430324b672SMichael J. Spencer   return getArch() == Triple::x86_64 ? 8 : 4;
8448e90adafSMichael J. Spencer }
8458e90adafSMichael J. Spencer 
8468e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
84744f51e51SDavid Majnemer   switch(getMachine()) {
8488e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8498e90adafSMichael J. Spencer     return "COFF-i386";
8508e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8518e90adafSMichael J. Spencer     return "COFF-x86-64";
8529b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8539b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8541eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8551eff5c9cSMartell Malone     return "COFF-ARM64";
8568e90adafSMichael J. Spencer   default:
8578e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8588e90adafSMichael J. Spencer   }
8598e90adafSMichael J. Spencer }
8608e90adafSMichael J. Spencer 
8618e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const {
86244f51e51SDavid Majnemer   switch (getMachine()) {
8638e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8648e90adafSMichael J. Spencer     return Triple::x86;
8658e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8668e90adafSMichael J. Spencer     return Triple::x86_64;
8679b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8689b7c0af2SSaleem Abdulrasool     return Triple::thumb;
8691eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8701eff5c9cSMartell Malone     return Triple::aarch64;
8718e90adafSMichael J. Spencer   default:
8728e90adafSMichael J. Spencer     return Triple::UnknownArch;
8738e90adafSMichael J. Spencer   }
8748e90adafSMichael J. Spencer }
8758e90adafSMichael J. Spencer 
876979fb40bSRui Ueyama iterator_range<import_directory_iterator>
877979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
878979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
879979fb40bSRui Ueyama }
880979fb40bSRui Ueyama 
881979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
882979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
883979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
884979fb40bSRui Ueyama                     delay_import_directory_end());
885979fb40bSRui Ueyama }
886979fb40bSRui Ueyama 
887979fb40bSRui Ueyama iterator_range<export_directory_iterator>
888979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
889979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
890979fb40bSRui Ueyama }
891979fb40bSRui Ueyama 
89274e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
89374e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
89474e85130SRui Ueyama }
89574e85130SRui Ueyama 
896db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
89782ebd8e3SRui Ueyama   Res = PE32Header;
8987d099195SRui Ueyama   return std::error_code();
89989a7a5eaSMichael J. Spencer }
90089a7a5eaSMichael J. Spencer 
901db4ed0bdSRafael Espindola std::error_code
90210ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
90310ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9047d099195SRui Ueyama   return std::error_code();
90510ed9ddcSRui Ueyama }
90610ed9ddcSRui Ueyama 
907db4ed0bdSRafael Espindola std::error_code
908db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
909ed64342bSRui Ueyama                                  const data_directory *&Res) const {
910ed64342bSRui Ueyama   // Error if if there's no data directory or the index is out of range.
911f69b0585SDavid Majnemer   if (!DataDirectory) {
912f69b0585SDavid Majnemer     Res = nullptr;
91310ed9ddcSRui Ueyama     return object_error::parse_failed;
914f69b0585SDavid Majnemer   }
91510ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
91610ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
91710ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
918f69b0585SDavid Majnemer   if (Index >= NumEnt) {
919f69b0585SDavid Majnemer     Res = nullptr;
920ed64342bSRui Ueyama     return object_error::parse_failed;
921f69b0585SDavid Majnemer   }
9228ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9237d099195SRui Ueyama   return std::error_code();
924ed64342bSRui Ueyama }
925ed64342bSRui Ueyama 
926db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9271d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9282617dcceSCraig Topper   Result = nullptr;
929236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9307d099195SRui Ueyama     return std::error_code();
931236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9321d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9338ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9347d099195SRui Ueyama     return std::error_code();
9358e90adafSMichael J. Spencer   }
936236b0ca7SDavid Majnemer   return object_error::parse_failed;
937236b0ca7SDavid Majnemer }
9388e90adafSMichael J. Spencer 
939db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9401d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9411d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9421d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9431d6167fdSMichael J. Spencer     return object_error::parse_failed;
9448ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9451d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
9468ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
9477d099195SRui Ueyama   return std::error_code();
9488e90adafSMichael J. Spencer }
949022ecdf2SBenjamin Kramer 
95044f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
95189a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
952e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
953e40d30f3SRui Ueyama }
954e40d30f3SRui Ueyama 
955e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
956e40d30f3SRui Ueyama                                               StringRef &Res) const {
95789a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
958e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
959e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
9608ff24d25SRui Ueyama       return EC;
9617d099195SRui Ueyama     return std::error_code();
96289a7a5eaSMichael J. Spencer   }
96389a7a5eaSMichael J. Spencer 
964e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
96589a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
966e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
96789a7a5eaSMichael J. Spencer   else
96889a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
969e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
9707d099195SRui Ueyama   return std::error_code();
97189a7a5eaSMichael J. Spencer }
97289a7a5eaSMichael J. Spencer 
97344f51e51SDavid Majnemer ArrayRef<uint8_t>
97444f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
9752617dcceSCraig Topper   const uint8_t *Aux = nullptr;
97671757ef3SMarshall Clow 
97744f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
97844f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
97971757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
98044f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
98171757ef3SMarshall Clow # ifndef NDEBUG
9828ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
9838ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
98444f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
98544f51e51SDavid Majnemer         Offset >=
98644f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
98771757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
98871757ef3SMarshall Clow 
98944f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
99044f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
99171757ef3SMarshall Clow # endif
992bfb85e67SMarshall Clow   }
99344f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
99471757ef3SMarshall Clow }
99571757ef3SMarshall Clow 
996db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
99753c2d547SMichael J. Spencer                                                StringRef &Res) const {
99853c2d547SMichael J. Spencer   StringRef Name;
99944f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
100053c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
100153c2d547SMichael J. Spencer     Name = Sec->Name;
100253c2d547SMichael J. Spencer   else
100353c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
100444f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
100553c2d547SMichael J. Spencer 
100653c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10072314b3deSDavid Majnemer   if (Name.startswith("/")) {
100853c2d547SMichael J. Spencer     uint32_t Offset;
10092314b3deSDavid Majnemer     if (Name.startswith("//")) {
10109d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10119d2c15efSNico Rieck         return object_error::parse_failed;
10129d2c15efSNico Rieck     } else {
101353c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
101453c2d547SMichael J. Spencer         return object_error::parse_failed;
10159d2c15efSNico Rieck     }
1016db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10178ff24d25SRui Ueyama       return EC;
101853c2d547SMichael J. Spencer   }
101953c2d547SMichael J. Spencer 
102053c2d547SMichael J. Spencer   Res = Name;
10217d099195SRui Ueyama   return std::error_code();
102253c2d547SMichael J. Spencer }
102353c2d547SMichael J. Spencer 
1024a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1025a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1026a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1027a9ee5c06SDavid Majnemer   //
1028a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1029d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1030a9ee5c06SDavid Majnemer   //
1031a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1032a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1033a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1034a9ee5c06SDavid Majnemer   // considered to be zero.
1035d5297ee7SRui Ueyama   if (getDOSHeader())
1036d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1037d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1038a9ee5c06SDavid Majnemer }
1039a9ee5c06SDavid Majnemer 
1040db4ed0bdSRafael Espindola std::error_code
1041db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
10429da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1043e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1044e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1045e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1046e2129662SDavid Majnemer     return object_error::parse_failed;
10479da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10489da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10499da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10509da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1051a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1052e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
10539da9e693SMichael J. Spencer     return object_error::parse_failed;
1054a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
10557d099195SRui Ueyama   return std::error_code();
10569da9e693SMichael J. Spencer }
10579da9e693SMichael J. Spencer 
1058022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1059e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1060022ecdf2SBenjamin Kramer }
10618ff24d25SRui Ueyama 
10625e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1063e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1064e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1065022ecdf2SBenjamin Kramer }
10668ff24d25SRui Ueyama 
106796d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
106858323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
106996d071cdSRafael Espindola   return R->VirtualAddress;
1070cbe72fc9SDanil Malyshev }
10718ff24d25SRui Ueyama 
1072806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1073022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
10748ff24d25SRui Ueyama   DataRefImpl Ref;
1075236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1076236b0ca7SDavid Majnemer     return symbol_end();
107744f51e51SDavid Majnemer   if (SymbolTable16)
107844f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
107944f51e51SDavid Majnemer   else if (SymbolTable32)
108044f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
108144f51e51SDavid Majnemer   else
1082c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
10838ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1084022ecdf2SBenjamin Kramer }
10858ff24d25SRui Ueyama 
108699c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1087022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
108899c041b7SRafael Espindola   return R->Type;
1089022ecdf2SBenjamin Kramer }
1090e5fd0047SMichael J. Spencer 
109127dc8394SAlexey Samsonov const coff_section *
109227dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
109327dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
109471757ef3SMarshall Clow }
109571757ef3SMarshall Clow 
109644f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
109744f51e51SDavid Majnemer   if (SymbolTable16)
109844f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
109944f51e51SDavid Majnemer   if (SymbolTable32)
110044f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
110144f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
110244f51e51SDavid Majnemer }
110344f51e51SDavid Majnemer 
110444f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
110544f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
110671757ef3SMarshall Clow }
110771757ef3SMarshall Clow 
1108f12b8282SRafael Espindola const coff_relocation *
110927dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
111027dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1111d3e2a76cSMarshall Clow }
1112d3e2a76cSMarshall Clow 
11136a75acb1SRui Ueyama iterator_range<const coff_relocation *>
11146a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11156a75acb1SRui Ueyama   const coff_relocation *I = getFirstReloc(Sec, Data, base());
11166a75acb1SRui Ueyama   const coff_relocation *E = I;
11176a75acb1SRui Ueyama   if (I)
11186a75acb1SRui Ueyama     E += getNumberOfRelocations(Sec, Data, base());
11196a75acb1SRui Ueyama   return make_range(I, E);
11206a75acb1SRui Ueyama }
11216a75acb1SRui Ueyama 
112227dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
112327dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
112427dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
112527dc8394SAlexey Samsonov     break;
1126e5fd0047SMichael J. Spencer 
112741bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
112841bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11298ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11308ff24d25SRui Ueyama   StringRef Res;
113144f51e51SDavid Majnemer   switch (getMachine()) {
1132e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11338ff24d25SRui Ueyama     switch (Reloc->Type) {
1134e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1135e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1136e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1137e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1138e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1139e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1140e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1141e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1142e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1143e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1144e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1145e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1146e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1147e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1148e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1149e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1150e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1151e5fd0047SMichael J. Spencer     default:
11528ff24d25SRui Ueyama       Res = "Unknown";
1153e5fd0047SMichael J. Spencer     }
1154e5fd0047SMichael J. Spencer     break;
11555c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
11565c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
11575c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11585c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11595c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11605c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11615c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11625c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
11635c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
11645c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
11655c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
11665c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
11675c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
11685c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
11695c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
11705c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
11715c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
11725c503bf4SSaleem Abdulrasool     default:
11735c503bf4SSaleem Abdulrasool       Res = "Unknown";
11745c503bf4SSaleem Abdulrasool     }
11755c503bf4SSaleem Abdulrasool     break;
1176e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
11778ff24d25SRui Ueyama     switch (Reloc->Type) {
1178e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1179e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1180e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1181e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1182e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1183e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1184e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1185e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1186e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1187e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1188e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1189e5fd0047SMichael J. Spencer     default:
11908ff24d25SRui Ueyama       Res = "Unknown";
1191e5fd0047SMichael J. Spencer     }
1192e5fd0047SMichael J. Spencer     break;
1193e5fd0047SMichael J. Spencer   default:
11948ff24d25SRui Ueyama     Res = "Unknown";
1195e5fd0047SMichael J. Spencer   }
11968ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1197e5fd0047SMichael J. Spencer }
1198e5fd0047SMichael J. Spencer 
1199e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1200e5fd0047SMichael J. Spencer 
1201c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1202c66d761bSRafael Espindola   return !DataDirectory;
1203c66d761bSRafael Espindola }
1204c66d761bSRafael Espindola 
1205c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1206c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1207a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1208c2bed429SRui Ueyama }
1209c2bed429SRui Ueyama 
12105e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12115e812afaSRafael Espindola   ++Index;
12121c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1213ad7b7e73SDavid Majnemer     Index = -1;
1214ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1215ad7b7e73SDavid Majnemer   }
1216c2bed429SRui Ueyama }
1217c2bed429SRui Ueyama 
1218db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12191c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1220ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1221c2bed429SRui Ueyama }
1222c2bed429SRui Ueyama 
1223861021f9SRui Ueyama static imported_symbol_iterator
122415d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1225861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
122615d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1227861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
122815d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1229861021f9SRui Ueyama   }
1230861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
123115d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1232861021f9SRui Ueyama }
1233861021f9SRui Ueyama 
123415d99359SRui Ueyama static imported_symbol_iterator
123515d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1236861021f9SRui Ueyama   uintptr_t IntPtr = 0;
123715d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
123815d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1239861021f9SRui Ueyama }
1240861021f9SRui Ueyama 
124115d99359SRui Ueyama static imported_symbol_iterator
124215d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1243861021f9SRui Ueyama   uintptr_t IntPtr = 0;
124415d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1245861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1246861021f9SRui Ueyama   int Index = 0;
124715d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1248861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1249861021f9SRui Ueyama     while (*Entry++)
1250861021f9SRui Ueyama       ++Index;
1251861021f9SRui Ueyama   } else {
1252861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1253861021f9SRui Ueyama     while (*Entry++)
1254861021f9SRui Ueyama       ++Index;
1255861021f9SRui Ueyama   }
125615d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
125715d99359SRui Ueyama }
125815d99359SRui Ueyama 
125915d99359SRui Ueyama imported_symbol_iterator
126015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
126160049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
126215d99359SRui Ueyama                              OwningObject);
126315d99359SRui Ueyama }
126415d99359SRui Ueyama 
126515d99359SRui Ueyama imported_symbol_iterator
126615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
126760049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
126815d99359SRui Ueyama                            OwningObject);
1269861021f9SRui Ueyama }
1270861021f9SRui Ueyama 
1271979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1272979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1273979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1274979fb40bSRui Ueyama }
1275979fb40bSRui Ueyama 
127660049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
127760049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
127860049526SDavid Majnemer                              OwningObject);
127960049526SDavid Majnemer }
128060049526SDavid Majnemer 
128160049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
128260049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
128360049526SDavid Majnemer                            OwningObject);
128460049526SDavid Majnemer }
128560049526SDavid Majnemer 
128660049526SDavid Majnemer iterator_range<imported_symbol_iterator>
128760049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
128860049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
128960049526SDavid Majnemer }
129060049526SDavid Majnemer 
1291db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1292c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1293db4ed0bdSRafael Espindola   if (std::error_code EC =
12941e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1295a045b73aSRui Ueyama     return EC;
1296a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
12977d099195SRui Ueyama   return std::error_code();
1298c2bed429SRui Ueyama }
1299c2bed429SRui Ueyama 
13001e152d5eSRui Ueyama std::error_code
13011e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13021e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13037d099195SRui Ueyama   return std::error_code();
13041e152d5eSRui Ueyama }
13051e152d5eSRui Ueyama 
13061e152d5eSRui Ueyama std::error_code
13071e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13081e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13097d099195SRui Ueyama   return std::error_code();
13101e152d5eSRui Ueyama }
13111e152d5eSRui Ueyama 
131215d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
131315d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
131415d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
131515d99359SRui Ueyama }
131615d99359SRui Ueyama 
131715d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
131815d99359SRui Ueyama   ++Index;
131915d99359SRui Ueyama }
132015d99359SRui Ueyama 
132115d99359SRui Ueyama imported_symbol_iterator
132215d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
132315d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
132415d99359SRui Ueyama                              OwningObject);
132515d99359SRui Ueyama }
132615d99359SRui Ueyama 
132715d99359SRui Ueyama imported_symbol_iterator
132815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
132915d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
133015d99359SRui Ueyama                            OwningObject);
133115d99359SRui Ueyama }
133215d99359SRui Ueyama 
1333979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1334979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1335979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1336979fb40bSRui Ueyama }
1337979fb40bSRui Ueyama 
133815d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
133915d99359SRui Ueyama   uintptr_t IntPtr = 0;
134015d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
134115d99359SRui Ueyama     return EC;
134215d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13437d099195SRui Ueyama   return std::error_code();
134415d99359SRui Ueyama }
134515d99359SRui Ueyama 
13461af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
13471af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
13481af08658SRui Ueyama   Result = Table;
13497d099195SRui Ueyama   return std::error_code();
13501af08658SRui Ueyama }
13511af08658SRui Ueyama 
1352ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1353ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1354ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1355ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1356ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1357ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1358ffa4cebeSRui Ueyama     return EC;
1359ffa4cebeSRui Ueyama   if (OwningObject->is64())
13605dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1361ffa4cebeSRui Ueyama   else
13625dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
13637d099195SRui Ueyama   return std::error_code();
1364ffa4cebeSRui Ueyama }
1365ffa4cebeSRui Ueyama 
1366ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1367ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1368ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1369ad882ba8SRui Ueyama }
1370ad882ba8SRui Ueyama 
13715e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
13725e812afaSRafael Espindola   ++Index;
1373ad882ba8SRui Ueyama }
1374ad882ba8SRui Ueyama 
1375da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1376da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1377db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1378da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1379db4ed0bdSRafael Espindola   if (std::error_code EC =
1380db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1381da49d0d4SRui Ueyama     return EC;
1382da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13837d099195SRui Ueyama   return std::error_code();
1384da49d0d4SRui Ueyama }
1385da49d0d4SRui Ueyama 
1386e5df6095SRui Ueyama // Returns the starting ordinal number.
1387db4ed0bdSRafael Espindola std::error_code
1388db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1389e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
13907d099195SRui Ueyama   return std::error_code();
1391e5df6095SRui Ueyama }
1392e5df6095SRui Ueyama 
1393ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1394db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1395ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
13967d099195SRui Ueyama   return std::error_code();
1397ad882ba8SRui Ueyama }
1398ad882ba8SRui Ueyama 
1399ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1400db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1401ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1402db4ed0bdSRafael Espindola   if (std::error_code EC =
1403db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1404ad882ba8SRui Ueyama     return EC;
140524fc2d64SRui Ueyama   const export_address_table_entry *entry =
140624fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1407ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14087d099195SRui Ueyama   return std::error_code();
1409ad882ba8SRui Ueyama }
1410ad882ba8SRui Ueyama 
1411ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1412ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1413db4ed0bdSRafael Espindola std::error_code
1414db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1415ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1416db4ed0bdSRafael Espindola   if (std::error_code EC =
1417db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1418ad882ba8SRui Ueyama     return EC;
1419ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1420ad882ba8SRui Ueyama 
1421ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1422ad882ba8SRui Ueyama   int Offset = 0;
1423ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1424ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1425ad882ba8SRui Ueyama     if (*I != Index)
1426ad882ba8SRui Ueyama       continue;
1427db4ed0bdSRafael Espindola     if (std::error_code EC =
1428db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1429ad882ba8SRui Ueyama       return EC;
1430ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1431db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1432ad882ba8SRui Ueyama       return EC;
1433ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14347d099195SRui Ueyama     return std::error_code();
1435ad882ba8SRui Ueyama   }
1436ad882ba8SRui Ueyama   Result = "";
14377d099195SRui Ueyama   return std::error_code();
1438ad882ba8SRui Ueyama }
1439ad882ba8SRui Ueyama 
14406161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
14416161b38dSRui Ueyama   const data_directory *DataEntry;
14426161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
14436161b38dSRui Ueyama     return EC;
14446161b38dSRui Ueyama   uint32_t RVA;
14456161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14466161b38dSRui Ueyama     return EC;
14476161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
14486161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
14496161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
14506161b38dSRui Ueyama   return std::error_code();
14516161b38dSRui Ueyama }
14526161b38dSRui Ueyama 
14536161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
14546161b38dSRui Ueyama   uint32_t RVA;
14556161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14566161b38dSRui Ueyama     return EC;
14576161b38dSRui Ueyama   uintptr_t IntPtr = 0;
14586161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
14596161b38dSRui Ueyama     return EC;
14606161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14616161b38dSRui Ueyama   return std::error_code();
14626161b38dSRui Ueyama }
14636161b38dSRui Ueyama 
1464861021f9SRui Ueyama bool ImportedSymbolRef::
1465861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1466861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1467861021f9SRui Ueyama       && Index == Other.Index;
1468861021f9SRui Ueyama }
1469861021f9SRui Ueyama 
1470861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1471861021f9SRui Ueyama   ++Index;
1472861021f9SRui Ueyama }
1473861021f9SRui Ueyama 
1474861021f9SRui Ueyama std::error_code
1475861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1476861021f9SRui Ueyama   uint32_t RVA;
1477861021f9SRui Ueyama   if (Entry32) {
1478861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1479861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
14807d099195SRui Ueyama       return std::error_code();
1481861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1482861021f9SRui Ueyama   } else {
1483861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
14847d099195SRui Ueyama       return std::error_code();
1485861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1486861021f9SRui Ueyama   }
1487861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1488861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1489861021f9SRui Ueyama     return EC;
1490861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1491861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
14927d099195SRui Ueyama   return std::error_code();
1493861021f9SRui Ueyama }
1494861021f9SRui Ueyama 
1495ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1496ad7b7e73SDavid Majnemer   if (Entry32)
1497ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1498ad7b7e73SDavid Majnemer   else
1499ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1500ad7b7e73SDavid Majnemer   return std::error_code();
1501ad7b7e73SDavid Majnemer }
1502ad7b7e73SDavid Majnemer 
1503ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1504ad7b7e73SDavid Majnemer   if (Entry32)
1505ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1506ad7b7e73SDavid Majnemer   else
1507ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1508ad7b7e73SDavid Majnemer   return std::error_code();
1509ad7b7e73SDavid Majnemer }
1510ad7b7e73SDavid Majnemer 
1511861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1512861021f9SRui Ueyama   uint32_t RVA;
1513861021f9SRui Ueyama   if (Entry32) {
1514861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1515861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15167d099195SRui Ueyama       return std::error_code();
1517861021f9SRui Ueyama     }
1518861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1519861021f9SRui Ueyama   } else {
1520861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1521861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15227d099195SRui Ueyama       return std::error_code();
1523861021f9SRui Ueyama     }
1524861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1525861021f9SRui Ueyama   }
1526861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1527861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1528861021f9SRui Ueyama     return EC;
1529861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15307d099195SRui Ueyama   return std::error_code();
1531861021f9SRui Ueyama }
1532861021f9SRui Ueyama 
1533437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>>
153448af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1535db4ed0bdSRafael Espindola   std::error_code EC;
153648af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1537692410efSRafael Espindola   if (EC)
1538692410efSRafael Espindola     return EC;
1539437b0d58SRafael Espindola   return std::move(Ret);
1540686738e2SRui Ueyama }
154174e85130SRui Ueyama 
154274e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
154374e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
154474e85130SRui Ueyama }
154574e85130SRui Ueyama 
154674e85130SRui Ueyama void BaseRelocRef::moveNext() {
154774e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
154874e85130SRui Ueyama   // size of the header itself.
154974e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1550970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
155174e85130SRui Ueyama   if (Size == Header->BlockSize) {
155274e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
155374e85130SRui Ueyama     // consists of the header followed by entries. The header contains
155474e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
155574e85130SRui Ueyama     // current block, proceed to the next block.
155674e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
155774e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
155874e85130SRui Ueyama     Index = 0;
155974e85130SRui Ueyama   } else {
156074e85130SRui Ueyama     ++Index;
156174e85130SRui Ueyama   }
156274e85130SRui Ueyama }
156374e85130SRui Ueyama 
156474e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
156574e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
156674e85130SRui Ueyama   Type = Entry[Index].getType();
15677d099195SRui Ueyama   return std::error_code();
156874e85130SRui Ueyama }
156974e85130SRui Ueyama 
157074e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
157174e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
157274e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
15737d099195SRui Ueyama   return std::error_code();
157474e85130SRui Ueyama }
1575