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 
160*6b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
161*6b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
162*6b2bba14SDavide Italiano   // up to 32 bytes.
163*6b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
164*6b2bba14SDavide Italiano   uint32_t Value = Symb.getValue();
165*6b2bba14SDavide Italiano   return std::min(uint64_t(32),
166*6b2bba14SDavide Italiano                   isPowerOf2_64(Value) ? Value : NextPowerOf2(Value));
167*6b2bba14SDavide Italiano }
168*6b2bba14SDavide Italiano 
169931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
170ed067c45SRafael Espindola   uint64_t Result = getSymbolValue(Ref);
17144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
172c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
173991af666SRafael Espindola 
174991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
175991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
176ed067c45SRafael Espindola     return Result;
17754c9f3daSRafael Espindola 
1782617dcceSCraig Topper   const coff_section *Section = nullptr;
179c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
180931cb65dSKevin Enderby     return errorCodeToError(EC);
181991af666SRafael Espindola   Result += Section->VirtualAddress;
18247ea9eceSReid Kleckner 
18347ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18447ea9eceSReid Kleckner   // return virtual addresses.
18521427adaSReid Kleckner   Result += getImageBase();
18647ea9eceSReid Kleckner 
187ed067c45SRafael Espindola   return Result;
188c7d7c6fbSDavid Majnemer }
189c7d7c6fbSDavid Majnemer 
1907bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
19144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
192c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
19344f51e51SDavid Majnemer 
194e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
195e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1962fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1972fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1982fa80cc5SRafael Espindola   if (Symb.isCommon())
1992fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2002fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2012fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2022fa80cc5SRafael Espindola 
2031a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2042fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2052fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2062fa80cc5SRafael Espindola 
2072fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2082fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2092fa80cc5SRafael Espindola 
2102fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
21175d1cf33SBenjamin Kramer }
21275d1cf33SBenjamin Kramer 
21320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21444f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21520122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21675d1cf33SBenjamin Kramer 
217c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2189dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2191df4b84dSDavid Meyer 
220c7d7c6fbSDavid Majnemer   if (Symb.isWeakExternal())
2211df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
2221df4b84dSDavid Meyer 
22344f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2241df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2251df4b84dSDavid Meyer 
226c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
227c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
228c7d7c6fbSDavid Majnemer 
229c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
230c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
231c7d7c6fbSDavid Majnemer 
232c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
233c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
234c7d7c6fbSDavid Majnemer 
235c7d7c6fbSDavid Majnemer   if (Symb.isAnyUndefined())
236c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
237c7d7c6fbSDavid Majnemer 
23820122a43SRafael Espindola   return Result;
23901759754SMichael J. Spencer }
24001759754SMichael J. Spencer 
241d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
242c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2435eb02e45SRafael Espindola   return Symb.getValue();
2448e90adafSMichael J. Spencer }
2458e90adafSMichael J. Spencer 
2467bd8d994SKevin Enderby Expected<section_iterator>
2478bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
24844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2498bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2508bab889bSRafael Espindola     return section_end();
2512617dcceSCraig Topper   const coff_section *Sec = nullptr;
25244f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2537bd8d994SKevin Enderby     return errorCodeToError(EC);
2548bab889bSRafael Espindola   DataRefImpl Ret;
2558bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2568bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25732173153SMichael J. Spencer }
25832173153SMichael J. Spencer 
2596bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2606bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2616bf32210SRafael Espindola   return Symb.getSectionNumber();
2626bf32210SRafael Espindola }
2636bf32210SRafael Espindola 
2645e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2658ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2668ff24d25SRui Ueyama   Sec += 1;
2678ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2688e90adafSMichael J. Spencer }
2698e90adafSMichael J. Spencer 
270db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
2711d6167fdSMichael J. Spencer                                                StringRef &Result) const {
2728ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2738ff24d25SRui Ueyama   return getSectionName(Sec, Result);
2748e90adafSMichael J. Spencer }
2758e90adafSMichael J. Spencer 
27680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2778ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2787c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2797c6a071bSDavid Majnemer 
2807c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2817c6a071bSDavid Majnemer   // return virtual addresses.
28221427adaSReid Kleckner   Result += getImageBase();
2837c6a071bSDavid Majnemer   return Result;
2848e90adafSMichael J. Spencer }
2858e90adafSMichael J. Spencer 
28680291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
287a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2888e90adafSMichael J. Spencer }
2898e90adafSMichael J. Spencer 
290db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
2911d6167fdSMichael J. Spencer                                                    StringRef &Result) const {
2928ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2939da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
294db4ed0bdSRafael Espindola   std::error_code EC = getSectionContents(Sec, Res);
2959da9e693SMichael J. Spencer   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
2969da9e693SMichael J. Spencer   return EC;
2978e90adafSMichael J. Spencer }
2988e90adafSMichael J. Spencer 
29980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3008ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
301511391feSDavid Majnemer   return Sec->getAlignment();
3027989460aSMichael J. Spencer }
3037989460aSMichael J. Spencer 
304401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
305401e4e57SGeorge Rimar   return false;
306401e4e57SGeorge Rimar }
307401e4e57SGeorge Rimar 
30880291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3098ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31080291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3118e90adafSMichael J. Spencer }
3128e90adafSMichael J. Spencer 
31380291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3148ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31580291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
316800619f2SMichael J. Spencer }
317800619f2SMichael J. Spencer 
31880291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3198ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3201a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3211a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3221a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3231a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
324800619f2SMichael J. Spencer }
325800619f2SMichael J. Spencer 
3266bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3276bf32210SRafael Espindola   uintptr_t Offset =
3286bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3296bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3306bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3316bf32210SRafael Espindola }
3326bf32210SRafael Espindola 
33380291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3348ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3351a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3361a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3371a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3382138ef6dSPreston Gurd }
3392138ef6dSPreston Gurd 
340e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
341e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
342e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
343e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
344e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
345e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
346e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
347e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
348e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
349e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
350e830c60dSDavid Majnemer       return 0;
35198fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
35298fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
353e830c60dSDavid Majnemer   }
354e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
355e830c60dSDavid Majnemer }
356e830c60dSDavid Majnemer 
35794751be7SDavid Majnemer static const coff_relocation *
35894751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
35994751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36094751be7SDavid Majnemer   if (!NumRelocs)
36194751be7SDavid Majnemer     return nullptr;
362827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
36394751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
364827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
365827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
366827c8a2bSRui Ueyama     // relocations.
367827c8a2bSRui Ueyama     begin++;
368827c8a2bSRui Ueyama   }
36994751be7SDavid Majnemer   if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
37094751be7SDavid Majnemer     return nullptr;
37194751be7SDavid Majnemer   return begin;
372827c8a2bSRui Ueyama }
37394751be7SDavid Majnemer 
37494751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
37594751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
37694751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
37776d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
37876d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
37994751be7SDavid Majnemer   DataRefImpl Ret;
38094751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3818ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
382e5fd0047SMichael J. Spencer }
383e5fd0047SMichael J. Spencer 
3848ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3858ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
38694751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
38794751be7SDavid Majnemer   if (I)
38894751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3898ff24d25SRui Ueyama   DataRefImpl Ret;
39094751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
3918ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
392e5fd0047SMichael J. Spencer }
393e5fd0047SMichael J. Spencer 
394c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
395db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
39644f51e51SDavid Majnemer   if (COFFHeader)
397236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
398236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
399236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40044f51e51SDavid Majnemer       return EC;
40144f51e51SDavid Majnemer 
40244f51e51SDavid Majnemer   if (COFFBigObjHeader)
403236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
404236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
405236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4068ff24d25SRui Ueyama       return EC;
407c2bed429SRui Ueyama 
408c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
409c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
410c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
411f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
41244f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
413f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
414c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
41548af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4168ff24d25SRui Ueyama     return EC;
417c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
418db4ed0bdSRafael Espindola   if (std::error_code EC =
41948af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4208ff24d25SRui Ueyama     return EC;
421c2bed429SRui Ueyama 
422773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
423773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
424773a5795SNico Rieck   if (StringTableSize < 4)
425773a5795SNico Rieck       StringTableSize = 4;
426773a5795SNico Rieck 
427c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
428773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
429c2bed429SRui Ueyama     return  object_error::parse_failed;
4307d099195SRui Ueyama   return std::error_code();
431c2bed429SRui Ueyama }
432c2bed429SRui Ueyama 
43321427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
434e94fef7bSReid Kleckner   if (PE32Header)
43521427adaSReid Kleckner     return PE32Header->ImageBase;
436e94fef7bSReid Kleckner   else if (PE32PlusHeader)
43721427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
43821427adaSReid Kleckner   // This actually comes up in practice.
43921427adaSReid Kleckner   return 0;
440e94fef7bSReid Kleckner }
441e94fef7bSReid Kleckner 
442215a586cSRui Ueyama // Returns the file offset for the given VA.
443db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
44421427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
445b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
446b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
447b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
448215a586cSRui Ueyama }
449215a586cSRui Ueyama 
450c2bed429SRui Ueyama // Returns the file offset for the given RVA.
451db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
45227dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
45327dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
454c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
455c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
456215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
457215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
458c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4597d099195SRui Ueyama       return std::error_code();
460c2bed429SRui Ueyama     }
461c2bed429SRui Ueyama   }
462c2bed429SRui Ueyama   return object_error::parse_failed;
463c2bed429SRui Ueyama }
464c2bed429SRui Ueyama 
4652da433eaSReid Kleckner std::error_code
4662da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4672da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4682da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4692da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4702da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4712da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4722da433eaSReid Kleckner     // overflow.
4732da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4742da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4752da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4762da433eaSReid Kleckner       uintptr_t Begin =
4772da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4782da433eaSReid Kleckner       Contents =
4792da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4802da433eaSReid Kleckner       return std::error_code();
4812da433eaSReid Kleckner     }
4822da433eaSReid Kleckner   }
4832da433eaSReid Kleckner   return object_error::parse_failed;
4842da433eaSReid Kleckner }
4852da433eaSReid Kleckner 
486c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
487c2bed429SRui Ueyama // table entry.
488db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
489db4ed0bdSRafael Espindola                                             StringRef &Name) const {
490c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
491db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
4928ff24d25SRui Ueyama     return EC;
493c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
494c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
495c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
4967d099195SRui Ueyama   return std::error_code();
497c2bed429SRui Ueyama }
498c2bed429SRui Ueyama 
49901528021SSaleem Abdulrasool std::error_code
50001528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
50101528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5022da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5032da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5042da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5052da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5062da433eaSReid Kleckner     return EC;
50701528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5082da433eaSReid Kleckner     return object_error::parse_failed;
50901528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
51001528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5112da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5122da433eaSReid Kleckner                           InfoBytes.size());
5132da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5142da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5152da433eaSReid Kleckner   return std::error_code();
5162da433eaSReid Kleckner }
5172da433eaSReid Kleckner 
51801528021SSaleem Abdulrasool std::error_code
51901528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
520f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
521f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
522f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
523f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
524f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
525f27f3f84SReid Kleckner   PDBInfo = nullptr;
526f27f3f84SReid Kleckner   PDBFileName = StringRef();
527f27f3f84SReid Kleckner   return std::error_code();
528f27f3f84SReid Kleckner }
529f27f3f84SReid Kleckner 
530c2bed429SRui Ueyama // Find the import table.
531db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
532c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
533c2bed429SRui Ueyama   // the import table, do nothing.
534c2bed429SRui Ueyama   const data_directory *DataEntry;
535c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5367d099195SRui Ueyama     return std::error_code();
537c2bed429SRui Ueyama 
538c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
539c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5407d099195SRui Ueyama     return std::error_code();
541c2bed429SRui Ueyama 
542c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
543c2bed429SRui Ueyama 
544c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
545c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
546c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
547db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5488ff24d25SRui Ueyama     return EC;
549ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
550ad7b7e73SDavid Majnemer     return EC;
551c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5521c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5537d099195SRui Ueyama   return std::error_code();
554ad882ba8SRui Ueyama }
555c2bed429SRui Ueyama 
55615d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
55715d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
55815d99359SRui Ueyama   const data_directory *DataEntry;
55915d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5607d099195SRui Ueyama     return std::error_code();
56115d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5627d099195SRui Ueyama     return std::error_code();
56315d99359SRui Ueyama 
56415d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
56515d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
56615d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
56715d99359SRui Ueyama 
56815d99359SRui Ueyama   uintptr_t IntPtr = 0;
56915d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57015d99359SRui Ueyama     return EC;
57115d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
57215d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5737d099195SRui Ueyama   return std::error_code();
57415d99359SRui Ueyama }
57515d99359SRui Ueyama 
576ad882ba8SRui Ueyama // Find the export table.
577db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
578ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
579ad882ba8SRui Ueyama   // the export table, do nothing.
580ad882ba8SRui Ueyama   const data_directory *DataEntry;
581ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5827d099195SRui Ueyama     return std::error_code();
583ad882ba8SRui Ueyama 
584ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
585ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5867d099195SRui Ueyama     return std::error_code();
587ad882ba8SRui Ueyama 
588ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
589ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
590db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
591ad882ba8SRui Ueyama     return EC;
59224fc2d64SRui Ueyama   ExportDirectory =
59324fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
5947d099195SRui Ueyama   return std::error_code();
595c2bed429SRui Ueyama }
596c2bed429SRui Ueyama 
59774e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
59874e85130SRui Ueyama   const data_directory *DataEntry;
59974e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6007d099195SRui Ueyama     return std::error_code();
60174e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6027d099195SRui Ueyama     return std::error_code();
60374e85130SRui Ueyama 
60474e85130SRui Ueyama   uintptr_t IntPtr = 0;
60574e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
60674e85130SRui Ueyama     return EC;
60774e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
60874e85130SRui Ueyama       IntPtr);
60974e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61074e85130SRui Ueyama       IntPtr + DataEntry->Size);
6117d099195SRui Ueyama   return std::error_code();
61274e85130SRui Ueyama }
61374e85130SRui Ueyama 
6142da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6152da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6162da433eaSReid Kleckner   const data_directory *DataEntry;
6172da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6182da433eaSReid Kleckner     return std::error_code();
6192da433eaSReid Kleckner 
6202da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6212da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6222da433eaSReid Kleckner     return std::error_code();
6232da433eaSReid Kleckner 
6242da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6252da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6262da433eaSReid Kleckner     return object_error::parse_failed;
6272da433eaSReid Kleckner 
6282da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6292da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6302da433eaSReid Kleckner     return EC;
6312da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6322da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(
6332da433eaSReid Kleckner           DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
6342da433eaSReid Kleckner     return EC;
6352da433eaSReid Kleckner   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
6362da433eaSReid Kleckner   return std::error_code();
6372da433eaSReid Kleckner }
6382da433eaSReid Kleckner 
63948af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
64048af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
64144f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
64244f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
64344f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
644ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
64515d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6462da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6472da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6481d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
64948af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
650c3f9b5a5SRafael Espindola     return;
651ee066fc4SEric Christopher 
65282ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
65382ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
65482ebd8e3SRui Ueyama 
65582ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
65682ebd8e3SRui Ueyama   // it is placed right after COFF header.
6578ff24d25SRui Ueyama   bool HasPEHeader = false;
658ee066fc4SEric Christopher 
6591d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
66050267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
661ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
662ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
66350267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
66450267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
66550267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
66682ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
66750267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6688ff24d25SRui Ueyama         EC = object_error::parse_failed;
6691d6167fdSMichael J. Spencer         return;
6701d6167fdSMichael J. Spencer       }
67144f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6728ff24d25SRui Ueyama       HasPEHeader = true;
673ee066fc4SEric Christopher     }
67450267222SDavid Majnemer   }
675ee066fc4SEric Christopher 
67648af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
6771d6167fdSMichael J. Spencer     return;
67844f51e51SDavid Majnemer 
67944f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
68044f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
68144f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
68244f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
68344f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
68444f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
68544f51e51SDavid Majnemer       return;
68644f51e51SDavid Majnemer 
68744f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
68844f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
68944f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
69044f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
69144f51e51SDavid Majnemer       COFFHeader = nullptr;
69244f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
69344f51e51SDavid Majnemer     } else {
69444f51e51SDavid Majnemer       // It's not a bigobj.
69544f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
69644f51e51SDavid Majnemer     }
69744f51e51SDavid Majnemer   }
69844f51e51SDavid Majnemer   if (COFFHeader) {
69944f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
70044f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7017d099195SRui Ueyama     EC = std::error_code();
70282ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
70382ebd8e3SRui Ueyama 
70444f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
70544f51e51SDavid Majnemer       return;
70644f51e51SDavid Majnemer   }
70744f51e51SDavid Majnemer 
7088ff24d25SRui Ueyama   if (HasPEHeader) {
70910ed9ddcSRui Ueyama     const pe32_header *Header;
71048af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
71182ebd8e3SRui Ueyama       return;
71210ed9ddcSRui Ueyama 
71310ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
71410ed9ddcSRui Ueyama     uint64_t DataDirSize;
71550267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
71610ed9ddcSRui Ueyama       PE32Header = Header;
71710ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
71810ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
71950267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
72010ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
72110ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
72210ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
72310ed9ddcSRui Ueyama     } else {
72410ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
72510ed9ddcSRui Ueyama       EC = object_error::parse_failed;
726ed64342bSRui Ueyama       return;
727ed64342bSRui Ueyama     }
72848af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
72910ed9ddcSRui Ueyama       return;
730f53c8cb4SRui Ueyama   }
731776c6828SRui Ueyama 
7328950a538SRui Ueyama   if (COFFHeader)
7338950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7348950a538SRui Ueyama 
73548af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
736236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7371d6167fdSMichael J. Spencer     return;
7381d6167fdSMichael J. Spencer 
739c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
740236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
741ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
742ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
743ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
744ac8cfab5SDavid Majnemer       StringTable = nullptr;
745ac8cfab5SDavid Majnemer       StringTableSize = 0;
746ac8cfab5SDavid Majnemer     }
747236b0ca7SDavid Majnemer   } else {
748236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
749236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
750236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
751236b0ca7SDavid Majnemer       return;
752236b0ca7SDavid Majnemer     }
753236b0ca7SDavid Majnemer   }
7548e90adafSMichael J. Spencer 
755c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7568ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
757ed64342bSRui Ueyama     return;
75815d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
75915d99359SRui Ueyama     return;
7601d6167fdSMichael J. Spencer 
761ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7628ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
763ad882ba8SRui Ueyama     return;
764ad882ba8SRui Ueyama 
76574e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
76674e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
76774e85130SRui Ueyama     return;
76874e85130SRui Ueyama 
7692da433eaSReid Kleckner   // Initialize the pointer to the export table.
7702da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7712da433eaSReid Kleckner     return;
7722da433eaSReid Kleckner 
7737d099195SRui Ueyama   EC = std::error_code();
7748e90adafSMichael J. Spencer }
7758e90adafSMichael J. Spencer 
776f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const {
7778ff24d25SRui Ueyama   DataRefImpl Ret;
77844f51e51SDavid Majnemer   Ret.p = getSymbolTable();
779f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7808e90adafSMichael J. Spencer }
7818e90adafSMichael J. Spencer 
782f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const {
7838e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
7848ff24d25SRui Ueyama   DataRefImpl Ret;
7858ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
786f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
7878e90adafSMichael J. Spencer }
7888e90adafSMichael J. Spencer 
789bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
790ad7b7e73SDavid Majnemer   if (!ImportDirectory)
791ad7b7e73SDavid Majnemer     return import_directory_end();
7921c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
793ad7b7e73SDavid Majnemer     return import_directory_end();
794a045b73aSRui Ueyama   return import_directory_iterator(
795a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
796c2bed429SRui Ueyama }
797c2bed429SRui Ueyama 
798bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
799a045b73aSRui Ueyama   return import_directory_iterator(
800ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
801c2bed429SRui Ueyama }
802c429b80dSDavid Meyer 
80315d99359SRui Ueyama delay_import_directory_iterator
80415d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
80515d99359SRui Ueyama   return delay_import_directory_iterator(
80615d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
80715d99359SRui Ueyama }
80815d99359SRui Ueyama 
80915d99359SRui Ueyama delay_import_directory_iterator
81015d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
81115d99359SRui Ueyama   return delay_import_directory_iterator(
81215d99359SRui Ueyama       DelayImportDirectoryEntryRef(
81315d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
81415d99359SRui Ueyama }
81515d99359SRui Ueyama 
816ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
817ad882ba8SRui Ueyama   return export_directory_iterator(
818ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
819ad882ba8SRui Ueyama }
820ad882ba8SRui Ueyama 
821ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8222617dcceSCraig Topper   if (!ExportDirectory)
8232617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8248ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
825ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8268ff24d25SRui Ueyama   return export_directory_iterator(Ref);
827ad882ba8SRui Ueyama }
828ad882ba8SRui Ueyama 
829b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8308ff24d25SRui Ueyama   DataRefImpl Ret;
8318ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8328ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8338e90adafSMichael J. Spencer }
8348e90adafSMichael J. Spencer 
835b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8368ff24d25SRui Ueyama   DataRefImpl Ret;
83744f51e51SDavid Majnemer   int NumSections =
83844f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8398ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8408ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8418e90adafSMichael J. Spencer }
8428e90adafSMichael J. Spencer 
84374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
84474e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
84574e85130SRui Ueyama }
84674e85130SRui Ueyama 
84774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
84874e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
84974e85130SRui Ueyama }
85074e85130SRui Ueyama 
8518e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
8520324b672SMichael J. Spencer   return getArch() == Triple::x86_64 ? 8 : 4;
8538e90adafSMichael J. Spencer }
8548e90adafSMichael J. Spencer 
8558e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
85644f51e51SDavid Majnemer   switch(getMachine()) {
8578e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8588e90adafSMichael J. Spencer     return "COFF-i386";
8598e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8608e90adafSMichael J. Spencer     return "COFF-x86-64";
8619b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8629b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8631eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8641eff5c9cSMartell Malone     return "COFF-ARM64";
8658e90adafSMichael J. Spencer   default:
8668e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8678e90adafSMichael J. Spencer   }
8688e90adafSMichael J. Spencer }
8698e90adafSMichael J. Spencer 
8708e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const {
87144f51e51SDavid Majnemer   switch (getMachine()) {
8728e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8738e90adafSMichael J. Spencer     return Triple::x86;
8748e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8758e90adafSMichael J. Spencer     return Triple::x86_64;
8769b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8779b7c0af2SSaleem Abdulrasool     return Triple::thumb;
8781eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8791eff5c9cSMartell Malone     return Triple::aarch64;
8808e90adafSMichael J. Spencer   default:
8818e90adafSMichael J. Spencer     return Triple::UnknownArch;
8828e90adafSMichael J. Spencer   }
8838e90adafSMichael J. Spencer }
8848e90adafSMichael J. Spencer 
885979fb40bSRui Ueyama iterator_range<import_directory_iterator>
886979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
887979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
888979fb40bSRui Ueyama }
889979fb40bSRui Ueyama 
890979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
891979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
892979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
893979fb40bSRui Ueyama                     delay_import_directory_end());
894979fb40bSRui Ueyama }
895979fb40bSRui Ueyama 
896979fb40bSRui Ueyama iterator_range<export_directory_iterator>
897979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
898979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
899979fb40bSRui Ueyama }
900979fb40bSRui Ueyama 
90174e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
90274e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
90374e85130SRui Ueyama }
90474e85130SRui Ueyama 
905db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
90682ebd8e3SRui Ueyama   Res = PE32Header;
9077d099195SRui Ueyama   return std::error_code();
90889a7a5eaSMichael J. Spencer }
90989a7a5eaSMichael J. Spencer 
910db4ed0bdSRafael Espindola std::error_code
91110ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
91210ed9ddcSRui Ueyama   Res = PE32PlusHeader;
9137d099195SRui Ueyama   return std::error_code();
91410ed9ddcSRui Ueyama }
91510ed9ddcSRui Ueyama 
916db4ed0bdSRafael Espindola std::error_code
917db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
918ed64342bSRui Ueyama                                  const data_directory *&Res) const {
919ed64342bSRui Ueyama   // Error if if there's no data directory or the index is out of range.
920f69b0585SDavid Majnemer   if (!DataDirectory) {
921f69b0585SDavid Majnemer     Res = nullptr;
92210ed9ddcSRui Ueyama     return object_error::parse_failed;
923f69b0585SDavid Majnemer   }
92410ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
92510ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
92610ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
927f69b0585SDavid Majnemer   if (Index >= NumEnt) {
928f69b0585SDavid Majnemer     Res = nullptr;
929ed64342bSRui Ueyama     return object_error::parse_failed;
930f69b0585SDavid Majnemer   }
9318ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9327d099195SRui Ueyama   return std::error_code();
933ed64342bSRui Ueyama }
934ed64342bSRui Ueyama 
935db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9361d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9372617dcceSCraig Topper   Result = nullptr;
938236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9397d099195SRui Ueyama     return std::error_code();
940236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9411d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9428ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9437d099195SRui Ueyama     return std::error_code();
9448e90adafSMichael J. Spencer   }
945236b0ca7SDavid Majnemer   return object_error::parse_failed;
946236b0ca7SDavid Majnemer }
9478e90adafSMichael J. Spencer 
948db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9491d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9501d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9511d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9521d6167fdSMichael J. Spencer     return object_error::parse_failed;
9538ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9541d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
9558ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
9567d099195SRui Ueyama   return std::error_code();
9578e90adafSMichael J. Spencer }
958022ecdf2SBenjamin Kramer 
95944f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
96089a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
961e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
962e40d30f3SRui Ueyama }
963e40d30f3SRui Ueyama 
964e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
965e40d30f3SRui Ueyama                                               StringRef &Res) const {
96689a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
967e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
968e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
9698ff24d25SRui Ueyama       return EC;
9707d099195SRui Ueyama     return std::error_code();
97189a7a5eaSMichael J. Spencer   }
97289a7a5eaSMichael J. Spencer 
973e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
97489a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
975e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
97689a7a5eaSMichael J. Spencer   else
97789a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
978e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
9797d099195SRui Ueyama   return std::error_code();
98089a7a5eaSMichael J. Spencer }
98189a7a5eaSMichael J. Spencer 
98244f51e51SDavid Majnemer ArrayRef<uint8_t>
98344f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
9842617dcceSCraig Topper   const uint8_t *Aux = nullptr;
98571757ef3SMarshall Clow 
98644f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
98744f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
98871757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
98944f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
99071757ef3SMarshall Clow # ifndef NDEBUG
9918ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
9928ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
99344f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
99444f51e51SDavid Majnemer         Offset >=
99544f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
99671757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
99771757ef3SMarshall Clow 
99844f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
99944f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
100071757ef3SMarshall Clow # endif
1001bfb85e67SMarshall Clow   }
100244f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
100371757ef3SMarshall Clow }
100471757ef3SMarshall Clow 
1005db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
100653c2d547SMichael J. Spencer                                                StringRef &Res) const {
100753c2d547SMichael J. Spencer   StringRef Name;
100844f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
100953c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
101053c2d547SMichael J. Spencer     Name = Sec->Name;
101153c2d547SMichael J. Spencer   else
101253c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
101344f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
101453c2d547SMichael J. Spencer 
101553c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10162314b3deSDavid Majnemer   if (Name.startswith("/")) {
101753c2d547SMichael J. Spencer     uint32_t Offset;
10182314b3deSDavid Majnemer     if (Name.startswith("//")) {
10199d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10209d2c15efSNico Rieck         return object_error::parse_failed;
10219d2c15efSNico Rieck     } else {
102253c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
102353c2d547SMichael J. Spencer         return object_error::parse_failed;
10249d2c15efSNico Rieck     }
1025db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10268ff24d25SRui Ueyama       return EC;
102753c2d547SMichael J. Spencer   }
102853c2d547SMichael J. Spencer 
102953c2d547SMichael J. Spencer   Res = Name;
10307d099195SRui Ueyama   return std::error_code();
103153c2d547SMichael J. Spencer }
103253c2d547SMichael J. Spencer 
1033a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1034a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1035a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1036a9ee5c06SDavid Majnemer   //
1037a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1038d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1039a9ee5c06SDavid Majnemer   //
1040a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1041a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1042a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1043a9ee5c06SDavid Majnemer   // considered to be zero.
1044d5297ee7SRui Ueyama   if (getDOSHeader())
1045d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1046d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1047a9ee5c06SDavid Majnemer }
1048a9ee5c06SDavid Majnemer 
1049db4ed0bdSRafael Espindola std::error_code
1050db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec,
10519da9e693SMichael J. Spencer                                    ArrayRef<uint8_t> &Res) const {
1052e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1053e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1054e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1055e2129662SDavid Majnemer     return object_error::parse_failed;
10569da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10579da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10589da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10599da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1060a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1061e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
10629da9e693SMichael J. Spencer     return object_error::parse_failed;
1063a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
10647d099195SRui Ueyama   return std::error_code();
10659da9e693SMichael J. Spencer }
10669da9e693SMichael J. Spencer 
1067022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1068e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1069022ecdf2SBenjamin Kramer }
10708ff24d25SRui Ueyama 
10715e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1072e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1073e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1074022ecdf2SBenjamin Kramer }
10758ff24d25SRui Ueyama 
107696d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
107758323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
107896d071cdSRafael Espindola   return R->VirtualAddress;
1079cbe72fc9SDanil Malyshev }
10808ff24d25SRui Ueyama 
1081806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1082022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
10838ff24d25SRui Ueyama   DataRefImpl Ref;
1084236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1085236b0ca7SDavid Majnemer     return symbol_end();
108644f51e51SDavid Majnemer   if (SymbolTable16)
108744f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
108844f51e51SDavid Majnemer   else if (SymbolTable32)
108944f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
109044f51e51SDavid Majnemer   else
1091c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
10928ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1093022ecdf2SBenjamin Kramer }
10948ff24d25SRui Ueyama 
109599c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1096022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
109799c041b7SRafael Espindola   return R->Type;
1098022ecdf2SBenjamin Kramer }
1099e5fd0047SMichael J. Spencer 
110027dc8394SAlexey Samsonov const coff_section *
110127dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
110227dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
110371757ef3SMarshall Clow }
110471757ef3SMarshall Clow 
110544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
110644f51e51SDavid Majnemer   if (SymbolTable16)
110744f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
110844f51e51SDavid Majnemer   if (SymbolTable32)
110944f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
111044f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
111144f51e51SDavid Majnemer }
111244f51e51SDavid Majnemer 
111344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
111444f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
111571757ef3SMarshall Clow }
111671757ef3SMarshall Clow 
1117f12b8282SRafael Espindola const coff_relocation *
111827dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
111927dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1120d3e2a76cSMarshall Clow }
1121d3e2a76cSMarshall Clow 
11226a75acb1SRui Ueyama iterator_range<const coff_relocation *>
11236a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11246a75acb1SRui Ueyama   const coff_relocation *I = getFirstReloc(Sec, Data, base());
11256a75acb1SRui Ueyama   const coff_relocation *E = I;
11266a75acb1SRui Ueyama   if (I)
11276a75acb1SRui Ueyama     E += getNumberOfRelocations(Sec, Data, base());
11286a75acb1SRui Ueyama   return make_range(I, E);
11296a75acb1SRui Ueyama }
11306a75acb1SRui Ueyama 
113127dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
113227dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
113327dc8394SAlexey Samsonov     Res = #reloc_type;                                                         \
113427dc8394SAlexey Samsonov     break;
1135e5fd0047SMichael J. Spencer 
113641bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName(
113741bb4325SRafael Espindola     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
11388ff24d25SRui Ueyama   const coff_relocation *Reloc = toRel(Rel);
11398ff24d25SRui Ueyama   StringRef Res;
114044f51e51SDavid Majnemer   switch (getMachine()) {
1141e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
11428ff24d25SRui Ueyama     switch (Reloc->Type) {
1143e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1144e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1145e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1146e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1147e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1148e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1149e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1150e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1151e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1152e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1153e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1154e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1155e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1156e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1157e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1158e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1159e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1160e5fd0047SMichael J. Spencer     default:
11618ff24d25SRui Ueyama       Res = "Unknown";
1162e5fd0047SMichael J. Spencer     }
1163e5fd0047SMichael J. Spencer     break;
11645c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
11655c503bf4SSaleem Abdulrasool     switch (Reloc->Type) {
11665c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11675c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11685c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11695c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11705c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11715c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
11725c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
11735c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
11745c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
11755c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
11765c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
11775c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
11785c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
11795c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
11805c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
11815c503bf4SSaleem Abdulrasool     default:
11825c503bf4SSaleem Abdulrasool       Res = "Unknown";
11835c503bf4SSaleem Abdulrasool     }
11845c503bf4SSaleem Abdulrasool     break;
1185e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
11868ff24d25SRui Ueyama     switch (Reloc->Type) {
1187e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1188e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1189e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1190e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1191e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1192e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1193e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1194e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1195e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1196e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1197e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1198e5fd0047SMichael J. Spencer     default:
11998ff24d25SRui Ueyama       Res = "Unknown";
1200e5fd0047SMichael J. Spencer     }
1201e5fd0047SMichael J. Spencer     break;
1202e5fd0047SMichael J. Spencer   default:
12038ff24d25SRui Ueyama     Res = "Unknown";
1204e5fd0047SMichael J. Spencer   }
12058ff24d25SRui Ueyama   Result.append(Res.begin(), Res.end());
1206e5fd0047SMichael J. Spencer }
1207e5fd0047SMichael J. Spencer 
1208e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1209e5fd0047SMichael J. Spencer 
1210c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1211c66d761bSRafael Espindola   return !DataDirectory;
1212c66d761bSRafael Espindola }
1213c66d761bSRafael Espindola 
1214c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1215c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1216a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1217c2bed429SRui Ueyama }
1218c2bed429SRui Ueyama 
12195e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12205e812afaSRafael Espindola   ++Index;
12211c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1222ad7b7e73SDavid Majnemer     Index = -1;
1223ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1224ad7b7e73SDavid Majnemer   }
1225c2bed429SRui Ueyama }
1226c2bed429SRui Ueyama 
1227db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12281c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1229ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1230c2bed429SRui Ueyama }
1231c2bed429SRui Ueyama 
1232861021f9SRui Ueyama static imported_symbol_iterator
123315d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1234861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
123515d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1236861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
123715d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1238861021f9SRui Ueyama   }
1239861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
124015d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1241861021f9SRui Ueyama }
1242861021f9SRui Ueyama 
124315d99359SRui Ueyama static imported_symbol_iterator
124415d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1245861021f9SRui Ueyama   uintptr_t IntPtr = 0;
124615d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
124715d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1248861021f9SRui Ueyama }
1249861021f9SRui Ueyama 
125015d99359SRui Ueyama static imported_symbol_iterator
125115d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1252861021f9SRui Ueyama   uintptr_t IntPtr = 0;
125315d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1254861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1255861021f9SRui Ueyama   int Index = 0;
125615d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1257861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1258861021f9SRui Ueyama     while (*Entry++)
1259861021f9SRui Ueyama       ++Index;
1260861021f9SRui Ueyama   } else {
1261861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1262861021f9SRui Ueyama     while (*Entry++)
1263861021f9SRui Ueyama       ++Index;
1264861021f9SRui Ueyama   }
126515d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
126615d99359SRui Ueyama }
126715d99359SRui Ueyama 
126815d99359SRui Ueyama imported_symbol_iterator
126915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
127060049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
127115d99359SRui Ueyama                              OwningObject);
127215d99359SRui Ueyama }
127315d99359SRui Ueyama 
127415d99359SRui Ueyama imported_symbol_iterator
127515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
127660049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
127715d99359SRui Ueyama                            OwningObject);
1278861021f9SRui Ueyama }
1279861021f9SRui Ueyama 
1280979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1281979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1282979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1283979fb40bSRui Ueyama }
1284979fb40bSRui Ueyama 
128560049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
128660049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
128760049526SDavid Majnemer                              OwningObject);
128860049526SDavid Majnemer }
128960049526SDavid Majnemer 
129060049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
129160049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
129260049526SDavid Majnemer                            OwningObject);
129360049526SDavid Majnemer }
129460049526SDavid Majnemer 
129560049526SDavid Majnemer iterator_range<imported_symbol_iterator>
129660049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
129760049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
129860049526SDavid Majnemer }
129960049526SDavid Majnemer 
1300db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1301c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1302db4ed0bdSRafael Espindola   if (std::error_code EC =
13031e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1304a045b73aSRui Ueyama     return EC;
1305a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13067d099195SRui Ueyama   return std::error_code();
1307c2bed429SRui Ueyama }
1308c2bed429SRui Ueyama 
13091e152d5eSRui Ueyama std::error_code
13101e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13111e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13127d099195SRui Ueyama   return std::error_code();
13131e152d5eSRui Ueyama }
13141e152d5eSRui Ueyama 
13151e152d5eSRui Ueyama std::error_code
13161e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13171e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13187d099195SRui Ueyama   return std::error_code();
13191e152d5eSRui Ueyama }
13201e152d5eSRui Ueyama 
132115d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
132215d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
132315d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
132415d99359SRui Ueyama }
132515d99359SRui Ueyama 
132615d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
132715d99359SRui Ueyama   ++Index;
132815d99359SRui Ueyama }
132915d99359SRui Ueyama 
133015d99359SRui Ueyama imported_symbol_iterator
133115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
133215d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
133315d99359SRui Ueyama                              OwningObject);
133415d99359SRui Ueyama }
133515d99359SRui Ueyama 
133615d99359SRui Ueyama imported_symbol_iterator
133715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
133815d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
133915d99359SRui Ueyama                            OwningObject);
134015d99359SRui Ueyama }
134115d99359SRui Ueyama 
1342979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1343979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1344979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1345979fb40bSRui Ueyama }
1346979fb40bSRui Ueyama 
134715d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
134815d99359SRui Ueyama   uintptr_t IntPtr = 0;
134915d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
135015d99359SRui Ueyama     return EC;
135115d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13527d099195SRui Ueyama   return std::error_code();
135315d99359SRui Ueyama }
135415d99359SRui Ueyama 
13551af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
13561af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
13571af08658SRui Ueyama   Result = Table;
13587d099195SRui Ueyama   return std::error_code();
13591af08658SRui Ueyama }
13601af08658SRui Ueyama 
1361ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1362ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1363ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1364ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1365ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1366ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1367ffa4cebeSRui Ueyama     return EC;
1368ffa4cebeSRui Ueyama   if (OwningObject->is64())
13695dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1370ffa4cebeSRui Ueyama   else
13715dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
13727d099195SRui Ueyama   return std::error_code();
1373ffa4cebeSRui Ueyama }
1374ffa4cebeSRui Ueyama 
1375ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1376ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1377ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1378ad882ba8SRui Ueyama }
1379ad882ba8SRui Ueyama 
13805e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
13815e812afaSRafael Espindola   ++Index;
1382ad882ba8SRui Ueyama }
1383ad882ba8SRui Ueyama 
1384da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1385da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1386db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1387da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1388db4ed0bdSRafael Espindola   if (std::error_code EC =
1389db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1390da49d0d4SRui Ueyama     return EC;
1391da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13927d099195SRui Ueyama   return std::error_code();
1393da49d0d4SRui Ueyama }
1394da49d0d4SRui Ueyama 
1395e5df6095SRui Ueyama // Returns the starting ordinal number.
1396db4ed0bdSRafael Espindola std::error_code
1397db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1398e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
13997d099195SRui Ueyama   return std::error_code();
1400e5df6095SRui Ueyama }
1401e5df6095SRui Ueyama 
1402ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1403db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1404ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14057d099195SRui Ueyama   return std::error_code();
1406ad882ba8SRui Ueyama }
1407ad882ba8SRui Ueyama 
1408ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1409db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1410ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1411db4ed0bdSRafael Espindola   if (std::error_code EC =
1412db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1413ad882ba8SRui Ueyama     return EC;
141424fc2d64SRui Ueyama   const export_address_table_entry *entry =
141524fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1416ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14177d099195SRui Ueyama   return std::error_code();
1418ad882ba8SRui Ueyama }
1419ad882ba8SRui Ueyama 
1420ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1421ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1422db4ed0bdSRafael Espindola std::error_code
1423db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1424ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1425db4ed0bdSRafael Espindola   if (std::error_code EC =
1426db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1427ad882ba8SRui Ueyama     return EC;
1428ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1429ad882ba8SRui Ueyama 
1430ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1431ad882ba8SRui Ueyama   int Offset = 0;
1432ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1433ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1434ad882ba8SRui Ueyama     if (*I != Index)
1435ad882ba8SRui Ueyama       continue;
1436db4ed0bdSRafael Espindola     if (std::error_code EC =
1437db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1438ad882ba8SRui Ueyama       return EC;
1439ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1440db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1441ad882ba8SRui Ueyama       return EC;
1442ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14437d099195SRui Ueyama     return std::error_code();
1444ad882ba8SRui Ueyama   }
1445ad882ba8SRui Ueyama   Result = "";
14467d099195SRui Ueyama   return std::error_code();
1447ad882ba8SRui Ueyama }
1448ad882ba8SRui Ueyama 
14496161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
14506161b38dSRui Ueyama   const data_directory *DataEntry;
14516161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
14526161b38dSRui Ueyama     return EC;
14536161b38dSRui Ueyama   uint32_t RVA;
14546161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14556161b38dSRui Ueyama     return EC;
14566161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
14576161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
14586161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
14596161b38dSRui Ueyama   return std::error_code();
14606161b38dSRui Ueyama }
14616161b38dSRui Ueyama 
14626161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
14636161b38dSRui Ueyama   uint32_t RVA;
14646161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
14656161b38dSRui Ueyama     return EC;
14666161b38dSRui Ueyama   uintptr_t IntPtr = 0;
14676161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
14686161b38dSRui Ueyama     return EC;
14696161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14706161b38dSRui Ueyama   return std::error_code();
14716161b38dSRui Ueyama }
14726161b38dSRui Ueyama 
1473861021f9SRui Ueyama bool ImportedSymbolRef::
1474861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1475861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1476861021f9SRui Ueyama       && Index == Other.Index;
1477861021f9SRui Ueyama }
1478861021f9SRui Ueyama 
1479861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1480861021f9SRui Ueyama   ++Index;
1481861021f9SRui Ueyama }
1482861021f9SRui Ueyama 
1483861021f9SRui Ueyama std::error_code
1484861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1485861021f9SRui Ueyama   uint32_t RVA;
1486861021f9SRui Ueyama   if (Entry32) {
1487861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1488861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
14897d099195SRui Ueyama       return std::error_code();
1490861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1491861021f9SRui Ueyama   } else {
1492861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
14937d099195SRui Ueyama       return std::error_code();
1494861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1495861021f9SRui Ueyama   }
1496861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1497861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1498861021f9SRui Ueyama     return EC;
1499861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1500861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15017d099195SRui Ueyama   return std::error_code();
1502861021f9SRui Ueyama }
1503861021f9SRui Ueyama 
1504ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1505ad7b7e73SDavid Majnemer   if (Entry32)
1506ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1507ad7b7e73SDavid Majnemer   else
1508ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1509ad7b7e73SDavid Majnemer   return std::error_code();
1510ad7b7e73SDavid Majnemer }
1511ad7b7e73SDavid Majnemer 
1512ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1513ad7b7e73SDavid Majnemer   if (Entry32)
1514ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1515ad7b7e73SDavid Majnemer   else
1516ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1517ad7b7e73SDavid Majnemer   return std::error_code();
1518ad7b7e73SDavid Majnemer }
1519ad7b7e73SDavid Majnemer 
1520861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1521861021f9SRui Ueyama   uint32_t RVA;
1522861021f9SRui Ueyama   if (Entry32) {
1523861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1524861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15257d099195SRui Ueyama       return std::error_code();
1526861021f9SRui Ueyama     }
1527861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1528861021f9SRui Ueyama   } else {
1529861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1530861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15317d099195SRui Ueyama       return std::error_code();
1532861021f9SRui Ueyama     }
1533861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1534861021f9SRui Ueyama   }
1535861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1536861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1537861021f9SRui Ueyama     return EC;
1538861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15397d099195SRui Ueyama   return std::error_code();
1540861021f9SRui Ueyama }
1541861021f9SRui Ueyama 
1542437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>>
154348af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1544db4ed0bdSRafael Espindola   std::error_code EC;
154548af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1546692410efSRafael Espindola   if (EC)
1547692410efSRafael Espindola     return EC;
1548437b0d58SRafael Espindola   return std::move(Ret);
1549686738e2SRui Ueyama }
155074e85130SRui Ueyama 
155174e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
155274e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
155374e85130SRui Ueyama }
155474e85130SRui Ueyama 
155574e85130SRui Ueyama void BaseRelocRef::moveNext() {
155674e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
155774e85130SRui Ueyama   // size of the header itself.
155874e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1559970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
156074e85130SRui Ueyama   if (Size == Header->BlockSize) {
156174e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
156274e85130SRui Ueyama     // consists of the header followed by entries. The header contains
156374e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
156474e85130SRui Ueyama     // current block, proceed to the next block.
156574e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
156674e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
156774e85130SRui Ueyama     Index = 0;
156874e85130SRui Ueyama   } else {
156974e85130SRui Ueyama     ++Index;
157074e85130SRui Ueyama   }
157174e85130SRui Ueyama }
157274e85130SRui Ueyama 
157374e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
157474e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
157574e85130SRui Ueyama   Type = Entry[Index].getType();
15767d099195SRui Ueyama   return std::error_code();
157774e85130SRui Ueyama }
157874e85130SRui Ueyama 
157974e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
158074e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
158174e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
15827d099195SRui Ueyama   return std::error_code();
158374e85130SRui Ueyama }
1584