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"
158e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h"
166a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h"
17264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h"
18d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
19d341c932SEugene Zelenko #include "llvm/Object/COFF.h"
20d341c932SEugene Zelenko #include "llvm/Object/Error.h"
21d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h"
22efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h"
23d341c932SEugene Zelenko #include "llvm/Support/Endian.h"
24d341c932SEugene Zelenko #include "llvm/Support/Error.h"
25d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
26d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h"
27d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
28d341c932SEugene Zelenko #include <algorithm>
29d341c932SEugene Zelenko #include <cassert>
30d341c932SEugene Zelenko #include <cstddef>
31d341c932SEugene Zelenko #include <cstdint>
32d341c932SEugene Zelenko #include <cstring>
339d2c15efSNico Rieck #include <limits>
34d341c932SEugene Zelenko #include <memory>
35d341c932SEugene Zelenko #include <system_error>
368e90adafSMichael J. Spencer 
378e90adafSMichael J. Spencer using namespace llvm;
388e90adafSMichael J. Spencer using namespace object;
398e90adafSMichael J. Spencer 
408e90adafSMichael J. Spencer using support::ulittle16_t;
418e90adafSMichael J. Spencer using support::ulittle32_t;
42861021f9SRui Ueyama using support::ulittle64_t;
438e90adafSMichael J. Spencer using support::little16_t;
448e90adafSMichael J. Spencer 
451d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec.
4648af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
47c3f9b5a5SRafael Espindola   if (M.getBufferSize() < Size) {
488ff24d25SRui Ueyama     EC = object_error::unexpected_eof;
491d6167fdSMichael J. Spencer     return false;
501d6167fdSMichael J. Spencer   }
511d6167fdSMichael J. Spencer   return true;
528e90adafSMichael J. Spencer }
538e90adafSMichael J. Spencer 
54ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
55ed64342bSRui Ueyama // Returns unexpected_eof if error.
56ed64342bSRui Ueyama template <typename T>
5748af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
5858323a97SDavid Majnemer                                  const void *Ptr,
59236b0ca7SDavid Majnemer                                  const uint64_t Size = sizeof(T)) {
60ed64342bSRui Ueyama   uintptr_t Addr = uintptr_t(Ptr);
61cbc7ee45SBenjamin Kramer   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
62e830c60dSDavid Majnemer     return EC;
63ed64342bSRui Ueyama   Obj = reinterpret_cast<const T *>(Addr);
647d099195SRui Ueyama   return std::error_code();
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 
106236b0ca7SDavid Majnemer   assert(!checkOffset(Data, 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.
1098ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
1101d6167fdSMichael J. Spencer 
11144f51e51SDavid Majnemer   assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
11244f51e51SDavid Majnemer          "Symbol did not point to the beginning of a symbol");
1131d6167fdSMichael J. Spencer #endif
1141d6167fdSMichael J. Spencer 
1158ff24d25SRui Ueyama   return Addr;
1161d6167fdSMichael J. Spencer }
1171d6167fdSMichael J. Spencer 
1188ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1198ff24d25SRui Ueyama   const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1201d6167fdSMichael J. Spencer 
1211d6167fdSMichael J. Spencer #ifndef NDEBUG
1221d6167fdSMichael J. Spencer   // Verify that the section points to a valid entry in the section table.
12344f51e51SDavid Majnemer   if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1241d6167fdSMichael J. Spencer     report_fatal_error("Section was outside of section table.");
1251d6167fdSMichael J. Spencer 
1268ff24d25SRui Ueyama   uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
1278ff24d25SRui Ueyama   assert(Offset % sizeof(coff_section) == 0 &&
1281d6167fdSMichael J. Spencer          "Section did not point to the beginning of a section");
1291d6167fdSMichael J. Spencer #endif
1301d6167fdSMichael J. Spencer 
1318ff24d25SRui Ueyama   return Addr;
1321d6167fdSMichael J. Spencer }
1331d6167fdSMichael J. Spencer 
1345e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
135236b0ca7SDavid Majnemer   auto End = reinterpret_cast<uintptr_t>(StringTable);
13644f51e51SDavid Majnemer   if (SymbolTable16) {
13744f51e51SDavid Majnemer     const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1388ff24d25SRui Ueyama     Symb += 1 + Symb->NumberOfAuxSymbols;
139236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14044f51e51SDavid Majnemer   } else if (SymbolTable32) {
14144f51e51SDavid Majnemer     const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
14244f51e51SDavid Majnemer     Symb += 1 + Symb->NumberOfAuxSymbols;
143236b0ca7SDavid Majnemer     Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
14444f51e51SDavid Majnemer   } else {
14544f51e51SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
14644f51e51SDavid Majnemer   }
1471d6167fdSMichael J. Spencer }
1481d6167fdSMichael J. Spencer 
14981e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
15044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
1515d0c2ffaSRafael Espindola   StringRef Result;
152efef15a0SEric Beckmann   if (std::error_code EC = getSymbolName(Symb, Result))
15381e8b7d9SKevin Enderby     return errorCodeToError(EC);
1545d0c2ffaSRafael Espindola   return Result;
1558e90adafSMichael J. Spencer }
1568e90adafSMichael J. Spencer 
157be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
158be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
159991af666SRafael Espindola }
160991af666SRafael Espindola 
1616b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1626b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1636b2bba14SDavide Italiano   // up to 32 bytes.
1646b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16503a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1666b2bba14SDavide Italiano }
1676b2bba14SDavide Italiano 
168931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
169*ff6a0b6aSXing GUO   uint64_t Result = cantFail(getSymbolValue(Ref));
17044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
171c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
172991af666SRafael Espindola 
173991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
174991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
175ed067c45SRafael Espindola     return Result;
17654c9f3daSRafael Espindola 
1772617dcceSCraig Topper   const coff_section *Section = nullptr;
178c7d7c6fbSDavid Majnemer   if (std::error_code EC = getSection(SectionNumber, Section))
179931cb65dSKevin Enderby     return errorCodeToError(EC);
180991af666SRafael Espindola   Result += Section->VirtualAddress;
18147ea9eceSReid Kleckner 
18247ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
18347ea9eceSReid Kleckner   // return virtual addresses.
18421427adaSReid Kleckner   Result += getImageBase();
18547ea9eceSReid Kleckner 
186ed067c45SRafael Espindola   return Result;
187c7d7c6fbSDavid Majnemer }
188c7d7c6fbSDavid Majnemer 
1897bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
19044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
191c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
19244f51e51SDavid Majnemer 
193e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
194e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1952fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1962fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1972fa80cc5SRafael Espindola   if (Symb.isCommon())
1982fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1992fa80cc5SRafael Espindola   if (Symb.isFileRecord())
2002fa80cc5SRafael Espindola     return SymbolRef::ST_File;
2012fa80cc5SRafael Espindola 
2021a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
2032fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2042fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2052fa80cc5SRafael Espindola 
2062fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2072fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2082fa80cc5SRafael Espindola 
2092fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
21075d1cf33SBenjamin Kramer }
21175d1cf33SBenjamin Kramer 
212ac00376aSvgxbj Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
21344f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21420122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21575d1cf33SBenjamin Kramer 
216c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2179dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2181df4b84dSDavid Meyer 
219a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2201df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
221a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
222a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2231079ef8dSMartell Malone   }
2241df4b84dSDavid Meyer 
22544f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2261df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2271df4b84dSDavid Meyer 
228c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
229c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
230c7d7c6fbSDavid Majnemer 
231c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
232c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
233c7d7c6fbSDavid Majnemer 
234c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
235c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
236c7d7c6fbSDavid Majnemer 
237a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
238c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
239c7d7c6fbSDavid Majnemer 
24020122a43SRafael Espindola   return Result;
24101759754SMichael J. Spencer }
24201759754SMichael J. Spencer 
243d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
244c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2455eb02e45SRafael Espindola   return Symb.getValue();
2468e90adafSMichael J. Spencer }
2478e90adafSMichael J. Spencer 
2487bd8d994SKevin Enderby Expected<section_iterator>
2498bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
25044f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2518bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2528bab889bSRafael Espindola     return section_end();
2532617dcceSCraig Topper   const coff_section *Sec = nullptr;
25444f51e51SDavid Majnemer   if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec))
2557bd8d994SKevin Enderby     return errorCodeToError(EC);
2568bab889bSRafael Espindola   DataRefImpl Ret;
2578bab889bSRafael Espindola   Ret.p = reinterpret_cast<uintptr_t>(Sec);
2588bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25932173153SMichael J. Spencer }
26032173153SMichael J. Spencer 
2616bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2626bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2636bf32210SRafael Espindola   return Symb.getSectionNumber();
2646bf32210SRafael Espindola }
2656bf32210SRafael Espindola 
2665e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2678ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2688ff24d25SRui Ueyama   Sec += 1;
2698ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2708e90adafSMichael J. Spencer }
2718e90adafSMichael J. Spencer 
2728be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2738ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2748be28cdcSFangrui Song   return getSectionName(Sec);
2758e90adafSMichael J. Spencer }
2768e90adafSMichael J. Spencer 
27780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2788ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2797c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2807c6a071bSDavid Majnemer 
2817c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2827c6a071bSDavid Majnemer   // return virtual addresses.
28321427adaSReid Kleckner   Result += getImageBase();
2847c6a071bSDavid Majnemer   return Result;
2858e90adafSMichael J. Spencer }
2868e90adafSMichael J. Spencer 
287a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
288a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
289a25d329bSGeorge Rimar }
290a25d329bSGeorge Rimar 
29180291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
292a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2938e90adafSMichael J. Spencer }
2948e90adafSMichael J. Spencer 
295e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
296e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2978ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2989da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
299e1cb2c0fSFangrui Song   if (Error E = getSectionContents(Sec, Res))
300c55cf4afSBill Wendling     return std::move(E);
301e1cb2c0fSFangrui Song   return Res;
3028e90adafSMichael J. Spencer }
3038e90adafSMichael J. Spencer 
30480291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3058ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
306511391feSDavid Majnemer   return Sec->getAlignment();
3077989460aSMichael J. Spencer }
3087989460aSMichael J. Spencer 
309401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
310401e4e57SGeorge Rimar   return false;
311401e4e57SGeorge Rimar }
312401e4e57SGeorge Rimar 
31380291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3148ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31580291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3168e90adafSMichael J. Spencer }
3178e90adafSMichael J. Spencer 
31880291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3198ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
32080291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
321800619f2SMichael J. Spencer }
322800619f2SMichael J. Spencer 
32380291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3248ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3251a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3261a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3271a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3281a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
329800619f2SMichael J. Spencer }
330800619f2SMichael J. Spencer 
33129d253c4SDjordje Todorovic // The .debug sections are the only debug sections for COFF
33229d253c4SDjordje Todorovic // (\see MCObjectFileInfo.cpp).
33329d253c4SDjordje Todorovic bool COFFObjectFile::isDebugSection(StringRef SectionName) const {
33429d253c4SDjordje Todorovic   return SectionName.startswith(".debug");
33529d253c4SDjordje Todorovic }
33629d253c4SDjordje Todorovic 
3376bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3386bf32210SRafael Espindola   uintptr_t Offset =
3396bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3406bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3416bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3426bf32210SRafael Espindola }
3436bf32210SRafael Espindola 
34480291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3458ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3461a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3471a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3481a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3492138ef6dSPreston Gurd }
3502138ef6dSPreston Gurd 
351e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
352e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
353e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
354e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
355e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
356e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
357e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
358e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
359e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
360e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
361e830c60dSDavid Majnemer       return 0;
36298fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
36398fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
364e830c60dSDavid Majnemer   }
365e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
366e830c60dSDavid Majnemer }
367e830c60dSDavid Majnemer 
36894751be7SDavid Majnemer static const coff_relocation *
36994751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
37094751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
37194751be7SDavid Majnemer   if (!NumRelocs)
37294751be7SDavid Majnemer     return nullptr;
373827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37494751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
375827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
376827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
377827c8a2bSRui Ueyama     // relocations.
378827c8a2bSRui Ueyama     begin++;
379827c8a2bSRui Ueyama   }
380cbc7ee45SBenjamin Kramer   if (Binary::checkOffset(M, uintptr_t(begin),
381cbc7ee45SBenjamin Kramer                           sizeof(coff_relocation) * NumRelocs))
38294751be7SDavid Majnemer     return nullptr;
38394751be7SDavid Majnemer   return begin;
384827c8a2bSRui Ueyama }
38594751be7SDavid Majnemer 
38694751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38794751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38894751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38976d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
39076d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
39194751be7SDavid Majnemer   DataRefImpl Ret;
39294751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3938ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
394e5fd0047SMichael J. Spencer }
395e5fd0047SMichael J. Spencer 
3968ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3978ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39894751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39994751be7SDavid Majnemer   if (I)
40094751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
4018ff24d25SRui Ueyama   DataRefImpl Ret;
40294751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
4038ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
404e5fd0047SMichael J. Spencer }
405e5fd0047SMichael J. Spencer 
406c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
407db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40844f51e51SDavid Majnemer   if (COFFHeader)
409236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
410236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
411236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
41244f51e51SDavid Majnemer       return EC;
41344f51e51SDavid Majnemer 
41444f51e51SDavid Majnemer   if (COFFBigObjHeader)
415236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
416236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
417236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4188ff24d25SRui Ueyama       return EC;
419c2bed429SRui Ueyama 
420c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
421c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
422c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
423f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42444f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
425f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
426c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42748af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4288ff24d25SRui Ueyama     return EC;
429c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
430db4ed0bdSRafael Espindola   if (std::error_code EC =
43148af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4328ff24d25SRui Ueyama     return EC;
433c2bed429SRui Ueyama 
434773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
435773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
436773a5795SNico Rieck   if (StringTableSize < 4)
437773a5795SNico Rieck       StringTableSize = 4;
438773a5795SNico Rieck 
439c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
440773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
441c2bed429SRui Ueyama     return  object_error::parse_failed;
4427d099195SRui Ueyama   return std::error_code();
443c2bed429SRui Ueyama }
444c2bed429SRui Ueyama 
44521427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
446e94fef7bSReid Kleckner   if (PE32Header)
44721427adaSReid Kleckner     return PE32Header->ImageBase;
448e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44921427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
45021427adaSReid Kleckner   // This actually comes up in practice.
45121427adaSReid Kleckner   return 0;
452e94fef7bSReid Kleckner }
453e94fef7bSReid Kleckner 
454215a586cSRui Ueyama // Returns the file offset for the given VA.
455db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45621427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
457b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
458b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
459b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
460215a586cSRui Ueyama }
461215a586cSRui Ueyama 
462c2bed429SRui Ueyama // Returns the file offset for the given RVA.
463db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46427dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46527dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
466c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
467c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
468215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
469215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
470c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4717d099195SRui Ueyama       return std::error_code();
472c2bed429SRui Ueyama     }
473c2bed429SRui Ueyama   }
474c2bed429SRui Ueyama   return object_error::parse_failed;
475c2bed429SRui Ueyama }
476c2bed429SRui Ueyama 
4772da433eaSReid Kleckner std::error_code
4782da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4792da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4802da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4812da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4822da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4832da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4842da433eaSReid Kleckner     // overflow.
4852da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4862da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4872da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4882da433eaSReid Kleckner       uintptr_t Begin =
4892da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4902da433eaSReid Kleckner       Contents =
4912da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4922da433eaSReid Kleckner       return std::error_code();
4932da433eaSReid Kleckner     }
4942da433eaSReid Kleckner   }
4952da433eaSReid Kleckner   return object_error::parse_failed;
4962da433eaSReid Kleckner }
4972da433eaSReid Kleckner 
498c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
499c2bed429SRui Ueyama // table entry.
500db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
501db4ed0bdSRafael Espindola                                             StringRef &Name) const {
502c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
503db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5048ff24d25SRui Ueyama     return EC;
505c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
506c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
507c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5087d099195SRui Ueyama   return std::error_code();
509c2bed429SRui Ueyama }
510c2bed429SRui Ueyama 
51101528021SSaleem Abdulrasool std::error_code
51201528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
51301528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5142da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5152da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5162da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5172da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5182da433eaSReid Kleckner     return EC;
51901528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5202da433eaSReid Kleckner     return object_error::parse_failed;
52101528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
52201528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5232da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5242da433eaSReid Kleckner                           InfoBytes.size());
5252da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5262da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5272da433eaSReid Kleckner   return std::error_code();
5282da433eaSReid Kleckner }
5292da433eaSReid Kleckner 
53001528021SSaleem Abdulrasool std::error_code
53101528021SSaleem Abdulrasool 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();
539f27f3f84SReid Kleckner   return std::error_code();
540f27f3f84SReid Kleckner }
541f27f3f84SReid Kleckner 
542c2bed429SRui Ueyama // Find the import table.
543db4ed0bdSRafael Espindola std::error_code 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.
546c2bed429SRui Ueyama   const data_directory *DataEntry;
547c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5487d099195SRui Ueyama     return std::error_code();
549c2bed429SRui Ueyama 
550c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
551c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5527d099195SRui Ueyama     return std::error_code();
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;
559db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5608ff24d25SRui Ueyama     return EC;
561ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
562ad7b7e73SDavid Majnemer     return EC;
563c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5641c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5657d099195SRui Ueyama   return std::error_code();
566ad882ba8SRui Ueyama }
567c2bed429SRui Ueyama 
56815d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56915d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
57015d99359SRui Ueyama   const data_directory *DataEntry;
57115d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5727d099195SRui Ueyama     return std::error_code();
57315d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5747d099195SRui Ueyama     return std::error_code();
57515d99359SRui Ueyama 
57615d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57715d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57815d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57915d99359SRui Ueyama 
58015d99359SRui Ueyama   uintptr_t IntPtr = 0;
58115d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
58215d99359SRui Ueyama     return EC;
58315d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58415d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5857d099195SRui Ueyama   return std::error_code();
58615d99359SRui Ueyama }
58715d99359SRui Ueyama 
588ad882ba8SRui Ueyama // Find the export table.
589db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
590ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
591ad882ba8SRui Ueyama   // the export table, do nothing.
592ad882ba8SRui Ueyama   const data_directory *DataEntry;
593ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5947d099195SRui Ueyama     return std::error_code();
595ad882ba8SRui Ueyama 
596ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
597ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5987d099195SRui Ueyama     return std::error_code();
599ad882ba8SRui Ueyama 
600ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
601ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
602db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
603ad882ba8SRui Ueyama     return EC;
60424fc2d64SRui Ueyama   ExportDirectory =
60524fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6067d099195SRui Ueyama   return std::error_code();
607c2bed429SRui Ueyama }
608c2bed429SRui Ueyama 
60974e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
61074e85130SRui Ueyama   const data_directory *DataEntry;
61174e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6127d099195SRui Ueyama     return std::error_code();
61374e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6147d099195SRui Ueyama     return std::error_code();
61574e85130SRui Ueyama 
61674e85130SRui Ueyama   uintptr_t IntPtr = 0;
61774e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61874e85130SRui Ueyama     return EC;
61974e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
62074e85130SRui Ueyama       IntPtr);
62174e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
62274e85130SRui Ueyama       IntPtr + DataEntry->Size);
623893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
624893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6257d099195SRui Ueyama   return std::error_code();
62674e85130SRui Ueyama }
62774e85130SRui Ueyama 
6282da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6292da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6302da433eaSReid Kleckner   const data_directory *DataEntry;
6312da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6322da433eaSReid Kleckner     return std::error_code();
6332da433eaSReid Kleckner 
6342da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6352da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6362da433eaSReid Kleckner     return std::error_code();
6372da433eaSReid Kleckner 
6382da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6392da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6402da433eaSReid Kleckner     return object_error::parse_failed;
6412da433eaSReid Kleckner 
6422da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6432da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6442da433eaSReid Kleckner     return EC;
6452da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
646893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
647893c6469SNico Weber       IntPtr + DataEntry->Size);
648893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
649893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6502da433eaSReid Kleckner   return std::error_code();
6512da433eaSReid Kleckner }
6522da433eaSReid Kleckner 
653b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
654b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
655b7d716c0SReid Kleckner   const data_directory *DataEntry;
656b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
657b7d716c0SReid Kleckner     return std::error_code();
658b7d716c0SReid Kleckner 
659b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
660b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
661b7d716c0SReid Kleckner     return std::error_code();
662b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
663b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
664b7d716c0SReid Kleckner     return EC;
665b7d716c0SReid Kleckner 
666b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
667b7d716c0SReid Kleckner   return std::error_code();
668b7d716c0SReid Kleckner }
669b7d716c0SReid Kleckner 
67048af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
67148af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
67244f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
67344f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
67444f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
675ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
67615d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6772da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6782da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6791d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
68048af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
681c3f9b5a5SRafael Espindola     return;
682ee066fc4SEric Christopher 
68382ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
68482ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
68582ebd8e3SRui Ueyama 
68682ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
68782ebd8e3SRui Ueyama   // it is placed right after COFF header.
6888ff24d25SRui Ueyama   bool HasPEHeader = false;
689ee066fc4SEric Christopher 
6901d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
69150267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
692ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
693ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
69450267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
69550267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69650267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
69782ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
69850267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6998ff24d25SRui Ueyama         EC = object_error::parse_failed;
7001d6167fdSMichael J. Spencer         return;
7011d6167fdSMichael J. Spencer       }
70244f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7038ff24d25SRui Ueyama       HasPEHeader = true;
704ee066fc4SEric Christopher     }
70550267222SDavid Majnemer   }
706ee066fc4SEric Christopher 
70748af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
7081d6167fdSMichael J. Spencer     return;
70944f51e51SDavid Majnemer 
71044f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
71144f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
71244f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
71344f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
71444f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
71544f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71644f51e51SDavid Majnemer       return;
71744f51e51SDavid Majnemer 
71844f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
71944f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
72044f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
72144f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
72244f51e51SDavid Majnemer       COFFHeader = nullptr;
72344f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
72444f51e51SDavid Majnemer     } else {
72544f51e51SDavid Majnemer       // It's not a bigobj.
72644f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
72744f51e51SDavid Majnemer     }
72844f51e51SDavid Majnemer   }
72944f51e51SDavid Majnemer   if (COFFHeader) {
73044f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
73144f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7327d099195SRui Ueyama     EC = std::error_code();
73382ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
73482ebd8e3SRui Ueyama 
73544f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
73644f51e51SDavid Majnemer       return;
73744f51e51SDavid Majnemer   }
73844f51e51SDavid Majnemer 
7398ff24d25SRui Ueyama   if (HasPEHeader) {
74010ed9ddcSRui Ueyama     const pe32_header *Header;
74148af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
74282ebd8e3SRui Ueyama       return;
74310ed9ddcSRui Ueyama 
74410ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
74510ed9ddcSRui Ueyama     uint64_t DataDirSize;
74650267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
74710ed9ddcSRui Ueyama       PE32Header = Header;
74810ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
74910ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
75050267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
75110ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
75210ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
75310ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
75410ed9ddcSRui Ueyama     } else {
75510ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
75610ed9ddcSRui Ueyama       EC = object_error::parse_failed;
757ed64342bSRui Ueyama       return;
758ed64342bSRui Ueyama     }
75948af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
76010ed9ddcSRui Ueyama       return;
761f53c8cb4SRui Ueyama   }
762776c6828SRui Ueyama 
7638950a538SRui Ueyama   if (COFFHeader)
7648950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7658950a538SRui Ueyama 
76648af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
767236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7681d6167fdSMichael J. Spencer     return;
7691d6167fdSMichael J. Spencer 
770c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
771236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
772ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
773ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
774ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
775ac8cfab5SDavid Majnemer       StringTable = nullptr;
776ac8cfab5SDavid Majnemer       StringTableSize = 0;
777ac8cfab5SDavid Majnemer     }
778236b0ca7SDavid Majnemer   } else {
779236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
780236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
781236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
782236b0ca7SDavid Majnemer       return;
783236b0ca7SDavid Majnemer     }
784236b0ca7SDavid Majnemer   }
7858e90adafSMichael J. Spencer 
786c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7878ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
788ed64342bSRui Ueyama     return;
78915d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
79015d99359SRui Ueyama     return;
7911d6167fdSMichael J. Spencer 
792ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7938ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
794ad882ba8SRui Ueyama     return;
795ad882ba8SRui Ueyama 
79674e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
79774e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
79874e85130SRui Ueyama     return;
79974e85130SRui Ueyama 
8002da433eaSReid Kleckner   // Initialize the pointer to the export table.
8012da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
8022da433eaSReid Kleckner     return;
8032da433eaSReid Kleckner 
804b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
805b7d716c0SReid Kleckner     return;
806b7d716c0SReid Kleckner 
8077d099195SRui Ueyama   EC = std::error_code();
8088e90adafSMichael J. Spencer }
8098e90adafSMichael J. Spencer 
810435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8118ff24d25SRui Ueyama   DataRefImpl Ret;
81244f51e51SDavid Majnemer   Ret.p = getSymbolTable();
813f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8148e90adafSMichael J. Spencer }
8158e90adafSMichael J. Spencer 
816435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8178e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8188ff24d25SRui Ueyama   DataRefImpl Ret;
8198ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
820f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8218e90adafSMichael J. Spencer }
8228e90adafSMichael J. Spencer 
823bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
824ad7b7e73SDavid Majnemer   if (!ImportDirectory)
825ad7b7e73SDavid Majnemer     return import_directory_end();
8261c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
827ad7b7e73SDavid Majnemer     return import_directory_end();
828a045b73aSRui Ueyama   return import_directory_iterator(
829a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
830c2bed429SRui Ueyama }
831c2bed429SRui Ueyama 
832bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
833a045b73aSRui Ueyama   return import_directory_iterator(
834ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
835c2bed429SRui Ueyama }
836c429b80dSDavid Meyer 
83715d99359SRui Ueyama delay_import_directory_iterator
83815d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
83915d99359SRui Ueyama   return delay_import_directory_iterator(
84015d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
84115d99359SRui Ueyama }
84215d99359SRui Ueyama 
84315d99359SRui Ueyama delay_import_directory_iterator
84415d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
84515d99359SRui Ueyama   return delay_import_directory_iterator(
84615d99359SRui Ueyama       DelayImportDirectoryEntryRef(
84715d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
84815d99359SRui Ueyama }
84915d99359SRui Ueyama 
850ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
851ad882ba8SRui Ueyama   return export_directory_iterator(
852ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
853ad882ba8SRui Ueyama }
854ad882ba8SRui Ueyama 
855ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8562617dcceSCraig Topper   if (!ExportDirectory)
8572617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8588ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
859ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8608ff24d25SRui Ueyama   return export_directory_iterator(Ref);
861ad882ba8SRui Ueyama }
862ad882ba8SRui Ueyama 
863b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8648ff24d25SRui Ueyama   DataRefImpl Ret;
8658ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8668ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8678e90adafSMichael J. Spencer }
8688e90adafSMichael J. Spencer 
869b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8708ff24d25SRui Ueyama   DataRefImpl Ret;
87144f51e51SDavid Majnemer   int NumSections =
87244f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8738ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8748ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8758e90adafSMichael J. Spencer }
8768e90adafSMichael J. Spencer 
87774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
87874e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
87974e85130SRui Ueyama }
88074e85130SRui Ueyama 
88174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
88274e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
88374e85130SRui Ueyama }
88474e85130SRui Ueyama 
8858e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
88643c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8878e90adafSMichael J. Spencer }
8888e90adafSMichael J. Spencer 
8898e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
89044f51e51SDavid Majnemer   switch(getMachine()) {
8918e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8928e90adafSMichael J. Spencer     return "COFF-i386";
8938e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8948e90adafSMichael J. Spencer     return "COFF-x86-64";
8959b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8969b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8971eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8981eff5c9cSMartell Malone     return "COFF-ARM64";
8998e90adafSMichael J. Spencer   default:
9008e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
9018e90adafSMichael J. Spencer   }
9028e90adafSMichael J. Spencer }
9038e90adafSMichael J. Spencer 
904260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
90544f51e51SDavid Majnemer   switch (getMachine()) {
9068e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9078e90adafSMichael J. Spencer     return Triple::x86;
9088e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9098e90adafSMichael J. Spencer     return Triple::x86_64;
9109b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9119b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9121eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9131eff5c9cSMartell Malone     return Triple::aarch64;
9148e90adafSMichael J. Spencer   default:
9158e90adafSMichael J. Spencer     return Triple::UnknownArch;
9168e90adafSMichael J. Spencer   }
9178e90adafSMichael J. Spencer }
9188e90adafSMichael J. Spencer 
919d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
920d2af4d6fSPaul Semel   if (PE32Header)
921d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
922d2af4d6fSPaul Semel   return 0;
923d2af4d6fSPaul Semel }
924d2af4d6fSPaul Semel 
925979fb40bSRui Ueyama iterator_range<import_directory_iterator>
926979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
927979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
928979fb40bSRui Ueyama }
929979fb40bSRui Ueyama 
930979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
931979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
932979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
933979fb40bSRui Ueyama                     delay_import_directory_end());
934979fb40bSRui Ueyama }
935979fb40bSRui Ueyama 
936979fb40bSRui Ueyama iterator_range<export_directory_iterator>
937979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
938979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
939979fb40bSRui Ueyama }
940979fb40bSRui Ueyama 
94174e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
94274e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
94374e85130SRui Ueyama }
94474e85130SRui Ueyama 
945e84a0b5aSMartin Storsjo std::error_code
946db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
947ed64342bSRui Ueyama                                  const data_directory *&Res) const {
948bcadfee2SHiroshi Inoue   // Error if there's no data directory or the index is out of range.
949f69b0585SDavid Majnemer   if (!DataDirectory) {
950f69b0585SDavid Majnemer     Res = nullptr;
95110ed9ddcSRui Ueyama     return object_error::parse_failed;
952f69b0585SDavid Majnemer   }
95310ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
95410ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
95510ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
956f69b0585SDavid Majnemer   if (Index >= NumEnt) {
957f69b0585SDavid Majnemer     Res = nullptr;
958ed64342bSRui Ueyama     return object_error::parse_failed;
959f69b0585SDavid Majnemer   }
9608ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9617d099195SRui Ueyama   return std::error_code();
962ed64342bSRui Ueyama }
963ed64342bSRui Ueyama 
964db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index,
9651d6167fdSMichael J. Spencer                                            const coff_section *&Result) const {
9662617dcceSCraig Topper   Result = nullptr;
967236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
9687d099195SRui Ueyama     return std::error_code();
969236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9701d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
9718ff24d25SRui Ueyama     Result = SectionTable + (Index - 1);
9727d099195SRui Ueyama     return std::error_code();
9738e90adafSMichael J. Spencer   }
974236b0ca7SDavid Majnemer   return object_error::parse_failed;
975236b0ca7SDavid Majnemer }
9768e90adafSMichael J. Spencer 
977b98f5048SPaul Semel std::error_code COFFObjectFile::getSection(StringRef SectionName,
978b98f5048SPaul Semel                                            const coff_section *&Result) const {
979b98f5048SPaul Semel   Result = nullptr;
980b98f5048SPaul Semel   for (const SectionRef &Section : sections()) {
981bcc00e1aSGeorge Rimar     auto NameOrErr = Section.getName();
982bcc00e1aSGeorge Rimar     if (!NameOrErr)
983bcc00e1aSGeorge Rimar       return errorToErrorCode(NameOrErr.takeError());
984bcc00e1aSGeorge Rimar 
985bcc00e1aSGeorge Rimar     if (*NameOrErr == SectionName) {
986b98f5048SPaul Semel       Result = getCOFFSection(Section);
987b98f5048SPaul Semel       return std::error_code();
988b98f5048SPaul Semel     }
989b98f5048SPaul Semel   }
990b98f5048SPaul Semel   return object_error::parse_failed;
991b98f5048SPaul Semel }
992b98f5048SPaul Semel 
993db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset,
9941d6167fdSMichael J. Spencer                                           StringRef &Result) const {
9951d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9961d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
9971d6167fdSMichael J. Spencer     return object_error::parse_failed;
9988ff24d25SRui Ueyama   if (Offset >= StringTableSize)
9991d6167fdSMichael J. Spencer     return object_error::unexpected_eof;
10008ff24d25SRui Ueyama   Result = StringRef(StringTable + Offset);
10017d099195SRui Ueyama   return std::error_code();
10028e90adafSMichael J. Spencer }
1003022ecdf2SBenjamin Kramer 
100444f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol,
100589a7a5eaSMichael J. Spencer                                               StringRef &Res) const {
1006e40d30f3SRui Ueyama   return getSymbolName(Symbol.getGeneric(), Res);
1007e40d30f3SRui Ueyama }
1008e40d30f3SRui Ueyama 
1009e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol,
1010e40d30f3SRui Ueyama                                               StringRef &Res) const {
101189a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
1012e40d30f3SRui Ueyama   if (Symbol->Name.Offset.Zeroes == 0) {
1013e40d30f3SRui Ueyama     if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res))
10148ff24d25SRui Ueyama       return EC;
10157d099195SRui Ueyama     return std::error_code();
101689a7a5eaSMichael J. Spencer   }
101789a7a5eaSMichael J. Spencer 
1018e40d30f3SRui Ueyama   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
101989a7a5eaSMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
1020e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName);
102189a7a5eaSMichael J. Spencer   else
102289a7a5eaSMichael J. Spencer     // Not null terminated, use all 8 bytes.
1023e40d30f3SRui Ueyama     Res = StringRef(Symbol->Name.ShortName, COFF::NameSize);
10247d099195SRui Ueyama   return std::error_code();
102589a7a5eaSMichael J. Spencer }
102689a7a5eaSMichael J. Spencer 
102744f51e51SDavid Majnemer ArrayRef<uint8_t>
102844f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10292617dcceSCraig Topper   const uint8_t *Aux = nullptr;
103071757ef3SMarshall Clow 
103144f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
103244f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
103371757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
103444f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
103571757ef3SMarshall Clow #ifndef NDEBUG
10368ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10378ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
103844f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
103944f51e51SDavid Majnemer         Offset >=
104044f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
104171757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
104271757ef3SMarshall Clow 
104344f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
104444f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
104571757ef3SMarshall Clow #endif
1046bfb85e67SMarshall Clow   }
104744f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
104871757ef3SMarshall Clow }
104971757ef3SMarshall Clow 
105074e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
105174e7d260SMartin Storsjo   uintptr_t Offset =
105274e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
105374e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
105474e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
105574e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
105674e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
105774e7d260SMartin Storsjo   return Index;
105874e7d260SMartin Storsjo }
105974e7d260SMartin Storsjo 
10608be28cdcSFangrui Song Expected<StringRef>
10618be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
106253c2d547SMichael J. Spencer   StringRef Name;
106344f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
106453c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
106553c2d547SMichael J. Spencer     Name = Sec->Name;
106653c2d547SMichael J. Spencer   else
106753c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
106844f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
106953c2d547SMichael J. Spencer 
107053c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10712314b3deSDavid Majnemer   if (Name.startswith("/")) {
107253c2d547SMichael J. Spencer     uint32_t Offset;
10732314b3deSDavid Majnemer     if (Name.startswith("//")) {
10749d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10758be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1076400b6c08Sserge-sans-paille                                  "invalid section name");
10779d2c15efSNico Rieck     } else {
107853c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
10798be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
10808be28cdcSFangrui Song                                  "invalid section name");
10819d2c15efSNico Rieck     }
1082db4ed0bdSRafael Espindola     if (std::error_code EC = getString(Offset, Name))
10838be28cdcSFangrui Song       return errorCodeToError(EC);
108453c2d547SMichael J. Spencer   }
108553c2d547SMichael J. Spencer 
10868be28cdcSFangrui Song   return Name;
108753c2d547SMichael J. Spencer }
108853c2d547SMichael J. Spencer 
1089a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1090a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1091a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1092a9ee5c06SDavid Majnemer   //
1093a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1094d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1095a9ee5c06SDavid Majnemer   //
1096a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1097a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1098a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1099a9ee5c06SDavid Majnemer   // considered to be zero.
1100d5297ee7SRui Ueyama   if (getDOSHeader())
1101d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1102d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1103a9ee5c06SDavid Majnemer }
1104a9ee5c06SDavid Majnemer 
1105e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11069da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1107e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1108e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1109e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1110e1cb2c0fSFangrui Song     return Error::success();
11119da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
11129da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
11139da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
11149da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1115a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1116e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
1117e1cb2c0fSFangrui Song     return make_error<BinaryError>();
1118a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1119e1cb2c0fSFangrui Song   return Error::success();
11209da9e693SMichael J. Spencer }
11219da9e693SMichael J. Spencer 
1122022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1123e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1124022ecdf2SBenjamin Kramer }
11258ff24d25SRui Ueyama 
11265e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1127e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1128e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1129022ecdf2SBenjamin Kramer }
11308ff24d25SRui Ueyama 
113196d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
113258323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
113396d071cdSRafael Espindola   return R->VirtualAddress;
1134cbe72fc9SDanil Malyshev }
11358ff24d25SRui Ueyama 
1136806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1137022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11388ff24d25SRui Ueyama   DataRefImpl Ref;
1139236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1140236b0ca7SDavid Majnemer     return symbol_end();
114144f51e51SDavid Majnemer   if (SymbolTable16)
114244f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
114344f51e51SDavid Majnemer   else if (SymbolTable32)
114444f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
114544f51e51SDavid Majnemer   else
1146c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11478ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1148022ecdf2SBenjamin Kramer }
11498ff24d25SRui Ueyama 
115099c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1151022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
115299c041b7SRafael Espindola   return R->Type;
1153022ecdf2SBenjamin Kramer }
1154e5fd0047SMichael J. Spencer 
115527dc8394SAlexey Samsonov const coff_section *
115627dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
115727dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
115871757ef3SMarshall Clow }
115971757ef3SMarshall Clow 
116044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
116144f51e51SDavid Majnemer   if (SymbolTable16)
116244f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
116344f51e51SDavid Majnemer   if (SymbolTable32)
116444f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
116544f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
116644f51e51SDavid Majnemer }
116744f51e51SDavid Majnemer 
116844f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
116944f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
117071757ef3SMarshall Clow }
117171757ef3SMarshall Clow 
1172f12b8282SRafael Espindola const coff_relocation *
117327dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
117427dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1175d3e2a76cSMarshall Clow }
1176d3e2a76cSMarshall Clow 
11772f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11786a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11792f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
11802f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
11816a75acb1SRui Ueyama }
11826a75acb1SRui Ueyama 
118327dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
118427dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1185114ebf4aSMartin Storsjo     return #reloc_type;
1186e5fd0047SMichael J. Spencer 
1187114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
118844f51e51SDavid Majnemer   switch (getMachine()) {
1189e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1190114ebf4aSMartin Storsjo     switch (Type) {
1191e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1192e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1193e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1194e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1195e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1196e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1197e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1198e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1199e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1200e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1201e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1202e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1203e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1204e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1205e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1206e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1207e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1208e5fd0047SMichael J. Spencer     default:
1209114ebf4aSMartin Storsjo       return "Unknown";
1210e5fd0047SMichael J. Spencer     }
1211e5fd0047SMichael J. Spencer     break;
12125c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1213114ebf4aSMartin Storsjo     switch (Type) {
12145c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12155c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12165c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12175c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12185c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12195c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12205c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12215c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1222e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12235c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12245c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12255c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12265c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12275c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12285c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12295c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1230e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12315c503bf4SSaleem Abdulrasool     default:
1232114ebf4aSMartin Storsjo       return "Unknown";
12335c503bf4SSaleem Abdulrasool     }
12345c503bf4SSaleem Abdulrasool     break;
12350c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1236114ebf4aSMartin Storsjo     switch (Type) {
12370c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12380c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12390c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12400c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12410c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12420c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12430c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12440c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12450c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12460c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12470c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12480c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12490c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12500c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12510c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12520c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12530c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1254e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12550c72172eSMandeep Singh Grang     default:
1256114ebf4aSMartin Storsjo       return "Unknown";
12570c72172eSMandeep Singh Grang     }
12580c72172eSMandeep Singh Grang     break;
1259e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1260114ebf4aSMartin Storsjo     switch (Type) {
1261e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1262e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1263e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1264e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1265e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1266e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1267e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1268e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1269e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1270e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1271e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1272e5fd0047SMichael J. Spencer     default:
1273114ebf4aSMartin Storsjo       return "Unknown";
1274e5fd0047SMichael J. Spencer     }
1275e5fd0047SMichael J. Spencer     break;
1276e5fd0047SMichael J. Spencer   default:
1277114ebf4aSMartin Storsjo     return "Unknown";
1278e5fd0047SMichael J. Spencer   }
1279e5fd0047SMichael J. Spencer }
1280e5fd0047SMichael J. Spencer 
1281e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1282e5fd0047SMichael J. Spencer 
1283114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1284114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1285114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1286114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1287114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1288114ebf4aSMartin Storsjo }
1289114ebf4aSMartin Storsjo 
1290c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1291c66d761bSRafael Espindola   return !DataDirectory;
1292c66d761bSRafael Espindola }
1293c66d761bSRafael Espindola 
1294e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1295e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1296e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1297e3093808SMartin Storsjo       .Default(Name);
1298e3093808SMartin Storsjo }
1299e3093808SMartin Storsjo 
1300c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1301c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1302a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1303c2bed429SRui Ueyama }
1304c2bed429SRui Ueyama 
13055e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
13065e812afaSRafael Espindola   ++Index;
13071c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1308ad7b7e73SDavid Majnemer     Index = -1;
1309ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1310ad7b7e73SDavid Majnemer   }
1311c2bed429SRui Ueyama }
1312c2bed429SRui Ueyama 
1313db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
13141c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1315ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1316c2bed429SRui Ueyama }
1317c2bed429SRui Ueyama 
1318861021f9SRui Ueyama static imported_symbol_iterator
131915d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1320861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
132115d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1322861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
132315d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1324861021f9SRui Ueyama   }
1325861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
132615d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1327861021f9SRui Ueyama }
1328861021f9SRui Ueyama 
132915d99359SRui Ueyama static imported_symbol_iterator
133015d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1331861021f9SRui Ueyama   uintptr_t IntPtr = 0;
133215d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
133315d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1334861021f9SRui Ueyama }
1335861021f9SRui Ueyama 
133615d99359SRui Ueyama static imported_symbol_iterator
133715d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1338861021f9SRui Ueyama   uintptr_t IntPtr = 0;
133915d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1340861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1341861021f9SRui Ueyama   int Index = 0;
134215d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1343861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1344861021f9SRui Ueyama     while (*Entry++)
1345861021f9SRui Ueyama       ++Index;
1346861021f9SRui Ueyama   } else {
1347861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1348861021f9SRui Ueyama     while (*Entry++)
1349861021f9SRui Ueyama       ++Index;
1350861021f9SRui Ueyama   }
135115d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
135215d99359SRui Ueyama }
135315d99359SRui Ueyama 
135415d99359SRui Ueyama imported_symbol_iterator
135515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
135660049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
135715d99359SRui Ueyama                              OwningObject);
135815d99359SRui Ueyama }
135915d99359SRui Ueyama 
136015d99359SRui Ueyama imported_symbol_iterator
136115d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
136260049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
136315d99359SRui Ueyama                            OwningObject);
1364861021f9SRui Ueyama }
1365861021f9SRui Ueyama 
1366979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1367979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1368979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1369979fb40bSRui Ueyama }
1370979fb40bSRui Ueyama 
137160049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
137260049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
137360049526SDavid Majnemer                              OwningObject);
137460049526SDavid Majnemer }
137560049526SDavid Majnemer 
137660049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
137760049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
137860049526SDavid Majnemer                            OwningObject);
137960049526SDavid Majnemer }
138060049526SDavid Majnemer 
138160049526SDavid Majnemer iterator_range<imported_symbol_iterator>
138260049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
138360049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
138460049526SDavid Majnemer }
138560049526SDavid Majnemer 
1386db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1387c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1388db4ed0bdSRafael Espindola   if (std::error_code EC =
13891e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1390a045b73aSRui Ueyama     return EC;
1391a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13927d099195SRui Ueyama   return std::error_code();
1393c2bed429SRui Ueyama }
1394c2bed429SRui Ueyama 
13951e152d5eSRui Ueyama std::error_code
13961e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13971e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13987d099195SRui Ueyama   return std::error_code();
13991e152d5eSRui Ueyama }
14001e152d5eSRui Ueyama 
14011e152d5eSRui Ueyama std::error_code
14021e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
14031e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
14047d099195SRui Ueyama   return std::error_code();
14051e152d5eSRui Ueyama }
14061e152d5eSRui Ueyama 
140715d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
140815d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
140915d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
141015d99359SRui Ueyama }
141115d99359SRui Ueyama 
141215d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
141315d99359SRui Ueyama   ++Index;
141415d99359SRui Ueyama }
141515d99359SRui Ueyama 
141615d99359SRui Ueyama imported_symbol_iterator
141715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
141815d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
141915d99359SRui Ueyama                              OwningObject);
142015d99359SRui Ueyama }
142115d99359SRui Ueyama 
142215d99359SRui Ueyama imported_symbol_iterator
142315d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
142415d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
142515d99359SRui Ueyama                            OwningObject);
142615d99359SRui Ueyama }
142715d99359SRui Ueyama 
1428979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1429979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1430979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1431979fb40bSRui Ueyama }
1432979fb40bSRui Ueyama 
143315d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
143415d99359SRui Ueyama   uintptr_t IntPtr = 0;
143515d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
143615d99359SRui Ueyama     return EC;
143715d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14387d099195SRui Ueyama   return std::error_code();
143915d99359SRui Ueyama }
144015d99359SRui Ueyama 
14411af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14421af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14439f598ac7SJoseph Tremoulet   Result = &Table[Index];
14447d099195SRui Ueyama   return std::error_code();
14451af08658SRui Ueyama }
14461af08658SRui Ueyama 
1447ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1448ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1449ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1450ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1451ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1452ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1453ffa4cebeSRui Ueyama     return EC;
1454ffa4cebeSRui Ueyama   if (OwningObject->is64())
14555dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1456ffa4cebeSRui Ueyama   else
14575dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14587d099195SRui Ueyama   return std::error_code();
1459ffa4cebeSRui Ueyama }
1460ffa4cebeSRui Ueyama 
1461ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1462ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1463ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1464ad882ba8SRui Ueyama }
1465ad882ba8SRui Ueyama 
14665e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14675e812afaSRafael Espindola   ++Index;
1468ad882ba8SRui Ueyama }
1469ad882ba8SRui Ueyama 
1470da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1471da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1472db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1473da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1474db4ed0bdSRafael Espindola   if (std::error_code EC =
1475db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1476da49d0d4SRui Ueyama     return EC;
1477da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14787d099195SRui Ueyama   return std::error_code();
1479da49d0d4SRui Ueyama }
1480da49d0d4SRui Ueyama 
1481e5df6095SRui Ueyama // Returns the starting ordinal number.
1482db4ed0bdSRafael Espindola std::error_code
1483db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1484e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14857d099195SRui Ueyama   return std::error_code();
1486e5df6095SRui Ueyama }
1487e5df6095SRui Ueyama 
1488ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1489db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1490ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14917d099195SRui Ueyama   return std::error_code();
1492ad882ba8SRui Ueyama }
1493ad882ba8SRui Ueyama 
1494ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1495db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1496ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1497db4ed0bdSRafael Espindola   if (std::error_code EC =
1498db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1499ad882ba8SRui Ueyama     return EC;
150024fc2d64SRui Ueyama   const export_address_table_entry *entry =
150124fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1502ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
15037d099195SRui Ueyama   return std::error_code();
1504ad882ba8SRui Ueyama }
1505ad882ba8SRui Ueyama 
1506ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1507ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1508db4ed0bdSRafael Espindola std::error_code
1509db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1510ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1511db4ed0bdSRafael Espindola   if (std::error_code EC =
1512db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1513ad882ba8SRui Ueyama     return EC;
1514ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1515ad882ba8SRui Ueyama 
1516ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1517ad882ba8SRui Ueyama   int Offset = 0;
1518ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1519ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1520ad882ba8SRui Ueyama     if (*I != Index)
1521ad882ba8SRui Ueyama       continue;
1522db4ed0bdSRafael Espindola     if (std::error_code EC =
1523db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1524ad882ba8SRui Ueyama       return EC;
1525ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1526db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1527ad882ba8SRui Ueyama       return EC;
1528ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15297d099195SRui Ueyama     return std::error_code();
1530ad882ba8SRui Ueyama   }
1531ad882ba8SRui Ueyama   Result = "";
15327d099195SRui Ueyama   return std::error_code();
1533ad882ba8SRui Ueyama }
1534ad882ba8SRui Ueyama 
15356161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15366161b38dSRui Ueyama   const data_directory *DataEntry;
15376161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15386161b38dSRui Ueyama     return EC;
15396161b38dSRui Ueyama   uint32_t RVA;
15406161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15416161b38dSRui Ueyama     return EC;
15426161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15436161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15446161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15456161b38dSRui Ueyama   return std::error_code();
15466161b38dSRui Ueyama }
15476161b38dSRui Ueyama 
15486161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15496161b38dSRui Ueyama   uint32_t RVA;
15506161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15516161b38dSRui Ueyama     return EC;
15526161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15536161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15546161b38dSRui Ueyama     return EC;
15556161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15566161b38dSRui Ueyama   return std::error_code();
15576161b38dSRui Ueyama }
15586161b38dSRui Ueyama 
1559861021f9SRui Ueyama bool ImportedSymbolRef::
1560861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1561861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1562861021f9SRui Ueyama       && Index == Other.Index;
1563861021f9SRui Ueyama }
1564861021f9SRui Ueyama 
1565861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1566861021f9SRui Ueyama   ++Index;
1567861021f9SRui Ueyama }
1568861021f9SRui Ueyama 
1569861021f9SRui Ueyama std::error_code
1570861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1571861021f9SRui Ueyama   uint32_t RVA;
1572861021f9SRui Ueyama   if (Entry32) {
1573861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1574861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15757d099195SRui Ueyama       return std::error_code();
1576861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1577861021f9SRui Ueyama   } else {
1578861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15797d099195SRui Ueyama       return std::error_code();
1580861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1581861021f9SRui Ueyama   }
1582861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1583861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1584861021f9SRui Ueyama     return EC;
1585861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1586861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15877d099195SRui Ueyama   return std::error_code();
1588861021f9SRui Ueyama }
1589861021f9SRui Ueyama 
1590ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1591ad7b7e73SDavid Majnemer   if (Entry32)
1592ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1593ad7b7e73SDavid Majnemer   else
1594ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1595ad7b7e73SDavid Majnemer   return std::error_code();
1596ad7b7e73SDavid Majnemer }
1597ad7b7e73SDavid Majnemer 
1598ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1599ad7b7e73SDavid Majnemer   if (Entry32)
1600ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1601ad7b7e73SDavid Majnemer   else
1602ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1603ad7b7e73SDavid Majnemer   return std::error_code();
1604ad7b7e73SDavid Majnemer }
1605ad7b7e73SDavid Majnemer 
1606861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1607861021f9SRui Ueyama   uint32_t RVA;
1608861021f9SRui Ueyama   if (Entry32) {
1609861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1610861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
16117d099195SRui Ueyama       return std::error_code();
1612861021f9SRui Ueyama     }
1613861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1614861021f9SRui Ueyama   } else {
1615861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1616861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
16177d099195SRui Ueyama       return std::error_code();
1618861021f9SRui Ueyama     }
1619861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1620861021f9SRui Ueyama   }
1621861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1622861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1623861021f9SRui Ueyama     return EC;
1624861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16257d099195SRui Ueyama   return std::error_code();
1626861021f9SRui Ueyama }
1627861021f9SRui Ueyama 
162812db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
162948af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1630db4ed0bdSRafael Espindola   std::error_code EC;
163148af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1632692410efSRafael Espindola   if (EC)
163312db383eSRafael Espindola     return errorCodeToError(EC);
1634c55cf4afSBill Wendling   return std::move(Ret);
1635686738e2SRui Ueyama }
163674e85130SRui Ueyama 
163774e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
163874e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
163974e85130SRui Ueyama }
164074e85130SRui Ueyama 
164174e85130SRui Ueyama void BaseRelocRef::moveNext() {
164274e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
164374e85130SRui Ueyama   // size of the header itself.
164474e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1645970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
164674e85130SRui Ueyama   if (Size == Header->BlockSize) {
164774e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
164874e85130SRui Ueyama     // consists of the header followed by entries. The header contains
164974e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
165074e85130SRui Ueyama     // current block, proceed to the next block.
165174e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
165274e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
165374e85130SRui Ueyama     Index = 0;
165474e85130SRui Ueyama   } else {
165574e85130SRui Ueyama     ++Index;
165674e85130SRui Ueyama   }
165774e85130SRui Ueyama }
165874e85130SRui Ueyama 
165974e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
166074e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
166174e85130SRui Ueyama   Type = Entry[Index].getType();
16627d099195SRui Ueyama   return std::error_code();
166374e85130SRui Ueyama }
166474e85130SRui Ueyama 
166574e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
166674e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
166774e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16687d099195SRui Ueyama   return std::error_code();
166974e85130SRui Ueyama }
1670efef15a0SEric Beckmann 
1671357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1672357a40ecSMartin Storsjo   do {                                                                         \
1673357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
167487867988SRafael Espindola     if (E)                                                                     \
1675c55cf4afSBill Wendling       return std::move(E);                                                     \
1676357a40ecSMartin Storsjo   } while (0)
1677efef15a0SEric Beckmann 
167887867988SRafael Espindola Expected<ArrayRef<UTF16>>
167987867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1680efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1681efef15a0SEric Beckmann   Reader.setOffset(Offset);
1682efef15a0SEric Beckmann   uint16_t Length;
1683efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1684efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1685efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1686cd704cb6SEric Beckmann   return RawDirString;
1687efef15a0SEric Beckmann }
1688efef15a0SEric Beckmann 
1689f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1690efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1691f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1692efef15a0SEric Beckmann }
1693efef15a0SEric Beckmann 
169487867988SRafael Espindola Expected<const coff_resource_dir_table &>
1695efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1696efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1697efef15a0SEric Beckmann 
1698efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1699efef15a0SEric Beckmann   Reader.setOffset(Offset);
1700efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1701efef15a0SEric Beckmann   assert(Table != nullptr);
1702efef15a0SEric Beckmann   return *Table;
1703efef15a0SEric Beckmann }
1704efef15a0SEric Beckmann 
1705edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1706edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1707edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1708edb6ab9bSMartin Storsjo 
1709edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1710edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1711edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1712edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1713edb6ab9bSMartin Storsjo   return *Entry;
1714edb6ab9bSMartin Storsjo }
1715edb6ab9bSMartin Storsjo 
17167ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17177ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17187ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
17197ba81d95SMartin Storsjo 
17207ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
17217ba81d95SMartin Storsjo   Reader.setOffset(Offset);
17227ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
17237ba81d95SMartin Storsjo   assert(Entry != nullptr);
17247ba81d95SMartin Storsjo   return *Entry;
17257ba81d95SMartin Storsjo }
17267ba81d95SMartin Storsjo 
1727f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1728efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17297ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1730f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1731efef15a0SEric Beckmann }
1732efef15a0SEric Beckmann 
17337ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17347ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17357ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
17367ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
17377ba81d95SMartin Storsjo }
17387ba81d95SMartin Storsjo 
1739f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1740f3404674SRafael Espindola   return getTableAtOffset(0);
1741efef15a0SEric Beckmann }
1742edb6ab9bSMartin Storsjo 
1743edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1744edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1745edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1746edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1747edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1748edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1749edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1750edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1751edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1752edb6ab9bSMartin Storsjo }
175394382217SMartin Storsjo 
175494382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
175594382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
175694382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
175794382217SMartin Storsjo     if (!Name)
175894382217SMartin Storsjo       return Name.takeError();
175994382217SMartin Storsjo 
176094382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
176194382217SMartin Storsjo       return load(O, S);
176294382217SMartin Storsjo   }
176394382217SMartin Storsjo   return createStringError(object_error::parse_failed,
176494382217SMartin Storsjo                            "no resource section found");
176594382217SMartin Storsjo }
176694382217SMartin Storsjo 
176794382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
176894382217SMartin Storsjo   Obj = O;
176994382217SMartin Storsjo   Section = S;
177094382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
177194382217SMartin Storsjo   if (!Contents)
177294382217SMartin Storsjo     return Contents.takeError();
177394382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
177494382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
177594382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
177694382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
177794382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
177894382217SMartin Storsjo     Relocs.push_back(&R);
177994382217SMartin Storsjo   std::sort(Relocs.begin(), Relocs.end(),
178094382217SMartin Storsjo             [](const coff_relocation *A, const coff_relocation *B) {
178194382217SMartin Storsjo               return A->VirtualAddress < B->VirtualAddress;
178294382217SMartin Storsjo             });
178394382217SMartin Storsjo   return Error::success();
178494382217SMartin Storsjo }
178594382217SMartin Storsjo 
178694382217SMartin Storsjo Expected<StringRef>
178794382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
178894382217SMartin Storsjo   if (!Obj)
178994382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
179094382217SMartin Storsjo 
179194382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
179294382217SMartin Storsjo   // the coff_resource_data_entry struct).
179394382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
179494382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
179594382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
179694382217SMartin Storsjo                               ulittle16_t(0)};
179794382217SMartin Storsjo   auto RelocsForOffset =
179894382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
179994382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
180094382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
180194382217SMartin Storsjo                        });
180294382217SMartin Storsjo 
180394382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
180494382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
180594382217SMartin Storsjo     // the expected type.
180694382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
180794382217SMartin Storsjo     uint16_t RVAReloc;
180894382217SMartin Storsjo     switch (Obj->getMachine()) {
180994382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
181094382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
181194382217SMartin Storsjo       break;
181294382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
181394382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
181494382217SMartin Storsjo       break;
181594382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
181694382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
181794382217SMartin Storsjo       break;
181894382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
181994382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
182094382217SMartin Storsjo       break;
182194382217SMartin Storsjo     default:
182294382217SMartin Storsjo       return createStringError(object_error::parse_failed,
182394382217SMartin Storsjo                                "unsupported architecture");
182494382217SMartin Storsjo     }
182594382217SMartin Storsjo     if (R.Type != RVAReloc)
182694382217SMartin Storsjo       return createStringError(object_error::parse_failed,
182794382217SMartin Storsjo                                "unexpected relocation type");
182894382217SMartin Storsjo     // Get the relocation's symbol
182994382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
183094382217SMartin Storsjo     if (!Sym)
183194382217SMartin Storsjo       return Sym.takeError();
183294382217SMartin Storsjo     const coff_section *Section = nullptr;
183394382217SMartin Storsjo     // And the symbol's section
183494382217SMartin Storsjo     if (std::error_code EC = Obj->getSection(Sym->getSectionNumber(), Section))
183594382217SMartin Storsjo       return errorCodeToError(EC);
183694382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
183794382217SMartin Storsjo     // data it points at.
183894382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
183994382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
184094382217SMartin Storsjo     if (Error E = Obj->getSectionContents(Section, Contents))
1841c55cf4afSBill Wendling       return std::move(E);
184294382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
184394382217SMartin Storsjo       return createStringError(object_error::parse_failed,
184494382217SMartin Storsjo                                "data outside of section");
184594382217SMartin Storsjo     // Return a reference to the data inside the section.
184694382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
184794382217SMartin Storsjo                      Entry.DataSize);
184894382217SMartin Storsjo   } else {
184994382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
185094382217SMartin Storsjo     if (Obj->isRelocatableObject())
185194382217SMartin Storsjo       return createStringError(object_error::parse_failed,
185294382217SMartin Storsjo                                "no relocation found for DataRVA");
185394382217SMartin Storsjo 
185494382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
185594382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
185694382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
185794382217SMartin Storsjo       if (VA >= S.getAddress() &&
185894382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
185994382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
186094382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
186194382217SMartin Storsjo         if (!Contents)
186294382217SMartin Storsjo           return Contents.takeError();
186394382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
186494382217SMartin Storsjo       }
186594382217SMartin Storsjo     }
186694382217SMartin Storsjo     return createStringError(object_error::parse_failed,
186794382217SMartin Storsjo                              "address not found in image");
186894382217SMartin Storsjo   }
186994382217SMartin Storsjo }
1870