16bc11b14SDimitry Andric //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric //                     The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
102754fe60SDimitry Andric // This file declares the COFFObjectFile class.
112754fe60SDimitry Andric //
122754fe60SDimitry Andric //===----------------------------------------------------------------------===//
132754fe60SDimitry Andric 
14dff0c46cSDimitry Andric #include "llvm/ADT/ArrayRef.h"
156bc11b14SDimitry Andric #include "llvm/ADT/StringRef.h"
162754fe60SDimitry Andric #include "llvm/ADT/Triple.h"
173dac3a9bSDimitry Andric #include "llvm/ADT/iterator_range.h"
18db17bf38SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
196bc11b14SDimitry Andric #include "llvm/Object/Binary.h"
206bc11b14SDimitry Andric #include "llvm/Object/COFF.h"
216bc11b14SDimitry Andric #include "llvm/Object/Error.h"
226bc11b14SDimitry Andric #include "llvm/Object/ObjectFile.h"
230f5676f4SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
246bc11b14SDimitry Andric #include "llvm/Support/Endian.h"
256bc11b14SDimitry Andric #include "llvm/Support/Error.h"
266bc11b14SDimitry Andric #include "llvm/Support/ErrorHandling.h"
276bc11b14SDimitry Andric #include "llvm/Support/MathExtras.h"
286bc11b14SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
296bc11b14SDimitry Andric #include <algorithm>
306bc11b14SDimitry Andric #include <cassert>
316bc11b14SDimitry Andric #include <cstddef>
326bc11b14SDimitry Andric #include <cstdint>
336bc11b14SDimitry Andric #include <cstring>
3491bc56edSDimitry Andric #include <limits>
356bc11b14SDimitry Andric #include <memory>
366bc11b14SDimitry Andric #include <system_error>
372754fe60SDimitry Andric 
382754fe60SDimitry Andric using namespace llvm;
392754fe60SDimitry Andric using namespace object;
402754fe60SDimitry Andric 
412754fe60SDimitry Andric using support::ulittle16_t;
422754fe60SDimitry Andric using support::ulittle32_t;
4339d628a0SDimitry Andric using support::ulittle64_t;
442754fe60SDimitry Andric using support::little16_t;
452754fe60SDimitry Andric 
4617a519f9SDimitry Andric // Returns false if size is greater than the buffer size. And sets ec.
checkSize(MemoryBufferRef M,std::error_code & EC,uint64_t Size)4739d628a0SDimitry Andric static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
4891bc56edSDimitry Andric   if (M.getBufferSize() < Size) {
4991bc56edSDimitry Andric     EC = object_error::unexpected_eof;
5017a519f9SDimitry Andric     return false;
5117a519f9SDimitry Andric   }
5217a519f9SDimitry Andric   return true;
532754fe60SDimitry Andric }
542754fe60SDimitry Andric 
55f785676fSDimitry Andric // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
56f785676fSDimitry Andric // Returns unexpected_eof if error.
57f785676fSDimitry Andric template <typename T>
getObject(const T * & Obj,MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))5839d628a0SDimitry Andric static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
5939d628a0SDimitry Andric                                  const void *Ptr,
6039d628a0SDimitry Andric                                  const uint64_t Size = sizeof(T)) {
61f785676fSDimitry Andric   uintptr_t Addr = uintptr_t(Ptr);
622cab237bSDimitry Andric   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
6339d628a0SDimitry Andric     return EC;
64f785676fSDimitry Andric   Obj = reinterpret_cast<const T *>(Addr);
6597bc6c73SDimitry Andric   return std::error_code();
6617a519f9SDimitry Andric }
6791bc56edSDimitry Andric 
6891bc56edSDimitry Andric // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
6991bc56edSDimitry Andric // prefixed slashes.
decodeBase64StringEntry(StringRef Str,uint32_t & Result)7091bc56edSDimitry Andric static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
7191bc56edSDimitry Andric   assert(Str.size() <= 6 && "String too long, possible overflow.");
7291bc56edSDimitry Andric   if (Str.size() > 6)
7391bc56edSDimitry Andric     return true;
7491bc56edSDimitry Andric 
7591bc56edSDimitry Andric   uint64_t Value = 0;
7691bc56edSDimitry Andric   while (!Str.empty()) {
7791bc56edSDimitry Andric     unsigned CharVal;
7891bc56edSDimitry Andric     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
7991bc56edSDimitry Andric       CharVal = Str[0] - 'A';
8091bc56edSDimitry Andric     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
8191bc56edSDimitry Andric       CharVal = Str[0] - 'a' + 26;
8291bc56edSDimitry Andric     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
8391bc56edSDimitry Andric       CharVal = Str[0] - '0' + 52;
8491bc56edSDimitry Andric     else if (Str[0] == '+') // 62
8591bc56edSDimitry Andric       CharVal = 62;
8691bc56edSDimitry Andric     else if (Str[0] == '/') // 63
8791bc56edSDimitry Andric       CharVal = 63;
8891bc56edSDimitry Andric     else
8991bc56edSDimitry Andric       return true;
9091bc56edSDimitry Andric 
9191bc56edSDimitry Andric     Value = (Value * 64) + CharVal;
9291bc56edSDimitry Andric     Str = Str.substr(1);
932754fe60SDimitry Andric   }
942754fe60SDimitry Andric 
9591bc56edSDimitry Andric   if (Value > std::numeric_limits<uint32_t>::max())
9691bc56edSDimitry Andric     return true;
9791bc56edSDimitry Andric 
9891bc56edSDimitry Andric   Result = static_cast<uint32_t>(Value);
9991bc56edSDimitry Andric   return false;
10091bc56edSDimitry Andric }
10191bc56edSDimitry Andric 
10239d628a0SDimitry Andric template <typename coff_symbol_type>
toSymb(DataRefImpl Ref) const10339d628a0SDimitry Andric const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10439d628a0SDimitry Andric   const coff_symbol_type *Addr =
10539d628a0SDimitry Andric       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1062754fe60SDimitry Andric 
10739d628a0SDimitry Andric   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
10817a519f9SDimitry Andric #ifndef NDEBUG
10917a519f9SDimitry Andric   // Verify that the symbol points to a valid entry in the symbol table.
11091bc56edSDimitry Andric   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
11117a519f9SDimitry Andric 
11239d628a0SDimitry Andric   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11339d628a0SDimitry Andric          "Symbol did not point to the beginning of a symbol");
11417a519f9SDimitry Andric #endif
11517a519f9SDimitry Andric 
11691bc56edSDimitry Andric   return Addr;
1172754fe60SDimitry Andric }
1182754fe60SDimitry Andric 
toSec(DataRefImpl Ref) const11991bc56edSDimitry Andric const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
12091bc56edSDimitry Andric   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1212754fe60SDimitry Andric 
12217a519f9SDimitry Andric #ifndef NDEBUG
12317a519f9SDimitry Andric   // Verify that the section points to a valid entry in the section table.
12439d628a0SDimitry Andric   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
12517a519f9SDimitry Andric     report_fatal_error("Section was outside of section table.");
1262754fe60SDimitry Andric 
12791bc56edSDimitry Andric   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
12891bc56edSDimitry Andric   assert(Offset % sizeof(coff_section) == 0 &&
12917a519f9SDimitry Andric          "Section did not point to the beginning of a section");
13017a519f9SDimitry Andric #endif
1312754fe60SDimitry Andric 
13291bc56edSDimitry Andric   return Addr;
13317a519f9SDimitry Andric }
1342754fe60SDimitry Andric 
moveSymbolNext(DataRefImpl & Ref) const13591bc56edSDimitry Andric void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
13639d628a0SDimitry Andric   auto End = reinterpret_cast<uintptr_t>(StringTable);
13739d628a0SDimitry Andric   if (SymbolTable16) {
13839d628a0SDimitry Andric     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
13991bc56edSDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
14039d628a0SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14139d628a0SDimitry Andric   } else if (SymbolTable32) {
14239d628a0SDimitry Andric     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14339d628a0SDimitry Andric     Symb += 1 + Symb->NumberOfAuxSymbols;
14439d628a0SDimitry Andric     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14539d628a0SDimitry Andric   } else {
14639d628a0SDimitry Andric     llvm_unreachable("no symbol table pointer!");
14739d628a0SDimitry Andric   }
1482754fe60SDimitry Andric }
1492754fe60SDimitry Andric 
getSymbolName(DataRefImpl Ref) const1503ca95b02SDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15139d628a0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1523dac3a9bSDimitry Andric   StringRef Result;
1530f5676f4SDimitry Andric   if (std::error_code EC = getSymbolName(Symb, Result))
1543ca95b02SDimitry Andric     return errorCodeToError(EC);
1553dac3a9bSDimitry Andric   return Result;
1563dac3a9bSDimitry Andric }
1573dac3a9bSDimitry Andric 
getSymbolValueImpl(DataRefImpl Ref) const158875ed548SDimitry Andric uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
159875ed548SDimitry Andric   return getCOFFSymbol(Ref).getValue();
1602754fe60SDimitry Andric }
1612754fe60SDimitry Andric 
getSymbolAlignment(DataRefImpl Ref) const162d88c1a5aSDimitry Andric uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
163d88c1a5aSDimitry Andric   // MSVC/link.exe seems to align symbols to the next-power-of-2
164d88c1a5aSDimitry Andric   // up to 32 bytes.
165d88c1a5aSDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
166d88c1a5aSDimitry Andric   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
167d88c1a5aSDimitry Andric }
168d88c1a5aSDimitry Andric 
getSymbolAddress(DataRefImpl Ref) const1693ca95b02SDimitry Andric Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
170875ed548SDimitry Andric   uint64_t Result = getSymbolValue(Ref);
17139d628a0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
17239d628a0SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
1733dac3a9bSDimitry Andric 
1743dac3a9bSDimitry Andric   if (Symb.isAnyUndefined() || Symb.isCommon() ||
1753dac3a9bSDimitry Andric       COFF::isReservedSectionNumber(SectionNumber))
176875ed548SDimitry Andric     return Result;
1773dac3a9bSDimitry Andric 
17891bc56edSDimitry Andric   const coff_section *Section = nullptr;
17939d628a0SDimitry Andric   if (std::error_code EC = getSection(SectionNumber, Section))
1803ca95b02SDimitry Andric     return errorCodeToError(EC);
1813dac3a9bSDimitry Andric   Result += Section->VirtualAddress;
1827d523365SDimitry Andric 
1837d523365SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
1847d523365SDimitry Andric   // return virtual addresses.
1857d523365SDimitry Andric   Result += getImageBase();
1867d523365SDimitry Andric 
187875ed548SDimitry Andric   return Result;
18839d628a0SDimitry Andric }
18939d628a0SDimitry Andric 
getSymbolType(DataRefImpl Ref) const1903ca95b02SDimitry Andric Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
19139d628a0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
19239d628a0SDimitry Andric   int32_t SectionNumber = Symb.getSectionNumber();
19339d628a0SDimitry Andric 
1947d523365SDimitry Andric   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
1957d523365SDimitry Andric     return SymbolRef::ST_Function;
1963dac3a9bSDimitry Andric   if (Symb.isAnyUndefined())
1973dac3a9bSDimitry Andric     return SymbolRef::ST_Unknown;
1983dac3a9bSDimitry Andric   if (Symb.isCommon())
1993dac3a9bSDimitry Andric     return SymbolRef::ST_Data;
2003dac3a9bSDimitry Andric   if (Symb.isFileRecord())
2013dac3a9bSDimitry Andric     return SymbolRef::ST_File;
2023dac3a9bSDimitry Andric 
203ff0cc061SDimitry Andric   // TODO: perhaps we need a new symbol type ST_Section.
2043dac3a9bSDimitry Andric   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2053dac3a9bSDimitry Andric     return SymbolRef::ST_Debug;
2063dac3a9bSDimitry Andric 
2073dac3a9bSDimitry Andric   if (!COFF::isReservedSectionNumber(SectionNumber))
2083dac3a9bSDimitry Andric     return SymbolRef::ST_Data;
2093dac3a9bSDimitry Andric 
2103dac3a9bSDimitry Andric   return SymbolRef::ST_Other;
2116122f3e6SDimitry Andric }
2126122f3e6SDimitry Andric 
getSymbolFlags(DataRefImpl Ref) const21391bc56edSDimitry Andric uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21439d628a0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21591bc56edSDimitry Andric   uint32_t Result = SymbolRef::SF_None;
216dff0c46cSDimitry Andric 
21739d628a0SDimitry Andric   if (Symb.isExternal() || Symb.isWeakExternal())
218dff0c46cSDimitry Andric     Result |= SymbolRef::SF_Global;
219dff0c46cSDimitry Andric 
2204ba319b5SDimitry Andric   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
221dff0c46cSDimitry Andric     Result |= SymbolRef::SF_Weak;
2224ba319b5SDimitry Andric     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
2234ba319b5SDimitry Andric       Result |= SymbolRef::SF_Undefined;
224b40b48b8SDimitry Andric   }
225dff0c46cSDimitry Andric 
22639d628a0SDimitry Andric   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
227dff0c46cSDimitry Andric     Result |= SymbolRef::SF_Absolute;
228dff0c46cSDimitry Andric 
22939d628a0SDimitry Andric   if (Symb.isFileRecord())
23039d628a0SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
23139d628a0SDimitry Andric 
23239d628a0SDimitry Andric   if (Symb.isSectionDefinition())
23339d628a0SDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
23439d628a0SDimitry Andric 
23539d628a0SDimitry Andric   if (Symb.isCommon())
23639d628a0SDimitry Andric     Result |= SymbolRef::SF_Common;
23739d628a0SDimitry Andric 
2384ba319b5SDimitry Andric   if (Symb.isUndefined())
23939d628a0SDimitry Andric     Result |= SymbolRef::SF_Undefined;
24039d628a0SDimitry Andric 
24191bc56edSDimitry Andric   return Result;
2426122f3e6SDimitry Andric }
2436122f3e6SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Ref) const2443dac3a9bSDimitry Andric uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
24539d628a0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
24697bc6c73SDimitry Andric   return Symb.getValue();
24739d628a0SDimitry Andric }
2482754fe60SDimitry Andric 
2493ca95b02SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Ref) const2507d523365SDimitry Andric COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
25139d628a0SDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2527d523365SDimitry Andric   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2537d523365SDimitry Andric     return section_end();
25491bc56edSDimitry Andric   const coff_section *Sec = nullptr;
25539d628a0SDimitry Andric   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2563ca95b02SDimitry Andric     return errorCodeToError(EC);
2577d523365SDimitry Andric   DataRefImpl Ret;
2587d523365SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2597d523365SDimitry Andric   return section_iterator(SectionRef(Ret, this));
2602754fe60SDimitry Andric }
2612754fe60SDimitry Andric 
getSymbolSectionID(SymbolRef Sym) const2623dac3a9bSDimitry Andric unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2633dac3a9bSDimitry Andric   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2643dac3a9bSDimitry Andric   return Symb.getSectionNumber();
2653dac3a9bSDimitry Andric }
2663dac3a9bSDimitry Andric 
moveSectionNext(DataRefImpl & Ref) const26791bc56edSDimitry Andric void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
26891bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
26991bc56edSDimitry Andric   Sec += 1;
27091bc56edSDimitry Andric   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2713861d79fSDimitry Andric }
2723861d79fSDimitry Andric 
getSectionName(DataRefImpl Ref,StringRef & Result) const27391bc56edSDimitry Andric std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
27417a519f9SDimitry Andric                                                StringRef &Result) const {
27591bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
27691bc56edSDimitry Andric   return getSectionName(Sec, Result);
2772754fe60SDimitry Andric }
2782754fe60SDimitry Andric 
getSectionAddress(DataRefImpl Ref) const27939d628a0SDimitry Andric uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
28091bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
2817d523365SDimitry Andric   uint64_t Result = Sec->VirtualAddress;
2827d523365SDimitry Andric 
2837d523365SDimitry Andric   // The section VirtualAddress does not include ImageBase, and we want to
2847d523365SDimitry Andric   // return virtual addresses.
2857d523365SDimitry Andric   Result += getImageBase();
2867d523365SDimitry Andric   return Result;
2872754fe60SDimitry Andric }
2882754fe60SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const289302affcbSDimitry Andric uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
290302affcbSDimitry Andric   return toSec(Sec) - SectionTable;
291302affcbSDimitry Andric }
292302affcbSDimitry Andric 
getSectionSize(DataRefImpl Ref) const29339d628a0SDimitry Andric uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
29439d628a0SDimitry Andric   return getSectionSize(toSec(Ref));
2952754fe60SDimitry Andric }
2962754fe60SDimitry Andric 
getSectionContents(DataRefImpl Ref,StringRef & Result) const29791bc56edSDimitry Andric std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
29817a519f9SDimitry Andric                                                    StringRef &Result) const {
29991bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
300dff0c46cSDimitry Andric   ArrayRef<uint8_t> Res;
30191bc56edSDimitry Andric   std::error_code EC = getSectionContents(Sec, Res);
302dff0c46cSDimitry Andric   Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
303dff0c46cSDimitry Andric   return EC;
3042754fe60SDimitry Andric }
3052754fe60SDimitry Andric 
getSectionAlignment(DataRefImpl Ref) const30639d628a0SDimitry Andric uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
30791bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
3083ca95b02SDimitry Andric   return Sec->getAlignment();
3093ca95b02SDimitry Andric }
3103ca95b02SDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const3113ca95b02SDimitry Andric bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
3123ca95b02SDimitry Andric   return false;
3136122f3e6SDimitry Andric }
3146122f3e6SDimitry Andric 
isSectionText(DataRefImpl Ref) const31539d628a0SDimitry Andric bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
31691bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
31739d628a0SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3182754fe60SDimitry Andric }
3192754fe60SDimitry Andric 
isSectionData(DataRefImpl Ref) const32039d628a0SDimitry Andric bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
32191bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
32239d628a0SDimitry Andric   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
3236122f3e6SDimitry Andric }
3246122f3e6SDimitry Andric 
isSectionBSS(DataRefImpl Ref) const32539d628a0SDimitry Andric bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
32691bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
327ff0cc061SDimitry Andric   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
328ff0cc061SDimitry Andric                             COFF::IMAGE_SCN_MEM_READ |
329ff0cc061SDimitry Andric                             COFF::IMAGE_SCN_MEM_WRITE;
330ff0cc061SDimitry Andric   return (Sec->Characteristics & BssFlags) == BssFlags;
3316122f3e6SDimitry Andric }
3326122f3e6SDimitry Andric 
getSectionID(SectionRef Sec) const3333dac3a9bSDimitry Andric unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3343dac3a9bSDimitry Andric   uintptr_t Offset =
3353dac3a9bSDimitry Andric       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3363dac3a9bSDimitry Andric   assert((Offset % sizeof(coff_section)) == 0);
3373dac3a9bSDimitry Andric   return (Offset / sizeof(coff_section)) + 1;
3383dac3a9bSDimitry Andric }
3393dac3a9bSDimitry Andric 
isSectionVirtual(DataRefImpl Ref) const34039d628a0SDimitry Andric bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
34191bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
342ff0cc061SDimitry Andric   // In COFF, a virtual section won't have any in-file
343ff0cc061SDimitry Andric   // content, so the file pointer to the content will be zero.
344ff0cc061SDimitry Andric   return Sec->PointerToRawData == 0;
345dff0c46cSDimitry Andric }
346dff0c46cSDimitry Andric 
getNumberOfRelocations(const coff_section * Sec,MemoryBufferRef M,const uint8_t * base)34791bc56edSDimitry Andric static uint32_t getNumberOfRelocations(const coff_section *Sec,
34839d628a0SDimitry Andric                                        MemoryBufferRef M, const uint8_t *base) {
34991bc56edSDimitry Andric   // The field for the number of relocations in COFF section table is only
35091bc56edSDimitry Andric   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
35191bc56edSDimitry Andric   // NumberOfRelocations field, and the actual relocation count is stored in the
35291bc56edSDimitry Andric   // VirtualAddress field in the first relocation entry.
35391bc56edSDimitry Andric   if (Sec->hasExtendedRelocations()) {
35439d628a0SDimitry Andric     const coff_relocation *FirstReloc;
35539d628a0SDimitry Andric     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
35639d628a0SDimitry Andric         base + Sec->PointerToRelocations)))
35739d628a0SDimitry Andric       return 0;
35839d628a0SDimitry Andric     // -1 to exclude this first relocation entry.
35939d628a0SDimitry Andric     return FirstReloc->VirtualAddress - 1;
36091bc56edSDimitry Andric   }
36191bc56edSDimitry Andric   return Sec->NumberOfRelocations;
36291bc56edSDimitry Andric }
3636122f3e6SDimitry Andric 
36439d628a0SDimitry Andric static const coff_relocation *
getFirstReloc(const coff_section * Sec,MemoryBufferRef M,const uint8_t * Base)36539d628a0SDimitry Andric getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36639d628a0SDimitry Andric   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36739d628a0SDimitry Andric   if (!NumRelocs)
36839d628a0SDimitry Andric     return nullptr;
36939d628a0SDimitry Andric   auto begin = reinterpret_cast<const coff_relocation *>(
37039d628a0SDimitry Andric       Base + Sec->PointerToRelocations);
37139d628a0SDimitry Andric   if (Sec->hasExtendedRelocations()) {
37239d628a0SDimitry Andric     // Skip the first relocation entry repurposed to store the number of
37339d628a0SDimitry Andric     // relocations.
37439d628a0SDimitry Andric     begin++;
37539d628a0SDimitry Andric   }
3762cab237bSDimitry Andric   if (Binary::checkOffset(M, uintptr_t(begin),
3772cab237bSDimitry Andric                           sizeof(coff_relocation) * NumRelocs))
37839d628a0SDimitry Andric     return nullptr;
37939d628a0SDimitry Andric   return begin;
38039d628a0SDimitry Andric }
38139d628a0SDimitry Andric 
section_rel_begin(DataRefImpl Ref) const38239d628a0SDimitry Andric relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38339d628a0SDimitry Andric   const coff_section *Sec = toSec(Ref);
38439d628a0SDimitry Andric   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
385875ed548SDimitry Andric   if (begin && Sec->VirtualAddress != 0)
386875ed548SDimitry Andric     report_fatal_error("Sections with relocations should have an address of 0");
38739d628a0SDimitry Andric   DataRefImpl Ret;
38839d628a0SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(begin);
38939d628a0SDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
39039d628a0SDimitry Andric }
39139d628a0SDimitry Andric 
section_rel_end(DataRefImpl Ref) const39291bc56edSDimitry Andric relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
39391bc56edSDimitry Andric   const coff_section *Sec = toSec(Ref);
39439d628a0SDimitry Andric   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39539d628a0SDimitry Andric   if (I)
39639d628a0SDimitry Andric     I += getNumberOfRelocations(Sec, Data, base());
39791bc56edSDimitry Andric   DataRefImpl Ret;
39839d628a0SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(I);
39991bc56edSDimitry Andric   return relocation_iterator(RelocationRef(Ret, this));
4006122f3e6SDimitry Andric }
4016122f3e6SDimitry Andric 
402f785676fSDimitry Andric // Initialize the pointer to the symbol table.
initSymbolTablePtr()40391bc56edSDimitry Andric std::error_code COFFObjectFile::initSymbolTablePtr() {
40439d628a0SDimitry Andric   if (COFFHeader)
40591bc56edSDimitry Andric     if (std::error_code EC = getObject(
40639d628a0SDimitry Andric             SymbolTable16, Data, base() + getPointerToSymbolTable(),
40739d628a0SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40839d628a0SDimitry Andric       return EC;
40939d628a0SDimitry Andric 
41039d628a0SDimitry Andric   if (COFFBigObjHeader)
41139d628a0SDimitry Andric     if (std::error_code EC = getObject(
41239d628a0SDimitry Andric             SymbolTable32, Data, base() + getPointerToSymbolTable(),
41339d628a0SDimitry Andric             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
41491bc56edSDimitry Andric       return EC;
415f785676fSDimitry Andric 
416f785676fSDimitry Andric   // Find string table. The first four byte of the string table contains the
417f785676fSDimitry Andric   // total size of the string table, including the size field itself. If the
418f785676fSDimitry Andric   // string table is empty, the value of the first four byte would be 4.
41939d628a0SDimitry Andric   uint32_t StringTableOffset = getPointerToSymbolTable() +
42039d628a0SDimitry Andric                                getNumberOfSymbols() * getSymbolTableEntrySize();
42139d628a0SDimitry Andric   const uint8_t *StringTableAddr = base() + StringTableOffset;
422f785676fSDimitry Andric   const ulittle32_t *StringTableSizePtr;
42339d628a0SDimitry Andric   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
42491bc56edSDimitry Andric     return EC;
425f785676fSDimitry Andric   StringTableSize = *StringTableSizePtr;
42691bc56edSDimitry Andric   if (std::error_code EC =
42739d628a0SDimitry Andric           getObject(StringTable, Data, StringTableAddr, StringTableSize))
42891bc56edSDimitry Andric     return EC;
42991bc56edSDimitry Andric 
43091bc56edSDimitry Andric   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
43191bc56edSDimitry Andric   // tools like cvtres write a size of 0 for an empty table instead of 4.
43291bc56edSDimitry Andric   if (StringTableSize < 4)
43391bc56edSDimitry Andric       StringTableSize = 4;
434f785676fSDimitry Andric 
435f785676fSDimitry Andric   // Check that the string table is null terminated if has any in it.
43691bc56edSDimitry Andric   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
437f785676fSDimitry Andric     return  object_error::parse_failed;
43897bc6c73SDimitry Andric   return std::error_code();
439f785676fSDimitry Andric }
440f785676fSDimitry Andric 
getImageBase() const4417d523365SDimitry Andric uint64_t COFFObjectFile::getImageBase() const {
4427d523365SDimitry Andric   if (PE32Header)
4437d523365SDimitry Andric     return PE32Header->ImageBase;
4447d523365SDimitry Andric   else if (PE32PlusHeader)
4457d523365SDimitry Andric     return PE32PlusHeader->ImageBase;
4467d523365SDimitry Andric   // This actually comes up in practice.
4477d523365SDimitry Andric   return 0;
4487d523365SDimitry Andric }
4497d523365SDimitry Andric 
45091bc56edSDimitry Andric // Returns the file offset for the given VA.
getVaPtr(uint64_t Addr,uintptr_t & Res) const45191bc56edSDimitry Andric std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
4527d523365SDimitry Andric   uint64_t ImageBase = getImageBase();
45391bc56edSDimitry Andric   uint64_t Rva = Addr - ImageBase;
45491bc56edSDimitry Andric   assert(Rva <= UINT32_MAX);
45591bc56edSDimitry Andric   return getRvaPtr((uint32_t)Rva, Res);
45691bc56edSDimitry Andric }
45791bc56edSDimitry Andric 
458f785676fSDimitry Andric // Returns the file offset for the given RVA.
getRvaPtr(uint32_t Addr,uintptr_t & Res) const45991bc56edSDimitry Andric std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46091bc56edSDimitry Andric   for (const SectionRef &S : sections()) {
46191bc56edSDimitry Andric     const coff_section *Section = getCOFFSection(S);
462f785676fSDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
463f785676fSDimitry Andric     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
46491bc56edSDimitry Andric     if (SectionStart <= Addr && Addr < SectionEnd) {
46591bc56edSDimitry Andric       uint32_t Offset = Addr - SectionStart;
466f785676fSDimitry Andric       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
46797bc6c73SDimitry Andric       return std::error_code();
468f785676fSDimitry Andric     }
469f785676fSDimitry Andric   }
470f785676fSDimitry Andric   return object_error::parse_failed;
471f785676fSDimitry Andric }
472f785676fSDimitry Andric 
4733ca95b02SDimitry Andric std::error_code
getRvaAndSizeAsBytes(uint32_t RVA,uint32_t Size,ArrayRef<uint8_t> & Contents) const4743ca95b02SDimitry Andric COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4753ca95b02SDimitry Andric                                      ArrayRef<uint8_t> &Contents) const {
4763ca95b02SDimitry Andric   for (const SectionRef &S : sections()) {
4773ca95b02SDimitry Andric     const coff_section *Section = getCOFFSection(S);
4783ca95b02SDimitry Andric     uint32_t SectionStart = Section->VirtualAddress;
4793ca95b02SDimitry Andric     // Check if this RVA is within the section bounds. Be careful about integer
4803ca95b02SDimitry Andric     // overflow.
4813ca95b02SDimitry Andric     uint32_t OffsetIntoSection = RVA - SectionStart;
4823ca95b02SDimitry Andric     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4833ca95b02SDimitry Andric         Size <= Section->VirtualSize - OffsetIntoSection) {
4843ca95b02SDimitry Andric       uintptr_t Begin =
4853ca95b02SDimitry Andric           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4863ca95b02SDimitry Andric       Contents =
4873ca95b02SDimitry Andric           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4883ca95b02SDimitry Andric       return std::error_code();
4893ca95b02SDimitry Andric     }
4903ca95b02SDimitry Andric   }
4913ca95b02SDimitry Andric   return object_error::parse_failed;
4923ca95b02SDimitry Andric }
4933ca95b02SDimitry Andric 
494f785676fSDimitry Andric // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
495f785676fSDimitry Andric // table entry.
getHintName(uint32_t Rva,uint16_t & Hint,StringRef & Name) const49691bc56edSDimitry Andric std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
49791bc56edSDimitry Andric                                             StringRef &Name) const {
498f785676fSDimitry Andric   uintptr_t IntPtr = 0;
49991bc56edSDimitry Andric   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
50091bc56edSDimitry Andric     return EC;
501f785676fSDimitry Andric   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
502f785676fSDimitry Andric   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
503f785676fSDimitry Andric   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
50497bc6c73SDimitry Andric   return std::error_code();
505f785676fSDimitry Andric }
506f785676fSDimitry Andric 
507d88c1a5aSDimitry Andric std::error_code
getDebugPDBInfo(const debug_directory * DebugDir,const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const508d88c1a5aSDimitry Andric COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
509d88c1a5aSDimitry Andric                                 const codeview::DebugInfo *&PDBInfo,
5103ca95b02SDimitry Andric                                 StringRef &PDBFileName) const {
5113ca95b02SDimitry Andric   ArrayRef<uint8_t> InfoBytes;
5123ca95b02SDimitry Andric   if (std::error_code EC = getRvaAndSizeAsBytes(
5133ca95b02SDimitry Andric           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5143ca95b02SDimitry Andric     return EC;
515d88c1a5aSDimitry Andric   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5163ca95b02SDimitry Andric     return object_error::parse_failed;
517d88c1a5aSDimitry Andric   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
518d88c1a5aSDimitry Andric   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5193ca95b02SDimitry Andric   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5203ca95b02SDimitry Andric                           InfoBytes.size());
5213ca95b02SDimitry Andric   // Truncate the name at the first null byte. Ignore any padding.
5223ca95b02SDimitry Andric   PDBFileName = PDBFileName.split('\0').first;
5233ca95b02SDimitry Andric   return std::error_code();
5243ca95b02SDimitry Andric }
5253ca95b02SDimitry Andric 
526d88c1a5aSDimitry Andric std::error_code
getDebugPDBInfo(const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const527d88c1a5aSDimitry Andric COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
5283ca95b02SDimitry Andric                                 StringRef &PDBFileName) const {
5293ca95b02SDimitry Andric   for (const debug_directory &D : debug_directories())
5303ca95b02SDimitry Andric     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
5313ca95b02SDimitry Andric       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
5323ca95b02SDimitry Andric   // If we get here, there is no PDB info to return.
5333ca95b02SDimitry Andric   PDBInfo = nullptr;
5343ca95b02SDimitry Andric   PDBFileName = StringRef();
5353ca95b02SDimitry Andric   return std::error_code();
5363ca95b02SDimitry Andric }
5373ca95b02SDimitry Andric 
538f785676fSDimitry Andric // Find the import table.
initImportTablePtr()53991bc56edSDimitry Andric std::error_code COFFObjectFile::initImportTablePtr() {
540f785676fSDimitry Andric   // First, we get the RVA of the import table. If the file lacks a pointer to
541f785676fSDimitry Andric   // the import table, do nothing.
542f785676fSDimitry Andric   const data_directory *DataEntry;
543f785676fSDimitry Andric   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
54497bc6c73SDimitry Andric     return std::error_code();
545f785676fSDimitry Andric 
546f785676fSDimitry Andric   // Do nothing if the pointer to import table is NULL.
547f785676fSDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
54897bc6c73SDimitry Andric     return std::error_code();
549f785676fSDimitry Andric 
550f785676fSDimitry Andric   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
551f785676fSDimitry Andric 
552f785676fSDimitry Andric   // Find the section that contains the RVA. This is needed because the RVA is
553f785676fSDimitry Andric   // the import table's memory address which is different from its file offset.
554f785676fSDimitry Andric   uintptr_t IntPtr = 0;
55591bc56edSDimitry Andric   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
55691bc56edSDimitry Andric     return EC;
5573ca95b02SDimitry Andric   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
5583ca95b02SDimitry Andric     return EC;
559f785676fSDimitry Andric   ImportDirectory = reinterpret_cast<
560d88c1a5aSDimitry Andric       const coff_import_directory_table_entry *>(IntPtr);
56197bc6c73SDimitry Andric   return std::error_code();
562f785676fSDimitry Andric }
563f785676fSDimitry Andric 
56439d628a0SDimitry Andric // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
initDelayImportTablePtr()56539d628a0SDimitry Andric std::error_code COFFObjectFile::initDelayImportTablePtr() {
56639d628a0SDimitry Andric   const data_directory *DataEntry;
56739d628a0SDimitry Andric   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
56897bc6c73SDimitry Andric     return std::error_code();
56939d628a0SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
57097bc6c73SDimitry Andric     return std::error_code();
57139d628a0SDimitry Andric 
57239d628a0SDimitry Andric   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57339d628a0SDimitry Andric   NumberOfDelayImportDirectory = DataEntry->Size /
57439d628a0SDimitry Andric       sizeof(delay_import_directory_table_entry) - 1;
57539d628a0SDimitry Andric 
57639d628a0SDimitry Andric   uintptr_t IntPtr = 0;
57739d628a0SDimitry Andric   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57839d628a0SDimitry Andric     return EC;
57939d628a0SDimitry Andric   DelayImportDirectory = reinterpret_cast<
58039d628a0SDimitry Andric       const delay_import_directory_table_entry *>(IntPtr);
58197bc6c73SDimitry Andric   return std::error_code();
58239d628a0SDimitry Andric }
58339d628a0SDimitry Andric 
58491bc56edSDimitry Andric // Find the export table.
initExportTablePtr()58591bc56edSDimitry Andric std::error_code COFFObjectFile::initExportTablePtr() {
58691bc56edSDimitry Andric   // First, we get the RVA of the export table. If the file lacks a pointer to
58791bc56edSDimitry Andric   // the export table, do nothing.
58891bc56edSDimitry Andric   const data_directory *DataEntry;
58991bc56edSDimitry Andric   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
59097bc6c73SDimitry Andric     return std::error_code();
59191bc56edSDimitry Andric 
59291bc56edSDimitry Andric   // Do nothing if the pointer to export table is NULL.
59391bc56edSDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
59497bc6c73SDimitry Andric     return std::error_code();
59591bc56edSDimitry Andric 
59691bc56edSDimitry Andric   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
59791bc56edSDimitry Andric   uintptr_t IntPtr = 0;
59891bc56edSDimitry Andric   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
59991bc56edSDimitry Andric     return EC;
60091bc56edSDimitry Andric   ExportDirectory =
60191bc56edSDimitry Andric       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
60297bc6c73SDimitry Andric   return std::error_code();
60391bc56edSDimitry Andric }
60491bc56edSDimitry Andric 
initBaseRelocPtr()60539d628a0SDimitry Andric std::error_code COFFObjectFile::initBaseRelocPtr() {
60639d628a0SDimitry Andric   const data_directory *DataEntry;
60739d628a0SDimitry Andric   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
60897bc6c73SDimitry Andric     return std::error_code();
60939d628a0SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
61097bc6c73SDimitry Andric     return std::error_code();
61139d628a0SDimitry Andric 
61239d628a0SDimitry Andric   uintptr_t IntPtr = 0;
61339d628a0SDimitry Andric   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61439d628a0SDimitry Andric     return EC;
61539d628a0SDimitry Andric   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61639d628a0SDimitry Andric       IntPtr);
61739d628a0SDimitry Andric   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61839d628a0SDimitry Andric       IntPtr + DataEntry->Size);
619*b5893f02SDimitry Andric   // FIXME: Verify the section containing BaseRelocHeader has at least
620*b5893f02SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
62197bc6c73SDimitry Andric   return std::error_code();
62239d628a0SDimitry Andric }
62339d628a0SDimitry Andric 
initDebugDirectoryPtr()6243ca95b02SDimitry Andric std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6253ca95b02SDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
6263ca95b02SDimitry Andric   const data_directory *DataEntry;
6273ca95b02SDimitry Andric   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6283ca95b02SDimitry Andric     return std::error_code();
6293ca95b02SDimitry Andric 
6303ca95b02SDimitry Andric   // Do nothing if the RVA is NULL.
6313ca95b02SDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
6323ca95b02SDimitry Andric     return std::error_code();
6333ca95b02SDimitry Andric 
6343ca95b02SDimitry Andric   // Check that the size is a multiple of the entry size.
6353ca95b02SDimitry Andric   if (DataEntry->Size % sizeof(debug_directory) != 0)
6363ca95b02SDimitry Andric     return object_error::parse_failed;
6373ca95b02SDimitry Andric 
6383ca95b02SDimitry Andric   uintptr_t IntPtr = 0;
6393ca95b02SDimitry Andric   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6403ca95b02SDimitry Andric     return EC;
6413ca95b02SDimitry Andric   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
642*b5893f02SDimitry Andric   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
643*b5893f02SDimitry Andric       IntPtr + DataEntry->Size);
644*b5893f02SDimitry Andric   // FIXME: Verify the section containing DebugDirectoryBegin has at least
645*b5893f02SDimitry Andric   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6463ca95b02SDimitry Andric   return std::error_code();
6473ca95b02SDimitry Andric }
6483ca95b02SDimitry Andric 
initLoadConfigPtr()649edd7eaddSDimitry Andric std::error_code COFFObjectFile::initLoadConfigPtr() {
650edd7eaddSDimitry Andric   // Get the RVA of the debug directory. Do nothing if it does not exist.
651edd7eaddSDimitry Andric   const data_directory *DataEntry;
652edd7eaddSDimitry Andric   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
653edd7eaddSDimitry Andric     return std::error_code();
654edd7eaddSDimitry Andric 
655edd7eaddSDimitry Andric   // Do nothing if the RVA is NULL.
656edd7eaddSDimitry Andric   if (DataEntry->RelativeVirtualAddress == 0)
657edd7eaddSDimitry Andric     return std::error_code();
658edd7eaddSDimitry Andric   uintptr_t IntPtr = 0;
659edd7eaddSDimitry Andric   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
660edd7eaddSDimitry Andric     return EC;
661edd7eaddSDimitry Andric 
662edd7eaddSDimitry Andric   LoadConfig = (const void *)IntPtr;
663edd7eaddSDimitry Andric   return std::error_code();
664edd7eaddSDimitry Andric }
665edd7eaddSDimitry Andric 
COFFObjectFile(MemoryBufferRef Object,std::error_code & EC)66639d628a0SDimitry Andric COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
66739d628a0SDimitry Andric     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
66839d628a0SDimitry Andric       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
66939d628a0SDimitry Andric       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
67039d628a0SDimitry Andric       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
6713ca95b02SDimitry Andric       ImportDirectory(nullptr),
67239d628a0SDimitry Andric       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6733ca95b02SDimitry Andric       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6743ca95b02SDimitry Andric       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
67517a519f9SDimitry Andric   // Check that we at least have enough room for a header.
67639d628a0SDimitry Andric   if (!checkSize(Data, EC, sizeof(coff_file_header)))
67791bc56edSDimitry Andric     return;
6783b0f4066SDimitry Andric 
679f785676fSDimitry Andric   // The current location in the file where we are looking at.
680f785676fSDimitry Andric   uint64_t CurPtr = 0;
681f785676fSDimitry Andric 
682f785676fSDimitry Andric   // PE header is optional and is present only in executables. If it exists,
683f785676fSDimitry Andric   // it is placed right after COFF header.
68491bc56edSDimitry Andric   bool HasPEHeader = false;
68517a519f9SDimitry Andric 
68617a519f9SDimitry Andric   // Check if this is a PE/COFF file.
68739d628a0SDimitry Andric   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
6883b0f4066SDimitry Andric     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
6893b0f4066SDimitry Andric     // PE signature to find 'normal' COFF header.
69039d628a0SDimitry Andric     const auto *DH = reinterpret_cast<const dos_header *>(base());
69139d628a0SDimitry Andric     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69239d628a0SDimitry Andric       CurPtr = DH->AddressOfNewExeHeader;
693f785676fSDimitry Andric       // Check the PE magic bytes. ("PE\0\0")
69439d628a0SDimitry Andric       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
69591bc56edSDimitry Andric         EC = object_error::parse_failed;
69617a519f9SDimitry Andric         return;
69717a519f9SDimitry Andric       }
69839d628a0SDimitry Andric       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
69991bc56edSDimitry Andric       HasPEHeader = true;
7003b0f4066SDimitry Andric     }
70139d628a0SDimitry Andric   }
7023b0f4066SDimitry Andric 
70339d628a0SDimitry Andric   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
70417a519f9SDimitry Andric     return;
70539d628a0SDimitry Andric 
70639d628a0SDimitry Andric   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
70739d628a0SDimitry Andric   // import libraries share a common prefix but bigobj is more restrictive.
70839d628a0SDimitry Andric   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
70939d628a0SDimitry Andric       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
71039d628a0SDimitry Andric       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
71139d628a0SDimitry Andric     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71239d628a0SDimitry Andric       return;
71339d628a0SDimitry Andric 
71439d628a0SDimitry Andric     // Verify that we are dealing with bigobj.
71539d628a0SDimitry Andric     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
71639d628a0SDimitry Andric         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
71739d628a0SDimitry Andric                     sizeof(COFF::BigObjMagic)) == 0) {
71839d628a0SDimitry Andric       COFFHeader = nullptr;
71939d628a0SDimitry Andric       CurPtr += sizeof(coff_bigobj_file_header);
72039d628a0SDimitry Andric     } else {
72139d628a0SDimitry Andric       // It's not a bigobj.
72239d628a0SDimitry Andric       COFFBigObjHeader = nullptr;
72339d628a0SDimitry Andric     }
72439d628a0SDimitry Andric   }
72539d628a0SDimitry Andric   if (COFFHeader) {
72639d628a0SDimitry Andric     // The prior checkSize call may have failed.  This isn't a hard error
72739d628a0SDimitry Andric     // because we were just trying to sniff out bigobj.
72897bc6c73SDimitry Andric     EC = std::error_code();
729f785676fSDimitry Andric     CurPtr += sizeof(coff_file_header);
73017a519f9SDimitry Andric 
73139d628a0SDimitry Andric     if (COFFHeader->isImportLibrary())
73239d628a0SDimitry Andric       return;
73339d628a0SDimitry Andric   }
73439d628a0SDimitry Andric 
73591bc56edSDimitry Andric   if (HasPEHeader) {
73691bc56edSDimitry Andric     const pe32_header *Header;
73739d628a0SDimitry Andric     if ((EC = getObject(Header, Data, base() + CurPtr)))
73817a519f9SDimitry Andric       return;
73991bc56edSDimitry Andric 
74091bc56edSDimitry Andric     const uint8_t *DataDirAddr;
74191bc56edSDimitry Andric     uint64_t DataDirSize;
74239d628a0SDimitry Andric     if (Header->Magic == COFF::PE32Header::PE32) {
74391bc56edSDimitry Andric       PE32Header = Header;
74491bc56edSDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
74591bc56edSDimitry Andric       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
74639d628a0SDimitry Andric     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
74791bc56edSDimitry Andric       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
74891bc56edSDimitry Andric       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
74991bc56edSDimitry Andric       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
75091bc56edSDimitry Andric     } else {
75191bc56edSDimitry Andric       // It's neither PE32 nor PE32+.
75291bc56edSDimitry Andric       EC = object_error::parse_failed;
75317a519f9SDimitry Andric       return;
75417a519f9SDimitry Andric     }
75539d628a0SDimitry Andric     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
75691bc56edSDimitry Andric       return;
757dff0c46cSDimitry Andric   }
75817a519f9SDimitry Andric 
759d88c1a5aSDimitry Andric   if (COFFHeader)
760d88c1a5aSDimitry Andric     CurPtr += COFFHeader->SizeOfOptionalHeader;
761d88c1a5aSDimitry Andric 
76239d628a0SDimitry Andric   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
76339d628a0SDimitry Andric                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
764f785676fSDimitry Andric     return;
765f785676fSDimitry Andric 
766f785676fSDimitry Andric   // Initialize the pointer to the symbol table.
76739d628a0SDimitry Andric   if (getPointerToSymbolTable() != 0) {
768d88c1a5aSDimitry Andric     if ((EC = initSymbolTablePtr())) {
769d88c1a5aSDimitry Andric       SymbolTable16 = nullptr;
770d88c1a5aSDimitry Andric       SymbolTable32 = nullptr;
771d88c1a5aSDimitry Andric       StringTable = nullptr;
772d88c1a5aSDimitry Andric       StringTableSize = 0;
773d88c1a5aSDimitry Andric     }
77439d628a0SDimitry Andric   } else {
77539d628a0SDimitry Andric     // We had better not have any symbols if we don't have a symbol table.
77639d628a0SDimitry Andric     if (getNumberOfSymbols() != 0) {
77739d628a0SDimitry Andric       EC = object_error::parse_failed;
77839d628a0SDimitry Andric       return;
77939d628a0SDimitry Andric     }
78039d628a0SDimitry Andric   }
781f785676fSDimitry Andric 
782f785676fSDimitry Andric   // Initialize the pointer to the beginning of the import table.
78391bc56edSDimitry Andric   if ((EC = initImportTablePtr()))
784f785676fSDimitry Andric     return;
78539d628a0SDimitry Andric   if ((EC = initDelayImportTablePtr()))
78639d628a0SDimitry Andric     return;
787f785676fSDimitry Andric 
78891bc56edSDimitry Andric   // Initialize the pointer to the export table.
78991bc56edSDimitry Andric   if ((EC = initExportTablePtr()))
79091bc56edSDimitry Andric     return;
79191bc56edSDimitry Andric 
79239d628a0SDimitry Andric   // Initialize the pointer to the base relocation table.
79339d628a0SDimitry Andric   if ((EC = initBaseRelocPtr()))
79439d628a0SDimitry Andric     return;
79539d628a0SDimitry Andric 
7963ca95b02SDimitry Andric   // Initialize the pointer to the export table.
7973ca95b02SDimitry Andric   if ((EC = initDebugDirectoryPtr()))
7983ca95b02SDimitry Andric     return;
7993ca95b02SDimitry Andric 
800edd7eaddSDimitry Andric   if ((EC = initLoadConfigPtr()))
801edd7eaddSDimitry Andric     return;
802edd7eaddSDimitry Andric 
80397bc6c73SDimitry Andric   EC = std::error_code();
8042754fe60SDimitry Andric }
8052754fe60SDimitry Andric 
symbol_begin() const806d88c1a5aSDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_begin() const {
80791bc56edSDimitry Andric   DataRefImpl Ret;
80839d628a0SDimitry Andric   Ret.p = getSymbolTable();
80991bc56edSDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
8102754fe60SDimitry Andric }
8112754fe60SDimitry Andric 
symbol_end() const812d88c1a5aSDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_end() const {
8132754fe60SDimitry Andric   // The symbol table ends where the string table begins.
81491bc56edSDimitry Andric   DataRefImpl Ret;
81591bc56edSDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
81691bc56edSDimitry Andric   return basic_symbol_iterator(SymbolRef(Ret, this));
8172754fe60SDimitry Andric }
8182754fe60SDimitry Andric 
import_directory_begin() const819f785676fSDimitry Andric import_directory_iterator COFFObjectFile::import_directory_begin() const {
8203ca95b02SDimitry Andric   if (!ImportDirectory)
8213ca95b02SDimitry Andric     return import_directory_end();
822d88c1a5aSDimitry Andric   if (ImportDirectory->isNull())
8233ca95b02SDimitry Andric     return import_directory_end();
82491bc56edSDimitry Andric   return import_directory_iterator(
82591bc56edSDimitry Andric       ImportDirectoryEntryRef(ImportDirectory, 0, this));
826f785676fSDimitry Andric }
827f785676fSDimitry Andric 
import_directory_end() const828f785676fSDimitry Andric import_directory_iterator COFFObjectFile::import_directory_end() const {
82991bc56edSDimitry Andric   return import_directory_iterator(
8303ca95b02SDimitry Andric       ImportDirectoryEntryRef(nullptr, -1, this));
831f785676fSDimitry Andric }
832dff0c46cSDimitry Andric 
83339d628a0SDimitry Andric delay_import_directory_iterator
delay_import_directory_begin() const83439d628a0SDimitry Andric COFFObjectFile::delay_import_directory_begin() const {
83539d628a0SDimitry Andric   return delay_import_directory_iterator(
83639d628a0SDimitry Andric       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
83739d628a0SDimitry Andric }
83839d628a0SDimitry Andric 
83939d628a0SDimitry Andric delay_import_directory_iterator
delay_import_directory_end() const84039d628a0SDimitry Andric COFFObjectFile::delay_import_directory_end() const {
84139d628a0SDimitry Andric   return delay_import_directory_iterator(
84239d628a0SDimitry Andric       DelayImportDirectoryEntryRef(
84339d628a0SDimitry Andric           DelayImportDirectory, NumberOfDelayImportDirectory, this));
84439d628a0SDimitry Andric }
84539d628a0SDimitry Andric 
export_directory_begin() const84691bc56edSDimitry Andric export_directory_iterator COFFObjectFile::export_directory_begin() const {
84791bc56edSDimitry Andric   return export_directory_iterator(
84891bc56edSDimitry Andric       ExportDirectoryEntryRef(ExportDirectory, 0, this));
8492754fe60SDimitry Andric }
8502754fe60SDimitry Andric 
export_directory_end() const85191bc56edSDimitry Andric export_directory_iterator COFFObjectFile::export_directory_end() const {
85291bc56edSDimitry Andric   if (!ExportDirectory)
85391bc56edSDimitry Andric     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
85491bc56edSDimitry Andric   ExportDirectoryEntryRef Ref(ExportDirectory,
85591bc56edSDimitry Andric                               ExportDirectory->AddressTableEntries, this);
85691bc56edSDimitry Andric   return export_directory_iterator(Ref);
85791bc56edSDimitry Andric }
85891bc56edSDimitry Andric 
section_begin() const85991bc56edSDimitry Andric section_iterator COFFObjectFile::section_begin() const {
86091bc56edSDimitry Andric   DataRefImpl Ret;
86191bc56edSDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
86291bc56edSDimitry Andric   return section_iterator(SectionRef(Ret, this));
86391bc56edSDimitry Andric }
86491bc56edSDimitry Andric 
section_end() const86591bc56edSDimitry Andric section_iterator COFFObjectFile::section_end() const {
86691bc56edSDimitry Andric   DataRefImpl Ret;
86739d628a0SDimitry Andric   int NumSections =
86839d628a0SDimitry Andric       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
86991bc56edSDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
87091bc56edSDimitry Andric   return section_iterator(SectionRef(Ret, this));
8712754fe60SDimitry Andric }
8722754fe60SDimitry Andric 
base_reloc_begin() const87339d628a0SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
87439d628a0SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
87539d628a0SDimitry Andric }
87639d628a0SDimitry Andric 
base_reloc_end() const87739d628a0SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_end() const {
87839d628a0SDimitry Andric   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
87939d628a0SDimitry Andric }
88039d628a0SDimitry Andric 
getBytesInAddress() const8812754fe60SDimitry Andric uint8_t COFFObjectFile::getBytesInAddress() const {
882a580b014SDimitry Andric   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8832754fe60SDimitry Andric }
8842754fe60SDimitry Andric 
getFileFormatName() const8852754fe60SDimitry Andric StringRef COFFObjectFile::getFileFormatName() const {
88639d628a0SDimitry Andric   switch(getMachine()) {
8872754fe60SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
8882754fe60SDimitry Andric     return "COFF-i386";
8892754fe60SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
8902754fe60SDimitry Andric     return "COFF-x86-64";
89191bc56edSDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
89291bc56edSDimitry Andric     return "COFF-ARM";
8937d523365SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
8947d523365SDimitry Andric     return "COFF-ARM64";
8952754fe60SDimitry Andric   default:
8962754fe60SDimitry Andric     return "COFF-<unknown arch>";
8972754fe60SDimitry Andric   }
8982754fe60SDimitry Andric }
8992754fe60SDimitry Andric 
getArch() const9002cab237bSDimitry Andric Triple::ArchType COFFObjectFile::getArch() const {
90139d628a0SDimitry Andric   switch (getMachine()) {
9022754fe60SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
9032754fe60SDimitry Andric     return Triple::x86;
9042754fe60SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
9052754fe60SDimitry Andric     return Triple::x86_64;
90691bc56edSDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
90791bc56edSDimitry Andric     return Triple::thumb;
9087d523365SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
9097d523365SDimitry Andric     return Triple::aarch64;
9102754fe60SDimitry Andric   default:
9112754fe60SDimitry Andric     return Triple::UnknownArch;
9122754fe60SDimitry Andric   }
9132754fe60SDimitry Andric }
9142754fe60SDimitry Andric 
getStartAddress() const9154ba319b5SDimitry Andric Expected<uint64_t> COFFObjectFile::getStartAddress() const {
9164ba319b5SDimitry Andric   if (PE32Header)
9174ba319b5SDimitry Andric     return PE32Header->AddressOfEntryPoint;
9184ba319b5SDimitry Andric   return 0;
9194ba319b5SDimitry Andric }
9204ba319b5SDimitry Andric 
92139d628a0SDimitry Andric iterator_range<import_directory_iterator>
import_directories() const92239d628a0SDimitry Andric COFFObjectFile::import_directories() const {
92339d628a0SDimitry Andric   return make_range(import_directory_begin(), import_directory_end());
924f785676fSDimitry Andric }
925f785676fSDimitry Andric 
92639d628a0SDimitry Andric iterator_range<delay_import_directory_iterator>
delay_import_directories() const92739d628a0SDimitry Andric COFFObjectFile::delay_import_directories() const {
92839d628a0SDimitry Andric   return make_range(delay_import_directory_begin(),
92939d628a0SDimitry Andric                     delay_import_directory_end());
93039d628a0SDimitry Andric }
93139d628a0SDimitry Andric 
93239d628a0SDimitry Andric iterator_range<export_directory_iterator>
export_directories() const93339d628a0SDimitry Andric COFFObjectFile::export_directories() const {
93439d628a0SDimitry Andric   return make_range(export_directory_begin(), export_directory_end());
93539d628a0SDimitry Andric }
93639d628a0SDimitry Andric 
base_relocs() const93739d628a0SDimitry Andric iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
93839d628a0SDimitry Andric   return make_range(base_reloc_begin(), base_reloc_end());
939f785676fSDimitry Andric }
940f785676fSDimitry Andric 
941*b5893f02SDimitry Andric std::error_code
getCOFFHeader(const coff_file_header * & Res) const942*b5893f02SDimitry Andric COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
943*b5893f02SDimitry Andric   Res = COFFHeader;
944*b5893f02SDimitry Andric   return std::error_code();
945*b5893f02SDimitry Andric }
946*b5893f02SDimitry Andric 
947*b5893f02SDimitry Andric std::error_code
getCOFFBigObjHeader(const coff_bigobj_file_header * & Res) const948*b5893f02SDimitry Andric COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const {
949*b5893f02SDimitry Andric   Res = COFFBigObjHeader;
950*b5893f02SDimitry Andric   return std::error_code();
951*b5893f02SDimitry Andric }
952*b5893f02SDimitry Andric 
getPE32Header(const pe32_header * & Res) const95391bc56edSDimitry Andric std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
954f785676fSDimitry Andric   Res = PE32Header;
95597bc6c73SDimitry Andric   return std::error_code();
956f785676fSDimitry Andric }
957f785676fSDimitry Andric 
95891bc56edSDimitry Andric std::error_code
getPE32PlusHeader(const pe32plus_header * & Res) const95991bc56edSDimitry Andric COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
96091bc56edSDimitry Andric   Res = PE32PlusHeader;
96197bc6c73SDimitry Andric   return std::error_code();
962dff0c46cSDimitry Andric }
963dff0c46cSDimitry Andric 
96491bc56edSDimitry Andric std::error_code
getDataDirectory(uint32_t Index,const data_directory * & Res) const96591bc56edSDimitry Andric COFFObjectFile::getDataDirectory(uint32_t Index,
96691bc56edSDimitry Andric                                  const data_directory *&Res) const {
9674ba319b5SDimitry Andric   // Error if there's no data directory or the index is out of range.
96839d628a0SDimitry Andric   if (!DataDirectory) {
96939d628a0SDimitry Andric     Res = nullptr;
97091bc56edSDimitry Andric     return object_error::parse_failed;
97139d628a0SDimitry Andric   }
97291bc56edSDimitry Andric   assert(PE32Header || PE32PlusHeader);
97391bc56edSDimitry Andric   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
97491bc56edSDimitry Andric                                : PE32PlusHeader->NumberOfRvaAndSize;
97539d628a0SDimitry Andric   if (Index >= NumEnt) {
97639d628a0SDimitry Andric     Res = nullptr;
97791bc56edSDimitry Andric     return object_error::parse_failed;
97839d628a0SDimitry Andric   }
97991bc56edSDimitry Andric   Res = &DataDirectory[Index];
98097bc6c73SDimitry Andric   return std::error_code();
98191bc56edSDimitry Andric }
98291bc56edSDimitry Andric 
getSection(int32_t Index,const coff_section * & Result) const98391bc56edSDimitry Andric std::error_code COFFObjectFile::getSection(int32_t Index,
98417a519f9SDimitry Andric                                            const coff_section *&Result) const {
98591bc56edSDimitry Andric   Result = nullptr;
98639d628a0SDimitry Andric   if (COFF::isReservedSectionNumber(Index))
98797bc6c73SDimitry Andric     return std::error_code();
98839d628a0SDimitry Andric   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
98917a519f9SDimitry Andric     // We already verified the section table data, so no need to check again.
99091bc56edSDimitry Andric     Result = SectionTable + (Index - 1);
99197bc6c73SDimitry Andric     return std::error_code();
9922754fe60SDimitry Andric   }
99339d628a0SDimitry Andric   return object_error::parse_failed;
99439d628a0SDimitry Andric }
9952754fe60SDimitry Andric 
getSection(StringRef SectionName,const coff_section * & Result) const9964ba319b5SDimitry Andric std::error_code COFFObjectFile::getSection(StringRef SectionName,
9974ba319b5SDimitry Andric                                            const coff_section *&Result) const {
9984ba319b5SDimitry Andric   Result = nullptr;
9994ba319b5SDimitry Andric   StringRef SecName;
10004ba319b5SDimitry Andric   for (const SectionRef &Section : sections()) {
10014ba319b5SDimitry Andric     if (std::error_code E = Section.getName(SecName))
10024ba319b5SDimitry Andric       return E;
10034ba319b5SDimitry Andric     if (SecName == SectionName) {
10044ba319b5SDimitry Andric       Result = getCOFFSection(Section);
10054ba319b5SDimitry Andric       return std::error_code();
10064ba319b5SDimitry Andric     }
10074ba319b5SDimitry Andric   }
10084ba319b5SDimitry Andric   return object_error::parse_failed;
10094ba319b5SDimitry Andric }
10104ba319b5SDimitry Andric 
getString(uint32_t Offset,StringRef & Result) const101191bc56edSDimitry Andric std::error_code COFFObjectFile::getString(uint32_t Offset,
101217a519f9SDimitry Andric                                           StringRef &Result) const {
101317a519f9SDimitry Andric   if (StringTableSize <= 4)
101417a519f9SDimitry Andric     // Tried to get a string from an empty string table.
101517a519f9SDimitry Andric     return object_error::parse_failed;
101691bc56edSDimitry Andric   if (Offset >= StringTableSize)
101717a519f9SDimitry Andric     return object_error::unexpected_eof;
101891bc56edSDimitry Andric   Result = StringRef(StringTable + Offset);
101997bc6c73SDimitry Andric   return std::error_code();
10202754fe60SDimitry Andric }
10212754fe60SDimitry Andric 
getSymbolName(COFFSymbolRef Symbol,StringRef & Res) const102239d628a0SDimitry Andric std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
1023dff0c46cSDimitry Andric                                               StringRef &Res) const {
10243dac3a9bSDimitry Andric   return getSymbolName(Symbol.getGeneric(), Res);
10253dac3a9bSDimitry Andric }
10263dac3a9bSDimitry Andric 
getSymbolName(const coff_symbol_generic * Symbol,StringRef & Res) const10273dac3a9bSDimitry Andric std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
10283dac3a9bSDimitry Andric                                               StringRef &Res) const {
1029dff0c46cSDimitry Andric   // Check for string table entry. First 4 bytes are 0.
10303dac3a9bSDimitry Andric   if (Symbol->Name.Offset.Zeroes == 0) {
10313dac3a9bSDimitry Andric     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
103291bc56edSDimitry Andric       return EC;
103397bc6c73SDimitry Andric     return std::error_code();
1034dff0c46cSDimitry Andric   }
1035dff0c46cSDimitry Andric 
10363dac3a9bSDimitry Andric   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
1037dff0c46cSDimitry Andric     // Null terminated, let ::strlen figure out the length.
10383dac3a9bSDimitry Andric     Res = StringRef(Symbol->Name.ShortName);
1039dff0c46cSDimitry Andric   else
1040dff0c46cSDimitry Andric     // Not null terminated, use all 8 bytes.
10413dac3a9bSDimitry Andric     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
104297bc6c73SDimitry Andric   return std::error_code();
1043dff0c46cSDimitry Andric }
1044dff0c46cSDimitry Andric 
104539d628a0SDimitry Andric ArrayRef<uint8_t>
getSymbolAuxData(COFFSymbolRef Symbol) const104639d628a0SDimitry Andric COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
104791bc56edSDimitry Andric   const uint8_t *Aux = nullptr;
10487ae0e2c9SDimitry Andric 
104939d628a0SDimitry Andric   size_t SymbolSize = getSymbolTableEntrySize();
105039d628a0SDimitry Andric   if (Symbol.getNumberOfAuxSymbols() > 0) {
10517ae0e2c9SDimitry Andric     // AUX data comes immediately after the symbol in COFF
105239d628a0SDimitry Andric     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
10537ae0e2c9SDimitry Andric #ifndef NDEBUG
105491bc56edSDimitry Andric     // Verify that the Aux symbol points to a valid entry in the symbol table.
105591bc56edSDimitry Andric     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
105639d628a0SDimitry Andric     if (Offset < getPointerToSymbolTable() ||
105739d628a0SDimitry Andric         Offset >=
105839d628a0SDimitry Andric             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
10597ae0e2c9SDimitry Andric       report_fatal_error("Aux Symbol data was outside of symbol table.");
10607ae0e2c9SDimitry Andric 
106139d628a0SDimitry Andric     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
106239d628a0SDimitry Andric            "Aux Symbol data did not point to the beginning of a symbol");
10637ae0e2c9SDimitry Andric #endif
10647ae0e2c9SDimitry Andric   }
106539d628a0SDimitry Andric   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
10667ae0e2c9SDimitry Andric }
10677ae0e2c9SDimitry Andric 
getSymbolIndex(COFFSymbolRef Symbol) const1068*b5893f02SDimitry Andric uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
1069*b5893f02SDimitry Andric   uintptr_t Offset =
1070*b5893f02SDimitry Andric       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
1071*b5893f02SDimitry Andric   assert(Offset % getSymbolTableEntrySize() == 0 &&
1072*b5893f02SDimitry Andric          "Symbol did not point to the beginning of a symbol");
1073*b5893f02SDimitry Andric   size_t Index = Offset / getSymbolTableEntrySize();
1074*b5893f02SDimitry Andric   assert(Index < getNumberOfSymbols());
1075*b5893f02SDimitry Andric   return Index;
1076*b5893f02SDimitry Andric }
1077*b5893f02SDimitry Andric 
getSectionName(const coff_section * Sec,StringRef & Res) const107891bc56edSDimitry Andric std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
1079dff0c46cSDimitry Andric                                                StringRef &Res) const {
1080dff0c46cSDimitry Andric   StringRef Name;
108139d628a0SDimitry Andric   if (Sec->Name[COFF::NameSize - 1] == 0)
1082dff0c46cSDimitry Andric     // Null terminated, let ::strlen figure out the length.
1083dff0c46cSDimitry Andric     Name = Sec->Name;
1084dff0c46cSDimitry Andric   else
1085dff0c46cSDimitry Andric     // Not null terminated, use all 8 bytes.
108639d628a0SDimitry Andric     Name = StringRef(Sec->Name, COFF::NameSize);
1087dff0c46cSDimitry Andric 
1088dff0c46cSDimitry Andric   // Check for string table entry. First byte is '/'.
108939d628a0SDimitry Andric   if (Name.startswith("/")) {
1090dff0c46cSDimitry Andric     uint32_t Offset;
109139d628a0SDimitry Andric     if (Name.startswith("//")) {
109291bc56edSDimitry Andric       if (decodeBase64StringEntry(Name.substr(2), Offset))
109391bc56edSDimitry Andric         return object_error::parse_failed;
109491bc56edSDimitry Andric     } else {
1095dff0c46cSDimitry Andric       if (Name.substr(1).getAsInteger(10, Offset))
1096dff0c46cSDimitry Andric         return object_error::parse_failed;
109791bc56edSDimitry Andric     }
109891bc56edSDimitry Andric     if (std::error_code EC = getString(Offset, Name))
109991bc56edSDimitry Andric       return EC;
1100dff0c46cSDimitry Andric   }
1101dff0c46cSDimitry Andric 
1102dff0c46cSDimitry Andric   Res = Name;
110397bc6c73SDimitry Andric   return std::error_code();
1104dff0c46cSDimitry Andric }
1105dff0c46cSDimitry Andric 
getSectionSize(const coff_section * Sec) const110639d628a0SDimitry Andric uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
110739d628a0SDimitry Andric   // SizeOfRawData and VirtualSize change what they represent depending on
110839d628a0SDimitry Andric   // whether or not we have an executable image.
110939d628a0SDimitry Andric   //
111039d628a0SDimitry Andric   // For object files, SizeOfRawData contains the size of section's data;
1111875ed548SDimitry Andric   // VirtualSize should be zero but isn't due to buggy COFF writers.
111239d628a0SDimitry Andric   //
111339d628a0SDimitry Andric   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
111439d628a0SDimitry Andric   // actual section size is in VirtualSize.  It is possible for VirtualSize to
111539d628a0SDimitry Andric   // be greater than SizeOfRawData; the contents past that point should be
111639d628a0SDimitry Andric   // considered to be zero.
1117875ed548SDimitry Andric   if (getDOSHeader())
1118875ed548SDimitry Andric     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1119875ed548SDimitry Andric   return Sec->SizeOfRawData;
112039d628a0SDimitry Andric }
112139d628a0SDimitry Andric 
112291bc56edSDimitry Andric std::error_code
getSectionContents(const coff_section * Sec,ArrayRef<uint8_t> & Res) const112391bc56edSDimitry Andric COFFObjectFile::getSectionContents(const coff_section *Sec,
1124dff0c46cSDimitry Andric                                    ArrayRef<uint8_t> &Res) const {
11253ca95b02SDimitry Andric   // In COFF, a virtual section won't have any in-file
11263ca95b02SDimitry Andric   // content, so the file pointer to the content will be zero.
11273ca95b02SDimitry Andric   if (Sec->PointerToRawData == 0)
11285517e702SDimitry Andric     return std::error_code();
1129dff0c46cSDimitry Andric   // The only thing that we need to verify is that the contents is contained
1130dff0c46cSDimitry Andric   // within the file bounds. We don't need to make sure it doesn't cover other
1131dff0c46cSDimitry Andric   // data, as there's nothing that says that is not allowed.
1132dff0c46cSDimitry Andric   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
113339d628a0SDimitry Andric   uint32_t SectionSize = getSectionSize(Sec);
113439d628a0SDimitry Andric   if (checkOffset(Data, ConStart, SectionSize))
1135dff0c46cSDimitry Andric     return object_error::parse_failed;
113639d628a0SDimitry Andric   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
113797bc6c73SDimitry Andric   return std::error_code();
1138dff0c46cSDimitry Andric }
1139dff0c46cSDimitry Andric 
toRel(DataRefImpl Rel) const11406122f3e6SDimitry Andric const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
11416122f3e6SDimitry Andric   return reinterpret_cast<const coff_relocation*>(Rel.p);
11426122f3e6SDimitry Andric }
114391bc56edSDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const114491bc56edSDimitry Andric void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
11456122f3e6SDimitry Andric   Rel.p = reinterpret_cast<uintptr_t>(
11466122f3e6SDimitry Andric             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
11476122f3e6SDimitry Andric }
114891bc56edSDimitry Andric 
getRelocationOffset(DataRefImpl Rel) const11493dac3a9bSDimitry Andric uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
115039d628a0SDimitry Andric   const coff_relocation *R = toRel(Rel);
11513dac3a9bSDimitry Andric   return R->VirtualAddress;
1152dff0c46cSDimitry Andric }
115391bc56edSDimitry Andric 
getRelocationSymbol(DataRefImpl Rel) const1154f785676fSDimitry Andric symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
11556122f3e6SDimitry Andric   const coff_relocation *R = toRel(Rel);
115691bc56edSDimitry Andric   DataRefImpl Ref;
115739d628a0SDimitry Andric   if (R->SymbolTableIndex >= getNumberOfSymbols())
115839d628a0SDimitry Andric     return symbol_end();
115939d628a0SDimitry Andric   if (SymbolTable16)
116039d628a0SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
116139d628a0SDimitry Andric   else if (SymbolTable32)
116239d628a0SDimitry Andric     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
116339d628a0SDimitry Andric   else
116439d628a0SDimitry Andric     llvm_unreachable("no symbol table pointer!");
116591bc56edSDimitry Andric   return symbol_iterator(SymbolRef(Ref, this));
11666122f3e6SDimitry Andric }
116791bc56edSDimitry Andric 
getRelocationType(DataRefImpl Rel) const11683dac3a9bSDimitry Andric uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
11696122f3e6SDimitry Andric   const coff_relocation* R = toRel(Rel);
11703dac3a9bSDimitry Andric   return R->Type;
11716122f3e6SDimitry Andric }
11726122f3e6SDimitry Andric 
117391bc56edSDimitry Andric const coff_section *
getCOFFSection(const SectionRef & Section) const117491bc56edSDimitry Andric COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
117591bc56edSDimitry Andric   return toSec(Section.getRawDataRefImpl());
11767ae0e2c9SDimitry Andric }
11777ae0e2c9SDimitry Andric 
getCOFFSymbol(const DataRefImpl & Ref) const117839d628a0SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
117939d628a0SDimitry Andric   if (SymbolTable16)
118039d628a0SDimitry Andric     return toSymb<coff_symbol16>(Ref);
118139d628a0SDimitry Andric   if (SymbolTable32)
118239d628a0SDimitry Andric     return toSymb<coff_symbol32>(Ref);
118339d628a0SDimitry Andric   llvm_unreachable("no symbol table pointer!");
118439d628a0SDimitry Andric }
118539d628a0SDimitry Andric 
getCOFFSymbol(const SymbolRef & Symbol) const118639d628a0SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
118739d628a0SDimitry Andric   return getCOFFSymbol(Symbol.getRawDataRefImpl());
11887ae0e2c9SDimitry Andric }
11897ae0e2c9SDimitry Andric 
119091bc56edSDimitry Andric const coff_relocation *
getCOFFRelocation(const RelocationRef & Reloc) const119191bc56edSDimitry Andric COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
119291bc56edSDimitry Andric   return toRel(Reloc.getRawDataRefImpl());
11937ae0e2c9SDimitry Andric }
11947ae0e2c9SDimitry Andric 
11954ba319b5SDimitry Andric ArrayRef<coff_relocation>
getRelocations(const coff_section * Sec) const11963dac3a9bSDimitry Andric COFFObjectFile::getRelocations(const coff_section *Sec) const {
11974ba319b5SDimitry Andric   return {getFirstReloc(Sec, Data, base()),
11984ba319b5SDimitry Andric           getNumberOfRelocations(Sec, Data, base())};
11993dac3a9bSDimitry Andric }
12003dac3a9bSDimitry Andric 
120191bc56edSDimitry Andric #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
120291bc56edSDimitry Andric   case COFF::reloc_type:                                                       \
1203*b5893f02SDimitry Andric     return #reloc_type;
12046122f3e6SDimitry Andric 
getRelocationTypeName(uint16_t Type) const1205*b5893f02SDimitry Andric StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
120639d628a0SDimitry Andric   switch (getMachine()) {
12076122f3e6SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_AMD64:
1208*b5893f02SDimitry Andric     switch (Type) {
12096122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
12106122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
12116122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
12126122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
12136122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
12146122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
12156122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
12166122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
12176122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
12186122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
12196122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
12206122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
12216122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
12226122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
12236122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
12246122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
12256122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
12266122f3e6SDimitry Andric     default:
1227*b5893f02SDimitry Andric       return "Unknown";
122891bc56edSDimitry Andric     }
122991bc56edSDimitry Andric     break;
123091bc56edSDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1231*b5893f02SDimitry Andric     switch (Type) {
123291bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
123391bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
123491bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
123591bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
123691bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
123791bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
123891bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
123991bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
124091bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
124191bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
124291bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
124391bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
124491bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
124591bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
124691bc56edSDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
124791bc56edSDimitry Andric     default:
1248*b5893f02SDimitry Andric       return "Unknown";
12496122f3e6SDimitry Andric     }
12506122f3e6SDimitry Andric     break;
1251a580b014SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_ARM64:
1252*b5893f02SDimitry Andric     switch (Type) {
1253a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
1254a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
1255a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
1256a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
1257a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
1258a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
1259a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
1260a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
1261a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
1262a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
1263a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
1264a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
1265a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
1266a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
1267a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
1268a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
1269a580b014SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1270a580b014SDimitry Andric     default:
1271*b5893f02SDimitry Andric       return "Unknown";
1272a580b014SDimitry Andric     }
1273a580b014SDimitry Andric     break;
12746122f3e6SDimitry Andric   case COFF::IMAGE_FILE_MACHINE_I386:
1275*b5893f02SDimitry Andric     switch (Type) {
12766122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
12776122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
12786122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
12796122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
12806122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
12816122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
12826122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
12836122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
12846122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
12856122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
12866122f3e6SDimitry Andric     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
12876122f3e6SDimitry Andric     default:
1288*b5893f02SDimitry Andric       return "Unknown";
12896122f3e6SDimitry Andric     }
12906122f3e6SDimitry Andric     break;
12916122f3e6SDimitry Andric   default:
1292*b5893f02SDimitry Andric     return "Unknown";
12936122f3e6SDimitry Andric   }
12946122f3e6SDimitry Andric }
12956122f3e6SDimitry Andric 
12966122f3e6SDimitry Andric #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
12976122f3e6SDimitry Andric 
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const1298*b5893f02SDimitry Andric void COFFObjectFile::getRelocationTypeName(
1299*b5893f02SDimitry Andric     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1300*b5893f02SDimitry Andric   const coff_relocation *Reloc = toRel(Rel);
1301*b5893f02SDimitry Andric   StringRef Res = getRelocationTypeName(Reloc->Type);
1302*b5893f02SDimitry Andric   Result.append(Res.begin(), Res.end());
1303*b5893f02SDimitry Andric }
1304*b5893f02SDimitry Andric 
isRelocatableObject() const130539d628a0SDimitry Andric bool COFFObjectFile::isRelocatableObject() const {
130639d628a0SDimitry Andric   return !DataDirectory;
1307dff0c46cSDimitry Andric }
1308dff0c46cSDimitry Andric 
mapDebugSectionName(StringRef Name) const1309*b5893f02SDimitry Andric StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1310*b5893f02SDimitry Andric   return StringSwitch<StringRef>(Name)
1311*b5893f02SDimitry Andric       .Case("eh_fram", "eh_frame")
1312*b5893f02SDimitry Andric       .Default(Name);
1313*b5893f02SDimitry Andric }
1314*b5893f02SDimitry Andric 
1315f785676fSDimitry Andric bool ImportDirectoryEntryRef::
operator ==(const ImportDirectoryEntryRef & Other) const1316f785676fSDimitry Andric operator==(const ImportDirectoryEntryRef &Other) const {
131791bc56edSDimitry Andric   return ImportTable == Other.ImportTable && Index == Other.Index;
1318f785676fSDimitry Andric }
1319f785676fSDimitry Andric 
moveNext()132091bc56edSDimitry Andric void ImportDirectoryEntryRef::moveNext() {
132191bc56edSDimitry Andric   ++Index;
1322d88c1a5aSDimitry Andric   if (ImportTable[Index].isNull()) {
13233ca95b02SDimitry Andric     Index = -1;
13243ca95b02SDimitry Andric     ImportTable = nullptr;
13253ca95b02SDimitry Andric   }
1326f785676fSDimitry Andric }
1327f785676fSDimitry Andric 
getImportTableEntry(const coff_import_directory_table_entry * & Result) const132891bc56edSDimitry Andric std::error_code ImportDirectoryEntryRef::getImportTableEntry(
1329d88c1a5aSDimitry Andric     const coff_import_directory_table_entry *&Result) const {
13303ca95b02SDimitry Andric   return getObject(Result, OwningObject->Data, ImportTable + Index);
1331f785676fSDimitry Andric }
1332f785676fSDimitry Andric 
133339d628a0SDimitry Andric static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile * Object,uintptr_t Ptr,int Index)133439d628a0SDimitry Andric makeImportedSymbolIterator(const COFFObjectFile *Object,
133539d628a0SDimitry Andric                            uintptr_t Ptr, int Index) {
133639d628a0SDimitry Andric   if (Object->getBytesInAddress() == 4) {
133739d628a0SDimitry Andric     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
133839d628a0SDimitry Andric     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
133939d628a0SDimitry Andric   }
134039d628a0SDimitry Andric   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
134139d628a0SDimitry Andric   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
134239d628a0SDimitry Andric }
134339d628a0SDimitry Andric 
134439d628a0SDimitry Andric static imported_symbol_iterator
importedSymbolBegin(uint32_t RVA,const COFFObjectFile * Object)134539d628a0SDimitry Andric importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
134639d628a0SDimitry Andric   uintptr_t IntPtr = 0;
134739d628a0SDimitry Andric   Object->getRvaPtr(RVA, IntPtr);
134839d628a0SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, 0);
134939d628a0SDimitry Andric }
135039d628a0SDimitry Andric 
135139d628a0SDimitry Andric static imported_symbol_iterator
importedSymbolEnd(uint32_t RVA,const COFFObjectFile * Object)135239d628a0SDimitry Andric importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
135339d628a0SDimitry Andric   uintptr_t IntPtr = 0;
135439d628a0SDimitry Andric   Object->getRvaPtr(RVA, IntPtr);
135539d628a0SDimitry Andric   // Forward the pointer to the last entry which is null.
135639d628a0SDimitry Andric   int Index = 0;
135739d628a0SDimitry Andric   if (Object->getBytesInAddress() == 4) {
135839d628a0SDimitry Andric     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
135939d628a0SDimitry Andric     while (*Entry++)
136039d628a0SDimitry Andric       ++Index;
136139d628a0SDimitry Andric   } else {
136239d628a0SDimitry Andric     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
136339d628a0SDimitry Andric     while (*Entry++)
136439d628a0SDimitry Andric       ++Index;
136539d628a0SDimitry Andric   }
136639d628a0SDimitry Andric   return makeImportedSymbolIterator(Object, IntPtr, Index);
136739d628a0SDimitry Andric }
136839d628a0SDimitry Andric 
136939d628a0SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const137039d628a0SDimitry Andric ImportDirectoryEntryRef::imported_symbol_begin() const {
1371d88c1a5aSDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
137239d628a0SDimitry Andric                              OwningObject);
137339d628a0SDimitry Andric }
137439d628a0SDimitry Andric 
137539d628a0SDimitry Andric imported_symbol_iterator
imported_symbol_end() const137639d628a0SDimitry Andric ImportDirectoryEntryRef::imported_symbol_end() const {
1377d88c1a5aSDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
137839d628a0SDimitry Andric                            OwningObject);
137939d628a0SDimitry Andric }
138039d628a0SDimitry Andric 
138139d628a0SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const138239d628a0SDimitry Andric ImportDirectoryEntryRef::imported_symbols() const {
138339d628a0SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
138439d628a0SDimitry Andric }
138539d628a0SDimitry Andric 
lookup_table_begin() const1386d88c1a5aSDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
1387d88c1a5aSDimitry Andric   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
1388d88c1a5aSDimitry Andric                              OwningObject);
1389d88c1a5aSDimitry Andric }
1390d88c1a5aSDimitry Andric 
lookup_table_end() const1391d88c1a5aSDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
1392d88c1a5aSDimitry Andric   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
1393d88c1a5aSDimitry Andric                            OwningObject);
1394d88c1a5aSDimitry Andric }
1395d88c1a5aSDimitry Andric 
1396d88c1a5aSDimitry Andric iterator_range<imported_symbol_iterator>
lookup_table_symbols() const1397d88c1a5aSDimitry Andric ImportDirectoryEntryRef::lookup_table_symbols() const {
1398d88c1a5aSDimitry Andric   return make_range(lookup_table_begin(), lookup_table_end());
1399d88c1a5aSDimitry Andric }
1400d88c1a5aSDimitry Andric 
getName(StringRef & Result) const140191bc56edSDimitry Andric std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1402f785676fSDimitry Andric   uintptr_t IntPtr = 0;
140391bc56edSDimitry Andric   if (std::error_code EC =
140439d628a0SDimitry Andric           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
140591bc56edSDimitry Andric     return EC;
140691bc56edSDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
140797bc6c73SDimitry Andric   return std::error_code();
1408f785676fSDimitry Andric }
1409f785676fSDimitry Andric 
141039d628a0SDimitry Andric std::error_code
getImportLookupTableRVA(uint32_t & Result) const141139d628a0SDimitry Andric ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
141239d628a0SDimitry Andric   Result = ImportTable[Index].ImportLookupTableRVA;
141397bc6c73SDimitry Andric   return std::error_code();
141439d628a0SDimitry Andric }
141539d628a0SDimitry Andric 
141639d628a0SDimitry Andric std::error_code
getImportAddressTableRVA(uint32_t & Result) const141739d628a0SDimitry Andric ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
141839d628a0SDimitry Andric   Result = ImportTable[Index].ImportAddressTableRVA;
141997bc6c73SDimitry Andric   return std::error_code();
142039d628a0SDimitry Andric }
142139d628a0SDimitry Andric 
142239d628a0SDimitry Andric bool DelayImportDirectoryEntryRef::
operator ==(const DelayImportDirectoryEntryRef & Other) const142339d628a0SDimitry Andric operator==(const DelayImportDirectoryEntryRef &Other) const {
142439d628a0SDimitry Andric   return Table == Other.Table && Index == Other.Index;
142539d628a0SDimitry Andric }
142639d628a0SDimitry Andric 
moveNext()142739d628a0SDimitry Andric void DelayImportDirectoryEntryRef::moveNext() {
142839d628a0SDimitry Andric   ++Index;
142939d628a0SDimitry Andric }
143039d628a0SDimitry Andric 
143139d628a0SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const143239d628a0SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_begin() const {
143339d628a0SDimitry Andric   return importedSymbolBegin(Table[Index].DelayImportNameTable,
143439d628a0SDimitry Andric                              OwningObject);
143539d628a0SDimitry Andric }
143639d628a0SDimitry Andric 
143739d628a0SDimitry Andric imported_symbol_iterator
imported_symbol_end() const143839d628a0SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_end() const {
143939d628a0SDimitry Andric   return importedSymbolEnd(Table[Index].DelayImportNameTable,
144039d628a0SDimitry Andric                            OwningObject);
144139d628a0SDimitry Andric }
144239d628a0SDimitry Andric 
144339d628a0SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const144439d628a0SDimitry Andric DelayImportDirectoryEntryRef::imported_symbols() const {
144539d628a0SDimitry Andric   return make_range(imported_symbol_begin(), imported_symbol_end());
144639d628a0SDimitry Andric }
144739d628a0SDimitry Andric 
getName(StringRef & Result) const144839d628a0SDimitry Andric std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
144939d628a0SDimitry Andric   uintptr_t IntPtr = 0;
145039d628a0SDimitry Andric   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
145139d628a0SDimitry Andric     return EC;
145239d628a0SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
145397bc6c73SDimitry Andric   return std::error_code();
145439d628a0SDimitry Andric }
145539d628a0SDimitry Andric 
145639d628a0SDimitry Andric std::error_code DelayImportDirectoryEntryRef::
getDelayImportTable(const delay_import_directory_table_entry * & Result) const145739d628a0SDimitry Andric getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
145839d628a0SDimitry Andric   Result = Table;
145997bc6c73SDimitry Andric   return std::error_code();
146039d628a0SDimitry Andric }
146139d628a0SDimitry Andric 
146239d628a0SDimitry Andric std::error_code DelayImportDirectoryEntryRef::
getImportAddress(int AddrIndex,uint64_t & Result) const146339d628a0SDimitry Andric getImportAddress(int AddrIndex, uint64_t &Result) const {
146439d628a0SDimitry Andric   uint32_t RVA = Table[Index].DelayImportAddressTable +
146539d628a0SDimitry Andric       AddrIndex * (OwningObject->is64() ? 8 : 4);
146639d628a0SDimitry Andric   uintptr_t IntPtr = 0;
146739d628a0SDimitry Andric   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
146839d628a0SDimitry Andric     return EC;
146939d628a0SDimitry Andric   if (OwningObject->is64())
147039d628a0SDimitry Andric     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
147139d628a0SDimitry Andric   else
147239d628a0SDimitry Andric     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
147397bc6c73SDimitry Andric   return std::error_code();
147439d628a0SDimitry Andric }
147539d628a0SDimitry Andric 
147691bc56edSDimitry Andric bool ExportDirectoryEntryRef::
operator ==(const ExportDirectoryEntryRef & Other) const147791bc56edSDimitry Andric operator==(const ExportDirectoryEntryRef &Other) const {
147891bc56edSDimitry Andric   return ExportTable == Other.ExportTable && Index == Other.Index;
14792754fe60SDimitry Andric }
14802754fe60SDimitry Andric 
moveNext()148191bc56edSDimitry Andric void ExportDirectoryEntryRef::moveNext() {
148291bc56edSDimitry Andric   ++Index;
148391bc56edSDimitry Andric }
148491bc56edSDimitry Andric 
148591bc56edSDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
148691bc56edSDimitry Andric // by ordinal, the empty string is set as a result.
getDllName(StringRef & Result) const148791bc56edSDimitry Andric std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
148891bc56edSDimitry Andric   uintptr_t IntPtr = 0;
148991bc56edSDimitry Andric   if (std::error_code EC =
149091bc56edSDimitry Andric           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
149191bc56edSDimitry Andric     return EC;
149291bc56edSDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
149397bc6c73SDimitry Andric   return std::error_code();
149491bc56edSDimitry Andric }
149591bc56edSDimitry Andric 
149691bc56edSDimitry Andric // Returns the starting ordinal number.
149791bc56edSDimitry Andric std::error_code
getOrdinalBase(uint32_t & Result) const149891bc56edSDimitry Andric ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
149991bc56edSDimitry Andric   Result = ExportTable->OrdinalBase;
150097bc6c73SDimitry Andric   return std::error_code();
150191bc56edSDimitry Andric }
150291bc56edSDimitry Andric 
150391bc56edSDimitry Andric // Returns the export ordinal of the current export symbol.
getOrdinal(uint32_t & Result) const150491bc56edSDimitry Andric std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
150591bc56edSDimitry Andric   Result = ExportTable->OrdinalBase + Index;
150697bc6c73SDimitry Andric   return std::error_code();
150791bc56edSDimitry Andric }
150891bc56edSDimitry Andric 
150991bc56edSDimitry Andric // Returns the address of the current export symbol.
getExportRVA(uint32_t & Result) const151091bc56edSDimitry Andric std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
151191bc56edSDimitry Andric   uintptr_t IntPtr = 0;
151291bc56edSDimitry Andric   if (std::error_code EC =
151391bc56edSDimitry Andric           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
151491bc56edSDimitry Andric     return EC;
151591bc56edSDimitry Andric   const export_address_table_entry *entry =
151691bc56edSDimitry Andric       reinterpret_cast<const export_address_table_entry *>(IntPtr);
151791bc56edSDimitry Andric   Result = entry[Index].ExportRVA;
151897bc6c73SDimitry Andric   return std::error_code();
151991bc56edSDimitry Andric }
152091bc56edSDimitry Andric 
152191bc56edSDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
152291bc56edSDimitry Andric // by ordinal, the empty string is set as a result.
152391bc56edSDimitry Andric std::error_code
getSymbolName(StringRef & Result) const152491bc56edSDimitry Andric ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
152591bc56edSDimitry Andric   uintptr_t IntPtr = 0;
152691bc56edSDimitry Andric   if (std::error_code EC =
152791bc56edSDimitry Andric           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
152891bc56edSDimitry Andric     return EC;
152991bc56edSDimitry Andric   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
153091bc56edSDimitry Andric 
153191bc56edSDimitry Andric   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
153291bc56edSDimitry Andric   int Offset = 0;
153391bc56edSDimitry Andric   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
153491bc56edSDimitry Andric        I < E; ++I, ++Offset) {
153591bc56edSDimitry Andric     if (*I != Index)
153691bc56edSDimitry Andric       continue;
153791bc56edSDimitry Andric     if (std::error_code EC =
153891bc56edSDimitry Andric             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
153991bc56edSDimitry Andric       return EC;
154091bc56edSDimitry Andric     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
154191bc56edSDimitry Andric     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
154291bc56edSDimitry Andric       return EC;
154391bc56edSDimitry Andric     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
154497bc6c73SDimitry Andric     return std::error_code();
154591bc56edSDimitry Andric   }
154691bc56edSDimitry Andric   Result = "";
154797bc6c73SDimitry Andric   return std::error_code();
154891bc56edSDimitry Andric }
154991bc56edSDimitry Andric 
isForwarder(bool & Result) const1550444ed5c5SDimitry Andric std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
1551444ed5c5SDimitry Andric   const data_directory *DataEntry;
1552444ed5c5SDimitry Andric   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
1553444ed5c5SDimitry Andric     return EC;
1554444ed5c5SDimitry Andric   uint32_t RVA;
1555444ed5c5SDimitry Andric   if (auto EC = getExportRVA(RVA))
1556444ed5c5SDimitry Andric     return EC;
1557444ed5c5SDimitry Andric   uint32_t Begin = DataEntry->RelativeVirtualAddress;
1558444ed5c5SDimitry Andric   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
1559444ed5c5SDimitry Andric   Result = (Begin <= RVA && RVA < End);
1560444ed5c5SDimitry Andric   return std::error_code();
1561444ed5c5SDimitry Andric }
1562444ed5c5SDimitry Andric 
getForwardTo(StringRef & Result) const1563444ed5c5SDimitry Andric std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
1564444ed5c5SDimitry Andric   uint32_t RVA;
1565444ed5c5SDimitry Andric   if (auto EC = getExportRVA(RVA))
1566444ed5c5SDimitry Andric     return EC;
1567444ed5c5SDimitry Andric   uintptr_t IntPtr = 0;
1568444ed5c5SDimitry Andric   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
1569444ed5c5SDimitry Andric     return EC;
1570444ed5c5SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1571444ed5c5SDimitry Andric   return std::error_code();
1572444ed5c5SDimitry Andric }
1573444ed5c5SDimitry Andric 
157439d628a0SDimitry Andric bool ImportedSymbolRef::
operator ==(const ImportedSymbolRef & Other) const157539d628a0SDimitry Andric operator==(const ImportedSymbolRef &Other) const {
157639d628a0SDimitry Andric   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
157739d628a0SDimitry Andric       && Index == Other.Index;
157839d628a0SDimitry Andric }
157939d628a0SDimitry Andric 
moveNext()158039d628a0SDimitry Andric void ImportedSymbolRef::moveNext() {
158139d628a0SDimitry Andric   ++Index;
158239d628a0SDimitry Andric }
158339d628a0SDimitry Andric 
158439d628a0SDimitry Andric std::error_code
getSymbolName(StringRef & Result) const158539d628a0SDimitry Andric ImportedSymbolRef::getSymbolName(StringRef &Result) const {
158639d628a0SDimitry Andric   uint32_t RVA;
158739d628a0SDimitry Andric   if (Entry32) {
158839d628a0SDimitry Andric     // If a symbol is imported only by ordinal, it has no name.
158939d628a0SDimitry Andric     if (Entry32[Index].isOrdinal())
159097bc6c73SDimitry Andric       return std::error_code();
159139d628a0SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
159239d628a0SDimitry Andric   } else {
159339d628a0SDimitry Andric     if (Entry64[Index].isOrdinal())
159497bc6c73SDimitry Andric       return std::error_code();
159539d628a0SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
159639d628a0SDimitry Andric   }
159739d628a0SDimitry Andric   uintptr_t IntPtr = 0;
159839d628a0SDimitry Andric   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
159939d628a0SDimitry Andric     return EC;
160039d628a0SDimitry Andric   // +2 because the first two bytes is hint.
160139d628a0SDimitry Andric   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
160297bc6c73SDimitry Andric   return std::error_code();
160339d628a0SDimitry Andric }
160439d628a0SDimitry Andric 
isOrdinal(bool & Result) const16053ca95b02SDimitry Andric std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
16063ca95b02SDimitry Andric   if (Entry32)
16073ca95b02SDimitry Andric     Result = Entry32[Index].isOrdinal();
16083ca95b02SDimitry Andric   else
16093ca95b02SDimitry Andric     Result = Entry64[Index].isOrdinal();
16103ca95b02SDimitry Andric   return std::error_code();
16113ca95b02SDimitry Andric }
16123ca95b02SDimitry Andric 
getHintNameRVA(uint32_t & Result) const16133ca95b02SDimitry Andric std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
16143ca95b02SDimitry Andric   if (Entry32)
16153ca95b02SDimitry Andric     Result = Entry32[Index].getHintNameRVA();
16163ca95b02SDimitry Andric   else
16173ca95b02SDimitry Andric     Result = Entry64[Index].getHintNameRVA();
16183ca95b02SDimitry Andric   return std::error_code();
16193ca95b02SDimitry Andric }
16203ca95b02SDimitry Andric 
getOrdinal(uint16_t & Result) const162139d628a0SDimitry Andric std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
162239d628a0SDimitry Andric   uint32_t RVA;
162339d628a0SDimitry Andric   if (Entry32) {
162439d628a0SDimitry Andric     if (Entry32[Index].isOrdinal()) {
162539d628a0SDimitry Andric       Result = Entry32[Index].getOrdinal();
162697bc6c73SDimitry Andric       return std::error_code();
162739d628a0SDimitry Andric     }
162839d628a0SDimitry Andric     RVA = Entry32[Index].getHintNameRVA();
162939d628a0SDimitry Andric   } else {
163039d628a0SDimitry Andric     if (Entry64[Index].isOrdinal()) {
163139d628a0SDimitry Andric       Result = Entry64[Index].getOrdinal();
163297bc6c73SDimitry Andric       return std::error_code();
163339d628a0SDimitry Andric     }
163439d628a0SDimitry Andric     RVA = Entry64[Index].getHintNameRVA();
163539d628a0SDimitry Andric   }
163639d628a0SDimitry Andric   uintptr_t IntPtr = 0;
163739d628a0SDimitry Andric   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
163839d628a0SDimitry Andric     return EC;
163939d628a0SDimitry Andric   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
164097bc6c73SDimitry Andric   return std::error_code();
164139d628a0SDimitry Andric }
164239d628a0SDimitry Andric 
16432cab237bSDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object)164439d628a0SDimitry Andric ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
164591bc56edSDimitry Andric   std::error_code EC;
164639d628a0SDimitry Andric   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
164791bc56edSDimitry Andric   if (EC)
16482cab237bSDimitry Andric     return errorCodeToError(EC);
164939d628a0SDimitry Andric   return std::move(Ret);
165039d628a0SDimitry Andric }
165139d628a0SDimitry Andric 
operator ==(const BaseRelocRef & Other) const165239d628a0SDimitry Andric bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
165339d628a0SDimitry Andric   return Header == Other.Header && Index == Other.Index;
165439d628a0SDimitry Andric }
165539d628a0SDimitry Andric 
moveNext()165639d628a0SDimitry Andric void BaseRelocRef::moveNext() {
165739d628a0SDimitry Andric   // Header->BlockSize is the size of the current block, including the
165839d628a0SDimitry Andric   // size of the header itself.
165939d628a0SDimitry Andric   uint32_t Size = sizeof(*Header) +
166039d628a0SDimitry Andric       sizeof(coff_base_reloc_block_entry) * (Index + 1);
166139d628a0SDimitry Andric   if (Size == Header->BlockSize) {
166239d628a0SDimitry Andric     // .reloc contains a list of base relocation blocks. Each block
166339d628a0SDimitry Andric     // consists of the header followed by entries. The header contains
166439d628a0SDimitry Andric     // how many entories will follow. When we reach the end of the
166539d628a0SDimitry Andric     // current block, proceed to the next block.
166639d628a0SDimitry Andric     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
166739d628a0SDimitry Andric         reinterpret_cast<const uint8_t *>(Header) + Size);
166839d628a0SDimitry Andric     Index = 0;
166939d628a0SDimitry Andric   } else {
167039d628a0SDimitry Andric     ++Index;
167139d628a0SDimitry Andric   }
167239d628a0SDimitry Andric }
167339d628a0SDimitry Andric 
getType(uint8_t & Type) const167439d628a0SDimitry Andric std::error_code BaseRelocRef::getType(uint8_t &Type) const {
167539d628a0SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
167639d628a0SDimitry Andric   Type = Entry[Index].getType();
167797bc6c73SDimitry Andric   return std::error_code();
167839d628a0SDimitry Andric }
167939d628a0SDimitry Andric 
getRVA(uint32_t & Result) const168039d628a0SDimitry Andric std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
168139d628a0SDimitry Andric   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
168239d628a0SDimitry Andric   Result = Header->PageRVA + Entry[Index].getOffset();
168397bc6c73SDimitry Andric   return std::error_code();
168491bc56edSDimitry Andric }
16850f5676f4SDimitry Andric 
16862cab237bSDimitry Andric #define RETURN_IF_ERROR(E)                                                     \
16872cab237bSDimitry Andric   if (E)                                                                       \
16882cab237bSDimitry Andric     return E;
16890f5676f4SDimitry Andric 
16902cab237bSDimitry Andric Expected<ArrayRef<UTF16>>
getDirStringAtOffset(uint32_t Offset)16912cab237bSDimitry Andric ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
16920f5676f4SDimitry Andric   BinaryStreamReader Reader = BinaryStreamReader(BBS);
16930f5676f4SDimitry Andric   Reader.setOffset(Offset);
16940f5676f4SDimitry Andric   uint16_t Length;
16950f5676f4SDimitry Andric   RETURN_IF_ERROR(Reader.readInteger(Length));
16960f5676f4SDimitry Andric   ArrayRef<UTF16> RawDirString;
16970f5676f4SDimitry Andric   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
16980f5676f4SDimitry Andric   return RawDirString;
16990f5676f4SDimitry Andric }
17000f5676f4SDimitry Andric 
17012cab237bSDimitry Andric Expected<ArrayRef<UTF16>>
getEntryNameString(const coff_resource_dir_entry & Entry)17020f5676f4SDimitry Andric ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
17030f5676f4SDimitry Andric   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
17040f5676f4SDimitry Andric }
17050f5676f4SDimitry Andric 
17062cab237bSDimitry Andric Expected<const coff_resource_dir_table &>
getTableAtOffset(uint32_t Offset)17070f5676f4SDimitry Andric ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
17080f5676f4SDimitry Andric   const coff_resource_dir_table *Table = nullptr;
17090f5676f4SDimitry Andric 
17100f5676f4SDimitry Andric   BinaryStreamReader Reader(BBS);
17110f5676f4SDimitry Andric   Reader.setOffset(Offset);
17120f5676f4SDimitry Andric   RETURN_IF_ERROR(Reader.readObject(Table));
17130f5676f4SDimitry Andric   assert(Table != nullptr);
17140f5676f4SDimitry Andric   return *Table;
17150f5676f4SDimitry Andric }
17160f5676f4SDimitry Andric 
17172cab237bSDimitry Andric Expected<const coff_resource_dir_table &>
getEntrySubDir(const coff_resource_dir_entry & Entry)17180f5676f4SDimitry Andric ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17190f5676f4SDimitry Andric   return getTableAtOffset(Entry.Offset.value());
17200f5676f4SDimitry Andric }
17210f5676f4SDimitry Andric 
getBaseTable()17222cab237bSDimitry Andric Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
17230f5676f4SDimitry Andric   return getTableAtOffset(0);
17240f5676f4SDimitry Andric }
1725