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 {
150*77ecf90cSReid Kleckner   return getSymbolName(getCOFFSymbol(Ref));
1518e90adafSMichael J. Spencer }
1528e90adafSMichael J. Spencer 
153be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
154be8b0ea8SRafael Espindola   return getCOFFSymbol(Ref).getValue();
155991af666SRafael Espindola }
156991af666SRafael Espindola 
1576b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1586b2bba14SDavide Italiano   // MSVC/link.exe seems to align symbols to the next-power-of-2
1596b2bba14SDavide Italiano   // up to 32 bytes.
1606b2bba14SDavide Italiano   COFFSymbolRef Symb = getCOFFSymbol(Ref);
16103a85680SDavide Italiano   return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1626b2bba14SDavide Italiano }
1636b2bba14SDavide Italiano 
164931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
165ff6a0b6aSXing GUO   uint64_t Result = cantFail(getSymbolValue(Ref));
16644f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
167c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
168991af666SRafael Espindola 
169991af666SRafael Espindola   if (Symb.isAnyUndefined() || Symb.isCommon() ||
170991af666SRafael Espindola       COFF::isReservedSectionNumber(SectionNumber))
171ed067c45SRafael Espindola     return Result;
17254c9f3daSRafael Espindola 
173*77ecf90cSReid Kleckner   Expected<const coff_section *> Section = getSection(SectionNumber);
174*77ecf90cSReid Kleckner   if (!Section)
175*77ecf90cSReid Kleckner     return Section.takeError();
176*77ecf90cSReid Kleckner   Result += (*Section)->VirtualAddress;
17747ea9eceSReid Kleckner 
17847ea9eceSReid Kleckner   // The section VirtualAddress does not include ImageBase, and we want to
17947ea9eceSReid Kleckner   // return virtual addresses.
18021427adaSReid Kleckner   Result += getImageBase();
18147ea9eceSReid Kleckner 
182ed067c45SRafael Espindola   return Result;
183c7d7c6fbSDavid Majnemer }
184c7d7c6fbSDavid Majnemer 
1857bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
18644f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
187c7d7c6fbSDavid Majnemer   int32_t SectionNumber = Symb.getSectionNumber();
18844f51e51SDavid Majnemer 
189e834f420SPeter Collingbourne   if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
190e834f420SPeter Collingbourne     return SymbolRef::ST_Function;
1912fa80cc5SRafael Espindola   if (Symb.isAnyUndefined())
1922fa80cc5SRafael Espindola     return SymbolRef::ST_Unknown;
1932fa80cc5SRafael Espindola   if (Symb.isCommon())
1942fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
1952fa80cc5SRafael Espindola   if (Symb.isFileRecord())
1962fa80cc5SRafael Espindola     return SymbolRef::ST_File;
1972fa80cc5SRafael Espindola 
1981a666e0fSDavid Majnemer   // TODO: perhaps we need a new symbol type ST_Section.
1992fa80cc5SRafael Espindola   if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2002fa80cc5SRafael Espindola     return SymbolRef::ST_Debug;
2012fa80cc5SRafael Espindola 
2022fa80cc5SRafael Espindola   if (!COFF::isReservedSectionNumber(SectionNumber))
2032fa80cc5SRafael Espindola     return SymbolRef::ST_Data;
2042fa80cc5SRafael Espindola 
2052fa80cc5SRafael Espindola   return SymbolRef::ST_Other;
20675d1cf33SBenjamin Kramer }
20775d1cf33SBenjamin Kramer 
208ac00376aSvgxbj Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
20944f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
21020122a43SRafael Espindola   uint32_t Result = SymbolRef::SF_None;
21175d1cf33SBenjamin Kramer 
212c7d7c6fbSDavid Majnemer   if (Symb.isExternal() || Symb.isWeakExternal())
2139dc0eb42SLang Hames     Result |= SymbolRef::SF_Global;
2141df4b84dSDavid Meyer 
215a6ffc9c8SMartin Storsjo   if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2161df4b84dSDavid Meyer     Result |= SymbolRef::SF_Weak;
217a6ffc9c8SMartin Storsjo     if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
218a6ffc9c8SMartin Storsjo       Result |= SymbolRef::SF_Undefined;
2191079ef8dSMartell Malone   }
2201df4b84dSDavid Meyer 
22144f51e51SDavid Majnemer   if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2221df4b84dSDavid Meyer     Result |= SymbolRef::SF_Absolute;
2231df4b84dSDavid Meyer 
224c7d7c6fbSDavid Majnemer   if (Symb.isFileRecord())
225c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
226c7d7c6fbSDavid Majnemer 
227c7d7c6fbSDavid Majnemer   if (Symb.isSectionDefinition())
228c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_FormatSpecific;
229c7d7c6fbSDavid Majnemer 
230c7d7c6fbSDavid Majnemer   if (Symb.isCommon())
231c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Common;
232c7d7c6fbSDavid Majnemer 
233a6ffc9c8SMartin Storsjo   if (Symb.isUndefined())
234c7d7c6fbSDavid Majnemer     Result |= SymbolRef::SF_Undefined;
235c7d7c6fbSDavid Majnemer 
23620122a43SRafael Espindola   return Result;
23701759754SMichael J. Spencer }
23801759754SMichael J. Spencer 
239d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
240c7d7c6fbSDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2415eb02e45SRafael Espindola   return Symb.getValue();
2428e90adafSMichael J. Spencer }
2438e90adafSMichael J. Spencer 
2447bd8d994SKevin Enderby Expected<section_iterator>
2458bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
24644f51e51SDavid Majnemer   COFFSymbolRef Symb = getCOFFSymbol(Ref);
2478bab889bSRafael Espindola   if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2488bab889bSRafael Espindola     return section_end();
249*77ecf90cSReid Kleckner   Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
250*77ecf90cSReid Kleckner   if (!Sec)
251*77ecf90cSReid Kleckner     return Sec.takeError();
2528bab889bSRafael Espindola   DataRefImpl Ret;
253*77ecf90cSReid Kleckner   Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2548bab889bSRafael Espindola   return section_iterator(SectionRef(Ret, this));
25532173153SMichael J. Spencer }
25632173153SMichael J. Spencer 
2576bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2586bf32210SRafael Espindola   COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2596bf32210SRafael Espindola   return Symb.getSectionNumber();
2606bf32210SRafael Espindola }
2616bf32210SRafael Espindola 
2625e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2638ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2648ff24d25SRui Ueyama   Sec += 1;
2658ff24d25SRui Ueyama   Ref.p = reinterpret_cast<uintptr_t>(Sec);
2668e90adafSMichael J. Spencer }
2678e90adafSMichael J. Spencer 
2688be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2698ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2708be28cdcSFangrui Song   return getSectionName(Sec);
2718e90adafSMichael J. Spencer }
2728e90adafSMichael J. Spencer 
27380291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2748ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2757c6a071bSDavid Majnemer   uint64_t Result = Sec->VirtualAddress;
2767c6a071bSDavid Majnemer 
2777c6a071bSDavid Majnemer   // The section VirtualAddress does not include ImageBase, and we want to
2787c6a071bSDavid Majnemer   // return virtual addresses.
27921427adaSReid Kleckner   Result += getImageBase();
2807c6a071bSDavid Majnemer   return Result;
2818e90adafSMichael J. Spencer }
2828e90adafSMichael J. Spencer 
283a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
284a25d329bSGeorge Rimar   return toSec(Sec) - SectionTable;
285a25d329bSGeorge Rimar }
286a25d329bSGeorge Rimar 
28780291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
288a9ee5c06SDavid Majnemer   return getSectionSize(toSec(Ref));
2898e90adafSMichael J. Spencer }
2908e90adafSMichael J. Spencer 
291e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>>
292e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2938ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
2949da9e693SMichael J. Spencer   ArrayRef<uint8_t> Res;
295e1cb2c0fSFangrui Song   if (Error E = getSectionContents(Sec, Res))
296c55cf4afSBill Wendling     return std::move(E);
297e1cb2c0fSFangrui Song   return Res;
2988e90adafSMichael J. Spencer }
2998e90adafSMichael J. Spencer 
30080291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3018ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
302511391feSDavid Majnemer   return Sec->getAlignment();
3037989460aSMichael J. Spencer }
3047989460aSMichael J. Spencer 
305401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
306401e4e57SGeorge Rimar   return false;
307401e4e57SGeorge Rimar }
308401e4e57SGeorge Rimar 
30980291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3108ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31180291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3128e90adafSMichael J. Spencer }
3138e90adafSMichael J. Spencer 
31480291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3158ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
31680291274SRafael Espindola   return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
317800619f2SMichael J. Spencer }
318800619f2SMichael J. Spencer 
31980291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3208ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3211a666e0fSDavid Majnemer   const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3221a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_READ |
3231a666e0fSDavid Majnemer                             COFF::IMAGE_SCN_MEM_WRITE;
3241a666e0fSDavid Majnemer   return (Sec->Characteristics & BssFlags) == BssFlags;
325800619f2SMichael J. Spencer }
326800619f2SMichael J. Spencer 
32729d253c4SDjordje Todorovic // The .debug sections are the only debug sections for COFF
32829d253c4SDjordje Todorovic // (\see MCObjectFileInfo.cpp).
32929d253c4SDjordje Todorovic bool COFFObjectFile::isDebugSection(StringRef SectionName) const {
33029d253c4SDjordje Todorovic   return SectionName.startswith(".debug");
33129d253c4SDjordje Todorovic }
33229d253c4SDjordje Todorovic 
3336bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3346bf32210SRafael Espindola   uintptr_t Offset =
3356bf32210SRafael Espindola       uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable);
3366bf32210SRafael Espindola   assert((Offset % sizeof(coff_section)) == 0);
3376bf32210SRafael Espindola   return (Offset / sizeof(coff_section)) + 1;
3386bf32210SRafael Espindola }
3396bf32210SRafael Espindola 
34080291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3418ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
3421a666e0fSDavid Majnemer   // In COFF, a virtual section won't have any in-file
3431a666e0fSDavid Majnemer   // content, so the file pointer to the content will be zero.
3441a666e0fSDavid Majnemer   return Sec->PointerToRawData == 0;
3452138ef6dSPreston Gurd }
3462138ef6dSPreston Gurd 
347e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec,
348e830c60dSDavid Majnemer                                        MemoryBufferRef M, const uint8_t *base) {
349e830c60dSDavid Majnemer   // The field for the number of relocations in COFF section table is only
350e830c60dSDavid Majnemer   // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
351e830c60dSDavid Majnemer   // NumberOfRelocations field, and the actual relocation count is stored in the
352e830c60dSDavid Majnemer   // VirtualAddress field in the first relocation entry.
353e830c60dSDavid Majnemer   if (Sec->hasExtendedRelocations()) {
354e830c60dSDavid Majnemer     const coff_relocation *FirstReloc;
355e830c60dSDavid Majnemer     if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>(
356e830c60dSDavid Majnemer         base + Sec->PointerToRelocations)))
357e830c60dSDavid Majnemer       return 0;
35898fe58a3SRui Ueyama     // -1 to exclude this first relocation entry.
35998fe58a3SRui Ueyama     return FirstReloc->VirtualAddress - 1;
360e830c60dSDavid Majnemer   }
361e830c60dSDavid Majnemer   return Sec->NumberOfRelocations;
362e830c60dSDavid Majnemer }
363e830c60dSDavid Majnemer 
36494751be7SDavid Majnemer static const coff_relocation *
36594751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
36694751be7SDavid Majnemer   uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
36794751be7SDavid Majnemer   if (!NumRelocs)
36894751be7SDavid Majnemer     return nullptr;
369827c8a2bSRui Ueyama   auto begin = reinterpret_cast<const coff_relocation *>(
37094751be7SDavid Majnemer       Base + Sec->PointerToRelocations);
371827c8a2bSRui Ueyama   if (Sec->hasExtendedRelocations()) {
372827c8a2bSRui Ueyama     // Skip the first relocation entry repurposed to store the number of
373827c8a2bSRui Ueyama     // relocations.
374827c8a2bSRui Ueyama     begin++;
375827c8a2bSRui Ueyama   }
376cbc7ee45SBenjamin Kramer   if (Binary::checkOffset(M, uintptr_t(begin),
377cbc7ee45SBenjamin Kramer                           sizeof(coff_relocation) * NumRelocs))
37894751be7SDavid Majnemer     return nullptr;
37994751be7SDavid Majnemer   return begin;
380827c8a2bSRui Ueyama }
38194751be7SDavid Majnemer 
38294751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
38394751be7SDavid Majnemer   const coff_section *Sec = toSec(Ref);
38494751be7SDavid Majnemer   const coff_relocation *begin = getFirstReloc(Sec, Data, base());
38576d650e8SRafael Espindola   if (begin && Sec->VirtualAddress != 0)
38676d650e8SRafael Espindola     report_fatal_error("Sections with relocations should have an address of 0");
38794751be7SDavid Majnemer   DataRefImpl Ret;
38894751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(begin);
3898ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
390e5fd0047SMichael J. Spencer }
391e5fd0047SMichael J. Spencer 
3928ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
3938ff24d25SRui Ueyama   const coff_section *Sec = toSec(Ref);
39494751be7SDavid Majnemer   const coff_relocation *I = getFirstReloc(Sec, Data, base());
39594751be7SDavid Majnemer   if (I)
39694751be7SDavid Majnemer     I += getNumberOfRelocations(Sec, Data, base());
3978ff24d25SRui Ueyama   DataRefImpl Ret;
39894751be7SDavid Majnemer   Ret.p = reinterpret_cast<uintptr_t>(I);
3998ff24d25SRui Ueyama   return relocation_iterator(RelocationRef(Ret, this));
400e5fd0047SMichael J. Spencer }
401e5fd0047SMichael J. Spencer 
402c2bed429SRui Ueyama // Initialize the pointer to the symbol table.
403db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() {
40444f51e51SDavid Majnemer   if (COFFHeader)
405236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
406236b0ca7SDavid Majnemer             SymbolTable16, Data, base() + getPointerToSymbolTable(),
407236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
40844f51e51SDavid Majnemer       return EC;
40944f51e51SDavid Majnemer 
41044f51e51SDavid Majnemer   if (COFFBigObjHeader)
411236b0ca7SDavid Majnemer     if (std::error_code EC = getObject(
412236b0ca7SDavid Majnemer             SymbolTable32, Data, base() + getPointerToSymbolTable(),
413236b0ca7SDavid Majnemer             (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4148ff24d25SRui Ueyama       return EC;
415c2bed429SRui Ueyama 
416c2bed429SRui Ueyama   // Find string table. The first four byte of the string table contains the
417c2bed429SRui Ueyama   // total size of the string table, including the size field itself. If the
418c2bed429SRui Ueyama   // string table is empty, the value of the first four byte would be 4.
419f69b0585SDavid Majnemer   uint32_t StringTableOffset = getPointerToSymbolTable() +
42044f51e51SDavid Majnemer                                getNumberOfSymbols() * getSymbolTableEntrySize();
421f69b0585SDavid Majnemer   const uint8_t *StringTableAddr = base() + StringTableOffset;
422c2bed429SRui Ueyama   const ulittle32_t *StringTableSizePtr;
42348af1c2aSRafael Espindola   if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
4248ff24d25SRui Ueyama     return EC;
425c2bed429SRui Ueyama   StringTableSize = *StringTableSizePtr;
426db4ed0bdSRafael Espindola   if (std::error_code EC =
42748af1c2aSRafael Espindola           getObject(StringTable, Data, StringTableAddr, StringTableSize))
4288ff24d25SRui Ueyama     return EC;
429c2bed429SRui Ueyama 
430773a5795SNico Rieck   // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
431773a5795SNico Rieck   // tools like cvtres write a size of 0 for an empty table instead of 4.
432773a5795SNico Rieck   if (StringTableSize < 4)
433773a5795SNico Rieck       StringTableSize = 4;
434773a5795SNico Rieck 
435c2bed429SRui Ueyama   // Check that the string table is null terminated if has any in it.
436773a5795SNico Rieck   if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
437c2bed429SRui Ueyama     return  object_error::parse_failed;
4387d099195SRui Ueyama   return std::error_code();
439c2bed429SRui Ueyama }
440c2bed429SRui Ueyama 
44121427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const {
442e94fef7bSReid Kleckner   if (PE32Header)
44321427adaSReid Kleckner     return PE32Header->ImageBase;
444e94fef7bSReid Kleckner   else if (PE32PlusHeader)
44521427adaSReid Kleckner     return PE32PlusHeader->ImageBase;
44621427adaSReid Kleckner   // This actually comes up in practice.
44721427adaSReid Kleckner   return 0;
448e94fef7bSReid Kleckner }
449e94fef7bSReid Kleckner 
450215a586cSRui Ueyama // Returns the file offset for the given VA.
451db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
45221427adaSReid Kleckner   uint64_t ImageBase = getImageBase();
453b7a40081SRui Ueyama   uint64_t Rva = Addr - ImageBase;
454b7a40081SRui Ueyama   assert(Rva <= UINT32_MAX);
455b7a40081SRui Ueyama   return getRvaPtr((uint32_t)Rva, Res);
456215a586cSRui Ueyama }
457215a586cSRui Ueyama 
458c2bed429SRui Ueyama // Returns the file offset for the given RVA.
459db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
46027dc8394SAlexey Samsonov   for (const SectionRef &S : sections()) {
46127dc8394SAlexey Samsonov     const coff_section *Section = getCOFFSection(S);
462c2bed429SRui Ueyama     uint32_t SectionStart = Section->VirtualAddress;
463c2bed429SRui Ueyama     uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
464215a586cSRui Ueyama     if (SectionStart <= Addr && Addr < SectionEnd) {
465215a586cSRui Ueyama       uint32_t Offset = Addr - SectionStart;
466c2bed429SRui Ueyama       Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
4677d099195SRui Ueyama       return std::error_code();
468c2bed429SRui Ueyama     }
469c2bed429SRui Ueyama   }
470c2bed429SRui Ueyama   return object_error::parse_failed;
471c2bed429SRui Ueyama }
472c2bed429SRui Ueyama 
4732da433eaSReid Kleckner std::error_code
4742da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4752da433eaSReid Kleckner                                      ArrayRef<uint8_t> &Contents) const {
4762da433eaSReid Kleckner   for (const SectionRef &S : sections()) {
4772da433eaSReid Kleckner     const coff_section *Section = getCOFFSection(S);
4782da433eaSReid Kleckner     uint32_t SectionStart = Section->VirtualAddress;
4792da433eaSReid Kleckner     // Check if this RVA is within the section bounds. Be careful about integer
4802da433eaSReid Kleckner     // overflow.
4812da433eaSReid Kleckner     uint32_t OffsetIntoSection = RVA - SectionStart;
4822da433eaSReid Kleckner     if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4832da433eaSReid Kleckner         Size <= Section->VirtualSize - OffsetIntoSection) {
4842da433eaSReid Kleckner       uintptr_t Begin =
4852da433eaSReid Kleckner           uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection;
4862da433eaSReid Kleckner       Contents =
4872da433eaSReid Kleckner           ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
4882da433eaSReid Kleckner       return std::error_code();
4892da433eaSReid Kleckner     }
4902da433eaSReid Kleckner   }
4912da433eaSReid Kleckner   return object_error::parse_failed;
4922da433eaSReid Kleckner }
4932da433eaSReid Kleckner 
494c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
495c2bed429SRui Ueyama // table entry.
496db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
497db4ed0bdSRafael Espindola                                             StringRef &Name) const {
498c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
499db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(Rva, IntPtr))
5008ff24d25SRui Ueyama     return EC;
501c2bed429SRui Ueyama   const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
502c2bed429SRui Ueyama   Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
503c2bed429SRui Ueyama   Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5047d099195SRui Ueyama   return std::error_code();
505c2bed429SRui Ueyama }
506c2bed429SRui Ueyama 
50701528021SSaleem Abdulrasool std::error_code
50801528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
50901528021SSaleem Abdulrasool                                 const codeview::DebugInfo *&PDBInfo,
5102da433eaSReid Kleckner                                 StringRef &PDBFileName) const {
5112da433eaSReid Kleckner   ArrayRef<uint8_t> InfoBytes;
5122da433eaSReid Kleckner   if (std::error_code EC = getRvaAndSizeAsBytes(
5132da433eaSReid Kleckner           DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5142da433eaSReid Kleckner     return EC;
51501528021SSaleem Abdulrasool   if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5162da433eaSReid Kleckner     return object_error::parse_failed;
51701528021SSaleem Abdulrasool   PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
51801528021SSaleem Abdulrasool   InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5192da433eaSReid Kleckner   PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5202da433eaSReid Kleckner                           InfoBytes.size());
5212da433eaSReid Kleckner   // Truncate the name at the first null byte. Ignore any padding.
5222da433eaSReid Kleckner   PDBFileName = PDBFileName.split('\0').first;
5232da433eaSReid Kleckner   return std::error_code();
5242da433eaSReid Kleckner }
5252da433eaSReid Kleckner 
52601528021SSaleem Abdulrasool std::error_code
52701528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
528f27f3f84SReid Kleckner                                 StringRef &PDBFileName) const {
529f27f3f84SReid Kleckner   for (const debug_directory &D : debug_directories())
530f27f3f84SReid Kleckner     if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
531f27f3f84SReid Kleckner       return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
532f27f3f84SReid Kleckner   // If we get here, there is no PDB info to return.
533f27f3f84SReid Kleckner   PDBInfo = nullptr;
534f27f3f84SReid Kleckner   PDBFileName = StringRef();
535f27f3f84SReid Kleckner   return std::error_code();
536f27f3f84SReid Kleckner }
537f27f3f84SReid Kleckner 
538c2bed429SRui Ueyama // Find the import table.
539db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() {
540c2bed429SRui Ueyama   // First, we get the RVA of the import table. If the file lacks a pointer to
541c2bed429SRui Ueyama   // the import table, do nothing.
542c2bed429SRui Ueyama   const data_directory *DataEntry;
543c2bed429SRui Ueyama   if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
5447d099195SRui Ueyama     return std::error_code();
545c2bed429SRui Ueyama 
546c2bed429SRui Ueyama   // Do nothing if the pointer to import table is NULL.
547c2bed429SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5487d099195SRui Ueyama     return std::error_code();
549c2bed429SRui Ueyama 
550c2bed429SRui Ueyama   uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
551c2bed429SRui Ueyama 
552c2bed429SRui Ueyama   // Find the section that contains the RVA. This is needed because the RVA is
553c2bed429SRui Ueyama   // the import table's memory address which is different from its file offset.
554c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
555db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
5568ff24d25SRui Ueyama     return EC;
557ad7b7e73SDavid Majnemer   if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
558ad7b7e73SDavid Majnemer     return EC;
559c2bed429SRui Ueyama   ImportDirectory = reinterpret_cast<
5601c0aa04eSDavid Majnemer       const coff_import_directory_table_entry *>(IntPtr);
5617d099195SRui Ueyama   return std::error_code();
562ad882ba8SRui Ueyama }
563c2bed429SRui Ueyama 
56415d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
56515d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() {
56615d99359SRui Ueyama   const data_directory *DataEntry;
56715d99359SRui Ueyama   if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
5687d099195SRui Ueyama     return std::error_code();
56915d99359SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5707d099195SRui Ueyama     return std::error_code();
57115d99359SRui Ueyama 
57215d99359SRui Ueyama   uint32_t RVA = DataEntry->RelativeVirtualAddress;
57315d99359SRui Ueyama   NumberOfDelayImportDirectory = DataEntry->Size /
57415d99359SRui Ueyama       sizeof(delay_import_directory_table_entry) - 1;
57515d99359SRui Ueyama 
57615d99359SRui Ueyama   uintptr_t IntPtr = 0;
57715d99359SRui Ueyama   if (std::error_code EC = getRvaPtr(RVA, IntPtr))
57815d99359SRui Ueyama     return EC;
57915d99359SRui Ueyama   DelayImportDirectory = reinterpret_cast<
58015d99359SRui Ueyama       const delay_import_directory_table_entry *>(IntPtr);
5817d099195SRui Ueyama   return std::error_code();
58215d99359SRui Ueyama }
58315d99359SRui Ueyama 
584ad882ba8SRui Ueyama // Find the export table.
585db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() {
586ad882ba8SRui Ueyama   // First, we get the RVA of the export table. If the file lacks a pointer to
587ad882ba8SRui Ueyama   // the export table, do nothing.
588ad882ba8SRui Ueyama   const data_directory *DataEntry;
589ad882ba8SRui Ueyama   if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
5907d099195SRui Ueyama     return std::error_code();
591ad882ba8SRui Ueyama 
592ad882ba8SRui Ueyama   // Do nothing if the pointer to export table is NULL.
593ad882ba8SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
5947d099195SRui Ueyama     return std::error_code();
595ad882ba8SRui Ueyama 
596ad882ba8SRui Ueyama   uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
597ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
598db4ed0bdSRafael Espindola   if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
599ad882ba8SRui Ueyama     return EC;
60024fc2d64SRui Ueyama   ExportDirectory =
60124fc2d64SRui Ueyama       reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6027d099195SRui Ueyama   return std::error_code();
603c2bed429SRui Ueyama }
604c2bed429SRui Ueyama 
60574e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() {
60674e85130SRui Ueyama   const data_directory *DataEntry;
60774e85130SRui Ueyama   if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
6087d099195SRui Ueyama     return std::error_code();
60974e85130SRui Ueyama   if (DataEntry->RelativeVirtualAddress == 0)
6107d099195SRui Ueyama     return std::error_code();
61174e85130SRui Ueyama 
61274e85130SRui Ueyama   uintptr_t IntPtr = 0;
61374e85130SRui Ueyama   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
61474e85130SRui Ueyama     return EC;
61574e85130SRui Ueyama   BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
61674e85130SRui Ueyama       IntPtr);
61774e85130SRui Ueyama   BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
61874e85130SRui Ueyama       IntPtr + DataEntry->Size);
619893c6469SNico Weber   // FIXME: Verify the section containing BaseRelocHeader has at least
620893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6217d099195SRui Ueyama   return std::error_code();
62274e85130SRui Ueyama }
62374e85130SRui Ueyama 
6242da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() {
6252da433eaSReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
6262da433eaSReid Kleckner   const data_directory *DataEntry;
6272da433eaSReid Kleckner   if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry))
6282da433eaSReid Kleckner     return std::error_code();
6292da433eaSReid Kleckner 
6302da433eaSReid Kleckner   // Do nothing if the RVA is NULL.
6312da433eaSReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
6322da433eaSReid Kleckner     return std::error_code();
6332da433eaSReid Kleckner 
6342da433eaSReid Kleckner   // Check that the size is a multiple of the entry size.
6352da433eaSReid Kleckner   if (DataEntry->Size % sizeof(debug_directory) != 0)
6362da433eaSReid Kleckner     return object_error::parse_failed;
6372da433eaSReid Kleckner 
6382da433eaSReid Kleckner   uintptr_t IntPtr = 0;
6392da433eaSReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6402da433eaSReid Kleckner     return EC;
6412da433eaSReid Kleckner   DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
642893c6469SNico Weber   DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
643893c6469SNico Weber       IntPtr + DataEntry->Size);
644893c6469SNico Weber   // FIXME: Verify the section containing DebugDirectoryBegin has at least
645893c6469SNico Weber   // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6462da433eaSReid Kleckner   return std::error_code();
6472da433eaSReid Kleckner }
6482da433eaSReid Kleckner 
649b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() {
650b7d716c0SReid Kleckner   // Get the RVA of the debug directory. Do nothing if it does not exist.
651b7d716c0SReid Kleckner   const data_directory *DataEntry;
652b7d716c0SReid Kleckner   if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
653b7d716c0SReid Kleckner     return std::error_code();
654b7d716c0SReid Kleckner 
655b7d716c0SReid Kleckner   // Do nothing if the RVA is NULL.
656b7d716c0SReid Kleckner   if (DataEntry->RelativeVirtualAddress == 0)
657b7d716c0SReid Kleckner     return std::error_code();
658b7d716c0SReid Kleckner   uintptr_t IntPtr = 0;
659b7d716c0SReid Kleckner   if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
660b7d716c0SReid Kleckner     return EC;
661b7d716c0SReid Kleckner 
662b7d716c0SReid Kleckner   LoadConfig = (const void *)IntPtr;
663b7d716c0SReid Kleckner   return std::error_code();
664b7d716c0SReid Kleckner }
665b7d716c0SReid Kleckner 
66648af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
66748af1c2aSRafael Espindola     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
66844f51e51SDavid Majnemer       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
66944f51e51SDavid Majnemer       DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
67044f51e51SDavid Majnemer       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
671ad7b7e73SDavid Majnemer       ImportDirectory(nullptr),
67215d99359SRui Ueyama       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
6732da433eaSReid Kleckner       ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
6742da433eaSReid Kleckner       DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
6751d6167fdSMichael J. Spencer   // Check that we at least have enough room for a header.
67648af1c2aSRafael Espindola   if (!checkSize(Data, EC, sizeof(coff_file_header)))
677c3f9b5a5SRafael Espindola     return;
678ee066fc4SEric Christopher 
67982ebd8e3SRui Ueyama   // The current location in the file where we are looking at.
68082ebd8e3SRui Ueyama   uint64_t CurPtr = 0;
68182ebd8e3SRui Ueyama 
68282ebd8e3SRui Ueyama   // PE header is optional and is present only in executables. If it exists,
68382ebd8e3SRui Ueyama   // it is placed right after COFF header.
6848ff24d25SRui Ueyama   bool HasPEHeader = false;
685ee066fc4SEric Christopher 
6861d6167fdSMichael J. Spencer   // Check if this is a PE/COFF file.
68750267222SDavid Majnemer   if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
688ee066fc4SEric Christopher     // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
689ee066fc4SEric Christopher     // PE signature to find 'normal' COFF header.
69050267222SDavid Majnemer     const auto *DH = reinterpret_cast<const dos_header *>(base());
69150267222SDavid Majnemer     if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
69250267222SDavid Majnemer       CurPtr = DH->AddressOfNewExeHeader;
69382ebd8e3SRui Ueyama       // Check the PE magic bytes. ("PE\0\0")
69450267222SDavid Majnemer       if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
6958ff24d25SRui Ueyama         EC = object_error::parse_failed;
6961d6167fdSMichael J. Spencer         return;
6971d6167fdSMichael J. Spencer       }
69844f51e51SDavid Majnemer       CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
6998ff24d25SRui Ueyama       HasPEHeader = true;
700ee066fc4SEric Christopher     }
70150267222SDavid Majnemer   }
702ee066fc4SEric Christopher 
70348af1c2aSRafael Espindola   if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
7041d6167fdSMichael J. Spencer     return;
70544f51e51SDavid Majnemer 
70644f51e51SDavid Majnemer   // It might be a bigobj file, let's check.  Note that COFF bigobj and COFF
70744f51e51SDavid Majnemer   // import libraries share a common prefix but bigobj is more restrictive.
70844f51e51SDavid Majnemer   if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
70944f51e51SDavid Majnemer       COFFHeader->NumberOfSections == uint16_t(0xffff) &&
71044f51e51SDavid Majnemer       checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
71144f51e51SDavid Majnemer     if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr)))
71244f51e51SDavid Majnemer       return;
71344f51e51SDavid Majnemer 
71444f51e51SDavid Majnemer     // Verify that we are dealing with bigobj.
71544f51e51SDavid Majnemer     if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
71644f51e51SDavid Majnemer         std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
71744f51e51SDavid Majnemer                     sizeof(COFF::BigObjMagic)) == 0) {
71844f51e51SDavid Majnemer       COFFHeader = nullptr;
71944f51e51SDavid Majnemer       CurPtr += sizeof(coff_bigobj_file_header);
72044f51e51SDavid Majnemer     } else {
72144f51e51SDavid Majnemer       // It's not a bigobj.
72244f51e51SDavid Majnemer       COFFBigObjHeader = nullptr;
72344f51e51SDavid Majnemer     }
72444f51e51SDavid Majnemer   }
72544f51e51SDavid Majnemer   if (COFFHeader) {
72644f51e51SDavid Majnemer     // The prior checkSize call may have failed.  This isn't a hard error
72744f51e51SDavid Majnemer     // because we were just trying to sniff out bigobj.
7287d099195SRui Ueyama     EC = std::error_code();
72982ebd8e3SRui Ueyama     CurPtr += sizeof(coff_file_header);
73082ebd8e3SRui Ueyama 
73144f51e51SDavid Majnemer     if (COFFHeader->isImportLibrary())
73244f51e51SDavid Majnemer       return;
73344f51e51SDavid Majnemer   }
73444f51e51SDavid Majnemer 
7358ff24d25SRui Ueyama   if (HasPEHeader) {
73610ed9ddcSRui Ueyama     const pe32_header *Header;
73748af1c2aSRafael Espindola     if ((EC = getObject(Header, Data, base() + CurPtr)))
73882ebd8e3SRui Ueyama       return;
73910ed9ddcSRui Ueyama 
74010ed9ddcSRui Ueyama     const uint8_t *DataDirAddr;
74110ed9ddcSRui Ueyama     uint64_t DataDirSize;
74250267222SDavid Majnemer     if (Header->Magic == COFF::PE32Header::PE32) {
74310ed9ddcSRui Ueyama       PE32Header = Header;
74410ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32_header);
74510ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
74650267222SDavid Majnemer     } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
74710ed9ddcSRui Ueyama       PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
74810ed9ddcSRui Ueyama       DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
74910ed9ddcSRui Ueyama       DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
75010ed9ddcSRui Ueyama     } else {
75110ed9ddcSRui Ueyama       // It's neither PE32 nor PE32+.
75210ed9ddcSRui Ueyama       EC = object_error::parse_failed;
753ed64342bSRui Ueyama       return;
754ed64342bSRui Ueyama     }
75548af1c2aSRafael Espindola     if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
75610ed9ddcSRui Ueyama       return;
757f53c8cb4SRui Ueyama   }
758776c6828SRui Ueyama 
7598950a538SRui Ueyama   if (COFFHeader)
7608950a538SRui Ueyama     CurPtr += COFFHeader->SizeOfOptionalHeader;
7618950a538SRui Ueyama 
76248af1c2aSRafael Espindola   if ((EC = getObject(SectionTable, Data, base() + CurPtr,
763236b0ca7SDavid Majnemer                       (uint64_t)getNumberOfSections() * sizeof(coff_section))))
7641d6167fdSMichael J. Spencer     return;
7651d6167fdSMichael J. Spencer 
766c2bed429SRui Ueyama   // Initialize the pointer to the symbol table.
767236b0ca7SDavid Majnemer   if (getPointerToSymbolTable() != 0) {
768ac8cfab5SDavid Majnemer     if ((EC = initSymbolTablePtr())) {
769ac8cfab5SDavid Majnemer       SymbolTable16 = nullptr;
770ac8cfab5SDavid Majnemer       SymbolTable32 = nullptr;
771ac8cfab5SDavid Majnemer       StringTable = nullptr;
772ac8cfab5SDavid Majnemer       StringTableSize = 0;
773ac8cfab5SDavid Majnemer     }
774236b0ca7SDavid Majnemer   } else {
775236b0ca7SDavid Majnemer     // We had better not have any symbols if we don't have a symbol table.
776236b0ca7SDavid Majnemer     if (getNumberOfSymbols() != 0) {
777236b0ca7SDavid Majnemer       EC = object_error::parse_failed;
778236b0ca7SDavid Majnemer       return;
779236b0ca7SDavid Majnemer     }
780236b0ca7SDavid Majnemer   }
7818e90adafSMichael J. Spencer 
782c2bed429SRui Ueyama   // Initialize the pointer to the beginning of the import table.
7838ff24d25SRui Ueyama   if ((EC = initImportTablePtr()))
784ed64342bSRui Ueyama     return;
78515d99359SRui Ueyama   if ((EC = initDelayImportTablePtr()))
78615d99359SRui Ueyama     return;
7871d6167fdSMichael J. Spencer 
788ad882ba8SRui Ueyama   // Initialize the pointer to the export table.
7898ff24d25SRui Ueyama   if ((EC = initExportTablePtr()))
790ad882ba8SRui Ueyama     return;
791ad882ba8SRui Ueyama 
79274e85130SRui Ueyama   // Initialize the pointer to the base relocation table.
79374e85130SRui Ueyama   if ((EC = initBaseRelocPtr()))
79474e85130SRui Ueyama     return;
79574e85130SRui Ueyama 
7962da433eaSReid Kleckner   // Initialize the pointer to the export table.
7972da433eaSReid Kleckner   if ((EC = initDebugDirectoryPtr()))
7982da433eaSReid Kleckner     return;
7992da433eaSReid Kleckner 
800b7d716c0SReid Kleckner   if ((EC = initLoadConfigPtr()))
801b7d716c0SReid Kleckner     return;
802b7d716c0SReid Kleckner 
8037d099195SRui Ueyama   EC = std::error_code();
8048e90adafSMichael J. Spencer }
8058e90adafSMichael J. Spencer 
806435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8078ff24d25SRui Ueyama   DataRefImpl Ret;
80844f51e51SDavid Majnemer   Ret.p = getSymbolTable();
809f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8108e90adafSMichael J. Spencer }
8118e90adafSMichael J. Spencer 
812435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const {
8138e90adafSMichael J. Spencer   // The symbol table ends where the string table begins.
8148ff24d25SRui Ueyama   DataRefImpl Ret;
8158ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(StringTable);
816f12b8282SRafael Espindola   return basic_symbol_iterator(SymbolRef(Ret, this));
8178e90adafSMichael J. Spencer }
8188e90adafSMichael J. Spencer 
819bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const {
820ad7b7e73SDavid Majnemer   if (!ImportDirectory)
821ad7b7e73SDavid Majnemer     return import_directory_end();
8221c0aa04eSDavid Majnemer   if (ImportDirectory->isNull())
823ad7b7e73SDavid Majnemer     return import_directory_end();
824a045b73aSRui Ueyama   return import_directory_iterator(
825a045b73aSRui Ueyama       ImportDirectoryEntryRef(ImportDirectory, 0, this));
826c2bed429SRui Ueyama }
827c2bed429SRui Ueyama 
828bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const {
829a045b73aSRui Ueyama   return import_directory_iterator(
830ad7b7e73SDavid Majnemer       ImportDirectoryEntryRef(nullptr, -1, this));
831c2bed429SRui Ueyama }
832c429b80dSDavid Meyer 
83315d99359SRui Ueyama delay_import_directory_iterator
83415d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const {
83515d99359SRui Ueyama   return delay_import_directory_iterator(
83615d99359SRui Ueyama       DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
83715d99359SRui Ueyama }
83815d99359SRui Ueyama 
83915d99359SRui Ueyama delay_import_directory_iterator
84015d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const {
84115d99359SRui Ueyama   return delay_import_directory_iterator(
84215d99359SRui Ueyama       DelayImportDirectoryEntryRef(
84315d99359SRui Ueyama           DelayImportDirectory, NumberOfDelayImportDirectory, this));
84415d99359SRui Ueyama }
84515d99359SRui Ueyama 
846ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const {
847ad882ba8SRui Ueyama   return export_directory_iterator(
848ad882ba8SRui Ueyama       ExportDirectoryEntryRef(ExportDirectory, 0, this));
849ad882ba8SRui Ueyama }
850ad882ba8SRui Ueyama 
851ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const {
8522617dcceSCraig Topper   if (!ExportDirectory)
8532617dcceSCraig Topper     return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
8548ff24d25SRui Ueyama   ExportDirectoryEntryRef Ref(ExportDirectory,
855ad882ba8SRui Ueyama                               ExportDirectory->AddressTableEntries, this);
8568ff24d25SRui Ueyama   return export_directory_iterator(Ref);
857ad882ba8SRui Ueyama }
858ad882ba8SRui Ueyama 
859b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const {
8608ff24d25SRui Ueyama   DataRefImpl Ret;
8618ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
8628ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8638e90adafSMichael J. Spencer }
8648e90adafSMichael J. Spencer 
865b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const {
8668ff24d25SRui Ueyama   DataRefImpl Ret;
86744f51e51SDavid Majnemer   int NumSections =
86844f51e51SDavid Majnemer       COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
8698ff24d25SRui Ueyama   Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
8708ff24d25SRui Ueyama   return section_iterator(SectionRef(Ret, this));
8718e90adafSMichael J. Spencer }
8728e90adafSMichael J. Spencer 
87374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
87474e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
87574e85130SRui Ueyama }
87674e85130SRui Ueyama 
87774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const {
87874e85130SRui Ueyama   return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
87974e85130SRui Ueyama }
88074e85130SRui Ueyama 
8818e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const {
88243c85453SMartin Storsjo   return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
8838e90adafSMichael J. Spencer }
8848e90adafSMichael J. Spencer 
8858e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const {
88644f51e51SDavid Majnemer   switch(getMachine()) {
8878e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
8888e90adafSMichael J. Spencer     return "COFF-i386";
8898e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
8908e90adafSMichael J. Spencer     return "COFF-x86-64";
8919b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
8929b7c0af2SSaleem Abdulrasool     return "COFF-ARM";
8931eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
8941eff5c9cSMartell Malone     return "COFF-ARM64";
8958e90adafSMichael J. Spencer   default:
8968e90adafSMichael J. Spencer     return "COFF-<unknown arch>";
8978e90adafSMichael J. Spencer   }
8988e90adafSMichael J. Spencer }
8998e90adafSMichael J. Spencer 
900260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const {
90144f51e51SDavid Majnemer   switch (getMachine()) {
9028e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
9038e90adafSMichael J. Spencer     return Triple::x86;
9048e90adafSMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
9058e90adafSMichael J. Spencer     return Triple::x86_64;
9069b7c0af2SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
9079b7c0af2SSaleem Abdulrasool     return Triple::thumb;
9081eff5c9cSMartell Malone   case COFF::IMAGE_FILE_MACHINE_ARM64:
9091eff5c9cSMartell Malone     return Triple::aarch64;
9108e90adafSMichael J. Spencer   default:
9118e90adafSMichael J. Spencer     return Triple::UnknownArch;
9128e90adafSMichael J. Spencer   }
9138e90adafSMichael J. Spencer }
9148e90adafSMichael J. Spencer 
915d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const {
916d2af4d6fSPaul Semel   if (PE32Header)
917d2af4d6fSPaul Semel     return PE32Header->AddressOfEntryPoint;
918d2af4d6fSPaul Semel   return 0;
919d2af4d6fSPaul Semel }
920d2af4d6fSPaul Semel 
921979fb40bSRui Ueyama iterator_range<import_directory_iterator>
922979fb40bSRui Ueyama COFFObjectFile::import_directories() const {
923979fb40bSRui Ueyama   return make_range(import_directory_begin(), import_directory_end());
924979fb40bSRui Ueyama }
925979fb40bSRui Ueyama 
926979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator>
927979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const {
928979fb40bSRui Ueyama   return make_range(delay_import_directory_begin(),
929979fb40bSRui Ueyama                     delay_import_directory_end());
930979fb40bSRui Ueyama }
931979fb40bSRui Ueyama 
932979fb40bSRui Ueyama iterator_range<export_directory_iterator>
933979fb40bSRui Ueyama COFFObjectFile::export_directories() const {
934979fb40bSRui Ueyama   return make_range(export_directory_begin(), export_directory_end());
935979fb40bSRui Ueyama }
936979fb40bSRui Ueyama 
93774e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
93874e85130SRui Ueyama   return make_range(base_reloc_begin(), base_reloc_end());
93974e85130SRui Ueyama }
94074e85130SRui Ueyama 
941e84a0b5aSMartin Storsjo std::error_code
942db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index,
943ed64342bSRui Ueyama                                  const data_directory *&Res) const {
944bcadfee2SHiroshi Inoue   // Error if there's no data directory or the index is out of range.
945f69b0585SDavid Majnemer   if (!DataDirectory) {
946f69b0585SDavid Majnemer     Res = nullptr;
94710ed9ddcSRui Ueyama     return object_error::parse_failed;
948f69b0585SDavid Majnemer   }
94910ed9ddcSRui Ueyama   assert(PE32Header || PE32PlusHeader);
95010ed9ddcSRui Ueyama   uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
95110ed9ddcSRui Ueyama                                : PE32PlusHeader->NumberOfRvaAndSize;
952f69b0585SDavid Majnemer   if (Index >= NumEnt) {
953f69b0585SDavid Majnemer     Res = nullptr;
954ed64342bSRui Ueyama     return object_error::parse_failed;
955f69b0585SDavid Majnemer   }
9568ff24d25SRui Ueyama   Res = &DataDirectory[Index];
9577d099195SRui Ueyama   return std::error_code();
958ed64342bSRui Ueyama }
959ed64342bSRui Ueyama 
960*77ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
961*77ecf90cSReid Kleckner   // Perhaps getting the section of a reserved section index should be an error,
962*77ecf90cSReid Kleckner   // but callers rely on this to return null.
963236b0ca7SDavid Majnemer   if (COFF::isReservedSectionNumber(Index))
964*77ecf90cSReid Kleckner     return (const coff_section *)nullptr;
965236b0ca7SDavid Majnemer   if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
9661d6167fdSMichael J. Spencer     // We already verified the section table data, so no need to check again.
967*77ecf90cSReid Kleckner     return SectionTable + (Index - 1);
9688e90adafSMichael J. Spencer   }
969*77ecf90cSReid Kleckner   return errorCodeToError(object_error::parse_failed);
970236b0ca7SDavid Majnemer }
9718e90adafSMichael J. Spencer 
972*77ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
9731d6167fdSMichael J. Spencer   if (StringTableSize <= 4)
9741d6167fdSMichael J. Spencer     // Tried to get a string from an empty string table.
975*77ecf90cSReid Kleckner     return errorCodeToError(object_error::parse_failed);
9768ff24d25SRui Ueyama   if (Offset >= StringTableSize)
977*77ecf90cSReid Kleckner     return errorCodeToError(object_error::unexpected_eof);
978*77ecf90cSReid Kleckner   return StringRef(StringTable + Offset);
9798e90adafSMichael J. Spencer }
980022ecdf2SBenjamin Kramer 
981*77ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
982*77ecf90cSReid Kleckner   return getSymbolName(Symbol.getGeneric());
983e40d30f3SRui Ueyama }
984e40d30f3SRui Ueyama 
985*77ecf90cSReid Kleckner Expected<StringRef>
986*77ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
98789a7a5eaSMichael J. Spencer   // Check for string table entry. First 4 bytes are 0.
988*77ecf90cSReid Kleckner   if (Symbol->Name.Offset.Zeroes == 0)
989*77ecf90cSReid Kleckner     return getString(Symbol->Name.Offset.Offset);
99089a7a5eaSMichael J. Spencer 
99189a7a5eaSMichael J. Spencer   // Null terminated, let ::strlen figure out the length.
992*77ecf90cSReid Kleckner   if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
993*77ecf90cSReid Kleckner     return StringRef(Symbol->Name.ShortName);
994*77ecf90cSReid Kleckner 
99589a7a5eaSMichael J. Spencer   // Not null terminated, use all 8 bytes.
996*77ecf90cSReid Kleckner   return StringRef(Symbol->Name.ShortName, COFF::NameSize);
99789a7a5eaSMichael J. Spencer }
99889a7a5eaSMichael J. Spencer 
99944f51e51SDavid Majnemer ArrayRef<uint8_t>
100044f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10012617dcceSCraig Topper   const uint8_t *Aux = nullptr;
100271757ef3SMarshall Clow 
100344f51e51SDavid Majnemer   size_t SymbolSize = getSymbolTableEntrySize();
100444f51e51SDavid Majnemer   if (Symbol.getNumberOfAuxSymbols() > 0) {
100571757ef3SMarshall Clow     // AUX data comes immediately after the symbol in COFF
100644f51e51SDavid Majnemer     Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
100771757ef3SMarshall Clow #ifndef NDEBUG
10088ff24d25SRui Ueyama     // Verify that the Aux symbol points to a valid entry in the symbol table.
10098ff24d25SRui Ueyama     uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
101044f51e51SDavid Majnemer     if (Offset < getPointerToSymbolTable() ||
101144f51e51SDavid Majnemer         Offset >=
101244f51e51SDavid Majnemer             getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
101371757ef3SMarshall Clow       report_fatal_error("Aux Symbol data was outside of symbol table.");
101471757ef3SMarshall Clow 
101544f51e51SDavid Majnemer     assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
101644f51e51SDavid Majnemer            "Aux Symbol data did not point to the beginning of a symbol");
101771757ef3SMarshall Clow #endif
1018bfb85e67SMarshall Clow   }
101944f51e51SDavid Majnemer   return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
102071757ef3SMarshall Clow }
102171757ef3SMarshall Clow 
102274e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
102374e7d260SMartin Storsjo   uintptr_t Offset =
102474e7d260SMartin Storsjo       reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
102574e7d260SMartin Storsjo   assert(Offset % getSymbolTableEntrySize() == 0 &&
102674e7d260SMartin Storsjo          "Symbol did not point to the beginning of a symbol");
102774e7d260SMartin Storsjo   size_t Index = Offset / getSymbolTableEntrySize();
102874e7d260SMartin Storsjo   assert(Index < getNumberOfSymbols());
102974e7d260SMartin Storsjo   return Index;
103074e7d260SMartin Storsjo }
103174e7d260SMartin Storsjo 
10328be28cdcSFangrui Song Expected<StringRef>
10338be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const {
103453c2d547SMichael J. Spencer   StringRef Name;
103544f51e51SDavid Majnemer   if (Sec->Name[COFF::NameSize - 1] == 0)
103653c2d547SMichael J. Spencer     // Null terminated, let ::strlen figure out the length.
103753c2d547SMichael J. Spencer     Name = Sec->Name;
103853c2d547SMichael J. Spencer   else
103953c2d547SMichael J. Spencer     // Not null terminated, use all 8 bytes.
104044f51e51SDavid Majnemer     Name = StringRef(Sec->Name, COFF::NameSize);
104153c2d547SMichael J. Spencer 
104253c2d547SMichael J. Spencer   // Check for string table entry. First byte is '/'.
10432314b3deSDavid Majnemer   if (Name.startswith("/")) {
104453c2d547SMichael J. Spencer     uint32_t Offset;
10452314b3deSDavid Majnemer     if (Name.startswith("//")) {
10469d2c15efSNico Rieck       if (decodeBase64StringEntry(Name.substr(2), Offset))
10478be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
1048400b6c08Sserge-sans-paille                                  "invalid section name");
10499d2c15efSNico Rieck     } else {
105053c2d547SMichael J. Spencer       if (Name.substr(1).getAsInteger(10, Offset))
10518be28cdcSFangrui Song         return createStringError(object_error::parse_failed,
10528be28cdcSFangrui Song                                  "invalid section name");
10539d2c15efSNico Rieck     }
1054*77ecf90cSReid Kleckner     return getString(Offset);
105553c2d547SMichael J. Spencer   }
105653c2d547SMichael J. Spencer 
10578be28cdcSFangrui Song   return Name;
105853c2d547SMichael J. Spencer }
105953c2d547SMichael J. Spencer 
1060a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
1061a9ee5c06SDavid Majnemer   // SizeOfRawData and VirtualSize change what they represent depending on
1062a9ee5c06SDavid Majnemer   // whether or not we have an executable image.
1063a9ee5c06SDavid Majnemer   //
1064a9ee5c06SDavid Majnemer   // For object files, SizeOfRawData contains the size of section's data;
1065d5297ee7SRui Ueyama   // VirtualSize should be zero but isn't due to buggy COFF writers.
1066a9ee5c06SDavid Majnemer   //
1067a9ee5c06SDavid Majnemer   // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
1068a9ee5c06SDavid Majnemer   // actual section size is in VirtualSize.  It is possible for VirtualSize to
1069a9ee5c06SDavid Majnemer   // be greater than SizeOfRawData; the contents past that point should be
1070a9ee5c06SDavid Majnemer   // considered to be zero.
1071d5297ee7SRui Ueyama   if (getDOSHeader())
1072d5297ee7SRui Ueyama     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
1073d5297ee7SRui Ueyama   return Sec->SizeOfRawData;
1074a9ee5c06SDavid Majnemer }
1075a9ee5c06SDavid Majnemer 
1076e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec,
10779da9e693SMichael J. Spencer                                          ArrayRef<uint8_t> &Res) const {
1078e2129662SDavid Majnemer   // In COFF, a virtual section won't have any in-file
1079e2129662SDavid Majnemer   // content, so the file pointer to the content will be zero.
1080e2129662SDavid Majnemer   if (Sec->PointerToRawData == 0)
1081e1cb2c0fSFangrui Song     return Error::success();
10829da9e693SMichael J. Spencer   // The only thing that we need to verify is that the contents is contained
10839da9e693SMichael J. Spencer   // within the file bounds. We don't need to make sure it doesn't cover other
10849da9e693SMichael J. Spencer   // data, as there's nothing that says that is not allowed.
10859da9e693SMichael J. Spencer   uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
1086a9ee5c06SDavid Majnemer   uint32_t SectionSize = getSectionSize(Sec);
1087e830c60dSDavid Majnemer   if (checkOffset(Data, ConStart, SectionSize))
1088e1cb2c0fSFangrui Song     return make_error<BinaryError>();
1089a9ee5c06SDavid Majnemer   Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
1090e1cb2c0fSFangrui Song   return Error::success();
10919da9e693SMichael J. Spencer }
10929da9e693SMichael J. Spencer 
1093022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
1094e5fd0047SMichael J. Spencer   return reinterpret_cast<const coff_relocation*>(Rel.p);
1095022ecdf2SBenjamin Kramer }
10968ff24d25SRui Ueyama 
10975e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1098e5fd0047SMichael J. Spencer   Rel.p = reinterpret_cast<uintptr_t>(
1099e5fd0047SMichael J. Spencer             reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
1100022ecdf2SBenjamin Kramer }
11018ff24d25SRui Ueyama 
110296d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
110358323a97SDavid Majnemer   const coff_relocation *R = toRel(Rel);
110496d071cdSRafael Espindola   return R->VirtualAddress;
1105cbe72fc9SDanil Malyshev }
11068ff24d25SRui Ueyama 
1107806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1108022ecdf2SBenjamin Kramer   const coff_relocation *R = toRel(Rel);
11098ff24d25SRui Ueyama   DataRefImpl Ref;
1110236b0ca7SDavid Majnemer   if (R->SymbolTableIndex >= getNumberOfSymbols())
1111236b0ca7SDavid Majnemer     return symbol_end();
111244f51e51SDavid Majnemer   if (SymbolTable16)
111344f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
111444f51e51SDavid Majnemer   else if (SymbolTable32)
111544f51e51SDavid Majnemer     Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
111644f51e51SDavid Majnemer   else
1117c7353b58SDavid Majnemer     llvm_unreachable("no symbol table pointer!");
11188ff24d25SRui Ueyama   return symbol_iterator(SymbolRef(Ref, this));
1119022ecdf2SBenjamin Kramer }
11208ff24d25SRui Ueyama 
112199c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
1122022ecdf2SBenjamin Kramer   const coff_relocation* R = toRel(Rel);
112399c041b7SRafael Espindola   return R->Type;
1124022ecdf2SBenjamin Kramer }
1125e5fd0047SMichael J. Spencer 
112627dc8394SAlexey Samsonov const coff_section *
112727dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
112827dc8394SAlexey Samsonov   return toSec(Section.getRawDataRefImpl());
112971757ef3SMarshall Clow }
113071757ef3SMarshall Clow 
113144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
113244f51e51SDavid Majnemer   if (SymbolTable16)
113344f51e51SDavid Majnemer     return toSymb<coff_symbol16>(Ref);
113444f51e51SDavid Majnemer   if (SymbolTable32)
113544f51e51SDavid Majnemer     return toSymb<coff_symbol32>(Ref);
113644f51e51SDavid Majnemer   llvm_unreachable("no symbol table pointer!");
113744f51e51SDavid Majnemer }
113844f51e51SDavid Majnemer 
113944f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
114044f51e51SDavid Majnemer   return getCOFFSymbol(Symbol.getRawDataRefImpl());
114171757ef3SMarshall Clow }
114271757ef3SMarshall Clow 
1143f12b8282SRafael Espindola const coff_relocation *
114427dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
114527dc8394SAlexey Samsonov   return toRel(Reloc.getRawDataRefImpl());
1146d3e2a76cSMarshall Clow }
1147d3e2a76cSMarshall Clow 
11482f6d0061SPeter Collingbourne ArrayRef<coff_relocation>
11496a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const {
11502f6d0061SPeter Collingbourne   return {getFirstReloc(Sec, Data, base()),
11512f6d0061SPeter Collingbourne           getNumberOfRelocations(Sec, Data, base())};
11526a75acb1SRui Ueyama }
11536a75acb1SRui Ueyama 
115427dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \
115527dc8394SAlexey Samsonov   case COFF::reloc_type:                                                       \
1156114ebf4aSMartin Storsjo     return #reloc_type;
1157e5fd0047SMichael J. Spencer 
1158114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
115944f51e51SDavid Majnemer   switch (getMachine()) {
1160e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_AMD64:
1161114ebf4aSMartin Storsjo     switch (Type) {
1162e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
1163e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
1164e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
1165e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
1166e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
1167e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
1168e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
1169e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
1170e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
1171e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
1172e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
1173e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
1174e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
1175e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
1176e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
1177e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
1178e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
1179e5fd0047SMichael J. Spencer     default:
1180114ebf4aSMartin Storsjo       return "Unknown";
1181e5fd0047SMichael J. Spencer     }
1182e5fd0047SMichael J. Spencer     break;
11835c503bf4SSaleem Abdulrasool   case COFF::IMAGE_FILE_MACHINE_ARMNT:
1184114ebf4aSMartin Storsjo     switch (Type) {
11855c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
11865c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
11875c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
11885c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
11895c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
11905c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
11915c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
11925c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
1193e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
11945c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
11955c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
11965c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
11975c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
11985c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
11995c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12005c503bf4SSaleem Abdulrasool     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
1201e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12025c503bf4SSaleem Abdulrasool     default:
1203114ebf4aSMartin Storsjo       return "Unknown";
12045c503bf4SSaleem Abdulrasool     }
12055c503bf4SSaleem Abdulrasool     break;
12060c72172eSMandeep Singh Grang   case COFF::IMAGE_FILE_MACHINE_ARM64:
1207114ebf4aSMartin Storsjo     switch (Type) {
12080c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12090c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12100c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12110c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12120c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12130c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12140c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12150c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12160c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12170c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12180c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12190c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12200c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12210c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12220c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12230c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12240c72172eSMandeep Singh Grang     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
1225e5eb6fb9SMartin Storsjo     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12260c72172eSMandeep Singh Grang     default:
1227114ebf4aSMartin Storsjo       return "Unknown";
12280c72172eSMandeep Singh Grang     }
12290c72172eSMandeep Singh Grang     break;
1230e5fd0047SMichael J. Spencer   case COFF::IMAGE_FILE_MACHINE_I386:
1231114ebf4aSMartin Storsjo     switch (Type) {
1232e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
1233e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
1234e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
1235e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
1236e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
1237e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
1238e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
1239e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
1240e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
1241e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
1242e5fd0047SMichael J. Spencer     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
1243e5fd0047SMichael J. Spencer     default:
1244114ebf4aSMartin Storsjo       return "Unknown";
1245e5fd0047SMichael J. Spencer     }
1246e5fd0047SMichael J. Spencer     break;
1247e5fd0047SMichael J. Spencer   default:
1248114ebf4aSMartin Storsjo     return "Unknown";
1249e5fd0047SMichael J. Spencer   }
1250e5fd0047SMichael J. Spencer }
1251e5fd0047SMichael J. Spencer 
1252e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
1253e5fd0047SMichael J. Spencer 
1254114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName(
1255114ebf4aSMartin Storsjo     DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
1256114ebf4aSMartin Storsjo   const coff_relocation *Reloc = toRel(Rel);
1257114ebf4aSMartin Storsjo   StringRef Res = getRelocationTypeName(Reloc->Type);
1258114ebf4aSMartin Storsjo   Result.append(Res.begin(), Res.end());
1259114ebf4aSMartin Storsjo }
1260114ebf4aSMartin Storsjo 
1261c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const {
1262c66d761bSRafael Espindola   return !DataDirectory;
1263c66d761bSRafael Espindola }
1264c66d761bSRafael Espindola 
1265e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
1266e3093808SMartin Storsjo   return StringSwitch<StringRef>(Name)
1267e3093808SMartin Storsjo       .Case("eh_fram", "eh_frame")
1268e3093808SMartin Storsjo       .Default(Name);
1269e3093808SMartin Storsjo }
1270e3093808SMartin Storsjo 
1271c2bed429SRui Ueyama bool ImportDirectoryEntryRef::
1272c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const {
1273a045b73aSRui Ueyama   return ImportTable == Other.ImportTable && Index == Other.Index;
1274c2bed429SRui Ueyama }
1275c2bed429SRui Ueyama 
12765e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() {
12775e812afaSRafael Espindola   ++Index;
12781c0aa04eSDavid Majnemer   if (ImportTable[Index].isNull()) {
1279ad7b7e73SDavid Majnemer     Index = -1;
1280ad7b7e73SDavid Majnemer     ImportTable = nullptr;
1281ad7b7e73SDavid Majnemer   }
1282c2bed429SRui Ueyama }
1283c2bed429SRui Ueyama 
1284db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry(
12851c0aa04eSDavid Majnemer     const coff_import_directory_table_entry *&Result) const {
1286ad7b7e73SDavid Majnemer   return getObject(Result, OwningObject->Data, ImportTable + Index);
1287c2bed429SRui Ueyama }
1288c2bed429SRui Ueyama 
1289861021f9SRui Ueyama static imported_symbol_iterator
129015d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object,
1291861021f9SRui Ueyama                            uintptr_t Ptr, int Index) {
129215d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1293861021f9SRui Ueyama     auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
129415d99359SRui Ueyama     return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1295861021f9SRui Ueyama   }
1296861021f9SRui Ueyama   auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
129715d99359SRui Ueyama   return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
1298861021f9SRui Ueyama }
1299861021f9SRui Ueyama 
130015d99359SRui Ueyama static imported_symbol_iterator
130115d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
1302861021f9SRui Ueyama   uintptr_t IntPtr = 0;
130315d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
130415d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, 0);
1305861021f9SRui Ueyama }
1306861021f9SRui Ueyama 
130715d99359SRui Ueyama static imported_symbol_iterator
130815d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
1309861021f9SRui Ueyama   uintptr_t IntPtr = 0;
131015d99359SRui Ueyama   Object->getRvaPtr(RVA, IntPtr);
1311861021f9SRui Ueyama   // Forward the pointer to the last entry which is null.
1312861021f9SRui Ueyama   int Index = 0;
131315d99359SRui Ueyama   if (Object->getBytesInAddress() == 4) {
1314861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
1315861021f9SRui Ueyama     while (*Entry++)
1316861021f9SRui Ueyama       ++Index;
1317861021f9SRui Ueyama   } else {
1318861021f9SRui Ueyama     auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
1319861021f9SRui Ueyama     while (*Entry++)
1320861021f9SRui Ueyama       ++Index;
1321861021f9SRui Ueyama   }
132215d99359SRui Ueyama   return makeImportedSymbolIterator(Object, IntPtr, Index);
132315d99359SRui Ueyama }
132415d99359SRui Ueyama 
132515d99359SRui Ueyama imported_symbol_iterator
132615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const {
132760049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
132815d99359SRui Ueyama                              OwningObject);
132915d99359SRui Ueyama }
133015d99359SRui Ueyama 
133115d99359SRui Ueyama imported_symbol_iterator
133215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const {
133360049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
133415d99359SRui Ueyama                            OwningObject);
1335861021f9SRui Ueyama }
1336861021f9SRui Ueyama 
1337979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1338979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const {
1339979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1340979fb40bSRui Ueyama }
1341979fb40bSRui Ueyama 
134260049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
134360049526SDavid Majnemer   return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
134460049526SDavid Majnemer                              OwningObject);
134560049526SDavid Majnemer }
134660049526SDavid Majnemer 
134760049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
134860049526SDavid Majnemer   return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
134960049526SDavid Majnemer                            OwningObject);
135060049526SDavid Majnemer }
135160049526SDavid Majnemer 
135260049526SDavid Majnemer iterator_range<imported_symbol_iterator>
135360049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const {
135460049526SDavid Majnemer   return make_range(lookup_table_begin(), lookup_table_end());
135560049526SDavid Majnemer }
135660049526SDavid Majnemer 
1357db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1358c2bed429SRui Ueyama   uintptr_t IntPtr = 0;
1359db4ed0bdSRafael Espindola   if (std::error_code EC =
13601e152d5eSRui Ueyama           OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
1361a045b73aSRui Ueyama     return EC;
1362a045b73aSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
13637d099195SRui Ueyama   return std::error_code();
1364c2bed429SRui Ueyama }
1365c2bed429SRui Ueyama 
13661e152d5eSRui Ueyama std::error_code
13671e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t  &Result) const {
13681e152d5eSRui Ueyama   Result = ImportTable[Index].ImportLookupTableRVA;
13697d099195SRui Ueyama   return std::error_code();
13701e152d5eSRui Ueyama }
13711e152d5eSRui Ueyama 
13721e152d5eSRui Ueyama std::error_code
13731e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
13741e152d5eSRui Ueyama   Result = ImportTable[Index].ImportAddressTableRVA;
13757d099195SRui Ueyama   return std::error_code();
13761e152d5eSRui Ueyama }
13771e152d5eSRui Ueyama 
137815d99359SRui Ueyama bool DelayImportDirectoryEntryRef::
137915d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const {
138015d99359SRui Ueyama   return Table == Other.Table && Index == Other.Index;
138115d99359SRui Ueyama }
138215d99359SRui Ueyama 
138315d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() {
138415d99359SRui Ueyama   ++Index;
138515d99359SRui Ueyama }
138615d99359SRui Ueyama 
138715d99359SRui Ueyama imported_symbol_iterator
138815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const {
138915d99359SRui Ueyama   return importedSymbolBegin(Table[Index].DelayImportNameTable,
139015d99359SRui Ueyama                              OwningObject);
139115d99359SRui Ueyama }
139215d99359SRui Ueyama 
139315d99359SRui Ueyama imported_symbol_iterator
139415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const {
139515d99359SRui Ueyama   return importedSymbolEnd(Table[Index].DelayImportNameTable,
139615d99359SRui Ueyama                            OwningObject);
139715d99359SRui Ueyama }
139815d99359SRui Ueyama 
1399979fb40bSRui Ueyama iterator_range<imported_symbol_iterator>
1400979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const {
1401979fb40bSRui Ueyama   return make_range(imported_symbol_begin(), imported_symbol_end());
1402979fb40bSRui Ueyama }
1403979fb40bSRui Ueyama 
140415d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
140515d99359SRui Ueyama   uintptr_t IntPtr = 0;
140615d99359SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
140715d99359SRui Ueyama     return EC;
140815d99359SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14097d099195SRui Ueyama   return std::error_code();
141015d99359SRui Ueyama }
141115d99359SRui Ueyama 
14121af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef::
14131af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const {
14149f598ac7SJoseph Tremoulet   Result = &Table[Index];
14157d099195SRui Ueyama   return std::error_code();
14161af08658SRui Ueyama }
14171af08658SRui Ueyama 
1418ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef::
1419ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const {
1420ffa4cebeSRui Ueyama   uint32_t RVA = Table[Index].DelayImportAddressTable +
1421ffa4cebeSRui Ueyama       AddrIndex * (OwningObject->is64() ? 8 : 4);
1422ffa4cebeSRui Ueyama   uintptr_t IntPtr = 0;
1423ffa4cebeSRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1424ffa4cebeSRui Ueyama     return EC;
1425ffa4cebeSRui Ueyama   if (OwningObject->is64())
14265dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
1427ffa4cebeSRui Ueyama   else
14285dcf11d1SRui Ueyama     Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14297d099195SRui Ueyama   return std::error_code();
1430ffa4cebeSRui Ueyama }
1431ffa4cebeSRui Ueyama 
1432ad882ba8SRui Ueyama bool ExportDirectoryEntryRef::
1433ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const {
1434ad882ba8SRui Ueyama   return ExportTable == Other.ExportTable && Index == Other.Index;
1435ad882ba8SRui Ueyama }
1436ad882ba8SRui Ueyama 
14375e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() {
14385e812afaSRafael Espindola   ++Index;
1439ad882ba8SRui Ueyama }
1440ad882ba8SRui Ueyama 
1441da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1442da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result.
1443db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1444da49d0d4SRui Ueyama   uintptr_t IntPtr = 0;
1445db4ed0bdSRafael Espindola   if (std::error_code EC =
1446db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1447da49d0d4SRui Ueyama     return EC;
1448da49d0d4SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14497d099195SRui Ueyama   return std::error_code();
1450da49d0d4SRui Ueyama }
1451da49d0d4SRui Ueyama 
1452e5df6095SRui Ueyama // Returns the starting ordinal number.
1453db4ed0bdSRafael Espindola std::error_code
1454db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1455e5df6095SRui Ueyama   Result = ExportTable->OrdinalBase;
14567d099195SRui Ueyama   return std::error_code();
1457e5df6095SRui Ueyama }
1458e5df6095SRui Ueyama 
1459ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol.
1460db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1461ad882ba8SRui Ueyama   Result = ExportTable->OrdinalBase + Index;
14627d099195SRui Ueyama   return std::error_code();
1463ad882ba8SRui Ueyama }
1464ad882ba8SRui Ueyama 
1465ad882ba8SRui Ueyama // Returns the address of the current export symbol.
1466db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1467ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1468db4ed0bdSRafael Espindola   if (std::error_code EC =
1469db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1470ad882ba8SRui Ueyama     return EC;
147124fc2d64SRui Ueyama   const export_address_table_entry *entry =
147224fc2d64SRui Ueyama       reinterpret_cast<const export_address_table_entry *>(IntPtr);
1473ad882ba8SRui Ueyama   Result = entry[Index].ExportRVA;
14747d099195SRui Ueyama   return std::error_code();
1475ad882ba8SRui Ueyama }
1476ad882ba8SRui Ueyama 
1477ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only
1478ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result.
1479db4ed0bdSRafael Espindola std::error_code
1480db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1481ad882ba8SRui Ueyama   uintptr_t IntPtr = 0;
1482db4ed0bdSRafael Espindola   if (std::error_code EC =
1483db4ed0bdSRafael Espindola           OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1484ad882ba8SRui Ueyama     return EC;
1485ad882ba8SRui Ueyama   const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1486ad882ba8SRui Ueyama 
1487ad882ba8SRui Ueyama   uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1488ad882ba8SRui Ueyama   int Offset = 0;
1489ad882ba8SRui Ueyama   for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1490ad882ba8SRui Ueyama        I < E; ++I, ++Offset) {
1491ad882ba8SRui Ueyama     if (*I != Index)
1492ad882ba8SRui Ueyama       continue;
1493db4ed0bdSRafael Espindola     if (std::error_code EC =
1494db4ed0bdSRafael Espindola             OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1495ad882ba8SRui Ueyama       return EC;
1496ad882ba8SRui Ueyama     const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1497db4ed0bdSRafael Espindola     if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1498ad882ba8SRui Ueyama       return EC;
1499ad882ba8SRui Ueyama     Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15007d099195SRui Ueyama     return std::error_code();
1501ad882ba8SRui Ueyama   }
1502ad882ba8SRui Ueyama   Result = "";
15037d099195SRui Ueyama   return std::error_code();
1504ad882ba8SRui Ueyama }
1505ad882ba8SRui Ueyama 
15066161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15076161b38dSRui Ueyama   const data_directory *DataEntry;
15086161b38dSRui Ueyama   if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
15096161b38dSRui Ueyama     return EC;
15106161b38dSRui Ueyama   uint32_t RVA;
15116161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15126161b38dSRui Ueyama     return EC;
15136161b38dSRui Ueyama   uint32_t Begin = DataEntry->RelativeVirtualAddress;
15146161b38dSRui Ueyama   uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15156161b38dSRui Ueyama   Result = (Begin <= RVA && RVA < End);
15166161b38dSRui Ueyama   return std::error_code();
15176161b38dSRui Ueyama }
15186161b38dSRui Ueyama 
15196161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15206161b38dSRui Ueyama   uint32_t RVA;
15216161b38dSRui Ueyama   if (auto EC = getExportRVA(RVA))
15226161b38dSRui Ueyama     return EC;
15236161b38dSRui Ueyama   uintptr_t IntPtr = 0;
15246161b38dSRui Ueyama   if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15256161b38dSRui Ueyama     return EC;
15266161b38dSRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15276161b38dSRui Ueyama   return std::error_code();
15286161b38dSRui Ueyama }
15296161b38dSRui Ueyama 
1530861021f9SRui Ueyama bool ImportedSymbolRef::
1531861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const {
1532861021f9SRui Ueyama   return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
1533861021f9SRui Ueyama       && Index == Other.Index;
1534861021f9SRui Ueyama }
1535861021f9SRui Ueyama 
1536861021f9SRui Ueyama void ImportedSymbolRef::moveNext() {
1537861021f9SRui Ueyama   ++Index;
1538861021f9SRui Ueyama }
1539861021f9SRui Ueyama 
1540861021f9SRui Ueyama std::error_code
1541861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const {
1542861021f9SRui Ueyama   uint32_t RVA;
1543861021f9SRui Ueyama   if (Entry32) {
1544861021f9SRui Ueyama     // If a symbol is imported only by ordinal, it has no name.
1545861021f9SRui Ueyama     if (Entry32[Index].isOrdinal())
15467d099195SRui Ueyama       return std::error_code();
1547861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1548861021f9SRui Ueyama   } else {
1549861021f9SRui Ueyama     if (Entry64[Index].isOrdinal())
15507d099195SRui Ueyama       return std::error_code();
1551861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1552861021f9SRui Ueyama   }
1553861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1554861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1555861021f9SRui Ueyama     return EC;
1556861021f9SRui Ueyama   // +2 because the first two bytes is hint.
1557861021f9SRui Ueyama   Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
15587d099195SRui Ueyama   return std::error_code();
1559861021f9SRui Ueyama }
1560861021f9SRui Ueyama 
1561ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
1562ad7b7e73SDavid Majnemer   if (Entry32)
1563ad7b7e73SDavid Majnemer     Result = Entry32[Index].isOrdinal();
1564ad7b7e73SDavid Majnemer   else
1565ad7b7e73SDavid Majnemer     Result = Entry64[Index].isOrdinal();
1566ad7b7e73SDavid Majnemer   return std::error_code();
1567ad7b7e73SDavid Majnemer }
1568ad7b7e73SDavid Majnemer 
1569ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
1570ad7b7e73SDavid Majnemer   if (Entry32)
1571ad7b7e73SDavid Majnemer     Result = Entry32[Index].getHintNameRVA();
1572ad7b7e73SDavid Majnemer   else
1573ad7b7e73SDavid Majnemer     Result = Entry64[Index].getHintNameRVA();
1574ad7b7e73SDavid Majnemer   return std::error_code();
1575ad7b7e73SDavid Majnemer }
1576ad7b7e73SDavid Majnemer 
1577861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
1578861021f9SRui Ueyama   uint32_t RVA;
1579861021f9SRui Ueyama   if (Entry32) {
1580861021f9SRui Ueyama     if (Entry32[Index].isOrdinal()) {
1581861021f9SRui Ueyama       Result = Entry32[Index].getOrdinal();
15827d099195SRui Ueyama       return std::error_code();
1583861021f9SRui Ueyama     }
1584861021f9SRui Ueyama     RVA = Entry32[Index].getHintNameRVA();
1585861021f9SRui Ueyama   } else {
1586861021f9SRui Ueyama     if (Entry64[Index].isOrdinal()) {
1587861021f9SRui Ueyama       Result = Entry64[Index].getOrdinal();
15887d099195SRui Ueyama       return std::error_code();
1589861021f9SRui Ueyama     }
1590861021f9SRui Ueyama     RVA = Entry64[Index].getHintNameRVA();
1591861021f9SRui Ueyama   }
1592861021f9SRui Ueyama   uintptr_t IntPtr = 0;
1593861021f9SRui Ueyama   if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
1594861021f9SRui Ueyama     return EC;
1595861021f9SRui Ueyama   Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
15967d099195SRui Ueyama   return std::error_code();
1597861021f9SRui Ueyama }
1598861021f9SRui Ueyama 
159912db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>>
160048af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
1601db4ed0bdSRafael Espindola   std::error_code EC;
160248af1c2aSRafael Espindola   std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
1603692410efSRafael Espindola   if (EC)
160412db383eSRafael Espindola     return errorCodeToError(EC);
1605c55cf4afSBill Wendling   return std::move(Ret);
1606686738e2SRui Ueyama }
160774e85130SRui Ueyama 
160874e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
160974e85130SRui Ueyama   return Header == Other.Header && Index == Other.Index;
161074e85130SRui Ueyama }
161174e85130SRui Ueyama 
161274e85130SRui Ueyama void BaseRelocRef::moveNext() {
161374e85130SRui Ueyama   // Header->BlockSize is the size of the current block, including the
161474e85130SRui Ueyama   // size of the header itself.
161574e85130SRui Ueyama   uint32_t Size = sizeof(*Header) +
1616970dda29SRui Ueyama       sizeof(coff_base_reloc_block_entry) * (Index + 1);
161774e85130SRui Ueyama   if (Size == Header->BlockSize) {
161874e85130SRui Ueyama     // .reloc contains a list of base relocation blocks. Each block
161974e85130SRui Ueyama     // consists of the header followed by entries. The header contains
162074e85130SRui Ueyama     // how many entories will follow. When we reach the end of the
162174e85130SRui Ueyama     // current block, proceed to the next block.
162274e85130SRui Ueyama     Header = reinterpret_cast<const coff_base_reloc_block_header *>(
162374e85130SRui Ueyama         reinterpret_cast<const uint8_t *>(Header) + Size);
162474e85130SRui Ueyama     Index = 0;
162574e85130SRui Ueyama   } else {
162674e85130SRui Ueyama     ++Index;
162774e85130SRui Ueyama   }
162874e85130SRui Ueyama }
162974e85130SRui Ueyama 
163074e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const {
163174e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
163274e85130SRui Ueyama   Type = Entry[Index].getType();
16337d099195SRui Ueyama   return std::error_code();
163474e85130SRui Ueyama }
163574e85130SRui Ueyama 
163674e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
163774e85130SRui Ueyama   auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
163874e85130SRui Ueyama   Result = Header->PageRVA + Entry[Index].getOffset();
16397d099195SRui Ueyama   return std::error_code();
164074e85130SRui Ueyama }
1641efef15a0SEric Beckmann 
1642357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr)                                                  \
1643357a40ecSMartin Storsjo   do {                                                                         \
1644357a40ecSMartin Storsjo     Error E = (Expr);                                                          \
164587867988SRafael Espindola     if (E)                                                                     \
1646c55cf4afSBill Wendling       return std::move(E);                                                     \
1647357a40ecSMartin Storsjo   } while (0)
1648efef15a0SEric Beckmann 
164987867988SRafael Espindola Expected<ArrayRef<UTF16>>
165087867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
1651efef15a0SEric Beckmann   BinaryStreamReader Reader = BinaryStreamReader(BBS);
1652efef15a0SEric Beckmann   Reader.setOffset(Offset);
1653efef15a0SEric Beckmann   uint16_t Length;
1654efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readInteger(Length));
1655efef15a0SEric Beckmann   ArrayRef<UTF16> RawDirString;
1656efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
1657cd704cb6SEric Beckmann   return RawDirString;
1658efef15a0SEric Beckmann }
1659efef15a0SEric Beckmann 
1660f3404674SRafael Espindola Expected<ArrayRef<UTF16>>
1661efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
1662f3404674SRafael Espindola   return getDirStringAtOffset(Entry.Identifier.getNameOffset());
1663efef15a0SEric Beckmann }
1664efef15a0SEric Beckmann 
166587867988SRafael Espindola Expected<const coff_resource_dir_table &>
1666efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
1667efef15a0SEric Beckmann   const coff_resource_dir_table *Table = nullptr;
1668efef15a0SEric Beckmann 
1669efef15a0SEric Beckmann   BinaryStreamReader Reader(BBS);
1670efef15a0SEric Beckmann   Reader.setOffset(Offset);
1671efef15a0SEric Beckmann   RETURN_IF_ERROR(Reader.readObject(Table));
1672efef15a0SEric Beckmann   assert(Table != nullptr);
1673efef15a0SEric Beckmann   return *Table;
1674efef15a0SEric Beckmann }
1675efef15a0SEric Beckmann 
1676edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1677edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
1678edb6ab9bSMartin Storsjo   const coff_resource_dir_entry *Entry = nullptr;
1679edb6ab9bSMartin Storsjo 
1680edb6ab9bSMartin Storsjo   BinaryStreamReader Reader(BBS);
1681edb6ab9bSMartin Storsjo   Reader.setOffset(Offset);
1682edb6ab9bSMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
1683edb6ab9bSMartin Storsjo   assert(Entry != nullptr);
1684edb6ab9bSMartin Storsjo   return *Entry;
1685edb6ab9bSMartin Storsjo }
1686edb6ab9bSMartin Storsjo 
16877ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
16887ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
16897ba81d95SMartin Storsjo   const coff_resource_data_entry *Entry = nullptr;
16907ba81d95SMartin Storsjo 
16917ba81d95SMartin Storsjo   BinaryStreamReader Reader(BBS);
16927ba81d95SMartin Storsjo   Reader.setOffset(Offset);
16937ba81d95SMartin Storsjo   RETURN_IF_ERROR(Reader.readObject(Entry));
16947ba81d95SMartin Storsjo   assert(Entry != nullptr);
16957ba81d95SMartin Storsjo   return *Entry;
16967ba81d95SMartin Storsjo }
16977ba81d95SMartin Storsjo 
1698f3404674SRafael Espindola Expected<const coff_resource_dir_table &>
1699efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17007ba81d95SMartin Storsjo   assert(Entry.Offset.isSubDir());
1701f3404674SRafael Espindola   return getTableAtOffset(Entry.Offset.value());
1702efef15a0SEric Beckmann }
1703efef15a0SEric Beckmann 
17047ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &>
17057ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17067ba81d95SMartin Storsjo   assert(!Entry.Offset.isSubDir());
17077ba81d95SMartin Storsjo   return getDataEntryAtOffset(Entry.Offset.value());
17087ba81d95SMartin Storsjo }
17097ba81d95SMartin Storsjo 
1710f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
1711f3404674SRafael Espindola   return getTableAtOffset(0);
1712efef15a0SEric Beckmann }
1713edb6ab9bSMartin Storsjo 
1714edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &>
1715edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
1716edb6ab9bSMartin Storsjo                                   uint32_t Index) {
1717edb6ab9bSMartin Storsjo   if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
1718edb6ab9bSMartin Storsjo     return createStringError(object_error::parse_failed, "index out of range");
1719edb6ab9bSMartin Storsjo   const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
1720edb6ab9bSMartin Storsjo   ptrdiff_t TableOffset = TablePtr - BBS.data().data();
1721edb6ab9bSMartin Storsjo   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
1722edb6ab9bSMartin Storsjo                                Index * sizeof(coff_resource_dir_entry));
1723edb6ab9bSMartin Storsjo }
172494382217SMartin Storsjo 
172594382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) {
172694382217SMartin Storsjo   for (const SectionRef &S : O->sections()) {
172794382217SMartin Storsjo     Expected<StringRef> Name = S.getName();
172894382217SMartin Storsjo     if (!Name)
172994382217SMartin Storsjo       return Name.takeError();
173094382217SMartin Storsjo 
173194382217SMartin Storsjo     if (*Name == ".rsrc" || *Name == ".rsrc$01")
173294382217SMartin Storsjo       return load(O, S);
173394382217SMartin Storsjo   }
173494382217SMartin Storsjo   return createStringError(object_error::parse_failed,
173594382217SMartin Storsjo                            "no resource section found");
173694382217SMartin Storsjo }
173794382217SMartin Storsjo 
173894382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
173994382217SMartin Storsjo   Obj = O;
174094382217SMartin Storsjo   Section = S;
174194382217SMartin Storsjo   Expected<StringRef> Contents = Section.getContents();
174294382217SMartin Storsjo   if (!Contents)
174394382217SMartin Storsjo     return Contents.takeError();
174494382217SMartin Storsjo   BBS = BinaryByteStream(*Contents, support::little);
174594382217SMartin Storsjo   const coff_section *COFFSect = Obj->getCOFFSection(Section);
174694382217SMartin Storsjo   ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
174794382217SMartin Storsjo   Relocs.reserve(OrigRelocs.size());
174894382217SMartin Storsjo   for (const coff_relocation &R : OrigRelocs)
174994382217SMartin Storsjo     Relocs.push_back(&R);
175094382217SMartin Storsjo   std::sort(Relocs.begin(), Relocs.end(),
175194382217SMartin Storsjo             [](const coff_relocation *A, const coff_relocation *B) {
175294382217SMartin Storsjo               return A->VirtualAddress < B->VirtualAddress;
175394382217SMartin Storsjo             });
175494382217SMartin Storsjo   return Error::success();
175594382217SMartin Storsjo }
175694382217SMartin Storsjo 
175794382217SMartin Storsjo Expected<StringRef>
175894382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
175994382217SMartin Storsjo   if (!Obj)
176094382217SMartin Storsjo     return createStringError(object_error::parse_failed, "no object provided");
176194382217SMartin Storsjo 
176294382217SMartin Storsjo   // Find a potential relocation at the DataRVA field (first member of
176394382217SMartin Storsjo   // the coff_resource_data_entry struct).
176494382217SMartin Storsjo   const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
176594382217SMartin Storsjo   ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
176694382217SMartin Storsjo   coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
176794382217SMartin Storsjo                               ulittle16_t(0)};
176894382217SMartin Storsjo   auto RelocsForOffset =
176994382217SMartin Storsjo       std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
177094382217SMartin Storsjo                        [](const coff_relocation *A, const coff_relocation *B) {
177194382217SMartin Storsjo                          return A->VirtualAddress < B->VirtualAddress;
177294382217SMartin Storsjo                        });
177394382217SMartin Storsjo 
177494382217SMartin Storsjo   if (RelocsForOffset.first != RelocsForOffset.second) {
177594382217SMartin Storsjo     // We found a relocation with the right offset. Check that it does have
177694382217SMartin Storsjo     // the expected type.
177794382217SMartin Storsjo     const coff_relocation &R = **RelocsForOffset.first;
177894382217SMartin Storsjo     uint16_t RVAReloc;
177994382217SMartin Storsjo     switch (Obj->getMachine()) {
178094382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_I386:
178194382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
178294382217SMartin Storsjo       break;
178394382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_AMD64:
178494382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
178594382217SMartin Storsjo       break;
178694382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARMNT:
178794382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
178894382217SMartin Storsjo       break;
178994382217SMartin Storsjo     case COFF::IMAGE_FILE_MACHINE_ARM64:
179094382217SMartin Storsjo       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
179194382217SMartin Storsjo       break;
179294382217SMartin Storsjo     default:
179394382217SMartin Storsjo       return createStringError(object_error::parse_failed,
179494382217SMartin Storsjo                                "unsupported architecture");
179594382217SMartin Storsjo     }
179694382217SMartin Storsjo     if (R.Type != RVAReloc)
179794382217SMartin Storsjo       return createStringError(object_error::parse_failed,
179894382217SMartin Storsjo                                "unexpected relocation type");
179994382217SMartin Storsjo     // Get the relocation's symbol
180094382217SMartin Storsjo     Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
180194382217SMartin Storsjo     if (!Sym)
180294382217SMartin Storsjo       return Sym.takeError();
180394382217SMartin Storsjo     // And the symbol's section
1804*77ecf90cSReid Kleckner     Expected<const coff_section *> Section =
1805*77ecf90cSReid Kleckner         Obj->getSection(Sym->getSectionNumber());
1806*77ecf90cSReid Kleckner     if (!Section)
1807*77ecf90cSReid Kleckner       return Section.takeError();
180894382217SMartin Storsjo     // Add the initial value of DataRVA to the symbol's offset to find the
180994382217SMartin Storsjo     // data it points at.
181094382217SMartin Storsjo     uint64_t Offset = Entry.DataRVA + Sym->getValue();
181194382217SMartin Storsjo     ArrayRef<uint8_t> Contents;
1812*77ecf90cSReid Kleckner     if (Error E = Obj->getSectionContents(*Section, Contents))
1813c55cf4afSBill Wendling       return std::move(E);
181494382217SMartin Storsjo     if (Offset + Entry.DataSize > Contents.size())
181594382217SMartin Storsjo       return createStringError(object_error::parse_failed,
181694382217SMartin Storsjo                                "data outside of section");
181794382217SMartin Storsjo     // Return a reference to the data inside the section.
181894382217SMartin Storsjo     return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
181994382217SMartin Storsjo                      Entry.DataSize);
182094382217SMartin Storsjo   } else {
182194382217SMartin Storsjo     // Relocatable objects need a relocation for the DataRVA field.
182294382217SMartin Storsjo     if (Obj->isRelocatableObject())
182394382217SMartin Storsjo       return createStringError(object_error::parse_failed,
182494382217SMartin Storsjo                                "no relocation found for DataRVA");
182594382217SMartin Storsjo 
182694382217SMartin Storsjo     // Locate the section that contains the address that DataRVA points at.
182794382217SMartin Storsjo     uint64_t VA = Entry.DataRVA + Obj->getImageBase();
182894382217SMartin Storsjo     for (const SectionRef &S : Obj->sections()) {
182994382217SMartin Storsjo       if (VA >= S.getAddress() &&
183094382217SMartin Storsjo           VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
183194382217SMartin Storsjo         uint64_t Offset = VA - S.getAddress();
183294382217SMartin Storsjo         Expected<StringRef> Contents = S.getContents();
183394382217SMartin Storsjo         if (!Contents)
183494382217SMartin Storsjo           return Contents.takeError();
183594382217SMartin Storsjo         return Contents->slice(Offset, Offset + Entry.DataSize);
183694382217SMartin Storsjo       }
183794382217SMartin Storsjo     }
183894382217SMartin Storsjo     return createStringError(object_error::parse_failed,
183994382217SMartin Storsjo                              "address not found in image");
184094382217SMartin Storsjo   }
184194382217SMartin Storsjo }
1842