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).
33129d253c4SDjordje Todorovic bool COFFObjectFile::isDebugSection(StringRef SectionName) const {
33229d253c4SDjordje Todorovic   return SectionName.startswith(".debug");
33329d253c4SDjordje Todorovic }
33429d253c4SDjordje Todorovic 
3356bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3366bf32210SRafael Espindola   uintptr_t Offset =
33722cf54a7SArthur O'Dwyer       Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3386bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3396bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3406bf32210SRafael Espindola }
3416bf32210SRafael Espindola 
34280291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3438ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3441a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3451a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3461a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3472138ef6dSPreston Gurd }
3482138ef6dSPreston Gurd 
349e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
350e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
351e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
352e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
353e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
354e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
355e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
356e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
3571c03389cSReid Kleckner     if (Error E = getObject(FirstReloc, M,
3581c03389cSReid Kleckner                             reinterpret_cast<const coff_relocation *>(
3591c03389cSReid Kleckner                                 base + Sec->PointerToRelocations))) {
3601c03389cSReid Kleckner       consumeError(std::move(E));
361e830c60dSDavid Majnemer       return 0;
3621c03389cSReid Kleckner     }
36398fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36498fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
365e830c60dSDavid Majnemer   }
366e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
367e830c60dSDavid Majnemer }
368e830c60dSDavid Majnemer 
36994751be7SDavid Majnemer static const coff_relocation *
37094751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37194751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37294751be7SDavid Majnemer   if (!NumRelocs)
37394751be7SDavid Majnemer     return nullptr;
374827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37594751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
376827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
377827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
378827c8a2bSRui Ueyama     // relocations.
379827c8a2bSRui Ueyama     begin++;
380827c8a2bSRui Ueyama   }
38122cf54a7SArthur O'Dwyer   if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
382e03a135bSReid Kleckner                                    sizeof(coff_relocation) * NumRelocs)) {
383e03a135bSReid Kleckner     consumeError(std::move(E));
38494751be7SDavid Majnemer     return nullptr;
385e03a135bSReid Kleckner   }
38694751be7SDavid Majnemer   return begin;
387827c8a2bSRui Ueyama }
38894751be7SDavid Majnemer 
38994751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
39094751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
39194751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
39276d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
39376d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
39494751be7SDavid Majnemer   DataRefImpl Ret;
39594751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3968ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
397e5fd0047SMichael J. Spencer }
398e5fd0047SMichael J. Spencer 
3998ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4008ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
40194751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
40294751be7SDavid Majnemer   if (I)
40394751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4048ff24d25SRui Ueyama   DataRefImpl Ret;
40594751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4068ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
407e5fd0047SMichael J. Spencer }
408e5fd0047SMichael J. Spencer 
409c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
4101c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() {
41144f51e51SDavid Majnemer   if (COFFHeader)
4121c03389cSReid Kleckner     if (Error E = getObject(
413236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
414236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4151c03389cSReid Kleckner       return E;
41644f51e51SDavid Majnemer 
41744f51e51SDavid Majnemer   if (COFFBigObjHeader)
4181c03389cSReid Kleckner     if (Error E = getObject(
419236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
420236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4211c03389cSReid Kleckner       return E;
422c2bed429SRui Ueyama 
423c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
424c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
425c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
426f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42744f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
428f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
429c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
4301c03389cSReid Kleckner   if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4311c03389cSReid Kleckner     return E;
432c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
4331c03389cSReid Kleckner   if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4341c03389cSReid Kleckner     return E;
435c2bed429SRui Ueyama 
436773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
437773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
438773a5795SNico Rieck   if (StringTableSize < 4)
439773a5795SNico Rieck     StringTableSize = 4;
440773a5795SNico Rieck 
441c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
442773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
4431c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
4441c03389cSReid Kleckner   return Error::success();
445c2bed429SRui Ueyama }
446c2bed429SRui Ueyama 
44721427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
448e94fef7bSReid Kleckner   if (PE32Header)
44921427adaSReid Kleckner     return PE32Header->ImageBase;
450e94fef7bSReid Kleckner   else if (PE32PlusHeader)
45121427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
45221427adaSReid Kleckner   // This actually comes up in practice.
45321427adaSReid Kleckner   return 0;
454e94fef7bSReid Kleckner }
455e94fef7bSReid Kleckner 
456215a586cSRui Ueyama // Returns the file offset for the given VA.
4571c03389cSReid Kleckner Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45821427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
459b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
460b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
461b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
462215a586cSRui Ueyama }
463215a586cSRui Ueyama 
464c2bed429SRui Ueyama // Returns the file offset for the given RVA.
4651c03389cSReid Kleckner Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46627dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46727dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
468c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
469c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
470215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
471215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
47222cf54a7SArthur O'Dwyer       Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
47322cf54a7SArthur O'Dwyer             Offset;
4741c03389cSReid Kleckner       return Error::success();
475c2bed429SRui Ueyama     }
476c2bed429SRui Ueyama   }
4771c03389cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
478c2bed429SRui Ueyama }
479c2bed429SRui Ueyama 
4801c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4812da433eaSReid Kleckner                                            ArrayRef<uint8_t> &Contents) const {
4822da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4832da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4842da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4852da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4862da433eaSReid Kleckner     // overflow.
4872da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4882da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4892da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
49022cf54a7SArthur O'Dwyer       uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
49122cf54a7SArthur O'Dwyer                         Section->PointerToRawData + OffsetIntoSection;
4922da433eaSReid Kleckner       Contents =
4932da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4941c03389cSReid Kleckner       return Error::success();
4952da433eaSReid Kleckner     }
4962da433eaSReid Kleckner   }
4971c03389cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
4982da433eaSReid Kleckner }
4992da433eaSReid Kleckner 
500c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
501c2bed429SRui Ueyama // table entry.
5021c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
503db4ed0bdSRafael Espindola                                   StringRef &Name) const {
504c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5051c03389cSReid Kleckner   if (Error E = getRvaPtr(Rva, IntPtr))
5061c03389cSReid Kleckner     return E;
507c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
508c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
509c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5101c03389cSReid Kleckner   return Error::success();
511c2bed429SRui Ueyama }
512c2bed429SRui Ueyama 
5131c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51401528021SSaleem Abdulrasool                                       const codeview::DebugInfo *&PDBInfo,
5152da433eaSReid Kleckner                                       StringRef &PDBFileName) const {
5162da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5171c03389cSReid Kleckner   if (Error E = getRvaAndSizeAsBytes(
5182da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5191c03389cSReid Kleckner     return E;
52001528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5211c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
52201528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
52301528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5242da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5252da433eaSReid Kleckner                           InfoBytes.size());
5262da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5272da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5281c03389cSReid Kleckner   return Error::success();
5292da433eaSReid Kleckner }
5302da433eaSReid Kleckner 
5311c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
532f27f3f84SReid Kleckner                                       StringRef &PDBFileName) const {
533f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
534f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
535f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
536f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
537f27f3f84SReid Kleckner   PDBInfo = nullptr;
538f27f3f84SReid Kleckner   PDBFileName = StringRef();
5391c03389cSReid Kleckner   return Error::success();
540f27f3f84SReid Kleckner }
541f27f3f84SReid Kleckner 
542c2bed429SRui Ueyama // Find the import table.
5431c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() {
544c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
545c2bed429SRui Ueyama   // the import table, do nothing.
5461c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5471c03389cSReid Kleckner   if (!DataEntry)
5481c03389cSReid Kleckner     return Error::success();
549c2bed429SRui Ueyama 
550c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
551c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5521c03389cSReid Kleckner     return Error::success();
553c2bed429SRui Ueyama 
554c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
555c2bed429SRui Ueyama 
556c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
557c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
558c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
5591c03389cSReid Kleckner   if (Error E = getRvaPtr(ImportTableRva, IntPtr))
5601c03389cSReid Kleckner     return E;
561e03a135bSReid Kleckner   if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5621c03389cSReid Kleckner     return E;
563c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5641c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5651c03389cSReid Kleckner   return Error::success();
566ad882ba8SRui Ueyama }
567c2bed429SRui Ueyama 
56815d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
5691c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() {
5701c03389cSReid Kleckner   const data_directory *DataEntry =
5711c03389cSReid Kleckner       getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
5721c03389cSReid Kleckner   if (!DataEntry)
5731c03389cSReid Kleckner     return Error::success();
57415d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5751c03389cSReid Kleckner     return Error::success();
57615d99359SRui Ueyama 
57715d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57815d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57915d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
58015d99359SRui Ueyama 
58115d99359SRui Ueyama   uintptr_t IntPtr = 0;
5821c03389cSReid Kleckner   if (Error E = getRvaPtr(RVA, IntPtr))
5831c03389cSReid Kleckner     return E;
58415d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58515d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5861c03389cSReid Kleckner   return Error::success();
58715d99359SRui Ueyama }
58815d99359SRui Ueyama 
589ad882ba8SRui Ueyama // Find the export table.
5901c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() {
591ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
592ad882ba8SRui Ueyama   // the export table, do nothing.
5931c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
5941c03389cSReid Kleckner   if (!DataEntry)
5951c03389cSReid Kleckner     return Error::success();
596ad882ba8SRui Ueyama 
597ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
598ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5991c03389cSReid Kleckner     return Error::success();
600ad882ba8SRui Ueyama 
601ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
602ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
6031c03389cSReid Kleckner   if (Error E = getRvaPtr(ExportTableRva, IntPtr))
6041c03389cSReid Kleckner     return E;
60524fc2d64SRui Ueyama   ExportDirectory =
60624fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6071c03389cSReid Kleckner   return Error::success();
608c2bed429SRui Ueyama }
609c2bed429SRui Ueyama 
6101c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() {
6111c03389cSReid Kleckner   const data_directory *DataEntry =
6121c03389cSReid Kleckner       getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6131c03389cSReid Kleckner   if (!DataEntry)
6141c03389cSReid Kleckner     return Error::success();
61574e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6161c03389cSReid Kleckner     return Error::success();
61774e85130SRui Ueyama 
61874e85130SRui Ueyama   uintptr_t IntPtr = 0;
6191c03389cSReid Kleckner   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6201c03389cSReid Kleckner     return E;
62174e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
62274e85130SRui Ueyama       IntPtr);
62374e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
62474e85130SRui Ueyama       IntPtr + DataEntry->Size);
625893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
626893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6271c03389cSReid Kleckner   return Error::success();
62874e85130SRui Ueyama }
62974e85130SRui Ueyama 
6301c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() {
6312da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6321c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6331c03389cSReid Kleckner   if (!DataEntry)
6341c03389cSReid Kleckner     return Error::success();
6352da433eaSReid Kleckner 
6362da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6372da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6381c03389cSReid Kleckner     return Error::success();
6392da433eaSReid Kleckner 
6402da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6412da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6421c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
6432da433eaSReid Kleckner 
6442da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6451c03389cSReid Kleckner   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6461c03389cSReid Kleckner     return E;
6472da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
648893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
649893c6469SNico Weber       IntPtr + DataEntry->Size);
650893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
651893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6521c03389cSReid Kleckner   return Error::success();
6532da433eaSReid Kleckner }
6542da433eaSReid Kleckner 
655568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() {
656568035acSLuqman Aden   // Get the RVA of the TLS directory. Do nothing if it does not exist.
657568035acSLuqman Aden   const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
658568035acSLuqman Aden   if (!DataEntry)
659568035acSLuqman Aden     return Error::success();
660568035acSLuqman Aden 
661568035acSLuqman Aden   // Do nothing if the RVA is NULL.
662568035acSLuqman Aden   if (DataEntry->RelativeVirtualAddress == 0)
663568035acSLuqman Aden     return Error::success();
664568035acSLuqman Aden 
665568035acSLuqman Aden   uint64_t DirSize =
666568035acSLuqman Aden       is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
667568035acSLuqman Aden 
668568035acSLuqman Aden   // Check that the size is correct.
669568035acSLuqman Aden   if (DataEntry->Size != DirSize)
670568035acSLuqman Aden     return createStringError(
671568035acSLuqman Aden         object_error::parse_failed,
6722980ce98SHubert Tong         "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
673568035acSLuqman Aden         static_cast<uint32_t>(DataEntry->Size), DirSize);
674568035acSLuqman Aden 
675568035acSLuqman Aden   uintptr_t IntPtr = 0;
676568035acSLuqman Aden   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
677568035acSLuqman Aden     return E;
678568035acSLuqman Aden 
679568035acSLuqman Aden   if (is64())
680568035acSLuqman Aden     TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
681568035acSLuqman Aden   else
682568035acSLuqman Aden     TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
683568035acSLuqman Aden 
684568035acSLuqman Aden   return Error::success();
685568035acSLuqman Aden }
686568035acSLuqman Aden 
6871c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() {
688b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6891c03389cSReid Kleckner   const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
6901c03389cSReid Kleckner   if (!DataEntry)
6911c03389cSReid Kleckner     return Error::success();
692b7d716c0SReid Kleckner 
693b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
694b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6951c03389cSReid Kleckner     return Error::success();
696b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
6971c03389cSReid Kleckner   if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6981c03389cSReid Kleckner     return E;
699b7d716c0SReid Kleckner 
700b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
7011c03389cSReid Kleckner   return Error::success();
702b7d716c0SReid Kleckner }
703b7d716c0SReid Kleckner 
70439772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>>
70539772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) {
70639772063SReid Kleckner   std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
70739772063SReid Kleckner   if (Error E = Obj->initialize())
70839772063SReid Kleckner     return std::move(E);
70939772063SReid Kleckner   return std::move(Obj);
71039772063SReid Kleckner }
71139772063SReid Kleckner 
71239772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
71348af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
71444f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
71544f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
71644f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
71739772063SReid Kleckner       ImportDirectory(nullptr), DelayImportDirectory(nullptr),
71839772063SReid Kleckner       NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
71939772063SReid Kleckner       BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
720568035acSLuqman Aden       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
721568035acSLuqman Aden       TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
72239772063SReid Kleckner 
723101fbc01SNico Weber Error COFFObjectFile::initialize() {
7241d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
72539772063SReid Kleckner   std::error_code EC;
72648af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
72739772063SReid Kleckner     return errorCodeToError(EC);
728ee066fc4SEric Christopher 
72982ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
73082ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
73182ebd8e3SRui Ueyama 
73282ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
73382ebd8e3SRui Ueyama   // it is placed right after COFF header.
7348ff24d25SRui Ueyama   bool HasPEHeader = false;
735ee066fc4SEric Christopher 
7361d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
73750267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
738ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
739ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
74050267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
74150267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
74250267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
74382ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
74450267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
74539772063SReid Kleckner         return errorCodeToError(object_error::parse_failed);
7461d6167fdSMichael J. Spencer       }
74744f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7488ff24d25SRui Ueyama       HasPEHeader = true;
749ee066fc4SEric Christopher     }
75050267222SDavid Majnemer   }
751ee066fc4SEric Christopher 
7521c03389cSReid Kleckner   if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
7531c03389cSReid Kleckner     return E;
75444f51e51SDavid Majnemer 
75544f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
75644f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
75744f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
75844f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
75944f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
7601c03389cSReid Kleckner     if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
7611c03389cSReid Kleckner       return E;
76244f51e51SDavid Majnemer 
76344f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
76444f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
76544f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
76644f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
76744f51e51SDavid Majnemer       COFFHeader = nullptr;
76844f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
76944f51e51SDavid Majnemer     } else {
77044f51e51SDavid Majnemer       // It's not a bigobj.
77144f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
77244f51e51SDavid Majnemer     }
77344f51e51SDavid Majnemer   }
77444f51e51SDavid Majnemer   if (COFFHeader) {
77544f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
77644f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7777d099195SRui Ueyama     EC = std::error_code();
77882ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
77982ebd8e3SRui Ueyama 
78044f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
78139772063SReid Kleckner       return errorCodeToError(EC);
78244f51e51SDavid Majnemer   }
78344f51e51SDavid Majnemer 
7848ff24d25SRui Ueyama   if (HasPEHeader) {
78510ed9ddcSRui Ueyama     const pe32_header *Header;
7861c03389cSReid Kleckner     if (Error E = getObject(Header, Data, base() + CurPtr))
7871c03389cSReid Kleckner       return E;
78810ed9ddcSRui Ueyama 
78910ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
79010ed9ddcSRui Ueyama     uint64_t DataDirSize;
79150267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
79210ed9ddcSRui Ueyama       PE32Header = Header;
79310ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
79410ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
79550267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
79610ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
79710ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
79810ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
79910ed9ddcSRui Ueyama     } else {
80010ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
80139772063SReid Kleckner       return errorCodeToError(object_error::parse_failed);
802ed64342bSRui Ueyama     }
8031c03389cSReid Kleckner     if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8041c03389cSReid Kleckner       return E;
805f53c8cb4SRui Ueyama   }
806776c6828SRui Ueyama 
8078950a538SRui Ueyama   if (COFFHeader)
8088950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
8098950a538SRui Ueyama 
8101c03389cSReid Kleckner   assert(COFFHeader || COFFBigObjHeader);
8111c03389cSReid Kleckner 
8121c03389cSReid Kleckner   if (Error E =
8131c03389cSReid Kleckner           getObject(SectionTable, Data, base() + CurPtr,
8141c03389cSReid Kleckner                     (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8151c03389cSReid Kleckner     return E;
8161d6167fdSMichael J. Spencer 
817c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
818236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
8191c03389cSReid Kleckner     if (Error E = initSymbolTablePtr()) {
8201c03389cSReid Kleckner       // Recover from errors reading the symbol table.
8211c03389cSReid Kleckner       consumeError(std::move(E));
822ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
823ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
824ac8cfab5SDavid Majnemer       StringTable = nullptr;
825ac8cfab5SDavid Majnemer       StringTableSize = 0;
826ac8cfab5SDavid Majnemer     }
827236b0ca7SDavid Majnemer   } else {
828236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
829236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
83039772063SReid Kleckner       return errorCodeToError(object_error::parse_failed);
831236b0ca7SDavid Majnemer     }
832236b0ca7SDavid Majnemer   }
8338e90adafSMichael J. Spencer 
834c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
8351c03389cSReid Kleckner   if (Error E = initImportTablePtr())
8361c03389cSReid Kleckner     return E;
8371c03389cSReid Kleckner   if (Error E = initDelayImportTablePtr())
8381c03389cSReid Kleckner     return E;
8391d6167fdSMichael J. Spencer 
840ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
8411c03389cSReid Kleckner   if (Error E = initExportTablePtr())
8421c03389cSReid Kleckner     return E;
843ad882ba8SRui Ueyama 
84474e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
8451c03389cSReid Kleckner   if (Error E = initBaseRelocPtr())
8461c03389cSReid Kleckner     return E;
84774e85130SRui Ueyama 
848568035acSLuqman Aden   // Initialize the pointer to the debug directory.
8491c03389cSReid Kleckner   if (Error E = initDebugDirectoryPtr())
8501c03389cSReid Kleckner     return E;
8512da433eaSReid Kleckner 
852568035acSLuqman Aden   // Initialize the pointer to the TLS directory.
853568035acSLuqman Aden   if (Error E = initTLSDirectoryPtr())
854568035acSLuqman Aden     return E;
855568035acSLuqman Aden 
8561c03389cSReid Kleckner   if (Error E = initLoadConfigPtr())
8571c03389cSReid Kleckner     return E;
858b7d716c0SReid Kleckner 
85939772063SReid Kleckner   return Error::success();
8608e90adafSMichael J. Spencer }
8618e90adafSMichael J. Spencer 
862435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8638ff24d25SRui Ueyama   DataRefImpl Ret;
86444f51e51SDavid Majnemer   Ret.p = getSymbolTable();
865f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8668e90adafSMichael J. Spencer }
8678e90adafSMichael J. Spencer 
868435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8698e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8708ff24d25SRui Ueyama   DataRefImpl Ret;
8718ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
872f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8738e90adafSMichael J. Spencer }
8748e90adafSMichael J. Spencer 
875bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
876ad7b7e73SDavid Majnemer   if (!ImportDirectory)
877ad7b7e73SDavid Majnemer     return import_directory_end();
8781c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
879ad7b7e73SDavid Majnemer     return import_directory_end();
880a045b73aSRui Ueyama   return import_directory_iterator(
881a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
882c2bed429SRui Ueyama }
883c2bed429SRui Ueyama 
884bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
885a045b73aSRui Ueyama   return import_directory_iterator(
886ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
887c2bed429SRui Ueyama }
888c429b80dSDavid Meyer 
88915d99359SRui Ueyama delay_import_directory_iterator
89015d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
89115d99359SRui Ueyama   return delay_import_directory_iterator(
89215d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
89315d99359SRui Ueyama }
89415d99359SRui Ueyama 
89515d99359SRui Ueyama delay_import_directory_iterator
89615d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
89715d99359SRui Ueyama   return delay_import_directory_iterator(
89815d99359SRui Ueyama       DelayImportDirectoryEntryRef(
89915d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
90015d99359SRui Ueyama }
90115d99359SRui Ueyama 
902ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
903ad882ba8SRui Ueyama   return export_directory_iterator(
904ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
905ad882ba8SRui Ueyama }
906ad882ba8SRui Ueyama 
907ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
9082617dcceSCraig Topper   if (!ExportDirectory)
9092617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9108ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
911ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
9128ff24d25SRui Ueyama   return export_directory_iterator(Ref);
913ad882ba8SRui Ueyama }
914ad882ba8SRui Ueyama 
915b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
9168ff24d25SRui Ueyama   DataRefImpl Ret;
9178ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9188ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9198e90adafSMichael J. Spencer }
9208e90adafSMichael J. Spencer 
921b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
9228ff24d25SRui Ueyama   DataRefImpl Ret;
92344f51e51SDavid Majnemer   int NumSections =
92444f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9258ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9268ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
9278e90adafSMichael J. Spencer }
9288e90adafSMichael J. Spencer 
92974e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
93074e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
93174e85130SRui Ueyama }
93274e85130SRui Ueyama 
93374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
93474e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
93574e85130SRui Ueyama }
93674e85130SRui Ueyama 
9378e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
93843c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
9398e90adafSMichael J. Spencer }
9408e90adafSMichael J. Spencer 
9418e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
94244f51e51SDavid Majnemer   switch(getMachine()) {
9438e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9448e90adafSMichael J. Spencer     return "COFF-i386";
9458e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9468e90adafSMichael J. Spencer     return "COFF-x86-64";
9479b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9489b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
9491eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9501eff5c9cSMartell Malone     return "COFF-ARM64";
9518e90adafSMichael J. Spencer   default:
9528e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
9538e90adafSMichael J. Spencer   }
9548e90adafSMichael J. Spencer }
9558e90adafSMichael J. Spencer 
956260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
95744f51e51SDavid Majnemer   switch (getMachine()) {
9588e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9598e90adafSMichael J. Spencer     return Triple::x86;
9608e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9618e90adafSMichael J. Spencer     return Triple::x86_64;
9629b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9639b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9641eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9651eff5c9cSMartell Malone     return Triple::aarch64;
9668e90adafSMichael J. Spencer   default:
9678e90adafSMichael J. Spencer     return Triple::UnknownArch;
9688e90adafSMichael J. Spencer   }
9698e90adafSMichael J. Spencer }
9708e90adafSMichael J. Spencer 
971d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
972d2af4d6fSPaul Semel   if (PE32Header)
973d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
974d2af4d6fSPaul Semel   return 0;
975d2af4d6fSPaul Semel }
976d2af4d6fSPaul Semel 
977979fb40bSRui Ueyama iterator_range<import_directory_iterator>
978979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
979979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
980979fb40bSRui Ueyama }
981979fb40bSRui Ueyama 
982979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
983979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
984979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
985979fb40bSRui Ueyama                     delay_import_directory_end());
986979fb40bSRui Ueyama }
987979fb40bSRui Ueyama 
988979fb40bSRui Ueyama iterator_range<export_directory_iterator>
989979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
990979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
991979fb40bSRui Ueyama }
992979fb40bSRui Ueyama 
99374e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
99474e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
99574e85130SRui Ueyama }
99674e85130SRui Ueyama 
9971c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
9981c03389cSReid Kleckner   if (!DataDirectory)
9991c03389cSReid Kleckner     return nullptr;
100010ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
100110ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
100210ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
10031c03389cSReid Kleckner   if (Index >= NumEnt)
10041c03389cSReid Kleckner     return nullptr;
10051c03389cSReid Kleckner   return &DataDirectory[Index];
1006ed64342bSRui Ueyama }
1007ed64342bSRui Ueyama 
100877ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
100977ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
101077ecf90cSReid Kleckner   // but callers rely on this to return null.
1011236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
101277ecf90cSReid Kleckner     return (const coff_section *)nullptr;
1013236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10141d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
101577ecf90cSReid Kleckner     return SectionTable + (Index - 1);
10168e90adafSMichael J. Spencer   }
101777ecf90cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
1018236b0ca7SDavid Majnemer }
10198e90adafSMichael J. Spencer 
102077ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10211d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
10221d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
102377ecf90cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
10248ff24d25SRui Ueyama   if (Offset >= StringTableSize)
102577ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
102677ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
10278e90adafSMichael J. Spencer }
1028022ecdf2SBenjamin Kramer 
102977ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
103077ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
1031e40d30f3SRui Ueyama }
1032e40d30f3SRui Ueyama 
103377ecf90cSReid Kleckner Expected<StringRef>
103477ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
103589a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
103677ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
103777ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
103889a7a5eaSMichael J. Spencer 
103989a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
104077ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
104177ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
104277ecf90cSReid Kleckner 
104389a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
104477ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
104589a7a5eaSMichael J. Spencer }
104689a7a5eaSMichael J. Spencer 
104744f51e51SDavid Majnemer ArrayRef<uint8_t>
104844f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10492617dcceSCraig Topper   const uint8_t *Aux = nullptr;
105071757ef3SMarshall Clow 
105144f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
105244f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
105371757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
105444f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
105571757ef3SMarshall Clow #ifndef NDEBUG
10568ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10578ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
105844f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
105944f51e51SDavid Majnemer         Offset >=
106044f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
106171757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
106271757ef3SMarshall Clow 
106344f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
106444f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
106571757ef3SMarshall Clow #endif
1066bfb85e67SMarshall Clow   }
106744f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
106871757ef3SMarshall Clow }
106971757ef3SMarshall Clow 
107074e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
107174e7d260SMartin Storsjo   uintptr_t Offset =
107274e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
107374e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
107474e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
107574e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
107674e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
107774e7d260SMartin Storsjo   return Index;
107874e7d260SMartin Storsjo }
107974e7d260SMartin Storsjo 
10808be28cdcSFangrui Song Expected<StringRef>
10818be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
108253c2d547SMichael J. Spencer   StringRef Name;
108344f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
108453c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
108553c2d547SMichael J. Spencer     Name = Sec->Name;
108653c2d547SMichael J. Spencer   else
108753c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
108844f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
108953c2d547SMichael J. Spencer 
109053c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10912314b3deSDavid Majnemer   if (Name.startswith("/")) {
109253c2d547SMichael J. Spencer     uint32_t Offset;
10932314b3deSDavid Majnemer     if (Name.startswith("//")) {
10949d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10958be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1096400b6c08Sserge-sans-paille                                  "invalid section name");
10979d2c15efSNico Rieck     } else {
109853c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
10998be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
11008be28cdcSFangrui Song                                  "invalid section name");
11019d2c15efSNico Rieck     }
110277ecf90cSReid Kleckner     return getString(Offset);
110353c2d547SMichael J. Spencer   }
110453c2d547SMichael J. Spencer 
11058be28cdcSFangrui Song   return Name;
110653c2d547SMichael J. Spencer }
110753c2d547SMichael J. Spencer 
1108a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1109a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1110a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1111a9ee5c06SDavid Majnemer   //
1112a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1113d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1114a9ee5c06SDavid Majnemer   //
1115a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1116a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1117a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1118a9ee5c06SDavid Majnemer   // considered to be zero.
1119d5297ee7SRui Ueyama   if (getDOSHeader())
1120d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1121d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1122a9ee5c06SDavid Majnemer }
1123a9ee5c06SDavid Majnemer 
1124e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11259da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1126e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1127e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1128e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1129e1cb2c0fSFangrui Song     return Error::success();
11309da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11319da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11329da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
113322cf54a7SArthur O'Dwyer   uintptr_t ConStart =
113422cf54a7SArthur O'Dwyer       reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
1135a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1136e03a135bSReid Kleckner   if (Error E = checkOffset(Data, ConStart, SectionSize))
1137e03a135bSReid Kleckner     return E;
1138a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1139e1cb2c0fSFangrui Song   return Error::success();
11409da9e693SMichael J. Spencer }
11419da9e693SMichael J. Spencer 
1142022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1143e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1144022ecdf2SBenjamin Kramer }
11458ff24d25SRui Ueyama 
11465e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1147e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1148e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1149022ecdf2SBenjamin Kramer }
11508ff24d25SRui Ueyama 
115196d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
115258323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
115396d071cdSRafael Espindola   return R->VirtualAddress;
1154cbe72fc9SDanil Malyshev }
11558ff24d25SRui Ueyama 
1156806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1157022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11588ff24d25SRui Ueyama   DataRefImpl Ref;
1159236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1160236b0ca7SDavid Majnemer     return symbol_end();
116144f51e51SDavid Majnemer   if (SymbolTable16)
116244f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
116344f51e51SDavid Majnemer   else if (SymbolTable32)
116444f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
116544f51e51SDavid Majnemer   else
1166c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11678ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1168022ecdf2SBenjamin Kramer }
11698ff24d25SRui Ueyama 
117099c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1171022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
117299c041b7SRafael Espindola   return R->Type;
1173022ecdf2SBenjamin Kramer }
1174e5fd0047SMichael J. Spencer 
117527dc8394SAlexey Samsonov const coff_section *
117627dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
117727dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
117871757ef3SMarshall Clow }
117971757ef3SMarshall Clow 
118044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
118144f51e51SDavid Majnemer   if (SymbolTable16)
118244f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
118344f51e51SDavid Majnemer   if (SymbolTable32)
118444f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
118544f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
118644f51e51SDavid Majnemer }
118744f51e51SDavid Majnemer 
118844f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
118944f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
119071757ef3SMarshall Clow }
119171757ef3SMarshall Clow 
1192f12b8282SRafael Espindola const coff_relocation *
119327dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
119427dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1195d3e2a76cSMarshall Clow }
1196d3e2a76cSMarshall Clow 
11972f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11986a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11992f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
12002f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
12016a75acb1SRui Ueyama }
12026a75acb1SRui Ueyama 
120327dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
120427dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1205114ebf4aSMartin Storsjo     return #reloc_type;
1206e5fd0047SMichael J. Spencer 
1207114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
120844f51e51SDavid Majnemer   switch (getMachine()) {
1209e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1210114ebf4aSMartin Storsjo     switch (Type) {
1211e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1212e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1213e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1214e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1215e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1216e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1217e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1218e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1219e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1220e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1221e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1222e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1223e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1224e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1225e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1226e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1227e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1228e5fd0047SMichael J. Spencer     default:
1229114ebf4aSMartin Storsjo       return "Unknown";
1230e5fd0047SMichael J. Spencer     }
1231e5fd0047SMichael J. Spencer     break;
12325c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1233114ebf4aSMartin Storsjo     switch (Type) {
12345c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12355c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12365c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12375c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12385c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12395c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12405c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12415c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1242e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12435c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12445c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12455c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12465c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12475c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12485c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12495c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1250e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12515c503bf4SSaleem Abdulrasool     default:
1252114ebf4aSMartin Storsjo       return "Unknown";
12535c503bf4SSaleem Abdulrasool     }
12545c503bf4SSaleem Abdulrasool     break;
12550c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1256114ebf4aSMartin Storsjo     switch (Type) {
12570c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12580c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12590c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12600c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12610c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12620c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12630c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12640c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12650c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12660c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12670c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12680c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12690c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12700c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12710c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12720c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12730c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1274e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12750c72172eSMandeep Singh Grang     default:
1276114ebf4aSMartin Storsjo       return "Unknown";
12770c72172eSMandeep Singh Grang     }
12780c72172eSMandeep Singh Grang     break;
1279e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1280114ebf4aSMartin Storsjo     switch (Type) {
1281e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1282e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1283e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1284e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1285e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1286e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1287e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1288e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1289e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1290e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1291e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1292e5fd0047SMichael J. Spencer     default:
1293114ebf4aSMartin Storsjo       return "Unknown";
1294e5fd0047SMichael J. Spencer     }
1295e5fd0047SMichael J. Spencer     break;
1296e5fd0047SMichael J. Spencer   default:
1297114ebf4aSMartin Storsjo     return "Unknown";
1298e5fd0047SMichael J. Spencer   }
1299e5fd0047SMichael J. Spencer }
1300e5fd0047SMichael J. Spencer 
1301e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1302e5fd0047SMichael J. Spencer 
1303114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1304114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1305114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1306114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1307114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1308114ebf4aSMartin Storsjo }
1309114ebf4aSMartin Storsjo 
1310c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1311c66d761bSRafael Espindola   return !DataDirectory;
1312c66d761bSRafael Espindola }
1313c66d761bSRafael Espindola 
1314e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1315e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1316e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1317e3093808SMartin Storsjo       .Default(Name);
1318e3093808SMartin Storsjo }
1319e3093808SMartin Storsjo 
1320c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1321c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1322a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1323c2bed429SRui Ueyama }
1324c2bed429SRui Ueyama 
13255e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13265e812afaSRafael Espindola   ++Index;
13271c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1328ad7b7e73SDavid Majnemer     Index = -1;
1329ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1330ad7b7e73SDavid Majnemer   }
1331c2bed429SRui Ueyama }
1332c2bed429SRui Ueyama 
13331c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry(
13341c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1335ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1336c2bed429SRui Ueyama }
1337c2bed429SRui Ueyama 
1338861021f9SRui Ueyama static imported_symbol_iterator
133915d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1340861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
134115d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1342861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
134315d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1344861021f9SRui Ueyama   }
1345861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
134615d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1347861021f9SRui Ueyama }
1348861021f9SRui Ueyama 
134915d99359SRui Ueyama static imported_symbol_iterator
135015d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1351861021f9SRui Ueyama   uintptr_t IntPtr = 0;
13521c03389cSReid Kleckner   // FIXME: Handle errors.
13531c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
135415d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1355861021f9SRui Ueyama }
1356861021f9SRui Ueyama 
135715d99359SRui Ueyama static imported_symbol_iterator
135815d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1359861021f9SRui Ueyama   uintptr_t IntPtr = 0;
13601c03389cSReid Kleckner   // FIXME: Handle errors.
13611c03389cSReid Kleckner   cantFail(Object->getRvaPtr(RVA, IntPtr));
1362861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1363861021f9SRui Ueyama   int Index = 0;
136415d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1365861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1366861021f9SRui Ueyama     while (*Entry++)
1367861021f9SRui Ueyama       ++Index;
1368861021f9SRui Ueyama   } else {
1369861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1370861021f9SRui Ueyama     while (*Entry++)
1371861021f9SRui Ueyama       ++Index;
1372861021f9SRui Ueyama   }
137315d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
137415d99359SRui Ueyama }
137515d99359SRui Ueyama 
137615d99359SRui Ueyama imported_symbol_iterator
137715d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
137860049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
137915d99359SRui Ueyama                              OwningObject);
138015d99359SRui Ueyama }
138115d99359SRui Ueyama 
138215d99359SRui Ueyama imported_symbol_iterator
138315d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
138460049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
138515d99359SRui Ueyama                            OwningObject);
1386861021f9SRui Ueyama }
1387861021f9SRui Ueyama 
1388979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1389979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1390979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1391979fb40bSRui Ueyama }
1392979fb40bSRui Ueyama 
139360049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
139460049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
139560049526SDavid Majnemer                              OwningObject);
139660049526SDavid Majnemer }
139760049526SDavid Majnemer 
139860049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
139960049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
140060049526SDavid Majnemer                            OwningObject);
140160049526SDavid Majnemer }
140260049526SDavid Majnemer 
140360049526SDavid Majnemer iterator_range<imported_symbol_iterator>
140460049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
140560049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
140660049526SDavid Majnemer }
140760049526SDavid Majnemer 
14081c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
1409c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
14101c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
14111c03389cSReid Kleckner     return E;
1412a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14131c03389cSReid Kleckner   return Error::success();
1414c2bed429SRui Ueyama }
1415c2bed429SRui Ueyama 
14161c03389cSReid Kleckner Error
14171e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
14181e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
14191c03389cSReid Kleckner   return Error::success();
14201e152d5eSRui Ueyama }
14211e152d5eSRui Ueyama 
14221c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14231c03389cSReid Kleckner     uint32_t &Result) const {
14241e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14251c03389cSReid Kleckner   return Error::success();
14261e152d5eSRui Ueyama }
14271e152d5eSRui Ueyama 
142815d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
142915d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
143015d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
143115d99359SRui Ueyama }
143215d99359SRui Ueyama 
143315d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
143415d99359SRui Ueyama   ++Index;
143515d99359SRui Ueyama }
143615d99359SRui Ueyama 
143715d99359SRui Ueyama imported_symbol_iterator
143815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
143915d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
144015d99359SRui Ueyama                              OwningObject);
144115d99359SRui Ueyama }
144215d99359SRui Ueyama 
144315d99359SRui Ueyama imported_symbol_iterator
144415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
144515d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
144615d99359SRui Ueyama                            OwningObject);
144715d99359SRui Ueyama }
144815d99359SRui Ueyama 
1449979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1450979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1451979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1452979fb40bSRui Ueyama }
1453979fb40bSRui Ueyama 
14541c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
145515d99359SRui Ueyama   uintptr_t IntPtr = 0;
14561c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
14571c03389cSReid Kleckner     return E;
145815d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14591c03389cSReid Kleckner   return Error::success();
146015d99359SRui Ueyama }
146115d99359SRui Ueyama 
14621c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable(
14631c03389cSReid Kleckner     const delay_import_directory_table_entry *&Result) const {
14649f598ac7SJoseph Tremoulet   Result = &Table[Index];
14651c03389cSReid Kleckner   return Error::success();
14661af08658SRui Ueyama }
14671af08658SRui Ueyama 
14681c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
14691c03389cSReid Kleckner                                                      uint64_t &Result) const {
1470ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1471ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1472ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
14731c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(RVA, IntPtr))
14741c03389cSReid Kleckner     return E;
1475ffa4cebeSRui Ueyama   if (OwningObject->is64())
14765dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1477ffa4cebeSRui Ueyama   else
14785dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14791c03389cSReid Kleckner   return Error::success();
1480ffa4cebeSRui Ueyama }
1481ffa4cebeSRui Ueyama 
1482ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1483ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1484ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1485ad882ba8SRui Ueyama }
1486ad882ba8SRui Ueyama 
14875e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14885e812afaSRafael Espindola   ++Index;
1489ad882ba8SRui Ueyama }
1490ad882ba8SRui Ueyama 
1491da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1492da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
14931c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1494da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
14951c03389cSReid Kleckner   if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
14961c03389cSReid Kleckner     return E;
1497da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14981c03389cSReid Kleckner   return Error::success();
1499da49d0d4SRui Ueyama }
1500da49d0d4SRui Ueyama 
1501e5df6095SRui Ueyama // Returns the starting ordinal number.
15021c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1503e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
15041c03389cSReid Kleckner   return Error::success();
1505e5df6095SRui Ueyama }
1506e5df6095SRui Ueyama 
1507ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
15081c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1509ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
15101c03389cSReid Kleckner   return Error::success();
1511ad882ba8SRui Ueyama }
1512ad882ba8SRui Ueyama 
1513ad882ba8SRui Ueyama // Returns the address of the current export symbol.
15141c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1515ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15161c03389cSReid Kleckner   if (Error EC =
1517db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1518ad882ba8SRui Ueyama     return EC;
151924fc2d64SRui Ueyama   const export_address_table_entry *entry =
152024fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1521ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15221c03389cSReid Kleckner   return Error::success();
1523ad882ba8SRui Ueyama }
1524ad882ba8SRui Ueyama 
1525ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1526ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
15271c03389cSReid Kleckner Error
1528db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1529ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
15301c03389cSReid Kleckner   if (Error EC =
1531db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1532ad882ba8SRui Ueyama     return EC;
1533ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1534ad882ba8SRui Ueyama 
1535ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1536ad882ba8SRui Ueyama   int Offset = 0;
1537ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1538ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1539ad882ba8SRui Ueyama     if (*I != Index)
1540ad882ba8SRui Ueyama       continue;
15411c03389cSReid Kleckner     if (Error EC =
1542db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1543ad882ba8SRui Ueyama       return EC;
1544ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
15451c03389cSReid Kleckner     if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1546ad882ba8SRui Ueyama       return EC;
1547ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15481c03389cSReid Kleckner     return Error::success();
1549ad882ba8SRui Ueyama   }
1550ad882ba8SRui Ueyama   Result = "";
15511c03389cSReid Kleckner   return Error::success();
1552ad882ba8SRui Ueyama }
1553ad882ba8SRui Ueyama 
15541c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15551c03389cSReid Kleckner   const data_directory *DataEntry =
15561c03389cSReid Kleckner       OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
15571c03389cSReid Kleckner   if (!DataEntry)
15581c03389cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
15596161b38dSRui Ueyama   uint32_t RVA;
15606161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15616161b38dSRui Ueyama     return EC;
15626161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15636161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15646161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15651c03389cSReid Kleckner   return Error::success();
15666161b38dSRui Ueyama }
15676161b38dSRui Ueyama 
15681c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15696161b38dSRui Ueyama   uint32_t RVA;
15706161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15716161b38dSRui Ueyama     return EC;
15726161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15736161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15746161b38dSRui Ueyama     return EC;
15756161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15761c03389cSReid Kleckner   return Error::success();
15776161b38dSRui Ueyama }
15786161b38dSRui Ueyama 
1579861021f9SRui Ueyama bool ImportedSymbolRef::
1580861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1581861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1582861021f9SRui Ueyama       && Index == Other.Index;
1583861021f9SRui Ueyama }
1584861021f9SRui Ueyama 
1585861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1586861021f9SRui Ueyama   ++Index;
1587861021f9SRui Ueyama }
1588861021f9SRui Ueyama 
15891c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1590861021f9SRui Ueyama   uint32_t RVA;
1591861021f9SRui Ueyama   if (Entry32) {
1592861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1593861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15941c03389cSReid Kleckner       return Error::success();
1595861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1596861021f9SRui Ueyama   } else {
1597861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15981c03389cSReid Kleckner       return Error::success();
1599861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1600861021f9SRui Ueyama   }
1601861021f9SRui Ueyama   uintptr_t IntPtr = 0;
16021c03389cSReid Kleckner   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
1603861021f9SRui Ueyama     return EC;
1604861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1605861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16061c03389cSReid Kleckner   return Error::success();
1607861021f9SRui Ueyama }
1608861021f9SRui Ueyama 
16091c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const {
1610ad7b7e73SDavid Majnemer   if (Entry32)
1611ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1612ad7b7e73SDavid Majnemer   else
1613ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
16141c03389cSReid Kleckner   return Error::success();
1615ad7b7e73SDavid Majnemer }
1616ad7b7e73SDavid Majnemer 
16171c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1618ad7b7e73SDavid Majnemer   if (Entry32)
1619ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1620ad7b7e73SDavid Majnemer   else
1621ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
16221c03389cSReid Kleckner   return Error::success();
1623ad7b7e73SDavid Majnemer }
1624ad7b7e73SDavid Majnemer 
16251c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1626861021f9SRui Ueyama   uint32_t RVA;
1627861021f9SRui Ueyama   if (Entry32) {
1628861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1629861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16301c03389cSReid Kleckner       return Error::success();
1631861021f9SRui Ueyama     }
1632861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1633861021f9SRui Ueyama   } else {
1634861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1635861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16361c03389cSReid Kleckner       return Error::success();
1637861021f9SRui Ueyama     }
1638861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1639861021f9SRui Ueyama   }
1640861021f9SRui Ueyama   uintptr_t IntPtr = 0;
16411c03389cSReid Kleckner   if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
1642861021f9SRui Ueyama     return EC;
1643861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16441c03389cSReid Kleckner   return Error::success();
1645861021f9SRui Ueyama }
1646861021f9SRui Ueyama 
164712db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
164848af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
164939772063SReid Kleckner   return COFFObjectFile::create(Object);
1650686738e2SRui Ueyama }
165174e85130SRui Ueyama 
165274e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
165374e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
165474e85130SRui Ueyama }
165574e85130SRui Ueyama 
165674e85130SRui Ueyama void BaseRelocRef::moveNext() {
165774e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
165874e85130SRui Ueyama   // size of the header itself.
165974e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1660970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
166174e85130SRui Ueyama   if (Size == Header->BlockSize) {
166274e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
166374e85130SRui Ueyama     // consists of the header followed by entries. The header contains
166474e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
166574e85130SRui Ueyama     // current block, proceed to the next block.
166674e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
166774e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
166874e85130SRui Ueyama     Index = 0;
166974e85130SRui Ueyama   } else {
167074e85130SRui Ueyama     ++Index;
167174e85130SRui Ueyama   }
167274e85130SRui Ueyama }
167374e85130SRui Ueyama 
16741c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const {
167574e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
167674e85130SRui Ueyama   Type = Entry[Index].getType();
16771c03389cSReid Kleckner   return Error::success();
167874e85130SRui Ueyama }
167974e85130SRui Ueyama 
16801c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const {
168174e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
168274e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16831c03389cSReid Kleckner   return Error::success();
168474e85130SRui Ueyama }
1685efef15a0SEric Beckmann 
1686357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1687357a40ecSMartin Storsjo   do {                                                                         \
1688357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
168987867988SRafael Espindola     if (E)                                                                     \
1690c55cf4afSBill Wendling       return std::move(E);                                                     \
1691357a40ecSMartin Storsjo   } while (0)
1692efef15a0SEric Beckmann 
169387867988SRafael Espindola Expected<ArrayRef<UTF16>>
169487867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1695efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1696efef15a0SEric Beckmann   Reader.setOffset(Offset);
1697efef15a0SEric Beckmann   uint16_t Length;
1698efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1699efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1700efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1701cd704cb6SEric Beckmann   return RawDirString;
1702efef15a0SEric Beckmann }
1703efef15a0SEric Beckmann 
1704f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1705efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1706f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1707efef15a0SEric Beckmann }
1708efef15a0SEric Beckmann 
170987867988SRafael Espindola Expected<const coff_resource_dir_table &>
1710efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1711efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1712efef15a0SEric Beckmann 
1713efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1714efef15a0SEric Beckmann   Reader.setOffset(Offset);
1715efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1716efef15a0SEric Beckmann   assert(Table != nullptr);
1717efef15a0SEric Beckmann   return *Table;
1718efef15a0SEric Beckmann }
1719efef15a0SEric Beckmann 
1720edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1721edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1722edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1723edb6ab9bSMartin Storsjo 
1724edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1725edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1726edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1727edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1728edb6ab9bSMartin Storsjo   return *Entry;
1729edb6ab9bSMartin Storsjo }
1730edb6ab9bSMartin Storsjo 
17317ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17327ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17337ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
17347ba81d95SMartin Storsjo 
17357ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
17367ba81d95SMartin Storsjo   Reader.setOffset(Offset);
17377ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
17387ba81d95SMartin Storsjo   assert(Entry != nullptr);
17397ba81d95SMartin Storsjo   return *Entry;
17407ba81d95SMartin Storsjo }
17417ba81d95SMartin Storsjo 
1742f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1743efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17447ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1745f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1746efef15a0SEric Beckmann }
1747efef15a0SEric Beckmann 
17487ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17497ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17507ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
17517ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
17527ba81d95SMartin Storsjo }
17537ba81d95SMartin Storsjo 
1754f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1755f3404674SRafael Espindola   return getTableAtOffset(0);
1756efef15a0SEric Beckmann }
1757edb6ab9bSMartin Storsjo 
1758edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1759edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1760edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1761edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1762edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1763edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1764edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1765edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1766edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1767edb6ab9bSMartin Storsjo }
176894382217SMartin Storsjo 
176994382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
177094382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
177194382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
177294382217SMartin Storsjo     if (!Name)
177394382217SMartin Storsjo       return Name.takeError();
177494382217SMartin Storsjo 
177594382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
177694382217SMartin Storsjo       return load(O, S);
177794382217SMartin Storsjo   }
177894382217SMartin Storsjo   return createStringError(object_error::parse_failed,
177994382217SMartin Storsjo                            "no resource section found");
178094382217SMartin Storsjo }
178194382217SMartin Storsjo 
178294382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
178394382217SMartin Storsjo   Obj = O;
178494382217SMartin Storsjo   Section = S;
178594382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
178694382217SMartin Storsjo   if (!Contents)
178794382217SMartin Storsjo     return Contents.takeError();
178894382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
178994382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
179094382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
179194382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
179294382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
179394382217SMartin Storsjo     Relocs.push_back(&R);
1794*352fcfc6SKazu Hirata   llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
179594382217SMartin Storsjo     return A->VirtualAddress < B->VirtualAddress;
179694382217SMartin Storsjo   });
179794382217SMartin Storsjo   return Error::success();
179894382217SMartin Storsjo }
179994382217SMartin Storsjo 
180094382217SMartin Storsjo Expected<StringRef>
180194382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
180294382217SMartin Storsjo   if (!Obj)
180394382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
180494382217SMartin Storsjo 
180594382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
180694382217SMartin Storsjo   // the coff_resource_data_entry struct).
180794382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
180894382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
180994382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
181094382217SMartin Storsjo                               ulittle16_t(0)};
181194382217SMartin Storsjo   auto RelocsForOffset =
181294382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
181394382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
181494382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
181594382217SMartin Storsjo                        });
181694382217SMartin Storsjo 
181794382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
181894382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
181994382217SMartin Storsjo     // the expected type.
182094382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
182194382217SMartin Storsjo     uint16_t RVAReloc;
182294382217SMartin Storsjo     switch (Obj->getMachine()) {
182394382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
182494382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
182594382217SMartin Storsjo       break;
182694382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
182794382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
182894382217SMartin Storsjo       break;
182994382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
183094382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
183194382217SMartin Storsjo       break;
183294382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
183394382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
183494382217SMartin Storsjo       break;
183594382217SMartin Storsjo     default:
183694382217SMartin Storsjo       return createStringError(object_error::parse_failed,
183794382217SMartin Storsjo                                "unsupported architecture");
183894382217SMartin Storsjo     }
183994382217SMartin Storsjo     if (R.Type != RVAReloc)
184094382217SMartin Storsjo       return createStringError(object_error::parse_failed,
184194382217SMartin Storsjo                                "unexpected relocation type");
184294382217SMartin Storsjo     // Get the relocation's symbol
184394382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
184494382217SMartin Storsjo     if (!Sym)
184594382217SMartin Storsjo       return Sym.takeError();
184694382217SMartin Storsjo     // And the symbol's section
184777ecf90cSReid Kleckner     Expected<const coff_section *> Section =
184877ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
184977ecf90cSReid Kleckner     if (!Section)
185077ecf90cSReid Kleckner       return Section.takeError();
185194382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
185294382217SMartin Storsjo     // data it points at.
185394382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
185494382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
185577ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1856c55cf4afSBill Wendling       return std::move(E);
185794382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
185894382217SMartin Storsjo       return createStringError(object_error::parse_failed,
185994382217SMartin Storsjo                                "data outside of section");
186094382217SMartin Storsjo     // Return a reference to the data inside the section.
186194382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
186294382217SMartin Storsjo                      Entry.DataSize);
186394382217SMartin Storsjo   } else {
186494382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
186594382217SMartin Storsjo     if (Obj->isRelocatableObject())
186694382217SMartin Storsjo       return createStringError(object_error::parse_failed,
186794382217SMartin Storsjo                                "no relocation found for DataRVA");
186894382217SMartin Storsjo 
186994382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
187094382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
187194382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
187294382217SMartin Storsjo       if (VA >= S.getAddress() &&
187394382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
187494382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
187594382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
187694382217SMartin Storsjo         if (!Contents)
187794382217SMartin Storsjo           return Contents.takeError();
187894382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
187994382217SMartin Storsjo       }
188094382217SMartin Storsjo     }
188194382217SMartin Storsjo     return createStringError(object_error::parse_failed,
188294382217SMartin Storsjo                              "address not found in image");
188394382217SMartin Storsjo   }
188494382217SMartin Storsjo }
1885