1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===//
28e90adafSMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68e90adafSMichael J. Spencer //
78e90adafSMichael J. Spencer //===----------------------------------------------------------------------===//
88e90adafSMichael J. Spencer //
98e90adafSMichael J. Spencer // This file declares the COFFObjectFile class.
108e90adafSMichael J. Spencer //
118e90adafSMichael J. Spencer //===----------------------------------------------------------------------===//
128e90adafSMichael J. Spencer 
139da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h"
14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h"
15*0ea52537SSimon Pilgrim #include "llvm/ADT/StringSwitch.h"
168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h"
176a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h"
18264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h"
19d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
20d341c932SEugene Zelenko #include "llvm/Object/COFF.h"
21d341c932SEugene Zelenko #include "llvm/Object/Error.h"
22d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h"
23efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
24d341c932SEugene Zelenko #include "llvm/Support/Endian.h"
25d341c932SEugene Zelenko #include "llvm/Support/Error.h"
26d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
27d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h"
28d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
29d341c932SEugene Zelenko #include <algorithm>
30d341c932SEugene Zelenko #include <cassert>
31d341c932SEugene Zelenko #include <cstddef>
32d341c932SEugene Zelenko #include <cstdint>
33d341c932SEugene Zelenko #include <cstring>
349d2c15efSNico Rieck #include <limits>
35d341c932SEugene Zelenko #include <memory>
36d341c932SEugene Zelenko #include <system_error>
378e90adafSMichael J. Spencer 
388e90adafSMichael J. Spencer using namespace llvm;
398e90adafSMichael J. Spencer using namespace object;
408e90adafSMichael J. Spencer 
418e90adafSMichael J. Spencer using support::ulittle16_t;
428e90adafSMichael J. Spencer using support::ulittle32_t;
43861021f9SRui Ueyama using support::ulittle64_t;
448e90adafSMichael J. Spencer using support::little16_t;
458e90adafSMichael J. Spencer 
461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
48c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
498ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
501d6167fdSMichael J. Spencer     return false;
511d6167fdSMichael J. Spencer   }
521d6167fdSMichael J. Spencer   return true;
538e90adafSMichael J. Spencer }
548e90adafSMichael J. Spencer 
55ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
56ed64342bSRui Ueyama // Returns unexpected_eof if error.
57ed64342bSRui Ueyama template <typename T>
5848af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
5958323a97SDavid Majnemer                                  const void *Ptr,
60236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
61ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
62cbc7ee45SBenjamin Kramer   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
63e830c60dSDavid Majnemer     return EC;
64ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
657d099195SRui Ueyama   return std::error_code();
661d6167fdSMichael J. Spencer }
671d6167fdSMichael J. Spencer 
689d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
699d2c15efSNico Rieck // prefixed slashes.
709d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
719d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
729d2c15efSNico Rieck   if (Str.size() > 6)
739d2c15efSNico Rieck     return true;
749d2c15efSNico Rieck 
759d2c15efSNico Rieck   uint64_t Value = 0;
769d2c15efSNico Rieck   while (!Str.empty()) {
779d2c15efSNico Rieck     unsigned CharVal;
789d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
799d2c15efSNico Rieck       CharVal = Str[0] - 'A';
809d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
819d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
829d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
839d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
849d2c15efSNico Rieck     else if (Str[0] == '+') // 62
855500b07cSRui Ueyama       CharVal = 62;
869d2c15efSNico Rieck     else if (Str[0] == '/') // 63
875500b07cSRui Ueyama       CharVal = 63;
889d2c15efSNico Rieck     else
899d2c15efSNico Rieck       return true;
909d2c15efSNico Rieck 
919d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
929d2c15efSNico Rieck     Str = Str.substr(1);
939d2c15efSNico Rieck   }
949d2c15efSNico Rieck 
959d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
969d2c15efSNico Rieck     return true;
979d2c15efSNico Rieck 
989d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
999d2c15efSNico Rieck   return false;
1009d2c15efSNico Rieck }
1019d2c15efSNico Rieck 
10244f51e51SDavid Majnemer template <typename coff_symbol_type>
10344f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10444f51e51SDavid Majnemer   const coff_symbol_type *Addr =
10544f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1061d6167fdSMichael J. Spencer 
107236b0ca7SDavid Majnemer   assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr)));
1081d6167fdSMichael J. Spencer #ifndef NDEBUG
1091d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
1108ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1111d6167fdSMichael J. Spencer 
11244f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11344f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1141d6167fdSMichael J. Spencer #endif
1151d6167fdSMichael J. Spencer 
1168ff24d25SRui Ueyama   return Addr;
1171d6167fdSMichael J. Spencer }
1181d6167fdSMichael J. Spencer 
1198ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1208ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1211d6167fdSMichael J. Spencer 
1221d6167fdSMichael J. Spencer #ifndef NDEBUG
1231d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
12444f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1251d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1261d6167fdSMichael J. Spencer 
1278ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1288ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1291d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1301d6167fdSMichael J. Spencer #endif
1311d6167fdSMichael J. Spencer 
1328ff24d25SRui Ueyama   return Addr;
1331d6167fdSMichael J. Spencer }
1341d6167fdSMichael J. Spencer 
1355e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
136236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13744f51e51SDavid Majnemer   if (SymbolTable16) {
13844f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1398ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
140236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14144f51e51SDavid Majnemer   } else if (SymbolTable32) {
14244f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14344f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
144236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14544f51e51SDavid Majnemer   } else {
14644f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14744f51e51SDavid Majnemer   }
1481d6167fdSMichael J. Spencer }
1491d6167fdSMichael J. Spencer 
15081e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15177ecf90cSReid Kleckner   return getSymbolName(getCOFFSymbol(Ref));
1528e90adafSMichael J. Spencer }
1538e90adafSMichael J. Spencer 
154be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
155be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
156991af666SRafael Espindola }
157991af666SRafael Espindola 
1586b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1596b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1606b2bba14SDavide Italiano   // up to 32 bytes.
1616b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16203a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1636b2bba14SDavide Italiano }
1646b2bba14SDavide Italiano 
165931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
166ff6a0b6aSXing GUO   uint64_t Result = cantFail(getSymbolValue(Ref));
16744f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
168c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
169991af666SRafael Espindola 
170991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
171991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
172ed067c45SRafael Espindola     return Result;
17354c9f3daSRafael Espindola 
17477ecf90cSReid Kleckner   Expected<const coff_section *> Section = getSection(SectionNumber);
17577ecf90cSReid Kleckner   if (!Section)
17677ecf90cSReid Kleckner     return Section.takeError();
17777ecf90cSReid Kleckner   Result += (*Section)->VirtualAddress;
17847ea9eceSReid Kleckner 
17947ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18047ea9eceSReid Kleckner   // return virtual addresses.
18121427adaSReid Kleckner   Result += getImageBase();
18247ea9eceSReid Kleckner 
183ed067c45SRafael Espindola   return Result;
184c7d7c6fbSDavid Majnemer }
185c7d7c6fbSDavid Majnemer 
1867bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
18744f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
188c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
18944f51e51SDavid Majnemer 
190e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
191e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1922fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1932fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1942fa80cc5SRafael Espindola   if (Symb.isCommon())
1952fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1962fa80cc5SRafael Espindola   if (Symb.isFileRecord())
1972fa80cc5SRafael Espindola     return SymbolRef::ST_File;
1982fa80cc5SRafael Espindola 
1991a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2002fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2012fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2022fa80cc5SRafael Espindola 
2032fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2042fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2052fa80cc5SRafael Espindola 
2062fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
20775d1cf33SBenjamin Kramer }
20875d1cf33SBenjamin Kramer 
209ac00376aSvgxbj Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21120122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21275d1cf33SBenjamin Kramer 
213c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2149dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2151df4b84dSDavid Meyer 
216a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2171df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
218a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
219a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2201079ef8dSMartell Malone   }
2211df4b84dSDavid Meyer 
22244f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2231df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2241df4b84dSDavid Meyer 
225c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
226c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
227c7d7c6fbSDavid Majnemer 
228c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
229c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
230c7d7c6fbSDavid Majnemer 
231c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
232c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
233c7d7c6fbSDavid Majnemer 
234a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
235c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
236c7d7c6fbSDavid Majnemer 
23720122a43SRafael Espindola   return Result;
23801759754SMichael J. Spencer }
23901759754SMichael J. Spencer 
240d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
241c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2425eb02e45SRafael Espindola   return Symb.getValue();
2438e90adafSMichael J. Spencer }
2448e90adafSMichael J. Spencer 
2457bd8d994SKevin Enderby Expected<section_iterator>
2468bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
24744f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2488bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2498bab889bSRafael Espindola     return section_end();
25077ecf90cSReid Kleckner   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
25177ecf90cSReid Kleckner   if (!Sec)
25277ecf90cSReid Kleckner     return Sec.takeError();
2538bab889bSRafael Espindola   DataRefImpl Ret;
25477ecf90cSReid Kleckner   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2558bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25632173153SMichael J. Spencer }
25732173153SMichael J. Spencer 
2586bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2596bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2606bf32210SRafael Espindola   return Symb.getSectionNumber();
2616bf32210SRafael Espindola }
2626bf32210SRafael Espindola 
2635e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2648ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2658ff24d25SRui Ueyama   Sec += 1;
2668ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2678e90adafSMichael J. Spencer }
2688e90adafSMichael J. Spencer 
2698be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2708ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2718be28cdcSFangrui Song   return getSectionName(Sec);
2728e90adafSMichael J. Spencer }
2738e90adafSMichael J. Spencer 
27480291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2758ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2767c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2777c6a071bSDavid Majnemer 
2787c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2797c6a071bSDavid Majnemer   // return virtual addresses.
28021427adaSReid Kleckner   Result += getImageBase();
2817c6a071bSDavid Majnemer   return Result;
2828e90adafSMichael J. Spencer }
2838e90adafSMichael J. Spencer 
284a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
285a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
286a25d329bSGeorge Rimar }
287a25d329bSGeorge Rimar 
28880291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
289a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2908e90adafSMichael J. Spencer }
2918e90adafSMichael J. Spencer 
292e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
293e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2948ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2959da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
296e1cb2c0fSFangrui Song   if (Error E = getSectionContents(Sec, Res))
297c55cf4afSBill Wendling     return std::move(E);
298e1cb2c0fSFangrui Song   return Res;
2998e90adafSMichael J. Spencer }
3008e90adafSMichael J. Spencer 
30180291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3028ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
303511391feSDavid Majnemer   return Sec->getAlignment();
3047989460aSMichael J. Spencer }
3057989460aSMichael J. Spencer 
306401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
307401e4e57SGeorge Rimar   return false;
308401e4e57SGeorge Rimar }
309401e4e57SGeorge Rimar 
31080291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3118ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31280291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3138e90adafSMichael J. Spencer }
3148e90adafSMichael J. Spencer 
31580291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3168ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31780291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
318800619f2SMichael J. Spencer }
319800619f2SMichael J. Spencer 
32080291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3218ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3221a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3231a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3241a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3251a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
326800619f2SMichael J. Spencer }
327800619f2SMichael J. Spencer 
32829d253c4SDjordje Todorovic // The .debug sections are the only debug sections for COFF
32929d253c4SDjordje Todorovic // (\see MCObjectFileInfo.cpp).
33029d253c4SDjordje Todorovic bool COFFObjectFile::isDebugSection(StringRef SectionName) const {
33129d253c4SDjordje Todorovic   return SectionName.startswith(".debug");
33229d253c4SDjordje Todorovic }
33329d253c4SDjordje Todorovic 
3346bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3356bf32210SRafael Espindola   uintptr_t Offset =
3366bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3376bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3386bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3396bf32210SRafael Espindola }
3406bf32210SRafael Espindola 
34180291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3428ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3431a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3441a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3451a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3462138ef6dSPreston Gurd }
3472138ef6dSPreston Gurd 
348e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
349e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
350e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
351e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
352e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
353e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
354e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
355e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
356e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
357e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
358e830c60dSDavid Majnemer       return 0;
35998fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36098fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
361e830c60dSDavid Majnemer   }
362e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
363e830c60dSDavid Majnemer }
364e830c60dSDavid Majnemer 
36594751be7SDavid Majnemer static const coff_relocation *
36694751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36794751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36894751be7SDavid Majnemer   if (!NumRelocs)
36994751be7SDavid Majnemer     return nullptr;
370827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37194751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
372827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
373827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
374827c8a2bSRui Ueyama     // relocations.
375827c8a2bSRui Ueyama     begin++;
376827c8a2bSRui Ueyama   }
377cbc7ee45SBenjamin Kramer   if (Binary::checkOffset(M, uintptr_t(begin),
378cbc7ee45SBenjamin Kramer                           sizeof(coff_relocation) * NumRelocs))
37994751be7SDavid Majnemer     return nullptr;
38094751be7SDavid Majnemer   return begin;
381827c8a2bSRui Ueyama }
38294751be7SDavid Majnemer 
38394751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38494751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38594751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38676d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38776d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
38894751be7SDavid Majnemer   DataRefImpl Ret;
38994751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3908ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
391e5fd0047SMichael J. Spencer }
392e5fd0047SMichael J. Spencer 
3938ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3948ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39594751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39694751be7SDavid Majnemer   if (I)
39794751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3988ff24d25SRui Ueyama   DataRefImpl Ret;
39994751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4008ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
401e5fd0047SMichael J. Spencer }
402e5fd0047SMichael J. Spencer 
403c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
404db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40544f51e51SDavid Majnemer   if (COFFHeader)
406236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
407236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
408236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40944f51e51SDavid Majnemer       return EC;
41044f51e51SDavid Majnemer 
41144f51e51SDavid Majnemer   if (COFFBigObjHeader)
412236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
413236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
414236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4158ff24d25SRui Ueyama       return EC;
416c2bed429SRui Ueyama 
417c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
418c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
419c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
420f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42144f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
422f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
423c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42448af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4258ff24d25SRui Ueyama     return EC;
426c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
427db4ed0bdSRafael Espindola   if (std::error_code EC =
42848af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4298ff24d25SRui Ueyama     return EC;
430c2bed429SRui Ueyama 
431773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
432773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
433773a5795SNico Rieck   if (StringTableSize < 4)
434773a5795SNico Rieck       StringTableSize = 4;
435773a5795SNico Rieck 
436c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
437773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
438c2bed429SRui Ueyama     return  object_error::parse_failed;
4397d099195SRui Ueyama   return std::error_code();
440c2bed429SRui Ueyama }
441c2bed429SRui Ueyama 
44221427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
443e94fef7bSReid Kleckner   if (PE32Header)
44421427adaSReid Kleckner     return PE32Header->ImageBase;
445e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44621427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44721427adaSReid Kleckner   // This actually comes up in practice.
44821427adaSReid Kleckner   return 0;
449e94fef7bSReid Kleckner }
450e94fef7bSReid Kleckner 
451215a586cSRui Ueyama // Returns the file offset for the given VA.
452db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45321427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
454b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
455b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
456b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
457215a586cSRui Ueyama }
458215a586cSRui Ueyama 
459c2bed429SRui Ueyama // Returns the file offset for the given RVA.
460db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46127dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46227dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
463c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
464c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
465215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
466215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
467c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4687d099195SRui Ueyama       return std::error_code();
469c2bed429SRui Ueyama     }
470c2bed429SRui Ueyama   }
471c2bed429SRui Ueyama   return object_error::parse_failed;
472c2bed429SRui Ueyama }
473c2bed429SRui Ueyama 
4742da433eaSReid Kleckner std::error_code
4752da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4762da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4772da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4782da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4792da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4802da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4812da433eaSReid Kleckner     // overflow.
4822da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4832da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4842da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4852da433eaSReid Kleckner       uintptr_t Begin =
4862da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4872da433eaSReid Kleckner       Contents =
4882da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4892da433eaSReid Kleckner       return std::error_code();
4902da433eaSReid Kleckner     }
4912da433eaSReid Kleckner   }
4922da433eaSReid Kleckner   return object_error::parse_failed;
4932da433eaSReid Kleckner }
4942da433eaSReid Kleckner 
495c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
496c2bed429SRui Ueyama // table entry.
497db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
498db4ed0bdSRafael Espindola                                             StringRef &Name) const {
499c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
500db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5018ff24d25SRui Ueyama     return EC;
502c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
503c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
504c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5057d099195SRui Ueyama   return std::error_code();
506c2bed429SRui Ueyama }
507c2bed429SRui Ueyama 
50801528021SSaleem Abdulrasool std::error_code
50901528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51001528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5112da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5122da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5132da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5142da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5152da433eaSReid Kleckner     return EC;
51601528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5172da433eaSReid Kleckner     return object_error::parse_failed;
51801528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
51901528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5202da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5212da433eaSReid Kleckner                           InfoBytes.size());
5222da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5232da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5242da433eaSReid Kleckner   return std::error_code();
5252da433eaSReid Kleckner }
5262da433eaSReid Kleckner 
52701528021SSaleem Abdulrasool std::error_code
52801528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
529f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
530f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
531f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
532f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
533f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
534f27f3f84SReid Kleckner   PDBInfo = nullptr;
535f27f3f84SReid Kleckner   PDBFileName = StringRef();
536f27f3f84SReid Kleckner   return std::error_code();
537f27f3f84SReid Kleckner }
538f27f3f84SReid Kleckner 
539c2bed429SRui Ueyama // Find the import table.
540db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
541c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
542c2bed429SRui Ueyama   // the import table, do nothing.
543c2bed429SRui Ueyama   const data_directory *DataEntry;
544c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5457d099195SRui Ueyama     return std::error_code();
546c2bed429SRui Ueyama 
547c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
548c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5497d099195SRui Ueyama     return std::error_code();
550c2bed429SRui Ueyama 
551c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
552c2bed429SRui Ueyama 
553c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
554c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
555c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
556db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5578ff24d25SRui Ueyama     return EC;
558ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
559ad7b7e73SDavid Majnemer     return EC;
560c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5611c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5627d099195SRui Ueyama   return std::error_code();
563ad882ba8SRui Ueyama }
564c2bed429SRui Ueyama 
56515d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56615d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56715d99359SRui Ueyama   const data_directory *DataEntry;
56815d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5697d099195SRui Ueyama     return std::error_code();
57015d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5717d099195SRui Ueyama     return std::error_code();
57215d99359SRui Ueyama 
57315d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57415d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57515d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57615d99359SRui Ueyama 
57715d99359SRui Ueyama   uintptr_t IntPtr = 0;
57815d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57915d99359SRui Ueyama     return EC;
58015d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58115d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5827d099195SRui Ueyama   return std::error_code();
58315d99359SRui Ueyama }
58415d99359SRui Ueyama 
585ad882ba8SRui Ueyama // Find the export table.
586db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
587ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
588ad882ba8SRui Ueyama   // the export table, do nothing.
589ad882ba8SRui Ueyama   const data_directory *DataEntry;
590ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5917d099195SRui Ueyama     return std::error_code();
592ad882ba8SRui Ueyama 
593ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
594ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5957d099195SRui Ueyama     return std::error_code();
596ad882ba8SRui Ueyama 
597ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
598ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
599db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
600ad882ba8SRui Ueyama     return EC;
60124fc2d64SRui Ueyama   ExportDirectory =
60224fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6037d099195SRui Ueyama   return std::error_code();
604c2bed429SRui Ueyama }
605c2bed429SRui Ueyama 
60674e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60774e85130SRui Ueyama   const data_directory *DataEntry;
60874e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6097d099195SRui Ueyama     return std::error_code();
61074e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6117d099195SRui Ueyama     return std::error_code();
61274e85130SRui Ueyama 
61374e85130SRui Ueyama   uintptr_t IntPtr = 0;
61474e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61574e85130SRui Ueyama     return EC;
61674e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61774e85130SRui Ueyama       IntPtr);
61874e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61974e85130SRui Ueyama       IntPtr + DataEntry->Size);
620893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
621893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6227d099195SRui Ueyama   return std::error_code();
62374e85130SRui Ueyama }
62474e85130SRui Ueyama 
6252da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6262da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6272da433eaSReid Kleckner   const data_directory *DataEntry;
6282da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6292da433eaSReid Kleckner     return std::error_code();
6302da433eaSReid Kleckner 
6312da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6322da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6332da433eaSReid Kleckner     return std::error_code();
6342da433eaSReid Kleckner 
6352da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6362da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6372da433eaSReid Kleckner     return object_error::parse_failed;
6382da433eaSReid Kleckner 
6392da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6402da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6412da433eaSReid Kleckner     return EC;
6422da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
643893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
644893c6469SNico Weber       IntPtr + DataEntry->Size);
645893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
646893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6472da433eaSReid Kleckner   return std::error_code();
6482da433eaSReid Kleckner }
6492da433eaSReid Kleckner 
650b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
651b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
652b7d716c0SReid Kleckner   const data_directory *DataEntry;
653b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
654b7d716c0SReid Kleckner     return std::error_code();
655b7d716c0SReid Kleckner 
656b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
657b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
658b7d716c0SReid Kleckner     return std::error_code();
659b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
660b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
661b7d716c0SReid Kleckner     return EC;
662b7d716c0SReid Kleckner 
663b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
664b7d716c0SReid Kleckner   return std::error_code();
665b7d716c0SReid Kleckner }
666b7d716c0SReid Kleckner 
66739772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>>
66839772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) {
66939772063SReid Kleckner   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
67039772063SReid Kleckner   if (Error E = Obj->initialize())
67139772063SReid Kleckner     return std::move(E);
67239772063SReid Kleckner   return std::move(Obj);
67339772063SReid Kleckner }
67439772063SReid Kleckner 
67539772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
67648af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
67744f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
67844f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
67944f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
68039772063SReid Kleckner       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
68139772063SReid Kleckner       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
68239772063SReid Kleckner       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
68339772063SReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {}
68439772063SReid Kleckner 
68539772063SReid Kleckner Error COFFObjectFile::initialize() {
6861d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
68739772063SReid Kleckner   std::error_code EC;
68848af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
68939772063SReid Kleckner     return errorCodeToError(EC);
690ee066fc4SEric Christopher 
69182ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
69282ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
69382ebd8e3SRui Ueyama 
69482ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
69582ebd8e3SRui Ueyama   // it is placed right after COFF header.
6968ff24d25SRui Ueyama   bool HasPEHeader = false;
697ee066fc4SEric Christopher 
6981d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
69950267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
700ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
701ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
70250267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
70350267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
70450267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
70582ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
70650267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
70739772063SReid Kleckner         return errorCodeToError(object_error::parse_failed);
7081d6167fdSMichael J. Spencer       }
70944f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7108ff24d25SRui Ueyama       HasPEHeader = true;
711ee066fc4SEric Christopher     }
71250267222SDavid Majnemer   }
713ee066fc4SEric Christopher 
71448af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
71539772063SReid Kleckner     return errorCodeToError(EC);
71644f51e51SDavid Majnemer 
71744f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
71844f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
71944f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
72044f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
72144f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
72244f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
72339772063SReid Kleckner       return errorCodeToError(EC);
72444f51e51SDavid Majnemer 
72544f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
72644f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
72744f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
72844f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
72944f51e51SDavid Majnemer       COFFHeader = nullptr;
73044f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
73144f51e51SDavid Majnemer     } else {
73244f51e51SDavid Majnemer       // It's not a bigobj.
73344f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
73444f51e51SDavid Majnemer     }
73544f51e51SDavid Majnemer   }
73644f51e51SDavid Majnemer   if (COFFHeader) {
73744f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
73844f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7397d099195SRui Ueyama     EC = std::error_code();
74082ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
74182ebd8e3SRui Ueyama 
74244f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
74339772063SReid Kleckner       return errorCodeToError(EC);
74444f51e51SDavid Majnemer   }
74544f51e51SDavid Majnemer 
7468ff24d25SRui Ueyama   if (HasPEHeader) {
74710ed9ddcSRui Ueyama     const pe32_header *Header;
74848af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
74939772063SReid Kleckner       return errorCodeToError(EC);
75010ed9ddcSRui Ueyama 
75110ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
75210ed9ddcSRui Ueyama     uint64_t DataDirSize;
75350267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
75410ed9ddcSRui Ueyama       PE32Header = Header;
75510ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
75610ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
75750267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
75810ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
75910ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
76010ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
76110ed9ddcSRui Ueyama     } else {
76210ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
76339772063SReid Kleckner       return errorCodeToError(object_error::parse_failed);
764ed64342bSRui Ueyama     }
76548af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
76639772063SReid Kleckner       return errorCodeToError(EC);
767f53c8cb4SRui Ueyama   }
768776c6828SRui Ueyama 
7698950a538SRui Ueyama   if (COFFHeader)
7708950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7718950a538SRui Ueyama 
77248af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
773236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
77439772063SReid Kleckner     return errorCodeToError(EC);
7751d6167fdSMichael J. Spencer 
776c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
777236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
778ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
779ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
780ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
781ac8cfab5SDavid Majnemer       StringTable = nullptr;
782ac8cfab5SDavid Majnemer       StringTableSize = 0;
783ac8cfab5SDavid Majnemer     }
784236b0ca7SDavid Majnemer   } else {
785236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
786236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
78739772063SReid Kleckner       return errorCodeToError(object_error::parse_failed);
788236b0ca7SDavid Majnemer     }
789236b0ca7SDavid Majnemer   }
7908e90adafSMichael J. Spencer 
791c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7928ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
79339772063SReid Kleckner     return errorCodeToError(EC);
79415d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
79539772063SReid Kleckner     return errorCodeToError(EC);
7961d6167fdSMichael J. Spencer 
797ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7988ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
79939772063SReid Kleckner     return errorCodeToError(EC);
800ad882ba8SRui Ueyama 
80174e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
80274e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
80339772063SReid Kleckner     return errorCodeToError(EC);
80474e85130SRui Ueyama 
8052da433eaSReid Kleckner   // Initialize the pointer to the export table.
8062da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
80739772063SReid Kleckner     return errorCodeToError(EC);
8082da433eaSReid Kleckner 
809b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
81039772063SReid Kleckner     return errorCodeToError(EC);
811b7d716c0SReid Kleckner 
81239772063SReid Kleckner   return Error::success();
8138e90adafSMichael J. Spencer }
8148e90adafSMichael J. Spencer 
815435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8168ff24d25SRui Ueyama   DataRefImpl Ret;
81744f51e51SDavid Majnemer   Ret.p = getSymbolTable();
818f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8198e90adafSMichael J. Spencer }
8208e90adafSMichael J. Spencer 
821435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8228e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8238ff24d25SRui Ueyama   DataRefImpl Ret;
8248ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
825f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8268e90adafSMichael J. Spencer }
8278e90adafSMichael J. Spencer 
828bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
829ad7b7e73SDavid Majnemer   if (!ImportDirectory)
830ad7b7e73SDavid Majnemer     return import_directory_end();
8311c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
832ad7b7e73SDavid Majnemer     return import_directory_end();
833a045b73aSRui Ueyama   return import_directory_iterator(
834a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
835c2bed429SRui Ueyama }
836c2bed429SRui Ueyama 
837bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
838a045b73aSRui Ueyama   return import_directory_iterator(
839ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
840c2bed429SRui Ueyama }
841c429b80dSDavid Meyer 
84215d99359SRui Ueyama delay_import_directory_iterator
84315d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
84415d99359SRui Ueyama   return delay_import_directory_iterator(
84515d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
84615d99359SRui Ueyama }
84715d99359SRui Ueyama 
84815d99359SRui Ueyama delay_import_directory_iterator
84915d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
85015d99359SRui Ueyama   return delay_import_directory_iterator(
85115d99359SRui Ueyama       DelayImportDirectoryEntryRef(
85215d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
85315d99359SRui Ueyama }
85415d99359SRui Ueyama 
855ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
856ad882ba8SRui Ueyama   return export_directory_iterator(
857ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
858ad882ba8SRui Ueyama }
859ad882ba8SRui Ueyama 
860ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8612617dcceSCraig Topper   if (!ExportDirectory)
8622617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8638ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
864ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8658ff24d25SRui Ueyama   return export_directory_iterator(Ref);
866ad882ba8SRui Ueyama }
867ad882ba8SRui Ueyama 
868b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8698ff24d25SRui Ueyama   DataRefImpl Ret;
8708ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8718ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8728e90adafSMichael J. Spencer }
8738e90adafSMichael J. Spencer 
874b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8758ff24d25SRui Ueyama   DataRefImpl Ret;
87644f51e51SDavid Majnemer   int NumSections =
87744f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8788ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8798ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8808e90adafSMichael J. Spencer }
8818e90adafSMichael J. Spencer 
88274e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
88374e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
88474e85130SRui Ueyama }
88574e85130SRui Ueyama 
88674e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
88774e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
88874e85130SRui Ueyama }
88974e85130SRui Ueyama 
8908e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
89143c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8928e90adafSMichael J. Spencer }
8938e90adafSMichael J. Spencer 
8948e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
89544f51e51SDavid Majnemer   switch(getMachine()) {
8968e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8978e90adafSMichael J. Spencer     return "COFF-i386";
8988e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8998e90adafSMichael J. Spencer     return "COFF-x86-64";
9009b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9019b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
9021eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9031eff5c9cSMartell Malone     return "COFF-ARM64";
9048e90adafSMichael J. Spencer   default:
9058e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
9068e90adafSMichael J. Spencer   }
9078e90adafSMichael J. Spencer }
9088e90adafSMichael J. Spencer 
909260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
91044f51e51SDavid Majnemer   switch (getMachine()) {
9118e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9128e90adafSMichael J. Spencer     return Triple::x86;
9138e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9148e90adafSMichael J. Spencer     return Triple::x86_64;
9159b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9169b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9171eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9181eff5c9cSMartell Malone     return Triple::aarch64;
9198e90adafSMichael J. Spencer   default:
9208e90adafSMichael J. Spencer     return Triple::UnknownArch;
9218e90adafSMichael J. Spencer   }
9228e90adafSMichael J. Spencer }
9238e90adafSMichael J. Spencer 
924d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
925d2af4d6fSPaul Semel   if (PE32Header)
926d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
927d2af4d6fSPaul Semel   return 0;
928d2af4d6fSPaul Semel }
929d2af4d6fSPaul Semel 
930979fb40bSRui Ueyama iterator_range<import_directory_iterator>
931979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
932979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
933979fb40bSRui Ueyama }
934979fb40bSRui Ueyama 
935979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
936979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
937979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
938979fb40bSRui Ueyama                     delay_import_directory_end());
939979fb40bSRui Ueyama }
940979fb40bSRui Ueyama 
941979fb40bSRui Ueyama iterator_range<export_directory_iterator>
942979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
943979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
944979fb40bSRui Ueyama }
945979fb40bSRui Ueyama 
94674e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
94774e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
94874e85130SRui Ueyama }
94974e85130SRui Ueyama 
950e84a0b5aSMartin Storsjo std::error_code
951db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
952ed64342bSRui Ueyama                                  const data_directory *&Res) const {
953bcadfee2SHiroshi Inoue   // Error if there's no data directory or the index is out of range.
954f69b0585SDavid Majnemer   if (!DataDirectory) {
955f69b0585SDavid Majnemer     Res = nullptr;
95610ed9ddcSRui Ueyama     return object_error::parse_failed;
957f69b0585SDavid Majnemer   }
95810ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
95910ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
96010ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
961f69b0585SDavid Majnemer   if (Index >= NumEnt) {
962f69b0585SDavid Majnemer     Res = nullptr;
963ed64342bSRui Ueyama     return object_error::parse_failed;
964f69b0585SDavid Majnemer   }
9658ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9667d099195SRui Ueyama   return std::error_code();
967ed64342bSRui Ueyama }
968ed64342bSRui Ueyama 
96977ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
97077ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
97177ecf90cSReid Kleckner   // but callers rely on this to return null.
972236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
97377ecf90cSReid Kleckner     return (const coff_section *)nullptr;
974236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9751d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
97677ecf90cSReid Kleckner     return SectionTable + (Index - 1);
9778e90adafSMichael J. Spencer   }
97877ecf90cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
979236b0ca7SDavid Majnemer }
9808e90adafSMichael J. Spencer 
98177ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
9821d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9831d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
98477ecf90cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
9858ff24d25SRui Ueyama   if (Offset >= StringTableSize)
98677ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
98777ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
9888e90adafSMichael J. Spencer }
989022ecdf2SBenjamin Kramer 
99077ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
99177ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
992e40d30f3SRui Ueyama }
993e40d30f3SRui Ueyama 
99477ecf90cSReid Kleckner Expected<StringRef>
99577ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
99689a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
99777ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
99877ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
99989a7a5eaSMichael J. Spencer 
100089a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
100177ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
100277ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
100377ecf90cSReid Kleckner 
100489a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
100577ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
100689a7a5eaSMichael J. Spencer }
100789a7a5eaSMichael J. Spencer 
100844f51e51SDavid Majnemer ArrayRef<uint8_t>
100944f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10102617dcceSCraig Topper   const uint8_t *Aux = nullptr;
101171757ef3SMarshall Clow 
101244f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
101344f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
101471757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
101544f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
101671757ef3SMarshall Clow #ifndef NDEBUG
10178ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10188ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
101944f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
102044f51e51SDavid Majnemer         Offset >=
102144f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
102271757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
102371757ef3SMarshall Clow 
102444f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
102544f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
102671757ef3SMarshall Clow #endif
1027bfb85e67SMarshall Clow   }
102844f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
102971757ef3SMarshall Clow }
103071757ef3SMarshall Clow 
103174e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
103274e7d260SMartin Storsjo   uintptr_t Offset =
103374e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
103474e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
103574e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
103674e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
103774e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
103874e7d260SMartin Storsjo   return Index;
103974e7d260SMartin Storsjo }
104074e7d260SMartin Storsjo 
10418be28cdcSFangrui Song Expected<StringRef>
10428be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
104353c2d547SMichael J. Spencer   StringRef Name;
104444f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
104553c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
104653c2d547SMichael J. Spencer     Name = Sec->Name;
104753c2d547SMichael J. Spencer   else
104853c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
104944f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
105053c2d547SMichael J. Spencer 
105153c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10522314b3deSDavid Majnemer   if (Name.startswith("/")) {
105353c2d547SMichael J. Spencer     uint32_t Offset;
10542314b3deSDavid Majnemer     if (Name.startswith("//")) {
10559d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10568be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1057400b6c08Sserge-sans-paille                                  "invalid section name");
10589d2c15efSNico Rieck     } else {
105953c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
10608be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
10618be28cdcSFangrui Song                                  "invalid section name");
10629d2c15efSNico Rieck     }
106377ecf90cSReid Kleckner     return getString(Offset);
106453c2d547SMichael J. Spencer   }
106553c2d547SMichael J. Spencer 
10668be28cdcSFangrui Song   return Name;
106753c2d547SMichael J. Spencer }
106853c2d547SMichael J. Spencer 
1069a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1070a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1071a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1072a9ee5c06SDavid Majnemer   //
1073a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1074d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1075a9ee5c06SDavid Majnemer   //
1076a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1077a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1078a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1079a9ee5c06SDavid Majnemer   // considered to be zero.
1080d5297ee7SRui Ueyama   if (getDOSHeader())
1081d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1082d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1083a9ee5c06SDavid Majnemer }
1084a9ee5c06SDavid Majnemer 
1085e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
10869da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1087e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1088e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1089e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1090e1cb2c0fSFangrui Song     return Error::success();
10919da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10929da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10939da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10949da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1095a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1096e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
1097e1cb2c0fSFangrui Song     return make_error<BinaryError>();
1098a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1099e1cb2c0fSFangrui Song   return Error::success();
11009da9e693SMichael J. Spencer }
11019da9e693SMichael J. Spencer 
1102022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1103e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1104022ecdf2SBenjamin Kramer }
11058ff24d25SRui Ueyama 
11065e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1107e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1108e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1109022ecdf2SBenjamin Kramer }
11108ff24d25SRui Ueyama 
111196d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
111258323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
111396d071cdSRafael Espindola   return R->VirtualAddress;
1114cbe72fc9SDanil Malyshev }
11158ff24d25SRui Ueyama 
1116806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1117022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11188ff24d25SRui Ueyama   DataRefImpl Ref;
1119236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1120236b0ca7SDavid Majnemer     return symbol_end();
112144f51e51SDavid Majnemer   if (SymbolTable16)
112244f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
112344f51e51SDavid Majnemer   else if (SymbolTable32)
112444f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
112544f51e51SDavid Majnemer   else
1126c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11278ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1128022ecdf2SBenjamin Kramer }
11298ff24d25SRui Ueyama 
113099c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1131022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
113299c041b7SRafael Espindola   return R->Type;
1133022ecdf2SBenjamin Kramer }
1134e5fd0047SMichael J. Spencer 
113527dc8394SAlexey Samsonov const coff_section *
113627dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
113727dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
113871757ef3SMarshall Clow }
113971757ef3SMarshall Clow 
114044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
114144f51e51SDavid Majnemer   if (SymbolTable16)
114244f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
114344f51e51SDavid Majnemer   if (SymbolTable32)
114444f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
114544f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
114644f51e51SDavid Majnemer }
114744f51e51SDavid Majnemer 
114844f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
114944f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
115071757ef3SMarshall Clow }
115171757ef3SMarshall Clow 
1152f12b8282SRafael Espindola const coff_relocation *
115327dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
115427dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1155d3e2a76cSMarshall Clow }
1156d3e2a76cSMarshall Clow 
11572f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11586a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11592f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
11602f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
11616a75acb1SRui Ueyama }
11626a75acb1SRui Ueyama 
116327dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
116427dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1165114ebf4aSMartin Storsjo     return #reloc_type;
1166e5fd0047SMichael J. Spencer 
1167114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
116844f51e51SDavid Majnemer   switch (getMachine()) {
1169e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1170114ebf4aSMartin Storsjo     switch (Type) {
1171e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1172e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1173e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1174e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1175e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1176e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1177e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1178e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1179e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1180e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1181e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1182e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1183e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1184e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1185e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1186e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1187e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1188e5fd0047SMichael J. Spencer     default:
1189114ebf4aSMartin Storsjo       return "Unknown";
1190e5fd0047SMichael J. Spencer     }
1191e5fd0047SMichael J. Spencer     break;
11925c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1193114ebf4aSMartin Storsjo     switch (Type) {
11945c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11955c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11965c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11975c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11985c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11995c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12005c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12015c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1202e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12035c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12045c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12055c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12065c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12075c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12085c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12095c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1210e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12115c503bf4SSaleem Abdulrasool     default:
1212114ebf4aSMartin Storsjo       return "Unknown";
12135c503bf4SSaleem Abdulrasool     }
12145c503bf4SSaleem Abdulrasool     break;
12150c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1216114ebf4aSMartin Storsjo     switch (Type) {
12170c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12180c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12190c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12200c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12210c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12220c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12230c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12240c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12250c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12260c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12270c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12280c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12290c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12300c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12310c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12320c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12330c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1234e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12350c72172eSMandeep Singh Grang     default:
1236114ebf4aSMartin Storsjo       return "Unknown";
12370c72172eSMandeep Singh Grang     }
12380c72172eSMandeep Singh Grang     break;
1239e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1240114ebf4aSMartin Storsjo     switch (Type) {
1241e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1242e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1243e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1244e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1245e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1246e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1247e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1248e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1249e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1250e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1251e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1252e5fd0047SMichael J. Spencer     default:
1253114ebf4aSMartin Storsjo       return "Unknown";
1254e5fd0047SMichael J. Spencer     }
1255e5fd0047SMichael J. Spencer     break;
1256e5fd0047SMichael J. Spencer   default:
1257114ebf4aSMartin Storsjo     return "Unknown";
1258e5fd0047SMichael J. Spencer   }
1259e5fd0047SMichael J. Spencer }
1260e5fd0047SMichael J. Spencer 
1261e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1262e5fd0047SMichael J. Spencer 
1263114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1264114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1265114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1266114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1267114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1268114ebf4aSMartin Storsjo }
1269114ebf4aSMartin Storsjo 
1270c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1271c66d761bSRafael Espindola   return !DataDirectory;
1272c66d761bSRafael Espindola }
1273c66d761bSRafael Espindola 
1274e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1275e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1276e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1277e3093808SMartin Storsjo       .Default(Name);
1278e3093808SMartin Storsjo }
1279e3093808SMartin Storsjo 
1280c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1281c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1282a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1283c2bed429SRui Ueyama }
1284c2bed429SRui Ueyama 
12855e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12865e812afaSRafael Espindola   ++Index;
12871c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1288ad7b7e73SDavid Majnemer     Index = -1;
1289ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1290ad7b7e73SDavid Majnemer   }
1291c2bed429SRui Ueyama }
1292c2bed429SRui Ueyama 
1293db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12941c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1295ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1296c2bed429SRui Ueyama }
1297c2bed429SRui Ueyama 
1298861021f9SRui Ueyama static imported_symbol_iterator
129915d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1300861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
130115d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1302861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
130315d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1304861021f9SRui Ueyama   }
1305861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
130615d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1307861021f9SRui Ueyama }
1308861021f9SRui Ueyama 
130915d99359SRui Ueyama static imported_symbol_iterator
131015d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1311861021f9SRui Ueyama   uintptr_t IntPtr = 0;
131215d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
131315d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1314861021f9SRui Ueyama }
1315861021f9SRui Ueyama 
131615d99359SRui Ueyama static imported_symbol_iterator
131715d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1318861021f9SRui Ueyama   uintptr_t IntPtr = 0;
131915d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1320861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1321861021f9SRui Ueyama   int Index = 0;
132215d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1323861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1324861021f9SRui Ueyama     while (*Entry++)
1325861021f9SRui Ueyama       ++Index;
1326861021f9SRui Ueyama   } else {
1327861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1328861021f9SRui Ueyama     while (*Entry++)
1329861021f9SRui Ueyama       ++Index;
1330861021f9SRui Ueyama   }
133115d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
133215d99359SRui Ueyama }
133315d99359SRui Ueyama 
133415d99359SRui Ueyama imported_symbol_iterator
133515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
133660049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
133715d99359SRui Ueyama                              OwningObject);
133815d99359SRui Ueyama }
133915d99359SRui Ueyama 
134015d99359SRui Ueyama imported_symbol_iterator
134115d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
134260049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
134315d99359SRui Ueyama                            OwningObject);
1344861021f9SRui Ueyama }
1345861021f9SRui Ueyama 
1346979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1347979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1348979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1349979fb40bSRui Ueyama }
1350979fb40bSRui Ueyama 
135160049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
135260049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
135360049526SDavid Majnemer                              OwningObject);
135460049526SDavid Majnemer }
135560049526SDavid Majnemer 
135660049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
135760049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
135860049526SDavid Majnemer                            OwningObject);
135960049526SDavid Majnemer }
136060049526SDavid Majnemer 
136160049526SDavid Majnemer iterator_range<imported_symbol_iterator>
136260049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
136360049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
136460049526SDavid Majnemer }
136560049526SDavid Majnemer 
1366db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1367c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1368db4ed0bdSRafael Espindola   if (std::error_code EC =
13691e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1370a045b73aSRui Ueyama     return EC;
1371a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13727d099195SRui Ueyama   return std::error_code();
1373c2bed429SRui Ueyama }
1374c2bed429SRui Ueyama 
13751e152d5eSRui Ueyama std::error_code
13761e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13771e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13787d099195SRui Ueyama   return std::error_code();
13791e152d5eSRui Ueyama }
13801e152d5eSRui Ueyama 
13811e152d5eSRui Ueyama std::error_code
13821e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13831e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13847d099195SRui Ueyama   return std::error_code();
13851e152d5eSRui Ueyama }
13861e152d5eSRui Ueyama 
138715d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
138815d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
138915d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
139015d99359SRui Ueyama }
139115d99359SRui Ueyama 
139215d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
139315d99359SRui Ueyama   ++Index;
139415d99359SRui Ueyama }
139515d99359SRui Ueyama 
139615d99359SRui Ueyama imported_symbol_iterator
139715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
139815d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
139915d99359SRui Ueyama                              OwningObject);
140015d99359SRui Ueyama }
140115d99359SRui Ueyama 
140215d99359SRui Ueyama imported_symbol_iterator
140315d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
140415d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
140515d99359SRui Ueyama                            OwningObject);
140615d99359SRui Ueyama }
140715d99359SRui Ueyama 
1408979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1409979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1410979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1411979fb40bSRui Ueyama }
1412979fb40bSRui Ueyama 
141315d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
141415d99359SRui Ueyama   uintptr_t IntPtr = 0;
141515d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
141615d99359SRui Ueyama     return EC;
141715d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14187d099195SRui Ueyama   return std::error_code();
141915d99359SRui Ueyama }
142015d99359SRui Ueyama 
14211af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14221af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14239f598ac7SJoseph Tremoulet   Result = &Table[Index];
14247d099195SRui Ueyama   return std::error_code();
14251af08658SRui Ueyama }
14261af08658SRui Ueyama 
1427ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1428ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1429ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1430ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1431ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1432ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1433ffa4cebeSRui Ueyama     return EC;
1434ffa4cebeSRui Ueyama   if (OwningObject->is64())
14355dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1436ffa4cebeSRui Ueyama   else
14375dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14387d099195SRui Ueyama   return std::error_code();
1439ffa4cebeSRui Ueyama }
1440ffa4cebeSRui Ueyama 
1441ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1442ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1443ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1444ad882ba8SRui Ueyama }
1445ad882ba8SRui Ueyama 
14465e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14475e812afaSRafael Espindola   ++Index;
1448ad882ba8SRui Ueyama }
1449ad882ba8SRui Ueyama 
1450da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1451da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1452db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1453da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1454db4ed0bdSRafael Espindola   if (std::error_code EC =
1455db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1456da49d0d4SRui Ueyama     return EC;
1457da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14587d099195SRui Ueyama   return std::error_code();
1459da49d0d4SRui Ueyama }
1460da49d0d4SRui Ueyama 
1461e5df6095SRui Ueyama // Returns the starting ordinal number.
1462db4ed0bdSRafael Espindola std::error_code
1463db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1464e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14657d099195SRui Ueyama   return std::error_code();
1466e5df6095SRui Ueyama }
1467e5df6095SRui Ueyama 
1468ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1469db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1470ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14717d099195SRui Ueyama   return std::error_code();
1472ad882ba8SRui Ueyama }
1473ad882ba8SRui Ueyama 
1474ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1475db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1476ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1477db4ed0bdSRafael Espindola   if (std::error_code EC =
1478db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1479ad882ba8SRui Ueyama     return EC;
148024fc2d64SRui Ueyama   const export_address_table_entry *entry =
148124fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1482ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14837d099195SRui Ueyama   return std::error_code();
1484ad882ba8SRui Ueyama }
1485ad882ba8SRui Ueyama 
1486ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1487ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1488db4ed0bdSRafael Espindola std::error_code
1489db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1490ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1491db4ed0bdSRafael Espindola   if (std::error_code EC =
1492db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1493ad882ba8SRui Ueyama     return EC;
1494ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1495ad882ba8SRui Ueyama 
1496ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1497ad882ba8SRui Ueyama   int Offset = 0;
1498ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1499ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1500ad882ba8SRui Ueyama     if (*I != Index)
1501ad882ba8SRui Ueyama       continue;
1502db4ed0bdSRafael Espindola     if (std::error_code EC =
1503db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1504ad882ba8SRui Ueyama       return EC;
1505ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1506db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1507ad882ba8SRui Ueyama       return EC;
1508ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15097d099195SRui Ueyama     return std::error_code();
1510ad882ba8SRui Ueyama   }
1511ad882ba8SRui Ueyama   Result = "";
15127d099195SRui Ueyama   return std::error_code();
1513ad882ba8SRui Ueyama }
1514ad882ba8SRui Ueyama 
15156161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15166161b38dSRui Ueyama   const data_directory *DataEntry;
15176161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15186161b38dSRui Ueyama     return EC;
15196161b38dSRui Ueyama   uint32_t RVA;
15206161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15216161b38dSRui Ueyama     return EC;
15226161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15236161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15246161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15256161b38dSRui Ueyama   return std::error_code();
15266161b38dSRui Ueyama }
15276161b38dSRui Ueyama 
15286161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15296161b38dSRui Ueyama   uint32_t RVA;
15306161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15316161b38dSRui Ueyama     return EC;
15326161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15336161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15346161b38dSRui Ueyama     return EC;
15356161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15366161b38dSRui Ueyama   return std::error_code();
15376161b38dSRui Ueyama }
15386161b38dSRui Ueyama 
1539861021f9SRui Ueyama bool ImportedSymbolRef::
1540861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1541861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1542861021f9SRui Ueyama       && Index == Other.Index;
1543861021f9SRui Ueyama }
1544861021f9SRui Ueyama 
1545861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1546861021f9SRui Ueyama   ++Index;
1547861021f9SRui Ueyama }
1548861021f9SRui Ueyama 
1549861021f9SRui Ueyama std::error_code
1550861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1551861021f9SRui Ueyama   uint32_t RVA;
1552861021f9SRui Ueyama   if (Entry32) {
1553861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1554861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15557d099195SRui Ueyama       return std::error_code();
1556861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1557861021f9SRui Ueyama   } else {
1558861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15597d099195SRui Ueyama       return std::error_code();
1560861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1561861021f9SRui Ueyama   }
1562861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1563861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1564861021f9SRui Ueyama     return EC;
1565861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1566861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15677d099195SRui Ueyama   return std::error_code();
1568861021f9SRui Ueyama }
1569861021f9SRui Ueyama 
1570ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1571ad7b7e73SDavid Majnemer   if (Entry32)
1572ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1573ad7b7e73SDavid Majnemer   else
1574ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1575ad7b7e73SDavid Majnemer   return std::error_code();
1576ad7b7e73SDavid Majnemer }
1577ad7b7e73SDavid Majnemer 
1578ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1579ad7b7e73SDavid Majnemer   if (Entry32)
1580ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1581ad7b7e73SDavid Majnemer   else
1582ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1583ad7b7e73SDavid Majnemer   return std::error_code();
1584ad7b7e73SDavid Majnemer }
1585ad7b7e73SDavid Majnemer 
1586861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1587861021f9SRui Ueyama   uint32_t RVA;
1588861021f9SRui Ueyama   if (Entry32) {
1589861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1590861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15917d099195SRui Ueyama       return std::error_code();
1592861021f9SRui Ueyama     }
1593861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1594861021f9SRui Ueyama   } else {
1595861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1596861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15977d099195SRui Ueyama       return std::error_code();
1598861021f9SRui Ueyama     }
1599861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1600861021f9SRui Ueyama   }
1601861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1602861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1603861021f9SRui Ueyama     return EC;
1604861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16057d099195SRui Ueyama   return std::error_code();
1606861021f9SRui Ueyama }
1607861021f9SRui Ueyama 
160812db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
160948af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
161039772063SReid Kleckner   return COFFObjectFile::create(Object);
1611686738e2SRui Ueyama }
161274e85130SRui Ueyama 
161374e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
161474e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
161574e85130SRui Ueyama }
161674e85130SRui Ueyama 
161774e85130SRui Ueyama void BaseRelocRef::moveNext() {
161874e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
161974e85130SRui Ueyama   // size of the header itself.
162074e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1621970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
162274e85130SRui Ueyama   if (Size == Header->BlockSize) {
162374e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
162474e85130SRui Ueyama     // consists of the header followed by entries. The header contains
162574e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
162674e85130SRui Ueyama     // current block, proceed to the next block.
162774e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
162874e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
162974e85130SRui Ueyama     Index = 0;
163074e85130SRui Ueyama   } else {
163174e85130SRui Ueyama     ++Index;
163274e85130SRui Ueyama   }
163374e85130SRui Ueyama }
163474e85130SRui Ueyama 
163574e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
163674e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
163774e85130SRui Ueyama   Type = Entry[Index].getType();
16387d099195SRui Ueyama   return std::error_code();
163974e85130SRui Ueyama }
164074e85130SRui Ueyama 
164174e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
164274e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
164374e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16447d099195SRui Ueyama   return std::error_code();
164574e85130SRui Ueyama }
1646efef15a0SEric Beckmann 
1647357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1648357a40ecSMartin Storsjo   do {                                                                         \
1649357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
165087867988SRafael Espindola     if (E)                                                                     \
1651c55cf4afSBill Wendling       return std::move(E);                                                     \
1652357a40ecSMartin Storsjo   } while (0)
1653efef15a0SEric Beckmann 
165487867988SRafael Espindola Expected<ArrayRef<UTF16>>
165587867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1656efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1657efef15a0SEric Beckmann   Reader.setOffset(Offset);
1658efef15a0SEric Beckmann   uint16_t Length;
1659efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1660efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1661efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1662cd704cb6SEric Beckmann   return RawDirString;
1663efef15a0SEric Beckmann }
1664efef15a0SEric Beckmann 
1665f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1666efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1667f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1668efef15a0SEric Beckmann }
1669efef15a0SEric Beckmann 
167087867988SRafael Espindola Expected<const coff_resource_dir_table &>
1671efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1672efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1673efef15a0SEric Beckmann 
1674efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1675efef15a0SEric Beckmann   Reader.setOffset(Offset);
1676efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1677efef15a0SEric Beckmann   assert(Table != nullptr);
1678efef15a0SEric Beckmann   return *Table;
1679efef15a0SEric Beckmann }
1680efef15a0SEric Beckmann 
1681edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1682edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1683edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1684edb6ab9bSMartin Storsjo 
1685edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1686edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1687edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1688edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1689edb6ab9bSMartin Storsjo   return *Entry;
1690edb6ab9bSMartin Storsjo }
1691edb6ab9bSMartin Storsjo 
16927ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
16937ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
16947ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
16957ba81d95SMartin Storsjo 
16967ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
16977ba81d95SMartin Storsjo   Reader.setOffset(Offset);
16987ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
16997ba81d95SMartin Storsjo   assert(Entry != nullptr);
17007ba81d95SMartin Storsjo   return *Entry;
17017ba81d95SMartin Storsjo }
17027ba81d95SMartin Storsjo 
1703f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1704efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17057ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1706f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1707efef15a0SEric Beckmann }
1708efef15a0SEric Beckmann 
17097ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17107ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17117ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
17127ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
17137ba81d95SMartin Storsjo }
17147ba81d95SMartin Storsjo 
1715f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1716f3404674SRafael Espindola   return getTableAtOffset(0);
1717efef15a0SEric Beckmann }
1718edb6ab9bSMartin Storsjo 
1719edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1720edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1721edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1722edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1723edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1724edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1725edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1726edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1727edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1728edb6ab9bSMartin Storsjo }
172994382217SMartin Storsjo 
173094382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
173194382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
173294382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
173394382217SMartin Storsjo     if (!Name)
173494382217SMartin Storsjo       return Name.takeError();
173594382217SMartin Storsjo 
173694382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
173794382217SMartin Storsjo       return load(O, S);
173894382217SMartin Storsjo   }
173994382217SMartin Storsjo   return createStringError(object_error::parse_failed,
174094382217SMartin Storsjo                            "no resource section found");
174194382217SMartin Storsjo }
174294382217SMartin Storsjo 
174394382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
174494382217SMartin Storsjo   Obj = O;
174594382217SMartin Storsjo   Section = S;
174694382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
174794382217SMartin Storsjo   if (!Contents)
174894382217SMartin Storsjo     return Contents.takeError();
174994382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
175094382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
175194382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
175294382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
175394382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
175494382217SMartin Storsjo     Relocs.push_back(&R);
175594382217SMartin Storsjo   std::sort(Relocs.begin(), Relocs.end(),
175694382217SMartin Storsjo             [](const coff_relocation *A, const coff_relocation *B) {
175794382217SMartin Storsjo               return A->VirtualAddress < B->VirtualAddress;
175894382217SMartin Storsjo             });
175994382217SMartin Storsjo   return Error::success();
176094382217SMartin Storsjo }
176194382217SMartin Storsjo 
176294382217SMartin Storsjo Expected<StringRef>
176394382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
176494382217SMartin Storsjo   if (!Obj)
176594382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
176694382217SMartin Storsjo 
176794382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
176894382217SMartin Storsjo   // the coff_resource_data_entry struct).
176994382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
177094382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
177194382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
177294382217SMartin Storsjo                               ulittle16_t(0)};
177394382217SMartin Storsjo   auto RelocsForOffset =
177494382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
177594382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
177694382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
177794382217SMartin Storsjo                        });
177894382217SMartin Storsjo 
177994382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
178094382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
178194382217SMartin Storsjo     // the expected type.
178294382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
178394382217SMartin Storsjo     uint16_t RVAReloc;
178494382217SMartin Storsjo     switch (Obj->getMachine()) {
178594382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
178694382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
178794382217SMartin Storsjo       break;
178894382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
178994382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
179094382217SMartin Storsjo       break;
179194382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
179294382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
179394382217SMartin Storsjo       break;
179494382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
179594382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
179694382217SMartin Storsjo       break;
179794382217SMartin Storsjo     default:
179894382217SMartin Storsjo       return createStringError(object_error::parse_failed,
179994382217SMartin Storsjo                                "unsupported architecture");
180094382217SMartin Storsjo     }
180194382217SMartin Storsjo     if (R.Type != RVAReloc)
180294382217SMartin Storsjo       return createStringError(object_error::parse_failed,
180394382217SMartin Storsjo                                "unexpected relocation type");
180494382217SMartin Storsjo     // Get the relocation's symbol
180594382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
180694382217SMartin Storsjo     if (!Sym)
180794382217SMartin Storsjo       return Sym.takeError();
180894382217SMartin Storsjo     // And the symbol's section
180977ecf90cSReid Kleckner     Expected<const coff_section *> Section =
181077ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
181177ecf90cSReid Kleckner     if (!Section)
181277ecf90cSReid Kleckner       return Section.takeError();
181394382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
181494382217SMartin Storsjo     // data it points at.
181594382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
181694382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
181777ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1818c55cf4afSBill Wendling       return std::move(E);
181994382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
182094382217SMartin Storsjo       return createStringError(object_error::parse_failed,
182194382217SMartin Storsjo                                "data outside of section");
182294382217SMartin Storsjo     // Return a reference to the data inside the section.
182394382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
182494382217SMartin Storsjo                      Entry.DataSize);
182594382217SMartin Storsjo   } else {
182694382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
182794382217SMartin Storsjo     if (Obj->isRelocatableObject())
182894382217SMartin Storsjo       return createStringError(object_error::parse_failed,
182994382217SMartin Storsjo                                "no relocation found for DataRVA");
183094382217SMartin Storsjo 
183194382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
183294382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
183394382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
183494382217SMartin Storsjo       if (VA >= S.getAddress() &&
183594382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
183694382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
183794382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
183894382217SMartin Storsjo         if (!Contents)
183994382217SMartin Storsjo           return Contents.takeError();
184094382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
184194382217SMartin Storsjo       }
184294382217SMartin Storsjo     }
184394382217SMartin Storsjo     return createStringError(object_error::parse_failed,
184494382217SMartin Storsjo                              "address not found in image");
184594382217SMartin Storsjo   }
184694382217SMartin Storsjo }
1847