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"
150ea52537SSimon 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>
312980ce98SHubert Tong #include <cinttypes>
32d341c932SEugene Zelenko #include <cstddef>
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>
581c03389cSReid Kleckner static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,
59236b0ca7SDavid Majnemer                        const uint64_t Size = sizeof(T)) {
6022cf54a7SArthur O'Dwyer   uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
61e03a135bSReid Kleckner   if (Error E = Binary::checkOffset(M, Addr, Size))
621c03389cSReid Kleckner     return E;
63ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
641c03389cSReid Kleckner   return Error::success();
651d6167fdSMichael J. Spencer }
661d6167fdSMichael J. Spencer 
679d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
689d2c15efSNico Rieck // prefixed slashes.
699d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
709d2c15efSNico Rieck   assert(Str.size() <= 6 && "String too long, possible overflow.");
719d2c15efSNico Rieck   if (Str.size() > 6)
729d2c15efSNico Rieck     return true;
739d2c15efSNico Rieck 
749d2c15efSNico Rieck   uint64_t Value = 0;
759d2c15efSNico Rieck   while (!Str.empty()) {
769d2c15efSNico Rieck     unsigned CharVal;
779d2c15efSNico Rieck     if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
789d2c15efSNico Rieck       CharVal = Str[0] - 'A';
799d2c15efSNico Rieck     else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
809d2c15efSNico Rieck       CharVal = Str[0] - 'a' + 26;
819d2c15efSNico Rieck     else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
829d2c15efSNico Rieck       CharVal = Str[0] - '0' + 52;
839d2c15efSNico Rieck     else if (Str[0] == '+') // 62
845500b07cSRui Ueyama       CharVal = 62;
859d2c15efSNico Rieck     else if (Str[0] == '/') // 63
865500b07cSRui Ueyama       CharVal = 63;
879d2c15efSNico Rieck     else
889d2c15efSNico Rieck       return true;
899d2c15efSNico Rieck 
909d2c15efSNico Rieck     Value = (Value * 64) + CharVal;
919d2c15efSNico Rieck     Str = Str.substr(1);
929d2c15efSNico Rieck   }
939d2c15efSNico Rieck 
949d2c15efSNico Rieck   if (Value > std::numeric_limits<uint32_t>::max())
959d2c15efSNico Rieck     return true;
969d2c15efSNico Rieck 
979d2c15efSNico Rieck   Result = static_cast<uint32_t>(Value);
989d2c15efSNico Rieck   return false;
999d2c15efSNico Rieck }
1009d2c15efSNico Rieck 
10144f51e51SDavid Majnemer template <typename coff_symbol_type>
10244f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
10344f51e51SDavid Majnemer   const coff_symbol_type *Addr =
10444f51e51SDavid Majnemer       reinterpret_cast<const coff_symbol_type *>(Ref.p);
1051d6167fdSMichael J. Spencer 
10622cf54a7SArthur O'Dwyer   assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr)));
1071d6167fdSMichael J. Spencer #ifndef NDEBUG
1081d6167fdSMichael J. Spencer   // Verify that the symbol points to a valid entry in the symbol table.
10922cf54a7SArthur O'Dwyer   uintptr_t Offset =
11022cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<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 
12722cf54a7SArthur O'Dwyer   uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -
12822cf54a7SArthur O'Dwyer                      reinterpret_cast<uintptr_t>(SectionTable);
1298ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1301d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1311d6167fdSMichael J. Spencer #endif
1321d6167fdSMichael J. Spencer 
1338ff24d25SRui Ueyama   return Addr;
1341d6167fdSMichael J. Spencer }
1351d6167fdSMichael J. Spencer 
1365e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
137236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13844f51e51SDavid Majnemer   if (SymbolTable16) {
13944f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1408ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
141236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14244f51e51SDavid Majnemer   } else if (SymbolTable32) {
14344f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14444f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
145236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14644f51e51SDavid Majnemer   } else {
14744f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14844f51e51SDavid Majnemer   }
1491d6167fdSMichael J. Spencer }
1501d6167fdSMichael J. Spencer 
15181e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15277ecf90cSReid Kleckner   return getSymbolName(getCOFFSymbol(Ref));
1538e90adafSMichael J. Spencer }
1548e90adafSMichael J. Spencer 
155be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
156be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
157991af666SRafael Espindola }
158991af666SRafael Espindola 
1596b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1606b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1616b2bba14SDavide Italiano   // up to 32 bytes.
1626b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16303a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1646b2bba14SDavide Italiano }
1656b2bba14SDavide Italiano 
166931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
167ff6a0b6aSXing GUO   uint64_t Result = cantFail(getSymbolValue(Ref));
16844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
169c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
170991af666SRafael Espindola 
171991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
172991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
173ed067c45SRafael Espindola     return Result;
17454c9f3daSRafael Espindola 
17577ecf90cSReid Kleckner   Expected<const coff_section *> Section = getSection(SectionNumber);
17677ecf90cSReid Kleckner   if (!Section)
17777ecf90cSReid Kleckner     return Section.takeError();
17877ecf90cSReid Kleckner   Result += (*Section)->VirtualAddress;
17947ea9eceSReid Kleckner 
18047ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18147ea9eceSReid Kleckner   // return virtual addresses.
18221427adaSReid Kleckner   Result += getImageBase();
18347ea9eceSReid Kleckner 
184ed067c45SRafael Espindola   return Result;
185c7d7c6fbSDavid Majnemer }
186c7d7c6fbSDavid Majnemer 
1877bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
18844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
189c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
19044f51e51SDavid Majnemer 
191e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
192e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1932fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1942fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1952fa80cc5SRafael Espindola   if (Symb.isCommon())
1962fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1972fa80cc5SRafael Espindola   if (Symb.isFileRecord())
1982fa80cc5SRafael Espindola     return SymbolRef::ST_File;
1992fa80cc5SRafael Espindola 
2001a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2012fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2022fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2032fa80cc5SRafael Espindola 
2042fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2052fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2062fa80cc5SRafael Espindola 
2072fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
20875d1cf33SBenjamin Kramer }
20975d1cf33SBenjamin Kramer 
210ac00376aSvgxbj Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21144f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21220122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21375d1cf33SBenjamin Kramer 
214c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2159dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2161df4b84dSDavid Meyer 
217a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2181df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
219a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
220a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2211079ef8dSMartell Malone   }
2221df4b84dSDavid Meyer 
22344f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2241df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2251df4b84dSDavid Meyer 
226c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
227c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
228c7d7c6fbSDavid Majnemer 
229c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
230c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
231c7d7c6fbSDavid Majnemer 
232c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
233c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
234c7d7c6fbSDavid Majnemer 
235a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
236c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
237c7d7c6fbSDavid Majnemer 
23820122a43SRafael Espindola   return Result;
23901759754SMichael J. Spencer }
24001759754SMichael J. Spencer 
241d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
242c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2435eb02e45SRafael Espindola   return Symb.getValue();
2448e90adafSMichael J. Spencer }
2458e90adafSMichael J. Spencer 
2467bd8d994SKevin Enderby Expected<section_iterator>
2478bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
24844f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2498bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2508bab889bSRafael Espindola     return section_end();
25177ecf90cSReid Kleckner   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
25277ecf90cSReid Kleckner   if (!Sec)
25377ecf90cSReid Kleckner     return Sec.takeError();
2548bab889bSRafael Espindola   DataRefImpl Ret;
25577ecf90cSReid Kleckner   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2568bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25732173153SMichael J. Spencer }
25832173153SMichael J. Spencer 
2596bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2606bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2616bf32210SRafael Espindola   return Symb.getSectionNumber();
2626bf32210SRafael Espindola }
2636bf32210SRafael Espindola 
2645e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2658ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2668ff24d25SRui Ueyama   Sec += 1;
2678ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2688e90adafSMichael J. Spencer }
2698e90adafSMichael J. Spencer 
2708be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2718ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2728be28cdcSFangrui Song   return getSectionName(Sec);
2738e90adafSMichael J. Spencer }
2748e90adafSMichael J. Spencer 
27580291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2768ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2777c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2787c6a071bSDavid Majnemer 
2797c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2807c6a071bSDavid Majnemer   // return virtual addresses.
28121427adaSReid Kleckner   Result += getImageBase();
2827c6a071bSDavid Majnemer   return Result;
2838e90adafSMichael J. Spencer }
2848e90adafSMichael J. Spencer 
285a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
286a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
287a25d329bSGeorge Rimar }
288a25d329bSGeorge Rimar 
28980291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
290a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2918e90adafSMichael J. Spencer }
2928e90adafSMichael J. Spencer 
293e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
294e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2958ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2969da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
297e1cb2c0fSFangrui Song   if (Error E = getSectionContents(Sec, Res))
298c55cf4afSBill Wendling     return std::move(E);
299e1cb2c0fSFangrui Song   return Res;
3008e90adafSMichael J. Spencer }
3018e90adafSMichael J. Spencer 
30280291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3038ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
304511391feSDavid Majnemer   return Sec->getAlignment();
3057989460aSMichael J. Spencer }
3067989460aSMichael J. Spencer 
307401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
308401e4e57SGeorge Rimar   return false;
309401e4e57SGeorge Rimar }
310401e4e57SGeorge Rimar 
31180291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3128ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31380291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3148e90adafSMichael J. Spencer }
3158e90adafSMichael J. Spencer 
31680291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3178ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31880291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
319800619f2SMichael J. Spencer }
320800619f2SMichael J. Spencer 
32180291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3228ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3231a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3241a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3251a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3261a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
327800619f2SMichael J. Spencer }
328800619f2SMichael J. Spencer 
32929d253c4SDjordje Todorovic // The .debug sections are the only debug sections for COFF
33029d253c4SDjordje Todorovic // (\see MCObjectFileInfo.cpp).
331*bf809cd1SEsme-Yi bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {
332*bf809cd1SEsme-Yi   Expected<StringRef> SectionNameOrErr = getSectionName(Ref);
333*bf809cd1SEsme-Yi   if (!SectionNameOrErr) {
334*bf809cd1SEsme-Yi     // TODO: Report the error message properly.
335*bf809cd1SEsme-Yi     consumeError(SectionNameOrErr.takeError());
336*bf809cd1SEsme-Yi     return false;
337*bf809cd1SEsme-Yi   }
338*bf809cd1SEsme-Yi   StringRef SectionName = SectionNameOrErr.get();
33929d253c4SDjordje Todorovic   return SectionName.startswith(".debug");
34029d253c4SDjordje Todorovic }
34129d253c4SDjordje Todorovic 
3426bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3436bf32210SRafael Espindola   uintptr_t Offset =
34422cf54a7SArthur O'Dwyer       Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3456bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3466bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3476bf32210SRafael Espindola }
3486bf32210SRafael Espindola 
34980291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3508ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3511a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3521a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3531a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3542138ef6dSPreston Gurd }
3552138ef6dSPreston Gurd 
356e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
357e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
358e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
359e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
360e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
361e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
362e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
363e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
3641c03389cSReid Kleckner     if (Error E = getObject(FirstReloc, M,
3651c03389cSReid Kleckner                             reinterpret_cast<const coff_relocation *>(
3661c03389cSReid Kleckner                                 base + Sec->PointerToRelocations))) {
3671c03389cSReid Kleckner       consumeError(std::move(E));
368e830c60dSDavid Majnemer       return 0;
3691c03389cSReid Kleckner     }
37098fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
37198fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
372e830c60dSDavid Majnemer   }
373e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
374e830c60dSDavid Majnemer }
375e830c60dSDavid Majnemer 
37694751be7SDavid Majnemer static const coff_relocation *
37794751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37894751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37994751be7SDavid Majnemer   if (!NumRelocs)
38094751be7SDavid Majnemer     return nullptr;
381827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
38294751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
383827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
384827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
385827c8a2bSRui Ueyama     // relocations.
386827c8a2bSRui Ueyama     begin++;
387827c8a2bSRui Ueyama   }
38822cf54a7SArthur O'Dwyer   if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
389e03a135bSReid Kleckner                                    sizeof(coff_relocation) * NumRelocs)) {
390e03a135bSReid Kleckner     consumeError(std::move(E));
39194751be7SDavid Majnemer     return nullptr;
392e03a135bSReid Kleckner   }
39394751be7SDavid Majnemer   return begin;
394827c8a2bSRui Ueyama }
39594751be7SDavid Majnemer 
39694751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
39794751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
39894751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
39976d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
40076d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
40194751be7SDavid Majnemer   DataRefImpl Ret;
40294751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
4038ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
404e5fd0047SMichael J. Spencer }
405e5fd0047SMichael J. Spencer 
4068ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4078ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
40894751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
40994751be7SDavid Majnemer   if (I)
41094751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4118ff24d25SRui Ueyama   DataRefImpl Ret;
41294751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4138ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
414e5fd0047SMichael J. Spencer }
415e5fd0047SMichael J. Spencer 
416c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
4171c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() {
41844f51e51SDavid Majnemer   if (COFFHeader)
4191c03389cSReid Kleckner     if (Error E = getObject(
420236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
421236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4221c03389cSReid Kleckner       return E;
42344f51e51SDavid Majnemer 
42444f51e51SDavid Majnemer   if (COFFBigObjHeader)
4251c03389cSReid Kleckner     if (Error E = getObject(
426236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
427236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4281c03389cSReid Kleckner       return E;
429c2bed429SRui Ueyama 
430c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
431c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
432c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
433f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
43444f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
435f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
436c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
4371c03389cSReid Kleckner   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4381c03389cSReid Kleckner     return E;
439c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
4401c03389cSReid Kleckner   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4411c03389cSReid Kleckner     return E;
442c2bed429SRui Ueyama 
443773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
444773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
445773a5795SNico Rieck   if (StringTableSize < 4)
446773a5795SNico Rieck     StringTableSize = 4;
447773a5795SNico Rieck 
448c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
449773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
4501c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
4511c03389cSReid Kleckner   return Error::success();
452c2bed429SRui Ueyama }
453c2bed429SRui Ueyama 
45421427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
455e94fef7bSReid Kleckner   if (PE32Header)
45621427adaSReid Kleckner     return PE32Header->ImageBase;
457e94fef7bSReid Kleckner   else if (PE32PlusHeader)
45821427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
45921427adaSReid Kleckner   // This actually comes up in practice.
46021427adaSReid Kleckner   return 0;
461e94fef7bSReid Kleckner }
462e94fef7bSReid Kleckner 
463215a586cSRui Ueyama // Returns the file offset for the given VA.
4641c03389cSReid Kleckner Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
46521427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
466b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
467b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
468b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
469215a586cSRui Ueyama }
470215a586cSRui Ueyama 
471c2bed429SRui Ueyama // Returns the file offset for the given RVA.
4721c03389cSReid Kleckner Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
47327dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
47427dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
475c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
476c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
477215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
478215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
47922cf54a7SArthur O'Dwyer       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
48022cf54a7SArthur O'Dwyer             Offset;
4811c03389cSReid Kleckner       return Error::success();
482c2bed429SRui Ueyama     }
483c2bed429SRui Ueyama   }
4841c03389cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
485c2bed429SRui Ueyama }
486c2bed429SRui Ueyama 
4871c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4882da433eaSReid Kleckner                                            ArrayRef<uint8_t> &Contents) const {
4892da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4902da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4912da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4922da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4932da433eaSReid Kleckner     // overflow.
4942da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4952da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4962da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
49722cf54a7SArthur O'Dwyer       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
49822cf54a7SArthur O'Dwyer                         Section->PointerToRawData + OffsetIntoSection;
4992da433eaSReid Kleckner       Contents =
5002da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5011c03389cSReid Kleckner       return Error::success();
5022da433eaSReid Kleckner     }
5032da433eaSReid Kleckner   }
5041c03389cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
5052da433eaSReid Kleckner }
5062da433eaSReid Kleckner 
507c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
508c2bed429SRui Ueyama // table entry.
5091c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
510db4ed0bdSRafael Espindola                                   StringRef &Name) const {
511c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5121c03389cSReid Kleckner   if (Error E = getRvaPtr(Rva, IntPtr))
5131c03389cSReid Kleckner     return E;
514c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
515c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
516c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5171c03389cSReid Kleckner   return Error::success();
518c2bed429SRui Ueyama }
519c2bed429SRui Ueyama 
5201c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
52101528021SSaleem Abdulrasool                                       const codeview::DebugInfo *&PDBInfo,
5222da433eaSReid Kleckner                                       StringRef &PDBFileName) const {
5232da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5241c03389cSReid Kleckner   if (Error E = getRvaAndSizeAsBytes(
5252da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5261c03389cSReid Kleckner     return E;
52701528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5281c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
52901528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
53001528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5312da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5322da433eaSReid Kleckner                           InfoBytes.size());
5332da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5342da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5351c03389cSReid Kleckner   return Error::success();
5362da433eaSReid Kleckner }
5372da433eaSReid Kleckner 
5381c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
539f27f3f84SReid Kleckner                                       StringRef &PDBFileName) const {
540f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
541f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
542f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
543f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
544f27f3f84SReid Kleckner   PDBInfo = nullptr;
545f27f3f84SReid Kleckner   PDBFileName = StringRef();
5461c03389cSReid Kleckner   return Error::success();
547f27f3f84SReid Kleckner }
548f27f3f84SReid Kleckner 
549c2bed429SRui Ueyama // Find the import table.
5501c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() {
551c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
552c2bed429SRui Ueyama   // the import table, do nothing.
5531c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5541c03389cSReid Kleckner   if (!DataEntry)
5551c03389cSReid Kleckner     return Error::success();
556c2bed429SRui Ueyama 
557c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
558c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5591c03389cSReid Kleckner     return Error::success();
560c2bed429SRui Ueyama 
561c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
562c2bed429SRui Ueyama 
563c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
564c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
565c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5661c03389cSReid Kleckner   if (Error E = getRvaPtr(ImportTableRva, IntPtr))
5671c03389cSReid Kleckner     return E;
568e03a135bSReid Kleckner   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5691c03389cSReid Kleckner     return E;
570c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5711c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5721c03389cSReid Kleckner   return Error::success();
573ad882ba8SRui Ueyama }
574c2bed429SRui Ueyama 
57515d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
5761c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() {
5771c03389cSReid Kleckner   const data_directory *DataEntry =
5781c03389cSReid Kleckner       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
5791c03389cSReid Kleckner   if (!DataEntry)
5801c03389cSReid Kleckner     return Error::success();
58115d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5821c03389cSReid Kleckner     return Error::success();
58315d99359SRui Ueyama 
58415d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
58515d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
58615d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
58715d99359SRui Ueyama 
58815d99359SRui Ueyama   uintptr_t IntPtr = 0;
5891c03389cSReid Kleckner   if (Error E = getRvaPtr(RVA, IntPtr))
5901c03389cSReid Kleckner     return E;
59115d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
59215d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5931c03389cSReid Kleckner   return Error::success();
59415d99359SRui Ueyama }
59515d99359SRui Ueyama 
596ad882ba8SRui Ueyama // Find the export table.
5971c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() {
598ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
599ad882ba8SRui Ueyama   // the export table, do nothing.
6001c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6011c03389cSReid Kleckner   if (!DataEntry)
6021c03389cSReid Kleckner     return Error::success();
603ad882ba8SRui Ueyama 
604ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
605ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6061c03389cSReid Kleckner     return Error::success();
607ad882ba8SRui Ueyama 
608ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
609ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
6101c03389cSReid Kleckner   if (Error E = getRvaPtr(ExportTableRva, IntPtr))
6111c03389cSReid Kleckner     return E;
61224fc2d64SRui Ueyama   ExportDirectory =
61324fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6141c03389cSReid Kleckner   return Error::success();
615c2bed429SRui Ueyama }
616c2bed429SRui Ueyama 
6171c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() {
6181c03389cSReid Kleckner   const data_directory *DataEntry =
6191c03389cSReid Kleckner       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6201c03389cSReid Kleckner   if (!DataEntry)
6211c03389cSReid Kleckner     return Error::success();
62274e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6231c03389cSReid Kleckner     return Error::success();
62474e85130SRui Ueyama 
62574e85130SRui Ueyama   uintptr_t IntPtr = 0;
6261c03389cSReid Kleckner   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6271c03389cSReid Kleckner     return E;
62874e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
62974e85130SRui Ueyama       IntPtr);
63074e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
63174e85130SRui Ueyama       IntPtr + DataEntry->Size);
632893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
633893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6341c03389cSReid Kleckner   return Error::success();
63574e85130SRui Ueyama }
63674e85130SRui Ueyama 
6371c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() {
6382da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6391c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6401c03389cSReid Kleckner   if (!DataEntry)
6411c03389cSReid Kleckner     return Error::success();
6422da433eaSReid Kleckner 
6432da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6442da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6451c03389cSReid Kleckner     return Error::success();
6462da433eaSReid Kleckner 
6472da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6482da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6491c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
6502da433eaSReid Kleckner 
6512da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6521c03389cSReid Kleckner   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6531c03389cSReid Kleckner     return E;
6542da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
655893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
656893c6469SNico Weber       IntPtr + DataEntry->Size);
657893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
658893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6591c03389cSReid Kleckner   return Error::success();
6602da433eaSReid Kleckner }
6612da433eaSReid Kleckner 
662568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() {
663568035acSLuqman Aden   // Get the RVA of the TLS directory. Do nothing if it does not exist.
664568035acSLuqman Aden   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
665568035acSLuqman Aden   if (!DataEntry)
666568035acSLuqman Aden     return Error::success();
667568035acSLuqman Aden 
668568035acSLuqman Aden   // Do nothing if the RVA is NULL.
669568035acSLuqman Aden   if (DataEntry->RelativeVirtualAddress == 0)
670568035acSLuqman Aden     return Error::success();
671568035acSLuqman Aden 
672568035acSLuqman Aden   uint64_t DirSize =
673568035acSLuqman Aden       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
674568035acSLuqman Aden 
675568035acSLuqman Aden   // Check that the size is correct.
676568035acSLuqman Aden   if (DataEntry->Size != DirSize)
677568035acSLuqman Aden     return createStringError(
678568035acSLuqman Aden         object_error::parse_failed,
6792980ce98SHubert Tong         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
680568035acSLuqman Aden         static_cast<uint32_t>(DataEntry->Size), DirSize);
681568035acSLuqman Aden 
682568035acSLuqman Aden   uintptr_t IntPtr = 0;
683568035acSLuqman Aden   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
684568035acSLuqman Aden     return E;
685568035acSLuqman Aden 
686568035acSLuqman Aden   if (is64())
687568035acSLuqman Aden     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
688568035acSLuqman Aden   else
689568035acSLuqman Aden     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
690568035acSLuqman Aden 
691568035acSLuqman Aden   return Error::success();
692568035acSLuqman Aden }
693568035acSLuqman Aden 
6941c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() {
695b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6961c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
6971c03389cSReid Kleckner   if (!DataEntry)
6981c03389cSReid Kleckner     return Error::success();
699b7d716c0SReid Kleckner 
700b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
701b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
7021c03389cSReid Kleckner     return Error::success();
703b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
7041c03389cSReid Kleckner   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
7051c03389cSReid Kleckner     return E;
706b7d716c0SReid Kleckner 
707b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
7081c03389cSReid Kleckner   return Error::success();
709b7d716c0SReid Kleckner }
710b7d716c0SReid Kleckner 
71139772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>>
71239772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) {
71339772063SReid Kleckner   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
71439772063SReid Kleckner   if (Error E = Obj->initialize())
71539772063SReid Kleckner     return std::move(E);
71639772063SReid Kleckner   return std::move(Obj);
71739772063SReid Kleckner }
71839772063SReid Kleckner 
71939772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
72048af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
72144f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
72244f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
72344f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
72439772063SReid Kleckner       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
72539772063SReid Kleckner       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
72639772063SReid Kleckner       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
727568035acSLuqman Aden       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
728568035acSLuqman Aden       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
72939772063SReid Kleckner 
730101fbc01SNico Weber Error COFFObjectFile::initialize() {
7311d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
73239772063SReid Kleckner   std::error_code EC;
73348af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
73439772063SReid Kleckner     return errorCodeToError(EC);
735ee066fc4SEric Christopher 
73682ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
73782ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
73882ebd8e3SRui Ueyama 
73982ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
74082ebd8e3SRui Ueyama   // it is placed right after COFF header.
7418ff24d25SRui Ueyama   bool HasPEHeader = false;
742ee066fc4SEric Christopher 
7431d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
74450267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
745ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
746ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
74750267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
74850267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
74950267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
75082ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
75150267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
75239772063SReid Kleckner         return errorCodeToError(object_error::parse_failed);
7531d6167fdSMichael J. Spencer       }
75444f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7558ff24d25SRui Ueyama       HasPEHeader = true;
756ee066fc4SEric Christopher     }
75750267222SDavid Majnemer   }
758ee066fc4SEric Christopher 
7591c03389cSReid Kleckner   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
7601c03389cSReid Kleckner     return E;
76144f51e51SDavid Majnemer 
76244f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
76344f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
76444f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
76544f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
76644f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
7671c03389cSReid Kleckner     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
7681c03389cSReid Kleckner       return E;
76944f51e51SDavid Majnemer 
77044f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
77144f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
77244f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
77344f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
77444f51e51SDavid Majnemer       COFFHeader = nullptr;
77544f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
77644f51e51SDavid Majnemer     } else {
77744f51e51SDavid Majnemer       // It's not a bigobj.
77844f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
77944f51e51SDavid Majnemer     }
78044f51e51SDavid Majnemer   }
78144f51e51SDavid Majnemer   if (COFFHeader) {
78244f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
78344f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7847d099195SRui Ueyama     EC = std::error_code();
78582ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
78682ebd8e3SRui Ueyama 
78744f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
78839772063SReid Kleckner       return errorCodeToError(EC);
78944f51e51SDavid Majnemer   }
79044f51e51SDavid Majnemer 
7918ff24d25SRui Ueyama   if (HasPEHeader) {
79210ed9ddcSRui Ueyama     const pe32_header *Header;
7931c03389cSReid Kleckner     if (Error E = getObject(Header, Data, base() + CurPtr))
7941c03389cSReid Kleckner       return E;
79510ed9ddcSRui Ueyama 
79610ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
79710ed9ddcSRui Ueyama     uint64_t DataDirSize;
79850267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
79910ed9ddcSRui Ueyama       PE32Header = Header;
80010ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
80110ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
80250267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
80310ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
80410ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
80510ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
80610ed9ddcSRui Ueyama     } else {
80710ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
80839772063SReid Kleckner       return errorCodeToError(object_error::parse_failed);
809ed64342bSRui Ueyama     }
8101c03389cSReid Kleckner     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8111c03389cSReid Kleckner       return E;
812f53c8cb4SRui Ueyama   }
813776c6828SRui Ueyama 
8148950a538SRui Ueyama   if (COFFHeader)
8158950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
8168950a538SRui Ueyama 
8171c03389cSReid Kleckner   assert(COFFHeader || COFFBigObjHeader);
8181c03389cSReid Kleckner 
8191c03389cSReid Kleckner   if (Error E =
8201c03389cSReid Kleckner           getObject(SectionTable, Data, base() + CurPtr,
8211c03389cSReid Kleckner                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8221c03389cSReid Kleckner     return E;
8231d6167fdSMichael J. Spencer 
824c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
825236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
8261c03389cSReid Kleckner     if (Error E = initSymbolTablePtr()) {
8271c03389cSReid Kleckner       // Recover from errors reading the symbol table.
8281c03389cSReid Kleckner       consumeError(std::move(E));
829ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
830ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
831ac8cfab5SDavid Majnemer       StringTable = nullptr;
832ac8cfab5SDavid Majnemer       StringTableSize = 0;
833ac8cfab5SDavid Majnemer     }
834236b0ca7SDavid Majnemer   } else {
835236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
836236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
83739772063SReid Kleckner       return errorCodeToError(object_error::parse_failed);
838236b0ca7SDavid Majnemer     }
839236b0ca7SDavid Majnemer   }
8408e90adafSMichael J. Spencer 
841c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
8421c03389cSReid Kleckner   if (Error E = initImportTablePtr())
8431c03389cSReid Kleckner     return E;
8441c03389cSReid Kleckner   if (Error E = initDelayImportTablePtr())
8451c03389cSReid Kleckner     return E;
8461d6167fdSMichael J. Spencer 
847ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
8481c03389cSReid Kleckner   if (Error E = initExportTablePtr())
8491c03389cSReid Kleckner     return E;
850ad882ba8SRui Ueyama 
85174e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
8521c03389cSReid Kleckner   if (Error E = initBaseRelocPtr())
8531c03389cSReid Kleckner     return E;
85474e85130SRui Ueyama 
855568035acSLuqman Aden   // Initialize the pointer to the debug directory.
8561c03389cSReid Kleckner   if (Error E = initDebugDirectoryPtr())
8571c03389cSReid Kleckner     return E;
8582da433eaSReid Kleckner 
859568035acSLuqman Aden   // Initialize the pointer to the TLS directory.
860568035acSLuqman Aden   if (Error E = initTLSDirectoryPtr())
861568035acSLuqman Aden     return E;
862568035acSLuqman Aden 
8631c03389cSReid Kleckner   if (Error E = initLoadConfigPtr())
8641c03389cSReid Kleckner     return E;
865b7d716c0SReid Kleckner 
86639772063SReid Kleckner   return Error::success();
8678e90adafSMichael J. Spencer }
8688e90adafSMichael J. Spencer 
869435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8708ff24d25SRui Ueyama   DataRefImpl Ret;
87144f51e51SDavid Majnemer   Ret.p = getSymbolTable();
872f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8738e90adafSMichael J. Spencer }
8748e90adafSMichael J. Spencer 
875435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8768e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8778ff24d25SRui Ueyama   DataRefImpl Ret;
8788ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
879f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8808e90adafSMichael J. Spencer }
8818e90adafSMichael J. Spencer 
882bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
883ad7b7e73SDavid Majnemer   if (!ImportDirectory)
884ad7b7e73SDavid Majnemer     return import_directory_end();
8851c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
886ad7b7e73SDavid Majnemer     return import_directory_end();
887a045b73aSRui Ueyama   return import_directory_iterator(
888a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
889c2bed429SRui Ueyama }
890c2bed429SRui Ueyama 
891bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
892a045b73aSRui Ueyama   return import_directory_iterator(
893ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
894c2bed429SRui Ueyama }
895c429b80dSDavid Meyer 
89615d99359SRui Ueyama delay_import_directory_iterator
89715d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
89815d99359SRui Ueyama   return delay_import_directory_iterator(
89915d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
90015d99359SRui Ueyama }
90115d99359SRui Ueyama 
90215d99359SRui Ueyama delay_import_directory_iterator
90315d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
90415d99359SRui Ueyama   return delay_import_directory_iterator(
90515d99359SRui Ueyama       DelayImportDirectoryEntryRef(
90615d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
90715d99359SRui Ueyama }
90815d99359SRui Ueyama 
909ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
910ad882ba8SRui Ueyama   return export_directory_iterator(
911ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
912ad882ba8SRui Ueyama }
913ad882ba8SRui Ueyama 
914ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
9152617dcceSCraig Topper   if (!ExportDirectory)
9162617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9178ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
918ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
9198ff24d25SRui Ueyama   return export_directory_iterator(Ref);
920ad882ba8SRui Ueyama }
921ad882ba8SRui Ueyama 
922b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
9238ff24d25SRui Ueyama   DataRefImpl Ret;
9248ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9258ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9268e90adafSMichael J. Spencer }
9278e90adafSMichael J. Spencer 
928b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
9298ff24d25SRui Ueyama   DataRefImpl Ret;
93044f51e51SDavid Majnemer   int NumSections =
93144f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9328ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9338ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9348e90adafSMichael J. Spencer }
9358e90adafSMichael J. Spencer 
93674e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
93774e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
93874e85130SRui Ueyama }
93974e85130SRui Ueyama 
94074e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
94174e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
94274e85130SRui Ueyama }
94374e85130SRui Ueyama 
9448e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
94543c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
9468e90adafSMichael J. Spencer }
9478e90adafSMichael J. Spencer 
9488e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
94944f51e51SDavid Majnemer   switch(getMachine()) {
9508e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9518e90adafSMichael J. Spencer     return "COFF-i386";
9528e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9538e90adafSMichael J. Spencer     return "COFF-x86-64";
9549b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9559b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
9561eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9571eff5c9cSMartell Malone     return "COFF-ARM64";
9588e90adafSMichael J. Spencer   default:
9598e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
9608e90adafSMichael J. Spencer   }
9618e90adafSMichael J. Spencer }
9628e90adafSMichael J. Spencer 
963260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
96444f51e51SDavid Majnemer   switch (getMachine()) {
9658e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9668e90adafSMichael J. Spencer     return Triple::x86;
9678e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9688e90adafSMichael J. Spencer     return Triple::x86_64;
9699b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9709b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9711eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9721eff5c9cSMartell Malone     return Triple::aarch64;
9738e90adafSMichael J. Spencer   default:
9748e90adafSMichael J. Spencer     return Triple::UnknownArch;
9758e90adafSMichael J. Spencer   }
9768e90adafSMichael J. Spencer }
9778e90adafSMichael J. Spencer 
978d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
979d2af4d6fSPaul Semel   if (PE32Header)
980d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
981d2af4d6fSPaul Semel   return 0;
982d2af4d6fSPaul Semel }
983d2af4d6fSPaul Semel 
984979fb40bSRui Ueyama iterator_range<import_directory_iterator>
985979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
986979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
987979fb40bSRui Ueyama }
988979fb40bSRui Ueyama 
989979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
990979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
991979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
992979fb40bSRui Ueyama                     delay_import_directory_end());
993979fb40bSRui Ueyama }
994979fb40bSRui Ueyama 
995979fb40bSRui Ueyama iterator_range<export_directory_iterator>
996979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
997979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
998979fb40bSRui Ueyama }
999979fb40bSRui Ueyama 
100074e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
100174e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
100274e85130SRui Ueyama }
100374e85130SRui Ueyama 
10041c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
10051c03389cSReid Kleckner   if (!DataDirectory)
10061c03389cSReid Kleckner     return nullptr;
100710ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
100810ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
100910ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
10101c03389cSReid Kleckner   if (Index >= NumEnt)
10111c03389cSReid Kleckner     return nullptr;
10121c03389cSReid Kleckner   return &DataDirectory[Index];
1013ed64342bSRui Ueyama }
1014ed64342bSRui Ueyama 
101577ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
101677ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
101777ecf90cSReid Kleckner   // but callers rely on this to return null.
1018236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
101977ecf90cSReid Kleckner     return (const coff_section *)nullptr;
1020236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10211d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
102277ecf90cSReid Kleckner     return SectionTable + (Index - 1);
10238e90adafSMichael J. Spencer   }
102477ecf90cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
1025236b0ca7SDavid Majnemer }
10268e90adafSMichael J. Spencer 
102777ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10281d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10291d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
103077ecf90cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
10318ff24d25SRui Ueyama   if (Offset >= StringTableSize)
103277ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
103377ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
10348e90adafSMichael J. Spencer }
1035022ecdf2SBenjamin Kramer 
103677ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
103777ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
1038e40d30f3SRui Ueyama }
1039e40d30f3SRui Ueyama 
104077ecf90cSReid Kleckner Expected<StringRef>
104177ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
104289a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
104377ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
104477ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
104589a7a5eaSMichael J. Spencer 
104689a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
104777ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
104877ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
104977ecf90cSReid Kleckner 
105089a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
105177ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
105289a7a5eaSMichael J. Spencer }
105389a7a5eaSMichael J. Spencer 
105444f51e51SDavid Majnemer ArrayRef<uint8_t>
105544f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10562617dcceSCraig Topper   const uint8_t *Aux = nullptr;
105771757ef3SMarshall Clow 
105844f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
105944f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
106071757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
106144f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
106271757ef3SMarshall Clow #ifndef NDEBUG
10638ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10648ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
106544f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
106644f51e51SDavid Majnemer         Offset >=
106744f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
106871757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
106971757ef3SMarshall Clow 
107044f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
107144f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
107271757ef3SMarshall Clow #endif
1073bfb85e67SMarshall Clow   }
107444f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
107571757ef3SMarshall Clow }
107671757ef3SMarshall Clow 
107774e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
107874e7d260SMartin Storsjo   uintptr_t Offset =
107974e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
108074e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
108174e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
108274e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
108374e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
108474e7d260SMartin Storsjo   return Index;
108574e7d260SMartin Storsjo }
108674e7d260SMartin Storsjo 
10878be28cdcSFangrui Song Expected<StringRef>
10888be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
108953c2d547SMichael J. Spencer   StringRef Name;
109044f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
109153c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
109253c2d547SMichael J. Spencer     Name = Sec->Name;
109353c2d547SMichael J. Spencer   else
109453c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
109544f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
109653c2d547SMichael J. Spencer 
109753c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10982314b3deSDavid Majnemer   if (Name.startswith("/")) {
109953c2d547SMichael J. Spencer     uint32_t Offset;
11002314b3deSDavid Majnemer     if (Name.startswith("//")) {
11019d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
11028be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1103400b6c08Sserge-sans-paille                                  "invalid section name");
11049d2c15efSNico Rieck     } else {
110553c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
11068be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
11078be28cdcSFangrui Song                                  "invalid section name");
11089d2c15efSNico Rieck     }
110977ecf90cSReid Kleckner     return getString(Offset);
111053c2d547SMichael J. Spencer   }
111153c2d547SMichael J. Spencer 
11128be28cdcSFangrui Song   return Name;
111353c2d547SMichael J. Spencer }
111453c2d547SMichael J. Spencer 
1115a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1116a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1117a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1118a9ee5c06SDavid Majnemer   //
1119a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1120d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1121a9ee5c06SDavid Majnemer   //
1122a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1123a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1124a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1125a9ee5c06SDavid Majnemer   // considered to be zero.
1126d5297ee7SRui Ueyama   if (getDOSHeader())
1127d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1128d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1129a9ee5c06SDavid Majnemer }
1130a9ee5c06SDavid Majnemer 
1131e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11329da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1133e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1134e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1135e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1136e1cb2c0fSFangrui Song     return Error::success();
11379da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11389da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11399da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
114022cf54a7SArthur O'Dwyer   uintptr_t ConStart =
114122cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
1142a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1143e03a135bSReid Kleckner   if (Error E = checkOffset(Data, ConStart, SectionSize))
1144e03a135bSReid Kleckner     return E;
1145a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1146e1cb2c0fSFangrui Song   return Error::success();
11479da9e693SMichael J. Spencer }
11489da9e693SMichael J. Spencer 
1149022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1150e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1151022ecdf2SBenjamin Kramer }
11528ff24d25SRui Ueyama 
11535e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1154e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1155e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1156022ecdf2SBenjamin Kramer }
11578ff24d25SRui Ueyama 
115896d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
115958323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
116096d071cdSRafael Espindola   return R->VirtualAddress;
1161cbe72fc9SDanil Malyshev }
11628ff24d25SRui Ueyama 
1163806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1164022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11658ff24d25SRui Ueyama   DataRefImpl Ref;
1166236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1167236b0ca7SDavid Majnemer     return symbol_end();
116844f51e51SDavid Majnemer   if (SymbolTable16)
116944f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
117044f51e51SDavid Majnemer   else if (SymbolTable32)
117144f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
117244f51e51SDavid Majnemer   else
1173c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11748ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1175022ecdf2SBenjamin Kramer }
11768ff24d25SRui Ueyama 
117799c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1178022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
117999c041b7SRafael Espindola   return R->Type;
1180022ecdf2SBenjamin Kramer }
1181e5fd0047SMichael J. Spencer 
118227dc8394SAlexey Samsonov const coff_section *
118327dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
118427dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
118571757ef3SMarshall Clow }
118671757ef3SMarshall Clow 
118744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
118844f51e51SDavid Majnemer   if (SymbolTable16)
118944f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
119044f51e51SDavid Majnemer   if (SymbolTable32)
119144f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
119244f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
119344f51e51SDavid Majnemer }
119444f51e51SDavid Majnemer 
119544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
119644f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
119771757ef3SMarshall Clow }
119871757ef3SMarshall Clow 
1199f12b8282SRafael Espindola const coff_relocation *
120027dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
120127dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1202d3e2a76cSMarshall Clow }
1203d3e2a76cSMarshall Clow 
12042f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
12056a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
12062f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
12072f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
12086a75acb1SRui Ueyama }
12096a75acb1SRui Ueyama 
121027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
121127dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1212114ebf4aSMartin Storsjo     return #reloc_type;
1213e5fd0047SMichael J. Spencer 
1214114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
121544f51e51SDavid Majnemer   switch (getMachine()) {
1216e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1217114ebf4aSMartin Storsjo     switch (Type) {
1218e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1219e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1220e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1221e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1222e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1223e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1224e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1225e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1226e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1227e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1228e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1229e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1230e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1231e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1232e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1233e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1234e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1235e5fd0047SMichael J. Spencer     default:
1236114ebf4aSMartin Storsjo       return "Unknown";
1237e5fd0047SMichael J. Spencer     }
1238e5fd0047SMichael J. Spencer     break;
12395c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1240114ebf4aSMartin Storsjo     switch (Type) {
12415c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12425c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12435c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12445c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12455c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12465c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12475c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12485c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1249e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12505c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12515c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12525c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12535c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12545c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12555c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12565c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1257e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12585c503bf4SSaleem Abdulrasool     default:
1259114ebf4aSMartin Storsjo       return "Unknown";
12605c503bf4SSaleem Abdulrasool     }
12615c503bf4SSaleem Abdulrasool     break;
12620c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1263114ebf4aSMartin Storsjo     switch (Type) {
12640c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12650c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12660c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12670c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12680c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12690c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12700c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12710c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12720c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12730c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12740c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12750c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12760c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12770c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12780c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12790c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12800c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1281e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12820c72172eSMandeep Singh Grang     default:
1283114ebf4aSMartin Storsjo       return "Unknown";
12840c72172eSMandeep Singh Grang     }
12850c72172eSMandeep Singh Grang     break;
1286e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1287114ebf4aSMartin Storsjo     switch (Type) {
1288e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1289e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1290e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1291e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1292e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1293e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1294e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1295e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1296e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1297e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1298e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1299e5fd0047SMichael J. Spencer     default:
1300114ebf4aSMartin Storsjo       return "Unknown";
1301e5fd0047SMichael J. Spencer     }
1302e5fd0047SMichael J. Spencer     break;
1303e5fd0047SMichael J. Spencer   default:
1304114ebf4aSMartin Storsjo     return "Unknown";
1305e5fd0047SMichael J. Spencer   }
1306e5fd0047SMichael J. Spencer }
1307e5fd0047SMichael J. Spencer 
1308e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1309e5fd0047SMichael J. Spencer 
1310114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1311114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1312114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1313114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1314114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1315114ebf4aSMartin Storsjo }
1316114ebf4aSMartin Storsjo 
1317c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1318c66d761bSRafael Espindola   return !DataDirectory;
1319c66d761bSRafael Espindola }
1320c66d761bSRafael Espindola 
1321e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1322e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1323e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1324e3093808SMartin Storsjo       .Default(Name);
1325e3093808SMartin Storsjo }
1326e3093808SMartin Storsjo 
1327c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1328c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1329a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1330c2bed429SRui Ueyama }
1331c2bed429SRui Ueyama 
13325e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13335e812afaSRafael Espindola   ++Index;
13341c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1335ad7b7e73SDavid Majnemer     Index = -1;
1336ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1337ad7b7e73SDavid Majnemer   }
1338c2bed429SRui Ueyama }
1339c2bed429SRui Ueyama 
13401c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry(
13411c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1342ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1343c2bed429SRui Ueyama }
1344c2bed429SRui Ueyama 
1345861021f9SRui Ueyama static imported_symbol_iterator
134615d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1347861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
134815d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1349861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
135015d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1351861021f9SRui Ueyama   }
1352861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
135315d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1354861021f9SRui Ueyama }
1355861021f9SRui Ueyama 
135615d99359SRui Ueyama static imported_symbol_iterator
135715d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1358861021f9SRui Ueyama   uintptr_t IntPtr = 0;
13591c03389cSReid Kleckner   // FIXME: Handle errors.
13601c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
136115d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1362861021f9SRui Ueyama }
1363861021f9SRui Ueyama 
136415d99359SRui Ueyama static imported_symbol_iterator
136515d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1366861021f9SRui Ueyama   uintptr_t IntPtr = 0;
13671c03389cSReid Kleckner   // FIXME: Handle errors.
13681c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
1369861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1370861021f9SRui Ueyama   int Index = 0;
137115d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1372861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1373861021f9SRui Ueyama     while (*Entry++)
1374861021f9SRui Ueyama       ++Index;
1375861021f9SRui Ueyama   } else {
1376861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1377861021f9SRui Ueyama     while (*Entry++)
1378861021f9SRui Ueyama       ++Index;
1379861021f9SRui Ueyama   }
138015d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
138115d99359SRui Ueyama }
138215d99359SRui Ueyama 
138315d99359SRui Ueyama imported_symbol_iterator
138415d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
138560049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
138615d99359SRui Ueyama                              OwningObject);
138715d99359SRui Ueyama }
138815d99359SRui Ueyama 
138915d99359SRui Ueyama imported_symbol_iterator
139015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
139160049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
139215d99359SRui Ueyama                            OwningObject);
1393861021f9SRui Ueyama }
1394861021f9SRui Ueyama 
1395979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1396979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1397979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1398979fb40bSRui Ueyama }
1399979fb40bSRui Ueyama 
140060049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
140160049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
140260049526SDavid Majnemer                              OwningObject);
140360049526SDavid Majnemer }
140460049526SDavid Majnemer 
140560049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
140660049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
140760049526SDavid Majnemer                            OwningObject);
140860049526SDavid Majnemer }
140960049526SDavid Majnemer 
141060049526SDavid Majnemer iterator_range<imported_symbol_iterator>
141160049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
141260049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
141360049526SDavid Majnemer }
141460049526SDavid Majnemer 
14151c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
1416c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
14171c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
14181c03389cSReid Kleckner     return E;
1419a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14201c03389cSReid Kleckner   return Error::success();
1421c2bed429SRui Ueyama }
1422c2bed429SRui Ueyama 
14231c03389cSReid Kleckner Error
14241e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14251e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14261c03389cSReid Kleckner   return Error::success();
14271e152d5eSRui Ueyama }
14281e152d5eSRui Ueyama 
14291c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14301c03389cSReid Kleckner     uint32_t &Result) const {
14311e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14321c03389cSReid Kleckner   return Error::success();
14331e152d5eSRui Ueyama }
14341e152d5eSRui Ueyama 
143515d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
143615d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
143715d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
143815d99359SRui Ueyama }
143915d99359SRui Ueyama 
144015d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
144115d99359SRui Ueyama   ++Index;
144215d99359SRui Ueyama }
144315d99359SRui Ueyama 
144415d99359SRui Ueyama imported_symbol_iterator
144515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
144615d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
144715d99359SRui Ueyama                              OwningObject);
144815d99359SRui Ueyama }
144915d99359SRui Ueyama 
145015d99359SRui Ueyama imported_symbol_iterator
145115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
145215d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
145315d99359SRui Ueyama                            OwningObject);
145415d99359SRui Ueyama }
145515d99359SRui Ueyama 
1456979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1457979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1458979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1459979fb40bSRui Ueyama }
1460979fb40bSRui Ueyama 
14611c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
146215d99359SRui Ueyama   uintptr_t IntPtr = 0;
14631c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
14641c03389cSReid Kleckner     return E;
146515d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14661c03389cSReid Kleckner   return Error::success();
146715d99359SRui Ueyama }
146815d99359SRui Ueyama 
14691c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable(
14701c03389cSReid Kleckner     const delay_import_directory_table_entry *&Result) const {
14719f598ac7SJoseph Tremoulet   Result = &Table[Index];
14721c03389cSReid Kleckner   return Error::success();
14731af08658SRui Ueyama }
14741af08658SRui Ueyama 
14751c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
14761c03389cSReid Kleckner                                                      uint64_t &Result) const {
1477ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1478ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1479ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
14801c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr))
14811c03389cSReid Kleckner     return E;
1482ffa4cebeSRui Ueyama   if (OwningObject->is64())
14835dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1484ffa4cebeSRui Ueyama   else
14855dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14861c03389cSReid Kleckner   return Error::success();
1487ffa4cebeSRui Ueyama }
1488ffa4cebeSRui Ueyama 
1489ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1490ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1491ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1492ad882ba8SRui Ueyama }
1493ad882ba8SRui Ueyama 
14945e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14955e812afaSRafael Espindola   ++Index;
1496ad882ba8SRui Ueyama }
1497ad882ba8SRui Ueyama 
1498da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1499da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
15001c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1501da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
15021c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
15031c03389cSReid Kleckner     return E;
1504da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15051c03389cSReid Kleckner   return Error::success();
1506da49d0d4SRui Ueyama }
1507da49d0d4SRui Ueyama 
1508e5df6095SRui Ueyama // Returns the starting ordinal number.
15091c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1510e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15111c03389cSReid Kleckner   return Error::success();
1512e5df6095SRui Ueyama }
1513e5df6095SRui Ueyama 
1514ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
15151c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1516ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15171c03389cSReid Kleckner   return Error::success();
1518ad882ba8SRui Ueyama }
1519ad882ba8SRui Ueyama 
1520ad882ba8SRui Ueyama // Returns the address of the current export symbol.
15211c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1522ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15231c03389cSReid Kleckner   if (Error EC =
1524db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1525ad882ba8SRui Ueyama     return EC;
152624fc2d64SRui Ueyama   const export_address_table_entry *entry =
152724fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1528ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15291c03389cSReid Kleckner   return Error::success();
1530ad882ba8SRui Ueyama }
1531ad882ba8SRui Ueyama 
1532ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1533ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
15341c03389cSReid Kleckner Error
1535db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1536ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15371c03389cSReid Kleckner   if (Error EC =
1538db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1539ad882ba8SRui Ueyama     return EC;
1540ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1541ad882ba8SRui Ueyama 
1542ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1543ad882ba8SRui Ueyama   int Offset = 0;
1544ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1545ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1546ad882ba8SRui Ueyama     if (*I != Index)
1547ad882ba8SRui Ueyama       continue;
15481c03389cSReid Kleckner     if (Error EC =
1549db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1550ad882ba8SRui Ueyama       return EC;
1551ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
15521c03389cSReid Kleckner     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1553ad882ba8SRui Ueyama       return EC;
1554ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15551c03389cSReid Kleckner     return Error::success();
1556ad882ba8SRui Ueyama   }
1557ad882ba8SRui Ueyama   Result = "";
15581c03389cSReid Kleckner   return Error::success();
1559ad882ba8SRui Ueyama }
1560ad882ba8SRui Ueyama 
15611c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15621c03389cSReid Kleckner   const data_directory *DataEntry =
15631c03389cSReid Kleckner       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
15641c03389cSReid Kleckner   if (!DataEntry)
15651c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
15666161b38dSRui Ueyama   uint32_t RVA;
15676161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15686161b38dSRui Ueyama     return EC;
15696161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15706161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15716161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15721c03389cSReid Kleckner   return Error::success();
15736161b38dSRui Ueyama }
15746161b38dSRui Ueyama 
15751c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15766161b38dSRui Ueyama   uint32_t RVA;
15776161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15786161b38dSRui Ueyama     return EC;
15796161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15806161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15816161b38dSRui Ueyama     return EC;
15826161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15831c03389cSReid Kleckner   return Error::success();
15846161b38dSRui Ueyama }
15856161b38dSRui Ueyama 
1586861021f9SRui Ueyama bool ImportedSymbolRef::
1587861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1588861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1589861021f9SRui Ueyama       && Index == Other.Index;
1590861021f9SRui Ueyama }
1591861021f9SRui Ueyama 
1592861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1593861021f9SRui Ueyama   ++Index;
1594861021f9SRui Ueyama }
1595861021f9SRui Ueyama 
15961c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1597861021f9SRui Ueyama   uint32_t RVA;
1598861021f9SRui Ueyama   if (Entry32) {
1599861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1600861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
16011c03389cSReid Kleckner       return Error::success();
1602861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1603861021f9SRui Ueyama   } else {
1604861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
16051c03389cSReid Kleckner       return Error::success();
1606861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1607861021f9SRui Ueyama   }
1608861021f9SRui Ueyama   uintptr_t IntPtr = 0;
16091c03389cSReid Kleckner   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
1610861021f9SRui Ueyama     return EC;
1611861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1612861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16131c03389cSReid Kleckner   return Error::success();
1614861021f9SRui Ueyama }
1615861021f9SRui Ueyama 
16161c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const {
1617ad7b7e73SDavid Majnemer   if (Entry32)
1618ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1619ad7b7e73SDavid Majnemer   else
1620ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
16211c03389cSReid Kleckner   return Error::success();
1622ad7b7e73SDavid Majnemer }
1623ad7b7e73SDavid Majnemer 
16241c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1625ad7b7e73SDavid Majnemer   if (Entry32)
1626ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1627ad7b7e73SDavid Majnemer   else
1628ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
16291c03389cSReid Kleckner   return Error::success();
1630ad7b7e73SDavid Majnemer }
1631ad7b7e73SDavid Majnemer 
16321c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1633861021f9SRui Ueyama   uint32_t RVA;
1634861021f9SRui Ueyama   if (Entry32) {
1635861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1636861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16371c03389cSReid Kleckner       return Error::success();
1638861021f9SRui Ueyama     }
1639861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1640861021f9SRui Ueyama   } else {
1641861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1642861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16431c03389cSReid Kleckner       return Error::success();
1644861021f9SRui Ueyama     }
1645861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1646861021f9SRui Ueyama   }
1647861021f9SRui Ueyama   uintptr_t IntPtr = 0;
16481c03389cSReid Kleckner   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
1649861021f9SRui Ueyama     return EC;
1650861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16511c03389cSReid Kleckner   return Error::success();
1652861021f9SRui Ueyama }
1653861021f9SRui Ueyama 
165412db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
165548af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
165639772063SReid Kleckner   return COFFObjectFile::create(Object);
1657686738e2SRui Ueyama }
165874e85130SRui Ueyama 
165974e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
166074e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
166174e85130SRui Ueyama }
166274e85130SRui Ueyama 
166374e85130SRui Ueyama void BaseRelocRef::moveNext() {
166474e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
166574e85130SRui Ueyama   // size of the header itself.
166674e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1667970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
166874e85130SRui Ueyama   if (Size == Header->BlockSize) {
166974e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
167074e85130SRui Ueyama     // consists of the header followed by entries. The header contains
167174e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
167274e85130SRui Ueyama     // current block, proceed to the next block.
167374e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
167474e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
167574e85130SRui Ueyama     Index = 0;
167674e85130SRui Ueyama   } else {
167774e85130SRui Ueyama     ++Index;
167874e85130SRui Ueyama   }
167974e85130SRui Ueyama }
168074e85130SRui Ueyama 
16811c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const {
168274e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
168374e85130SRui Ueyama   Type = Entry[Index].getType();
16841c03389cSReid Kleckner   return Error::success();
168574e85130SRui Ueyama }
168674e85130SRui Ueyama 
16871c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const {
168874e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
168974e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16901c03389cSReid Kleckner   return Error::success();
169174e85130SRui Ueyama }
1692efef15a0SEric Beckmann 
1693357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1694357a40ecSMartin Storsjo   do {                                                                         \
1695357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
169687867988SRafael Espindola     if (E)                                                                     \
1697c55cf4afSBill Wendling       return std::move(E);                                                     \
1698357a40ecSMartin Storsjo   } while (0)
1699efef15a0SEric Beckmann 
170087867988SRafael Espindola Expected<ArrayRef<UTF16>>
170187867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1702efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1703efef15a0SEric Beckmann   Reader.setOffset(Offset);
1704efef15a0SEric Beckmann   uint16_t Length;
1705efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1706efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1707efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1708cd704cb6SEric Beckmann   return RawDirString;
1709efef15a0SEric Beckmann }
1710efef15a0SEric Beckmann 
1711f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1712efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1713f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1714efef15a0SEric Beckmann }
1715efef15a0SEric Beckmann 
171687867988SRafael Espindola Expected<const coff_resource_dir_table &>
1717efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1718efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1719efef15a0SEric Beckmann 
1720efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1721efef15a0SEric Beckmann   Reader.setOffset(Offset);
1722efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1723efef15a0SEric Beckmann   assert(Table != nullptr);
1724efef15a0SEric Beckmann   return *Table;
1725efef15a0SEric Beckmann }
1726efef15a0SEric Beckmann 
1727edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1728edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1729edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1730edb6ab9bSMartin Storsjo 
1731edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1732edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1733edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1734edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1735edb6ab9bSMartin Storsjo   return *Entry;
1736edb6ab9bSMartin Storsjo }
1737edb6ab9bSMartin Storsjo 
17387ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17397ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17407ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
17417ba81d95SMartin Storsjo 
17427ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
17437ba81d95SMartin Storsjo   Reader.setOffset(Offset);
17447ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
17457ba81d95SMartin Storsjo   assert(Entry != nullptr);
17467ba81d95SMartin Storsjo   return *Entry;
17477ba81d95SMartin Storsjo }
17487ba81d95SMartin Storsjo 
1749f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1750efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17517ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1752f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1753efef15a0SEric Beckmann }
1754efef15a0SEric Beckmann 
17557ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17567ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17577ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
17587ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
17597ba81d95SMartin Storsjo }
17607ba81d95SMartin Storsjo 
1761f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1762f3404674SRafael Espindola   return getTableAtOffset(0);
1763efef15a0SEric Beckmann }
1764edb6ab9bSMartin Storsjo 
1765edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1766edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1767edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1768edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1769edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1770edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1771edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1772edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1773edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1774edb6ab9bSMartin Storsjo }
177594382217SMartin Storsjo 
177694382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
177794382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
177894382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
177994382217SMartin Storsjo     if (!Name)
178094382217SMartin Storsjo       return Name.takeError();
178194382217SMartin Storsjo 
178294382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
178394382217SMartin Storsjo       return load(O, S);
178494382217SMartin Storsjo   }
178594382217SMartin Storsjo   return createStringError(object_error::parse_failed,
178694382217SMartin Storsjo                            "no resource section found");
178794382217SMartin Storsjo }
178894382217SMartin Storsjo 
178994382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
179094382217SMartin Storsjo   Obj = O;
179194382217SMartin Storsjo   Section = S;
179294382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
179394382217SMartin Storsjo   if (!Contents)
179494382217SMartin Storsjo     return Contents.takeError();
179594382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
179694382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
179794382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
179894382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
179994382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
180094382217SMartin Storsjo     Relocs.push_back(&R);
1801352fcfc6SKazu Hirata   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
180294382217SMartin Storsjo     return A->VirtualAddress < B->VirtualAddress;
180394382217SMartin Storsjo   });
180494382217SMartin Storsjo   return Error::success();
180594382217SMartin Storsjo }
180694382217SMartin Storsjo 
180794382217SMartin Storsjo Expected<StringRef>
180894382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
180994382217SMartin Storsjo   if (!Obj)
181094382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
181194382217SMartin Storsjo 
181294382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
181394382217SMartin Storsjo   // the coff_resource_data_entry struct).
181494382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
181594382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
181694382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
181794382217SMartin Storsjo                               ulittle16_t(0)};
181894382217SMartin Storsjo   auto RelocsForOffset =
181994382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
182094382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
182194382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
182294382217SMartin Storsjo                        });
182394382217SMartin Storsjo 
182494382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
182594382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
182694382217SMartin Storsjo     // the expected type.
182794382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
182894382217SMartin Storsjo     uint16_t RVAReloc;
182994382217SMartin Storsjo     switch (Obj->getMachine()) {
183094382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
183194382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
183294382217SMartin Storsjo       break;
183394382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
183494382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
183594382217SMartin Storsjo       break;
183694382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
183794382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
183894382217SMartin Storsjo       break;
183994382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
184094382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
184194382217SMartin Storsjo       break;
184294382217SMartin Storsjo     default:
184394382217SMartin Storsjo       return createStringError(object_error::parse_failed,
184494382217SMartin Storsjo                                "unsupported architecture");
184594382217SMartin Storsjo     }
184694382217SMartin Storsjo     if (R.Type != RVAReloc)
184794382217SMartin Storsjo       return createStringError(object_error::parse_failed,
184894382217SMartin Storsjo                                "unexpected relocation type");
184994382217SMartin Storsjo     // Get the relocation's symbol
185094382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
185194382217SMartin Storsjo     if (!Sym)
185294382217SMartin Storsjo       return Sym.takeError();
185394382217SMartin Storsjo     // And the symbol's section
185477ecf90cSReid Kleckner     Expected<const coff_section *> Section =
185577ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
185677ecf90cSReid Kleckner     if (!Section)
185777ecf90cSReid Kleckner       return Section.takeError();
185894382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
185994382217SMartin Storsjo     // data it points at.
186094382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
186194382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
186277ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1863c55cf4afSBill Wendling       return std::move(E);
186494382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
186594382217SMartin Storsjo       return createStringError(object_error::parse_failed,
186694382217SMartin Storsjo                                "data outside of section");
186794382217SMartin Storsjo     // Return a reference to the data inside the section.
186894382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
186994382217SMartin Storsjo                      Entry.DataSize);
187094382217SMartin Storsjo   } else {
187194382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
187294382217SMartin Storsjo     if (Obj->isRelocatableObject())
187394382217SMartin Storsjo       return createStringError(object_error::parse_failed,
187494382217SMartin Storsjo                                "no relocation found for DataRVA");
187594382217SMartin Storsjo 
187694382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
187794382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
187894382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
187994382217SMartin Storsjo       if (VA >= S.getAddress() &&
188094382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
188194382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
188294382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
188394382217SMartin Storsjo         if (!Contents)
188494382217SMartin Storsjo           return Contents.takeError();
188594382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
188694382217SMartin Storsjo       }
188794382217SMartin Storsjo     }
188894382217SMartin Storsjo     return createStringError(object_error::parse_failed,
188994382217SMartin Storsjo                              "address not found in image");
189094382217SMartin Storsjo   }
189194382217SMartin Storsjo }
1892