1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 28e90adafSMichael J. Spencer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68e90adafSMichael J. Spencer // 78e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 88e90adafSMichael J. Spencer // 98e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 108e90adafSMichael J. Spencer // 118e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 128e90adafSMichael J. Spencer 139da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h" 150ea52537SSimon Pilgrim #include "llvm/ADT/StringSwitch.h" 168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 176a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h" 18264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h" 19d341c932SEugene Zelenko #include "llvm/Object/Binary.h" 20d341c932SEugene Zelenko #include "llvm/Object/COFF.h" 21d341c932SEugene Zelenko #include "llvm/Object/Error.h" 22d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h" 23efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h" 24d341c932SEugene Zelenko #include "llvm/Support/Endian.h" 25d341c932SEugene Zelenko #include "llvm/Support/Error.h" 26d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 27d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h" 28d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h" 29d341c932SEugene Zelenko #include <algorithm> 30d341c932SEugene Zelenko #include <cassert> 31d341c932SEugene Zelenko #include <cstddef> 32d341c932SEugene Zelenko #include <cstdint> 33d341c932SEugene Zelenko #include <cstring> 349d2c15efSNico Rieck #include <limits> 35d341c932SEugene Zelenko #include <memory> 36d341c932SEugene Zelenko #include <system_error> 378e90adafSMichael J. Spencer 388e90adafSMichael J. Spencer using namespace llvm; 398e90adafSMichael J. Spencer using namespace object; 408e90adafSMichael J. Spencer 418e90adafSMichael J. Spencer using support::ulittle16_t; 428e90adafSMichael J. Spencer using support::ulittle32_t; 43861021f9SRui Ueyama using support::ulittle64_t; 448e90adafSMichael J. Spencer using support::little16_t; 458e90adafSMichael J. Spencer 461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 48c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 498ff24d25SRui Ueyama EC = object_error::unexpected_eof; 501d6167fdSMichael J. Spencer return false; 511d6167fdSMichael J. Spencer } 521d6167fdSMichael J. Spencer return true; 538e90adafSMichael J. Spencer } 548e90adafSMichael J. Spencer 55ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 56ed64342bSRui Ueyama // Returns unexpected_eof if error. 57ed64342bSRui Ueyama template <typename T> 581c03389cSReid Kleckner static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, 59236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 60ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 61e03a135bSReid Kleckner if (Error E = Binary::checkOffset(M, Addr, Size)) 621c03389cSReid Kleckner return E; 63ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 641c03389cSReid Kleckner return Error::success(); 651d6167fdSMichael J. Spencer } 661d6167fdSMichael J. Spencer 679d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 689d2c15efSNico Rieck // prefixed slashes. 699d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 709d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 719d2c15efSNico Rieck if (Str.size() > 6) 729d2c15efSNico Rieck return true; 739d2c15efSNico Rieck 749d2c15efSNico Rieck uint64_t Value = 0; 759d2c15efSNico Rieck while (!Str.empty()) { 769d2c15efSNico Rieck unsigned CharVal; 779d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 789d2c15efSNico Rieck CharVal = Str[0] - 'A'; 799d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 809d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 819d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 829d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 839d2c15efSNico Rieck else if (Str[0] == '+') // 62 845500b07cSRui Ueyama CharVal = 62; 859d2c15efSNico Rieck else if (Str[0] == '/') // 63 865500b07cSRui Ueyama CharVal = 63; 879d2c15efSNico Rieck else 889d2c15efSNico Rieck return true; 899d2c15efSNico Rieck 909d2c15efSNico Rieck Value = (Value * 64) + CharVal; 919d2c15efSNico Rieck Str = Str.substr(1); 929d2c15efSNico Rieck } 939d2c15efSNico Rieck 949d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 959d2c15efSNico Rieck return true; 969d2c15efSNico Rieck 979d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 989d2c15efSNico Rieck return false; 999d2c15efSNico Rieck } 1009d2c15efSNico Rieck 10144f51e51SDavid Majnemer template <typename coff_symbol_type> 10244f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10344f51e51SDavid Majnemer const coff_symbol_type *Addr = 10444f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1051d6167fdSMichael J. Spencer 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 { 15077ecf90cSReid 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 17377ecf90cSReid Kleckner Expected<const coff_section *> Section = getSection(SectionNumber); 17477ecf90cSReid Kleckner if (!Section) 17577ecf90cSReid Kleckner return Section.takeError(); 17677ecf90cSReid 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(); 24977ecf90cSReid Kleckner Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber()); 25077ecf90cSReid Kleckner if (!Sec) 25177ecf90cSReid Kleckner return Sec.takeError(); 2528bab889bSRafael Espindola DataRefImpl Ret; 25377ecf90cSReid 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; 3551c03389cSReid Kleckner if (Error E = getObject(FirstReloc, M, 3561c03389cSReid Kleckner reinterpret_cast<const coff_relocation *>( 3571c03389cSReid Kleckner base + Sec->PointerToRelocations))) { 3581c03389cSReid Kleckner consumeError(std::move(E)); 359e830c60dSDavid Majnemer return 0; 3601c03389cSReid Kleckner } 36198fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 36298fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 363e830c60dSDavid Majnemer } 364e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 365e830c60dSDavid Majnemer } 366e830c60dSDavid Majnemer 36794751be7SDavid Majnemer static const coff_relocation * 36894751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 36994751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 37094751be7SDavid Majnemer if (!NumRelocs) 37194751be7SDavid Majnemer return nullptr; 372827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 37394751be7SDavid Majnemer Base + Sec->PointerToRelocations); 374827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 375827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 376827c8a2bSRui Ueyama // relocations. 377827c8a2bSRui Ueyama begin++; 378827c8a2bSRui Ueyama } 379e03a135bSReid Kleckner if (auto E = Binary::checkOffset(M, uintptr_t(begin), 380e03a135bSReid Kleckner sizeof(coff_relocation) * NumRelocs)) { 381e03a135bSReid Kleckner consumeError(std::move(E)); 38294751be7SDavid Majnemer return nullptr; 383e03a135bSReid Kleckner } 38494751be7SDavid Majnemer return begin; 385827c8a2bSRui Ueyama } 38694751be7SDavid Majnemer 38794751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 38894751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 38994751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 39076d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 39176d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 39294751be7SDavid Majnemer DataRefImpl Ret; 39394751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3948ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 395e5fd0047SMichael J. Spencer } 396e5fd0047SMichael J. Spencer 3978ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3988ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 39994751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 40094751be7SDavid Majnemer if (I) 40194751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 4028ff24d25SRui Ueyama DataRefImpl Ret; 40394751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 4048ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 405e5fd0047SMichael J. Spencer } 406e5fd0047SMichael J. Spencer 407c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 4081c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() { 40944f51e51SDavid Majnemer if (COFFHeader) 4101c03389cSReid Kleckner if (Error E = getObject( 411236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 412236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4131c03389cSReid Kleckner return E; 41444f51e51SDavid Majnemer 41544f51e51SDavid Majnemer if (COFFBigObjHeader) 4161c03389cSReid Kleckner if (Error E = getObject( 417236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 418236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4191c03389cSReid Kleckner return E; 420c2bed429SRui Ueyama 421c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 422c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 423c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 424f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 42544f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 426f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 427c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 4281c03389cSReid Kleckner if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr)) 4291c03389cSReid Kleckner return E; 430c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 4311c03389cSReid Kleckner if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4321c03389cSReid Kleckner return E; 433c2bed429SRui Ueyama 434773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 435773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 436773a5795SNico Rieck if (StringTableSize < 4) 437773a5795SNico Rieck StringTableSize = 4; 438773a5795SNico Rieck 439c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 440773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 4411c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 4421c03389cSReid Kleckner return Error::success(); 443c2bed429SRui Ueyama } 444c2bed429SRui Ueyama 44521427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 446e94fef7bSReid Kleckner if (PE32Header) 44721427adaSReid Kleckner return PE32Header->ImageBase; 448e94fef7bSReid Kleckner else if (PE32PlusHeader) 44921427adaSReid Kleckner return PE32PlusHeader->ImageBase; 45021427adaSReid Kleckner // This actually comes up in practice. 45121427adaSReid Kleckner return 0; 452e94fef7bSReid Kleckner } 453e94fef7bSReid Kleckner 454215a586cSRui Ueyama // Returns the file offset for the given VA. 4551c03389cSReid Kleckner Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 45621427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 457b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 458b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 459b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 460215a586cSRui Ueyama } 461215a586cSRui Ueyama 462c2bed429SRui Ueyama // Returns the file offset for the given RVA. 4631c03389cSReid Kleckner Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 46427dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 46527dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 466c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 467c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 468215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 469215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 470c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4711c03389cSReid Kleckner return Error::success(); 472c2bed429SRui Ueyama } 473c2bed429SRui Ueyama } 4741c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 475c2bed429SRui Ueyama } 476c2bed429SRui Ueyama 4771c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4782da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4792da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4802da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4812da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4822da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4832da433eaSReid Kleckner // overflow. 4842da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4852da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4862da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4872da433eaSReid Kleckner uintptr_t Begin = 4882da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4892da433eaSReid Kleckner Contents = 4902da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4911c03389cSReid Kleckner return Error::success(); 4922da433eaSReid Kleckner } 4932da433eaSReid Kleckner } 4941c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 4952da433eaSReid Kleckner } 4962da433eaSReid Kleckner 497c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 498c2bed429SRui Ueyama // table entry. 4991c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 500db4ed0bdSRafael Espindola StringRef &Name) const { 501c2bed429SRui Ueyama uintptr_t IntPtr = 0; 5021c03389cSReid Kleckner if (Error E = getRvaPtr(Rva, IntPtr)) 5031c03389cSReid Kleckner return E; 504c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 505c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 506c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5071c03389cSReid Kleckner return Error::success(); 508c2bed429SRui Ueyama } 509c2bed429SRui Ueyama 5101c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 51101528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5122da433eaSReid Kleckner StringRef &PDBFileName) const { 5132da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5141c03389cSReid Kleckner if (Error E = getRvaAndSizeAsBytes( 5152da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5161c03389cSReid Kleckner return E; 51701528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5181c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 51901528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 52001528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5212da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5222da433eaSReid Kleckner InfoBytes.size()); 5232da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5242da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5251c03389cSReid Kleckner return Error::success(); 5262da433eaSReid Kleckner } 5272da433eaSReid Kleckner 5281c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 529f27f3f84SReid Kleckner StringRef &PDBFileName) const { 530f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 531f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 532f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 533f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 534f27f3f84SReid Kleckner PDBInfo = nullptr; 535f27f3f84SReid Kleckner PDBFileName = StringRef(); 5361c03389cSReid Kleckner return Error::success(); 537f27f3f84SReid Kleckner } 538f27f3f84SReid Kleckner 539c2bed429SRui Ueyama // Find the import table. 5401c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() { 541c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 542c2bed429SRui Ueyama // the import table, do nothing. 5431c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE); 5441c03389cSReid Kleckner if (!DataEntry) 5451c03389cSReid Kleckner return Error::success(); 546c2bed429SRui Ueyama 547c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 548c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5491c03389cSReid Kleckner return Error::success(); 550c2bed429SRui Ueyama 551c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 552c2bed429SRui Ueyama 553c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 554c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 555c2bed429SRui Ueyama uintptr_t IntPtr = 0; 5561c03389cSReid Kleckner if (Error E = getRvaPtr(ImportTableRva, IntPtr)) 5571c03389cSReid Kleckner return E; 558e03a135bSReid Kleckner if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 5591c03389cSReid Kleckner return E; 560c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5611c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5621c03389cSReid Kleckner return Error::success(); 563ad882ba8SRui Ueyama } 564c2bed429SRui Ueyama 56515d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 5661c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() { 5671c03389cSReid Kleckner const data_directory *DataEntry = 5681c03389cSReid Kleckner getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR); 5691c03389cSReid Kleckner if (!DataEntry) 5701c03389cSReid Kleckner return Error::success(); 57115d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5721c03389cSReid Kleckner return Error::success(); 57315d99359SRui Ueyama 57415d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 57515d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 57615d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 57715d99359SRui Ueyama 57815d99359SRui Ueyama uintptr_t IntPtr = 0; 5791c03389cSReid Kleckner if (Error E = getRvaPtr(RVA, IntPtr)) 5801c03389cSReid Kleckner return E; 58115d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 58215d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5831c03389cSReid Kleckner return Error::success(); 58415d99359SRui Ueyama } 58515d99359SRui Ueyama 586ad882ba8SRui Ueyama // Find the export table. 5871c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() { 588ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 589ad882ba8SRui Ueyama // the export table, do nothing. 5901c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE); 5911c03389cSReid Kleckner if (!DataEntry) 5921c03389cSReid Kleckner return Error::success(); 593ad882ba8SRui Ueyama 594ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 595ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5961c03389cSReid Kleckner return Error::success(); 597ad882ba8SRui Ueyama 598ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 599ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 6001c03389cSReid Kleckner if (Error E = getRvaPtr(ExportTableRva, IntPtr)) 6011c03389cSReid Kleckner return E; 60224fc2d64SRui Ueyama ExportDirectory = 60324fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6041c03389cSReid Kleckner return Error::success(); 605c2bed429SRui Ueyama } 606c2bed429SRui Ueyama 6071c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() { 6081c03389cSReid Kleckner const data_directory *DataEntry = 6091c03389cSReid Kleckner getDataDirectory(COFF::BASE_RELOCATION_TABLE); 6101c03389cSReid Kleckner if (!DataEntry) 6111c03389cSReid Kleckner return Error::success(); 61274e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6131c03389cSReid Kleckner return Error::success(); 61474e85130SRui Ueyama 61574e85130SRui Ueyama uintptr_t IntPtr = 0; 6161c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6171c03389cSReid Kleckner return E; 61874e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 61974e85130SRui Ueyama IntPtr); 62074e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 62174e85130SRui Ueyama IntPtr + DataEntry->Size); 622893c6469SNico Weber // FIXME: Verify the section containing BaseRelocHeader has at least 623893c6469SNico Weber // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6241c03389cSReid Kleckner return Error::success(); 62574e85130SRui Ueyama } 62674e85130SRui Ueyama 6271c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() { 6282da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6291c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY); 6301c03389cSReid Kleckner if (!DataEntry) 6311c03389cSReid Kleckner return Error::success(); 6322da433eaSReid Kleckner 6332da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6342da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6351c03389cSReid Kleckner return Error::success(); 6362da433eaSReid Kleckner 6372da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6382da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6391c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 6402da433eaSReid Kleckner 6412da433eaSReid Kleckner uintptr_t IntPtr = 0; 6421c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6431c03389cSReid Kleckner return E; 6442da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 645893c6469SNico Weber DebugDirectoryEnd = reinterpret_cast<const debug_directory *>( 646893c6469SNico Weber IntPtr + DataEntry->Size); 647893c6469SNico Weber // FIXME: Verify the section containing DebugDirectoryBegin has at least 648893c6469SNico Weber // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6491c03389cSReid Kleckner return Error::success(); 6502da433eaSReid Kleckner } 6512da433eaSReid Kleckner 652*568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() { 653*568035acSLuqman Aden // Get the RVA of the TLS directory. Do nothing if it does not exist. 654*568035acSLuqman Aden const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE); 655*568035acSLuqman Aden if (!DataEntry) 656*568035acSLuqman Aden return Error::success(); 657*568035acSLuqman Aden 658*568035acSLuqman Aden // Do nothing if the RVA is NULL. 659*568035acSLuqman Aden if (DataEntry->RelativeVirtualAddress == 0) 660*568035acSLuqman Aden return Error::success(); 661*568035acSLuqman Aden 662*568035acSLuqman Aden uint64_t DirSize = 663*568035acSLuqman Aden is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32); 664*568035acSLuqman Aden 665*568035acSLuqman Aden // Check that the size is correct. 666*568035acSLuqman Aden if (DataEntry->Size != DirSize) 667*568035acSLuqman Aden return createStringError( 668*568035acSLuqman Aden object_error::parse_failed, 669*568035acSLuqman Aden "TLS Directory size (%u) is not the expected size (%u).", 670*568035acSLuqman Aden static_cast<uint32_t>(DataEntry->Size), DirSize); 671*568035acSLuqman Aden 672*568035acSLuqman Aden uintptr_t IntPtr = 0; 673*568035acSLuqman Aden if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 674*568035acSLuqman Aden return E; 675*568035acSLuqman Aden 676*568035acSLuqman Aden if (is64()) 677*568035acSLuqman Aden TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr); 678*568035acSLuqman Aden else 679*568035acSLuqman Aden TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr); 680*568035acSLuqman Aden 681*568035acSLuqman Aden return Error::success(); 682*568035acSLuqman Aden } 683*568035acSLuqman Aden 6841c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() { 685b7d716c0SReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6861c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE); 6871c03389cSReid Kleckner if (!DataEntry) 6881c03389cSReid Kleckner return Error::success(); 689b7d716c0SReid Kleckner 690b7d716c0SReid Kleckner // Do nothing if the RVA is NULL. 691b7d716c0SReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6921c03389cSReid Kleckner return Error::success(); 693b7d716c0SReid Kleckner uintptr_t IntPtr = 0; 6941c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6951c03389cSReid Kleckner return E; 696b7d716c0SReid Kleckner 697b7d716c0SReid Kleckner LoadConfig = (const void *)IntPtr; 6981c03389cSReid Kleckner return Error::success(); 699b7d716c0SReid Kleckner } 700b7d716c0SReid Kleckner 70139772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>> 70239772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) { 70339772063SReid Kleckner std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object))); 70439772063SReid Kleckner if (Error E = Obj->initialize()) 70539772063SReid Kleckner return std::move(E); 70639772063SReid Kleckner return std::move(Obj); 70739772063SReid Kleckner } 70839772063SReid Kleckner 70939772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object) 71048af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 71144f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 71244f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 71344f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 71439772063SReid Kleckner ImportDirectory(nullptr), DelayImportDirectory(nullptr), 71539772063SReid Kleckner NumberOfDelayImportDirectory(0), ExportDirectory(nullptr), 71639772063SReid Kleckner BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 717*568035acSLuqman Aden DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr), 718*568035acSLuqman Aden TLSDirectory32(nullptr), TLSDirectory64(nullptr) {} 71939772063SReid Kleckner 720101fbc01SNico Weber Error COFFObjectFile::initialize() { 7211d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 72239772063SReid Kleckner std::error_code EC; 72348af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 72439772063SReid Kleckner return errorCodeToError(EC); 725ee066fc4SEric Christopher 72682ebd8e3SRui Ueyama // The current location in the file where we are looking at. 72782ebd8e3SRui Ueyama uint64_t CurPtr = 0; 72882ebd8e3SRui Ueyama 72982ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 73082ebd8e3SRui Ueyama // it is placed right after COFF header. 7318ff24d25SRui Ueyama bool HasPEHeader = false; 732ee066fc4SEric Christopher 7331d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 73450267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 735ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 736ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 73750267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 73850267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 73950267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 74082ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 74150267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 74239772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 7431d6167fdSMichael J. Spencer } 74444f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 7458ff24d25SRui Ueyama HasPEHeader = true; 746ee066fc4SEric Christopher } 74750267222SDavid Majnemer } 748ee066fc4SEric Christopher 7491c03389cSReid Kleckner if (Error E = getObject(COFFHeader, Data, base() + CurPtr)) 7501c03389cSReid Kleckner return E; 75144f51e51SDavid Majnemer 75244f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 75344f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 75444f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 75544f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 75644f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 7571c03389cSReid Kleckner if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr)) 7581c03389cSReid Kleckner return E; 75944f51e51SDavid Majnemer 76044f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 76144f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 76244f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 76344f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 76444f51e51SDavid Majnemer COFFHeader = nullptr; 76544f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 76644f51e51SDavid Majnemer } else { 76744f51e51SDavid Majnemer // It's not a bigobj. 76844f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 76944f51e51SDavid Majnemer } 77044f51e51SDavid Majnemer } 77144f51e51SDavid Majnemer if (COFFHeader) { 77244f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 77344f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7747d099195SRui Ueyama EC = std::error_code(); 77582ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 77682ebd8e3SRui Ueyama 77744f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 77839772063SReid Kleckner return errorCodeToError(EC); 77944f51e51SDavid Majnemer } 78044f51e51SDavid Majnemer 7818ff24d25SRui Ueyama if (HasPEHeader) { 78210ed9ddcSRui Ueyama const pe32_header *Header; 7831c03389cSReid Kleckner if (Error E = getObject(Header, Data, base() + CurPtr)) 7841c03389cSReid Kleckner return E; 78510ed9ddcSRui Ueyama 78610ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 78710ed9ddcSRui Ueyama uint64_t DataDirSize; 78850267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 78910ed9ddcSRui Ueyama PE32Header = Header; 79010ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 79110ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 79250267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 79310ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 79410ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 79510ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 79610ed9ddcSRui Ueyama } else { 79710ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 79839772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 799ed64342bSRui Ueyama } 8001c03389cSReid Kleckner if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)) 8011c03389cSReid Kleckner return E; 802f53c8cb4SRui Ueyama } 803776c6828SRui Ueyama 8048950a538SRui Ueyama if (COFFHeader) 8058950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 8068950a538SRui Ueyama 8071c03389cSReid Kleckner assert(COFFHeader || COFFBigObjHeader); 8081c03389cSReid Kleckner 8091c03389cSReid Kleckner if (Error E = 8101c03389cSReid Kleckner getObject(SectionTable, Data, base() + CurPtr, 8111c03389cSReid Kleckner (uint64_t)getNumberOfSections() * sizeof(coff_section))) 8121c03389cSReid Kleckner return E; 8131d6167fdSMichael J. Spencer 814c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 815236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 8161c03389cSReid Kleckner if (Error E = initSymbolTablePtr()) { 8171c03389cSReid Kleckner // Recover from errors reading the symbol table. 8181c03389cSReid Kleckner consumeError(std::move(E)); 819ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 820ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 821ac8cfab5SDavid Majnemer StringTable = nullptr; 822ac8cfab5SDavid Majnemer StringTableSize = 0; 823ac8cfab5SDavid Majnemer } 824236b0ca7SDavid Majnemer } else { 825236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 826236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 82739772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 828236b0ca7SDavid Majnemer } 829236b0ca7SDavid Majnemer } 8308e90adafSMichael J. Spencer 831c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 8321c03389cSReid Kleckner if (Error E = initImportTablePtr()) 8331c03389cSReid Kleckner return E; 8341c03389cSReid Kleckner if (Error E = initDelayImportTablePtr()) 8351c03389cSReid Kleckner return E; 8361d6167fdSMichael J. Spencer 837ad882ba8SRui Ueyama // Initialize the pointer to the export table. 8381c03389cSReid Kleckner if (Error E = initExportTablePtr()) 8391c03389cSReid Kleckner return E; 840ad882ba8SRui Ueyama 84174e85130SRui Ueyama // Initialize the pointer to the base relocation table. 8421c03389cSReid Kleckner if (Error E = initBaseRelocPtr()) 8431c03389cSReid Kleckner return E; 84474e85130SRui Ueyama 845*568035acSLuqman Aden // Initialize the pointer to the debug directory. 8461c03389cSReid Kleckner if (Error E = initDebugDirectoryPtr()) 8471c03389cSReid Kleckner return E; 8482da433eaSReid Kleckner 849*568035acSLuqman Aden // Initialize the pointer to the TLS directory. 850*568035acSLuqman Aden if (Error E = initTLSDirectoryPtr()) 851*568035acSLuqman Aden return E; 852*568035acSLuqman Aden 8531c03389cSReid Kleckner if (Error E = initLoadConfigPtr()) 8541c03389cSReid Kleckner return E; 855b7d716c0SReid Kleckner 85639772063SReid Kleckner return Error::success(); 8578e90adafSMichael J. Spencer } 8588e90adafSMichael J. Spencer 859435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 8608ff24d25SRui Ueyama DataRefImpl Ret; 86144f51e51SDavid Majnemer Ret.p = getSymbolTable(); 862f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8638e90adafSMichael J. Spencer } 8648e90adafSMichael J. Spencer 865435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 8668e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 8678ff24d25SRui Ueyama DataRefImpl Ret; 8688ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 869f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8708e90adafSMichael J. Spencer } 8718e90adafSMichael J. Spencer 872bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 873ad7b7e73SDavid Majnemer if (!ImportDirectory) 874ad7b7e73SDavid Majnemer return import_directory_end(); 8751c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 876ad7b7e73SDavid Majnemer return import_directory_end(); 877a045b73aSRui Ueyama return import_directory_iterator( 878a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 879c2bed429SRui Ueyama } 880c2bed429SRui Ueyama 881bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 882a045b73aSRui Ueyama return import_directory_iterator( 883ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 884c2bed429SRui Ueyama } 885c429b80dSDavid Meyer 88615d99359SRui Ueyama delay_import_directory_iterator 88715d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 88815d99359SRui Ueyama return delay_import_directory_iterator( 88915d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 89015d99359SRui Ueyama } 89115d99359SRui Ueyama 89215d99359SRui Ueyama delay_import_directory_iterator 89315d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 89415d99359SRui Ueyama return delay_import_directory_iterator( 89515d99359SRui Ueyama DelayImportDirectoryEntryRef( 89615d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 89715d99359SRui Ueyama } 89815d99359SRui Ueyama 899ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 900ad882ba8SRui Ueyama return export_directory_iterator( 901ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 902ad882ba8SRui Ueyama } 903ad882ba8SRui Ueyama 904ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 9052617dcceSCraig Topper if (!ExportDirectory) 9062617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 9078ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 908ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 9098ff24d25SRui Ueyama return export_directory_iterator(Ref); 910ad882ba8SRui Ueyama } 911ad882ba8SRui Ueyama 912b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 9138ff24d25SRui Ueyama DataRefImpl Ret; 9148ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 9158ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 9168e90adafSMichael J. Spencer } 9178e90adafSMichael J. Spencer 918b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 9198ff24d25SRui Ueyama DataRefImpl Ret; 92044f51e51SDavid Majnemer int NumSections = 92144f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 9228ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 9238ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 9248e90adafSMichael J. Spencer } 9258e90adafSMichael J. Spencer 92674e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 92774e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 92874e85130SRui Ueyama } 92974e85130SRui Ueyama 93074e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 93174e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 93274e85130SRui Ueyama } 93374e85130SRui Ueyama 9348e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 93543c85453SMartin Storsjo return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 9368e90adafSMichael J. Spencer } 9378e90adafSMichael J. Spencer 9388e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 93944f51e51SDavid Majnemer switch(getMachine()) { 9408e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9418e90adafSMichael J. Spencer return "COFF-i386"; 9428e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9438e90adafSMichael J. Spencer return "COFF-x86-64"; 9449b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9459b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 9461eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9471eff5c9cSMartell Malone return "COFF-ARM64"; 9488e90adafSMichael J. Spencer default: 9498e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 9508e90adafSMichael J. Spencer } 9518e90adafSMichael J. Spencer } 9528e90adafSMichael J. Spencer 953260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const { 95444f51e51SDavid Majnemer switch (getMachine()) { 9558e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9568e90adafSMichael J. Spencer return Triple::x86; 9578e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9588e90adafSMichael J. Spencer return Triple::x86_64; 9599b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9609b7c0af2SSaleem Abdulrasool return Triple::thumb; 9611eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9621eff5c9cSMartell Malone return Triple::aarch64; 9638e90adafSMichael J. Spencer default: 9648e90adafSMichael J. Spencer return Triple::UnknownArch; 9658e90adafSMichael J. Spencer } 9668e90adafSMichael J. Spencer } 9678e90adafSMichael J. Spencer 968d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const { 969d2af4d6fSPaul Semel if (PE32Header) 970d2af4d6fSPaul Semel return PE32Header->AddressOfEntryPoint; 971d2af4d6fSPaul Semel return 0; 972d2af4d6fSPaul Semel } 973d2af4d6fSPaul Semel 974979fb40bSRui Ueyama iterator_range<import_directory_iterator> 975979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 976979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 977979fb40bSRui Ueyama } 978979fb40bSRui Ueyama 979979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 980979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 981979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 982979fb40bSRui Ueyama delay_import_directory_end()); 983979fb40bSRui Ueyama } 984979fb40bSRui Ueyama 985979fb40bSRui Ueyama iterator_range<export_directory_iterator> 986979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 987979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 988979fb40bSRui Ueyama } 989979fb40bSRui Ueyama 99074e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 99174e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 99274e85130SRui Ueyama } 99374e85130SRui Ueyama 9941c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const { 9951c03389cSReid Kleckner if (!DataDirectory) 9961c03389cSReid Kleckner return nullptr; 99710ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 99810ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 99910ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 10001c03389cSReid Kleckner if (Index >= NumEnt) 10011c03389cSReid Kleckner return nullptr; 10021c03389cSReid Kleckner return &DataDirectory[Index]; 1003ed64342bSRui Ueyama } 1004ed64342bSRui Ueyama 100577ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const { 100677ecf90cSReid Kleckner // Perhaps getting the section of a reserved section index should be an error, 100777ecf90cSReid Kleckner // but callers rely on this to return null. 1008236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 100977ecf90cSReid Kleckner return (const coff_section *)nullptr; 1010236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 10111d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 101277ecf90cSReid Kleckner return SectionTable + (Index - 1); 10138e90adafSMichael J. Spencer } 101477ecf90cSReid Kleckner return errorCodeToError(object_error::parse_failed); 1015236b0ca7SDavid Majnemer } 10168e90adafSMichael J. Spencer 101777ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const { 10181d6167fdSMichael J. Spencer if (StringTableSize <= 4) 10191d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 102077ecf90cSReid Kleckner return errorCodeToError(object_error::parse_failed); 10218ff24d25SRui Ueyama if (Offset >= StringTableSize) 102277ecf90cSReid Kleckner return errorCodeToError(object_error::unexpected_eof); 102377ecf90cSReid Kleckner return StringRef(StringTable + Offset); 10248e90adafSMichael J. Spencer } 1025022ecdf2SBenjamin Kramer 102677ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const { 102777ecf90cSReid Kleckner return getSymbolName(Symbol.getGeneric()); 1028e40d30f3SRui Ueyama } 1029e40d30f3SRui Ueyama 103077ecf90cSReid Kleckner Expected<StringRef> 103177ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const { 103289a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 103377ecf90cSReid Kleckner if (Symbol->Name.Offset.Zeroes == 0) 103477ecf90cSReid Kleckner return getString(Symbol->Name.Offset.Offset); 103589a7a5eaSMichael J. Spencer 103689a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 103777ecf90cSReid Kleckner if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 103877ecf90cSReid Kleckner return StringRef(Symbol->Name.ShortName); 103977ecf90cSReid Kleckner 104089a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 104177ecf90cSReid Kleckner return StringRef(Symbol->Name.ShortName, COFF::NameSize); 104289a7a5eaSMichael J. Spencer } 104389a7a5eaSMichael J. Spencer 104444f51e51SDavid Majnemer ArrayRef<uint8_t> 104544f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 10462617dcceSCraig Topper const uint8_t *Aux = nullptr; 104771757ef3SMarshall Clow 104844f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 104944f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 105071757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 105144f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 105271757ef3SMarshall Clow #ifndef NDEBUG 10538ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10548ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 105544f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 105644f51e51SDavid Majnemer Offset >= 105744f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 105871757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 105971757ef3SMarshall Clow 106044f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 106144f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 106271757ef3SMarshall Clow #endif 1063bfb85e67SMarshall Clow } 106444f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 106571757ef3SMarshall Clow } 106671757ef3SMarshall Clow 106774e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { 106874e7d260SMartin Storsjo uintptr_t Offset = 106974e7d260SMartin Storsjo reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable(); 107074e7d260SMartin Storsjo assert(Offset % getSymbolTableEntrySize() == 0 && 107174e7d260SMartin Storsjo "Symbol did not point to the beginning of a symbol"); 107274e7d260SMartin Storsjo size_t Index = Offset / getSymbolTableEntrySize(); 107374e7d260SMartin Storsjo assert(Index < getNumberOfSymbols()); 107474e7d260SMartin Storsjo return Index; 107574e7d260SMartin Storsjo } 107674e7d260SMartin Storsjo 10778be28cdcSFangrui Song Expected<StringRef> 10788be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const { 107953c2d547SMichael J. Spencer StringRef Name; 108044f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 108153c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 108253c2d547SMichael J. Spencer Name = Sec->Name; 108353c2d547SMichael J. Spencer else 108453c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 108544f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 108653c2d547SMichael J. Spencer 108753c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10882314b3deSDavid Majnemer if (Name.startswith("/")) { 108953c2d547SMichael J. Spencer uint32_t Offset; 10902314b3deSDavid Majnemer if (Name.startswith("//")) { 10919d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10928be28cdcSFangrui Song return createStringError(object_error::parse_failed, 1093400b6c08Sserge-sans-paille "invalid section name"); 10949d2c15efSNico Rieck } else { 109553c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 10968be28cdcSFangrui Song return createStringError(object_error::parse_failed, 10978be28cdcSFangrui Song "invalid section name"); 10989d2c15efSNico Rieck } 109977ecf90cSReid Kleckner return getString(Offset); 110053c2d547SMichael J. Spencer } 110153c2d547SMichael J. Spencer 11028be28cdcSFangrui Song return Name; 110353c2d547SMichael J. Spencer } 110453c2d547SMichael J. Spencer 1105a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1106a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1107a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1108a9ee5c06SDavid Majnemer // 1109a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1110d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1111a9ee5c06SDavid Majnemer // 1112a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1113a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1114a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1115a9ee5c06SDavid Majnemer // considered to be zero. 1116d5297ee7SRui Ueyama if (getDOSHeader()) 1117d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1118d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1119a9ee5c06SDavid Majnemer } 1120a9ee5c06SDavid Majnemer 1121e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec, 11229da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1123e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1124e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1125e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1126e1cb2c0fSFangrui Song return Error::success(); 11279da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 11289da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 11299da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 11309da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1131a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1132e03a135bSReid Kleckner if (Error E = checkOffset(Data, ConStart, SectionSize)) 1133e03a135bSReid Kleckner return E; 1134a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 1135e1cb2c0fSFangrui Song return Error::success(); 11369da9e693SMichael J. Spencer } 11379da9e693SMichael J. Spencer 1138022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1139e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1140022ecdf2SBenjamin Kramer } 11418ff24d25SRui Ueyama 11425e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1143e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1144e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1145022ecdf2SBenjamin Kramer } 11468ff24d25SRui Ueyama 114796d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 114858323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 114996d071cdSRafael Espindola return R->VirtualAddress; 1150cbe72fc9SDanil Malyshev } 11518ff24d25SRui Ueyama 1152806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1153022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 11548ff24d25SRui Ueyama DataRefImpl Ref; 1155236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1156236b0ca7SDavid Majnemer return symbol_end(); 115744f51e51SDavid Majnemer if (SymbolTable16) 115844f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 115944f51e51SDavid Majnemer else if (SymbolTable32) 116044f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 116144f51e51SDavid Majnemer else 1162c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11638ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1164022ecdf2SBenjamin Kramer } 11658ff24d25SRui Ueyama 116699c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1167022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 116899c041b7SRafael Espindola return R->Type; 1169022ecdf2SBenjamin Kramer } 1170e5fd0047SMichael J. Spencer 117127dc8394SAlexey Samsonov const coff_section * 117227dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 117327dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 117471757ef3SMarshall Clow } 117571757ef3SMarshall Clow 117644f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 117744f51e51SDavid Majnemer if (SymbolTable16) 117844f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 117944f51e51SDavid Majnemer if (SymbolTable32) 118044f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 118144f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 118244f51e51SDavid Majnemer } 118344f51e51SDavid Majnemer 118444f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 118544f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 118671757ef3SMarshall Clow } 118771757ef3SMarshall Clow 1188f12b8282SRafael Espindola const coff_relocation * 118927dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 119027dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1191d3e2a76cSMarshall Clow } 1192d3e2a76cSMarshall Clow 11932f6d0061SPeter Collingbourne ArrayRef<coff_relocation> 11946a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11952f6d0061SPeter Collingbourne return {getFirstReloc(Sec, Data, base()), 11962f6d0061SPeter Collingbourne getNumberOfRelocations(Sec, Data, base())}; 11976a75acb1SRui Ueyama } 11986a75acb1SRui Ueyama 119927dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 120027dc8394SAlexey Samsonov case COFF::reloc_type: \ 1201114ebf4aSMartin Storsjo return #reloc_type; 1202e5fd0047SMichael J. Spencer 1203114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { 120444f51e51SDavid Majnemer switch (getMachine()) { 1205e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 1206114ebf4aSMartin Storsjo switch (Type) { 1207e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1208e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1209e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1210e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1211e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1212e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1213e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1214e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1215e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1216e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1217e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1218e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1219e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1220e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1221e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1222e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1223e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1224e5fd0047SMichael J. Spencer default: 1225114ebf4aSMartin Storsjo return "Unknown"; 1226e5fd0047SMichael J. Spencer } 1227e5fd0047SMichael J. Spencer break; 12285c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 1229114ebf4aSMartin Storsjo switch (Type) { 12305c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 12315c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 12325c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 12335c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 12345c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 12355c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 12365c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 12375c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 1238e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32); 12395c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 12405c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 12415c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 12425c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 12435c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 12445c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 12455c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 1246e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR); 12475c503bf4SSaleem Abdulrasool default: 1248114ebf4aSMartin Storsjo return "Unknown"; 12495c503bf4SSaleem Abdulrasool } 12505c503bf4SSaleem Abdulrasool break; 12510c72172eSMandeep Singh Grang case COFF::IMAGE_FILE_MACHINE_ARM64: 1252114ebf4aSMartin Storsjo switch (Type) { 12530c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 12540c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 12550c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 12560c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 12570c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 12580c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 12590c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 12600c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 12610c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 12620c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 12630c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 12640c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 12650c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 12660c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 12670c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 12680c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 12690c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 1270e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32); 12710c72172eSMandeep Singh Grang default: 1272114ebf4aSMartin Storsjo return "Unknown"; 12730c72172eSMandeep Singh Grang } 12740c72172eSMandeep Singh Grang break; 1275e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 1276114ebf4aSMartin Storsjo switch (Type) { 1277e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1278e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1279e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1280e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1281e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1282e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1283e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1284e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1285e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1286e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1287e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1288e5fd0047SMichael J. Spencer default: 1289114ebf4aSMartin Storsjo return "Unknown"; 1290e5fd0047SMichael J. Spencer } 1291e5fd0047SMichael J. Spencer break; 1292e5fd0047SMichael J. Spencer default: 1293114ebf4aSMartin Storsjo return "Unknown"; 1294e5fd0047SMichael J. Spencer } 1295e5fd0047SMichael J. Spencer } 1296e5fd0047SMichael J. Spencer 1297e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1298e5fd0047SMichael J. Spencer 1299114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName( 1300114ebf4aSMartin Storsjo DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1301114ebf4aSMartin Storsjo const coff_relocation *Reloc = toRel(Rel); 1302114ebf4aSMartin Storsjo StringRef Res = getRelocationTypeName(Reloc->Type); 1303114ebf4aSMartin Storsjo Result.append(Res.begin(), Res.end()); 1304114ebf4aSMartin Storsjo } 1305114ebf4aSMartin Storsjo 1306c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1307c66d761bSRafael Espindola return !DataDirectory; 1308c66d761bSRafael Espindola } 1309c66d761bSRafael Espindola 1310e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const { 1311e3093808SMartin Storsjo return StringSwitch<StringRef>(Name) 1312e3093808SMartin Storsjo .Case("eh_fram", "eh_frame") 1313e3093808SMartin Storsjo .Default(Name); 1314e3093808SMartin Storsjo } 1315e3093808SMartin Storsjo 1316c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1317c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1318a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1319c2bed429SRui Ueyama } 1320c2bed429SRui Ueyama 13215e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 13225e812afaSRafael Espindola ++Index; 13231c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1324ad7b7e73SDavid Majnemer Index = -1; 1325ad7b7e73SDavid Majnemer ImportTable = nullptr; 1326ad7b7e73SDavid Majnemer } 1327c2bed429SRui Ueyama } 1328c2bed429SRui Ueyama 13291c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry( 13301c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1331ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1332c2bed429SRui Ueyama } 1333c2bed429SRui Ueyama 1334861021f9SRui Ueyama static imported_symbol_iterator 133515d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1336861021f9SRui Ueyama uintptr_t Ptr, int Index) { 133715d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1338861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 133915d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1340861021f9SRui Ueyama } 1341861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 134215d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1343861021f9SRui Ueyama } 1344861021f9SRui Ueyama 134515d99359SRui Ueyama static imported_symbol_iterator 134615d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1347861021f9SRui Ueyama uintptr_t IntPtr = 0; 13481c03389cSReid Kleckner // FIXME: Handle errors. 13491c03389cSReid Kleckner cantFail(Object->getRvaPtr(RVA, IntPtr)); 135015d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1351861021f9SRui Ueyama } 1352861021f9SRui Ueyama 135315d99359SRui Ueyama static imported_symbol_iterator 135415d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1355861021f9SRui Ueyama uintptr_t IntPtr = 0; 13561c03389cSReid Kleckner // FIXME: Handle errors. 13571c03389cSReid Kleckner cantFail(Object->getRvaPtr(RVA, IntPtr)); 1358861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1359861021f9SRui Ueyama int Index = 0; 136015d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1361861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1362861021f9SRui Ueyama while (*Entry++) 1363861021f9SRui Ueyama ++Index; 1364861021f9SRui Ueyama } else { 1365861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1366861021f9SRui Ueyama while (*Entry++) 1367861021f9SRui Ueyama ++Index; 1368861021f9SRui Ueyama } 136915d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 137015d99359SRui Ueyama } 137115d99359SRui Ueyama 137215d99359SRui Ueyama imported_symbol_iterator 137315d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 137460049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 137515d99359SRui Ueyama OwningObject); 137615d99359SRui Ueyama } 137715d99359SRui Ueyama 137815d99359SRui Ueyama imported_symbol_iterator 137915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 138060049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 138115d99359SRui Ueyama OwningObject); 1382861021f9SRui Ueyama } 1383861021f9SRui Ueyama 1384979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1385979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1386979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1387979fb40bSRui Ueyama } 1388979fb40bSRui Ueyama 138960049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 139060049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 139160049526SDavid Majnemer OwningObject); 139260049526SDavid Majnemer } 139360049526SDavid Majnemer 139460049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 139560049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 139660049526SDavid Majnemer OwningObject); 139760049526SDavid Majnemer } 139860049526SDavid Majnemer 139960049526SDavid Majnemer iterator_range<imported_symbol_iterator> 140060049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 140160049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 140260049526SDavid Majnemer } 140360049526SDavid Majnemer 14041c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const { 1405c2bed429SRui Ueyama uintptr_t IntPtr = 0; 14061c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 14071c03389cSReid Kleckner return E; 1408a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14091c03389cSReid Kleckner return Error::success(); 1410c2bed429SRui Ueyama } 1411c2bed429SRui Ueyama 14121c03389cSReid Kleckner Error 14131e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 14141e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 14151c03389cSReid Kleckner return Error::success(); 14161e152d5eSRui Ueyama } 14171e152d5eSRui Ueyama 14181c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA( 14191c03389cSReid Kleckner uint32_t &Result) const { 14201e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 14211c03389cSReid Kleckner return Error::success(); 14221e152d5eSRui Ueyama } 14231e152d5eSRui Ueyama 142415d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 142515d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 142615d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 142715d99359SRui Ueyama } 142815d99359SRui Ueyama 142915d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 143015d99359SRui Ueyama ++Index; 143115d99359SRui Ueyama } 143215d99359SRui Ueyama 143315d99359SRui Ueyama imported_symbol_iterator 143415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 143515d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 143615d99359SRui Ueyama OwningObject); 143715d99359SRui Ueyama } 143815d99359SRui Ueyama 143915d99359SRui Ueyama imported_symbol_iterator 144015d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 144115d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 144215d99359SRui Ueyama OwningObject); 144315d99359SRui Ueyama } 144415d99359SRui Ueyama 1445979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1446979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1447979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1448979fb40bSRui Ueyama } 1449979fb40bSRui Ueyama 14501c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 145115d99359SRui Ueyama uintptr_t IntPtr = 0; 14521c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 14531c03389cSReid Kleckner return E; 145415d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14551c03389cSReid Kleckner return Error::success(); 145615d99359SRui Ueyama } 145715d99359SRui Ueyama 14581c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable( 14591c03389cSReid Kleckner const delay_import_directory_table_entry *&Result) const { 14609f598ac7SJoseph Tremoulet Result = &Table[Index]; 14611c03389cSReid Kleckner return Error::success(); 14621af08658SRui Ueyama } 14631af08658SRui Ueyama 14641c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex, 14651c03389cSReid Kleckner uint64_t &Result) const { 1466ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1467ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1468ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 14691c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(RVA, IntPtr)) 14701c03389cSReid Kleckner return E; 1471ffa4cebeSRui Ueyama if (OwningObject->is64()) 14725dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1473ffa4cebeSRui Ueyama else 14745dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 14751c03389cSReid Kleckner return Error::success(); 1476ffa4cebeSRui Ueyama } 1477ffa4cebeSRui Ueyama 1478ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1479ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1480ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1481ad882ba8SRui Ueyama } 1482ad882ba8SRui Ueyama 14835e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 14845e812afaSRafael Espindola ++Index; 1485ad882ba8SRui Ueyama } 1486ad882ba8SRui Ueyama 1487da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1488da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 14891c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1490da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 14911c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 14921c03389cSReid Kleckner return E; 1493da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14941c03389cSReid Kleckner return Error::success(); 1495da49d0d4SRui Ueyama } 1496da49d0d4SRui Ueyama 1497e5df6095SRui Ueyama // Returns the starting ordinal number. 14981c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1499e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 15001c03389cSReid Kleckner return Error::success(); 1501e5df6095SRui Ueyama } 1502e5df6095SRui Ueyama 1503ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 15041c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1505ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 15061c03389cSReid Kleckner return Error::success(); 1507ad882ba8SRui Ueyama } 1508ad882ba8SRui Ueyama 1509ad882ba8SRui Ueyama // Returns the address of the current export symbol. 15101c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1511ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 15121c03389cSReid Kleckner if (Error EC = 1513db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1514ad882ba8SRui Ueyama return EC; 151524fc2d64SRui Ueyama const export_address_table_entry *entry = 151624fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1517ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 15181c03389cSReid Kleckner return Error::success(); 1519ad882ba8SRui Ueyama } 1520ad882ba8SRui Ueyama 1521ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1522ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 15231c03389cSReid Kleckner Error 1524db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1525ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 15261c03389cSReid Kleckner if (Error EC = 1527db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1528ad882ba8SRui Ueyama return EC; 1529ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1530ad882ba8SRui Ueyama 1531ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1532ad882ba8SRui Ueyama int Offset = 0; 1533ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1534ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1535ad882ba8SRui Ueyama if (*I != Index) 1536ad882ba8SRui Ueyama continue; 15371c03389cSReid Kleckner if (Error EC = 1538db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1539ad882ba8SRui Ueyama return EC; 1540ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 15411c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1542ad882ba8SRui Ueyama return EC; 1543ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15441c03389cSReid Kleckner return Error::success(); 1545ad882ba8SRui Ueyama } 1546ad882ba8SRui Ueyama Result = ""; 15471c03389cSReid Kleckner return Error::success(); 1548ad882ba8SRui Ueyama } 1549ad882ba8SRui Ueyama 15501c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const { 15511c03389cSReid Kleckner const data_directory *DataEntry = 15521c03389cSReid Kleckner OwningObject->getDataDirectory(COFF::EXPORT_TABLE); 15531c03389cSReid Kleckner if (!DataEntry) 15541c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 15556161b38dSRui Ueyama uint32_t RVA; 15566161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15576161b38dSRui Ueyama return EC; 15586161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 15596161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 15606161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 15611c03389cSReid Kleckner return Error::success(); 15626161b38dSRui Ueyama } 15636161b38dSRui Ueyama 15641c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 15656161b38dSRui Ueyama uint32_t RVA; 15666161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15676161b38dSRui Ueyama return EC; 15686161b38dSRui Ueyama uintptr_t IntPtr = 0; 15696161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 15706161b38dSRui Ueyama return EC; 15716161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15721c03389cSReid Kleckner return Error::success(); 15736161b38dSRui Ueyama } 15746161b38dSRui Ueyama 1575861021f9SRui Ueyama bool ImportedSymbolRef:: 1576861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1577861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1578861021f9SRui Ueyama && Index == Other.Index; 1579861021f9SRui Ueyama } 1580861021f9SRui Ueyama 1581861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1582861021f9SRui Ueyama ++Index; 1583861021f9SRui Ueyama } 1584861021f9SRui Ueyama 15851c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1586861021f9SRui Ueyama uint32_t RVA; 1587861021f9SRui Ueyama if (Entry32) { 1588861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1589861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 15901c03389cSReid Kleckner return Error::success(); 1591861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1592861021f9SRui Ueyama } else { 1593861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 15941c03389cSReid Kleckner return Error::success(); 1595861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1596861021f9SRui Ueyama } 1597861021f9SRui Ueyama uintptr_t IntPtr = 0; 15981c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1599861021f9SRui Ueyama return EC; 1600861021f9SRui Ueyama // +2 because the first two bytes is hint. 1601861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 16021c03389cSReid Kleckner return Error::success(); 1603861021f9SRui Ueyama } 1604861021f9SRui Ueyama 16051c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const { 1606ad7b7e73SDavid Majnemer if (Entry32) 1607ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1608ad7b7e73SDavid Majnemer else 1609ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 16101c03389cSReid Kleckner return Error::success(); 1611ad7b7e73SDavid Majnemer } 1612ad7b7e73SDavid Majnemer 16131c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1614ad7b7e73SDavid Majnemer if (Entry32) 1615ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1616ad7b7e73SDavid Majnemer else 1617ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 16181c03389cSReid Kleckner return Error::success(); 1619ad7b7e73SDavid Majnemer } 1620ad7b7e73SDavid Majnemer 16211c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1622861021f9SRui Ueyama uint32_t RVA; 1623861021f9SRui Ueyama if (Entry32) { 1624861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1625861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 16261c03389cSReid Kleckner return Error::success(); 1627861021f9SRui Ueyama } 1628861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1629861021f9SRui Ueyama } else { 1630861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1631861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 16321c03389cSReid Kleckner return Error::success(); 1633861021f9SRui Ueyama } 1634861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1635861021f9SRui Ueyama } 1636861021f9SRui Ueyama uintptr_t IntPtr = 0; 16371c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1638861021f9SRui Ueyama return EC; 1639861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 16401c03389cSReid Kleckner return Error::success(); 1641861021f9SRui Ueyama } 1642861021f9SRui Ueyama 164312db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>> 164448af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 164539772063SReid Kleckner return COFFObjectFile::create(Object); 1646686738e2SRui Ueyama } 164774e85130SRui Ueyama 164874e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 164974e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 165074e85130SRui Ueyama } 165174e85130SRui Ueyama 165274e85130SRui Ueyama void BaseRelocRef::moveNext() { 165374e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 165474e85130SRui Ueyama // size of the header itself. 165574e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1656970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 165774e85130SRui Ueyama if (Size == Header->BlockSize) { 165874e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 165974e85130SRui Ueyama // consists of the header followed by entries. The header contains 166074e85130SRui Ueyama // how many entories will follow. When we reach the end of the 166174e85130SRui Ueyama // current block, proceed to the next block. 166274e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 166374e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 166474e85130SRui Ueyama Index = 0; 166574e85130SRui Ueyama } else { 166674e85130SRui Ueyama ++Index; 166774e85130SRui Ueyama } 166874e85130SRui Ueyama } 166974e85130SRui Ueyama 16701c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const { 167174e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 167274e85130SRui Ueyama Type = Entry[Index].getType(); 16731c03389cSReid Kleckner return Error::success(); 167474e85130SRui Ueyama } 167574e85130SRui Ueyama 16761c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const { 167774e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 167874e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 16791c03389cSReid Kleckner return Error::success(); 168074e85130SRui Ueyama } 1681efef15a0SEric Beckmann 1682357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr) \ 1683357a40ecSMartin Storsjo do { \ 1684357a40ecSMartin Storsjo Error E = (Expr); \ 168587867988SRafael Espindola if (E) \ 1686c55cf4afSBill Wendling return std::move(E); \ 1687357a40ecSMartin Storsjo } while (0) 1688efef15a0SEric Beckmann 168987867988SRafael Espindola Expected<ArrayRef<UTF16>> 169087867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1691efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1692efef15a0SEric Beckmann Reader.setOffset(Offset); 1693efef15a0SEric Beckmann uint16_t Length; 1694efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1695efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1696efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1697cd704cb6SEric Beckmann return RawDirString; 1698efef15a0SEric Beckmann } 1699efef15a0SEric Beckmann 1700f3404674SRafael Espindola Expected<ArrayRef<UTF16>> 1701efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1702f3404674SRafael Espindola return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1703efef15a0SEric Beckmann } 1704efef15a0SEric Beckmann 170587867988SRafael Espindola Expected<const coff_resource_dir_table &> 1706efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1707efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1708efef15a0SEric Beckmann 1709efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1710efef15a0SEric Beckmann Reader.setOffset(Offset); 1711efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1712efef15a0SEric Beckmann assert(Table != nullptr); 1713efef15a0SEric Beckmann return *Table; 1714efef15a0SEric Beckmann } 1715efef15a0SEric Beckmann 1716edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &> 1717edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) { 1718edb6ab9bSMartin Storsjo const coff_resource_dir_entry *Entry = nullptr; 1719edb6ab9bSMartin Storsjo 1720edb6ab9bSMartin Storsjo BinaryStreamReader Reader(BBS); 1721edb6ab9bSMartin Storsjo Reader.setOffset(Offset); 1722edb6ab9bSMartin Storsjo RETURN_IF_ERROR(Reader.readObject(Entry)); 1723edb6ab9bSMartin Storsjo assert(Entry != nullptr); 1724edb6ab9bSMartin Storsjo return *Entry; 1725edb6ab9bSMartin Storsjo } 1726edb6ab9bSMartin Storsjo 17277ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &> 17287ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) { 17297ba81d95SMartin Storsjo const coff_resource_data_entry *Entry = nullptr; 17307ba81d95SMartin Storsjo 17317ba81d95SMartin Storsjo BinaryStreamReader Reader(BBS); 17327ba81d95SMartin Storsjo Reader.setOffset(Offset); 17337ba81d95SMartin Storsjo RETURN_IF_ERROR(Reader.readObject(Entry)); 17347ba81d95SMartin Storsjo assert(Entry != nullptr); 17357ba81d95SMartin Storsjo return *Entry; 17367ba81d95SMartin Storsjo } 17377ba81d95SMartin Storsjo 1738f3404674SRafael Espindola Expected<const coff_resource_dir_table &> 1739efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 17407ba81d95SMartin Storsjo assert(Entry.Offset.isSubDir()); 1741f3404674SRafael Espindola return getTableAtOffset(Entry.Offset.value()); 1742efef15a0SEric Beckmann } 1743efef15a0SEric Beckmann 17447ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &> 17457ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) { 17467ba81d95SMartin Storsjo assert(!Entry.Offset.isSubDir()); 17477ba81d95SMartin Storsjo return getDataEntryAtOffset(Entry.Offset.value()); 17487ba81d95SMartin Storsjo } 17497ba81d95SMartin Storsjo 1750f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1751f3404674SRafael Espindola return getTableAtOffset(0); 1752efef15a0SEric Beckmann } 1753edb6ab9bSMartin Storsjo 1754edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &> 1755edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table, 1756edb6ab9bSMartin Storsjo uint32_t Index) { 1757edb6ab9bSMartin Storsjo if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) 1758edb6ab9bSMartin Storsjo return createStringError(object_error::parse_failed, "index out of range"); 1759edb6ab9bSMartin Storsjo const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table); 1760edb6ab9bSMartin Storsjo ptrdiff_t TableOffset = TablePtr - BBS.data().data(); 1761edb6ab9bSMartin Storsjo return getTableEntryAtOffset(TableOffset + sizeof(Table) + 1762edb6ab9bSMartin Storsjo Index * sizeof(coff_resource_dir_entry)); 1763edb6ab9bSMartin Storsjo } 176494382217SMartin Storsjo 176594382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) { 176694382217SMartin Storsjo for (const SectionRef &S : O->sections()) { 176794382217SMartin Storsjo Expected<StringRef> Name = S.getName(); 176894382217SMartin Storsjo if (!Name) 176994382217SMartin Storsjo return Name.takeError(); 177094382217SMartin Storsjo 177194382217SMartin Storsjo if (*Name == ".rsrc" || *Name == ".rsrc$01") 177294382217SMartin Storsjo return load(O, S); 177394382217SMartin Storsjo } 177494382217SMartin Storsjo return createStringError(object_error::parse_failed, 177594382217SMartin Storsjo "no resource section found"); 177694382217SMartin Storsjo } 177794382217SMartin Storsjo 177894382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) { 177994382217SMartin Storsjo Obj = O; 178094382217SMartin Storsjo Section = S; 178194382217SMartin Storsjo Expected<StringRef> Contents = Section.getContents(); 178294382217SMartin Storsjo if (!Contents) 178394382217SMartin Storsjo return Contents.takeError(); 178494382217SMartin Storsjo BBS = BinaryByteStream(*Contents, support::little); 178594382217SMartin Storsjo const coff_section *COFFSect = Obj->getCOFFSection(Section); 178694382217SMartin Storsjo ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect); 178794382217SMartin Storsjo Relocs.reserve(OrigRelocs.size()); 178894382217SMartin Storsjo for (const coff_relocation &R : OrigRelocs) 178994382217SMartin Storsjo Relocs.push_back(&R); 179094382217SMartin Storsjo std::sort(Relocs.begin(), Relocs.end(), 179194382217SMartin Storsjo [](const coff_relocation *A, const coff_relocation *B) { 179294382217SMartin Storsjo return A->VirtualAddress < B->VirtualAddress; 179394382217SMartin Storsjo }); 179494382217SMartin Storsjo return Error::success(); 179594382217SMartin Storsjo } 179694382217SMartin Storsjo 179794382217SMartin Storsjo Expected<StringRef> 179894382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { 179994382217SMartin Storsjo if (!Obj) 180094382217SMartin Storsjo return createStringError(object_error::parse_failed, "no object provided"); 180194382217SMartin Storsjo 180294382217SMartin Storsjo // Find a potential relocation at the DataRVA field (first member of 180394382217SMartin Storsjo // the coff_resource_data_entry struct). 180494382217SMartin Storsjo const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry); 180594382217SMartin Storsjo ptrdiff_t EntryOffset = EntryPtr - BBS.data().data(); 180694382217SMartin Storsjo coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0), 180794382217SMartin Storsjo ulittle16_t(0)}; 180894382217SMartin Storsjo auto RelocsForOffset = 180994382217SMartin Storsjo std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget, 181094382217SMartin Storsjo [](const coff_relocation *A, const coff_relocation *B) { 181194382217SMartin Storsjo return A->VirtualAddress < B->VirtualAddress; 181294382217SMartin Storsjo }); 181394382217SMartin Storsjo 181494382217SMartin Storsjo if (RelocsForOffset.first != RelocsForOffset.second) { 181594382217SMartin Storsjo // We found a relocation with the right offset. Check that it does have 181694382217SMartin Storsjo // the expected type. 181794382217SMartin Storsjo const coff_relocation &R = **RelocsForOffset.first; 181894382217SMartin Storsjo uint16_t RVAReloc; 181994382217SMartin Storsjo switch (Obj->getMachine()) { 182094382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_I386: 182194382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_I386_DIR32NB; 182294382217SMartin Storsjo break; 182394382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_AMD64: 182494382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB; 182594382217SMartin Storsjo break; 182694382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_ARMNT: 182794382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB; 182894382217SMartin Storsjo break; 182994382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_ARM64: 183094382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB; 183194382217SMartin Storsjo break; 183294382217SMartin Storsjo default: 183394382217SMartin Storsjo return createStringError(object_error::parse_failed, 183494382217SMartin Storsjo "unsupported architecture"); 183594382217SMartin Storsjo } 183694382217SMartin Storsjo if (R.Type != RVAReloc) 183794382217SMartin Storsjo return createStringError(object_error::parse_failed, 183894382217SMartin Storsjo "unexpected relocation type"); 183994382217SMartin Storsjo // Get the relocation's symbol 184094382217SMartin Storsjo Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex); 184194382217SMartin Storsjo if (!Sym) 184294382217SMartin Storsjo return Sym.takeError(); 184394382217SMartin Storsjo // And the symbol's section 184477ecf90cSReid Kleckner Expected<const coff_section *> Section = 184577ecf90cSReid Kleckner Obj->getSection(Sym->getSectionNumber()); 184677ecf90cSReid Kleckner if (!Section) 184777ecf90cSReid Kleckner return Section.takeError(); 184894382217SMartin Storsjo // Add the initial value of DataRVA to the symbol's offset to find the 184994382217SMartin Storsjo // data it points at. 185094382217SMartin Storsjo uint64_t Offset = Entry.DataRVA + Sym->getValue(); 185194382217SMartin Storsjo ArrayRef<uint8_t> Contents; 185277ecf90cSReid Kleckner if (Error E = Obj->getSectionContents(*Section, Contents)) 1853c55cf4afSBill Wendling return std::move(E); 185494382217SMartin Storsjo if (Offset + Entry.DataSize > Contents.size()) 185594382217SMartin Storsjo return createStringError(object_error::parse_failed, 185694382217SMartin Storsjo "data outside of section"); 185794382217SMartin Storsjo // Return a reference to the data inside the section. 185894382217SMartin Storsjo return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset, 185994382217SMartin Storsjo Entry.DataSize); 186094382217SMartin Storsjo } else { 186194382217SMartin Storsjo // Relocatable objects need a relocation for the DataRVA field. 186294382217SMartin Storsjo if (Obj->isRelocatableObject()) 186394382217SMartin Storsjo return createStringError(object_error::parse_failed, 186494382217SMartin Storsjo "no relocation found for DataRVA"); 186594382217SMartin Storsjo 186694382217SMartin Storsjo // Locate the section that contains the address that DataRVA points at. 186794382217SMartin Storsjo uint64_t VA = Entry.DataRVA + Obj->getImageBase(); 186894382217SMartin Storsjo for (const SectionRef &S : Obj->sections()) { 186994382217SMartin Storsjo if (VA >= S.getAddress() && 187094382217SMartin Storsjo VA + Entry.DataSize <= S.getAddress() + S.getSize()) { 187194382217SMartin Storsjo uint64_t Offset = VA - S.getAddress(); 187294382217SMartin Storsjo Expected<StringRef> Contents = S.getContents(); 187394382217SMartin Storsjo if (!Contents) 187494382217SMartin Storsjo return Contents.takeError(); 187594382217SMartin Storsjo return Contents->slice(Offset, Offset + Entry.DataSize); 187694382217SMartin Storsjo } 187794382217SMartin Storsjo } 187894382217SMartin Storsjo return createStringError(object_error::parse_failed, 187994382217SMartin Storsjo "address not found in image"); 188094382217SMartin Storsjo } 188194382217SMartin Storsjo } 1882