1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 28e90adafSMichael J. Spencer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68e90adafSMichael J. Spencer // 78e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 88e90adafSMichael J. Spencer // 98e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 108e90adafSMichael J. Spencer // 118e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 128e90adafSMichael J. Spencer 139da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h" 158e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 166a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h" 17264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h" 18d341c932SEugene Zelenko #include "llvm/Object/Binary.h" 19d341c932SEugene Zelenko #include "llvm/Object/COFF.h" 20d341c932SEugene Zelenko #include "llvm/Object/Error.h" 21d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h" 22efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h" 23d341c932SEugene Zelenko #include "llvm/Support/Endian.h" 24d341c932SEugene Zelenko #include "llvm/Support/Error.h" 25d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 26d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h" 27d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h" 28d341c932SEugene Zelenko #include <algorithm> 29d341c932SEugene Zelenko #include <cassert> 30d341c932SEugene Zelenko #include <cstddef> 31d341c932SEugene Zelenko #include <cstdint> 32d341c932SEugene Zelenko #include <cstring> 339d2c15efSNico Rieck #include <limits> 34d341c932SEugene Zelenko #include <memory> 35d341c932SEugene Zelenko #include <system_error> 368e90adafSMichael J. Spencer 378e90adafSMichael J. Spencer using namespace llvm; 388e90adafSMichael J. Spencer using namespace object; 398e90adafSMichael J. Spencer 408e90adafSMichael J. Spencer using support::ulittle16_t; 418e90adafSMichael J. Spencer using support::ulittle32_t; 42861021f9SRui Ueyama using support::ulittle64_t; 438e90adafSMichael J. Spencer using support::little16_t; 448e90adafSMichael J. Spencer 451d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 4648af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 47c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 488ff24d25SRui Ueyama EC = object_error::unexpected_eof; 491d6167fdSMichael J. Spencer return false; 501d6167fdSMichael J. Spencer } 511d6167fdSMichael J. Spencer return true; 528e90adafSMichael J. Spencer } 538e90adafSMichael J. Spencer 54ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 55ed64342bSRui Ueyama // Returns unexpected_eof if error. 56ed64342bSRui Ueyama template <typename T> 5748af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5858323a97SDavid Majnemer const void *Ptr, 59236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 60ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 61cbc7ee45SBenjamin Kramer if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) 62e830c60dSDavid Majnemer return EC; 63ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 647d099195SRui Ueyama return std::error_code(); 651d6167fdSMichael J. Spencer } 661d6167fdSMichael J. Spencer 679d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 689d2c15efSNico Rieck // prefixed slashes. 699d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 709d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 719d2c15efSNico Rieck if (Str.size() > 6) 729d2c15efSNico Rieck return true; 739d2c15efSNico Rieck 749d2c15efSNico Rieck uint64_t Value = 0; 759d2c15efSNico Rieck while (!Str.empty()) { 769d2c15efSNico Rieck unsigned CharVal; 779d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 789d2c15efSNico Rieck CharVal = Str[0] - 'A'; 799d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 809d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 819d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 829d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 839d2c15efSNico Rieck else if (Str[0] == '+') // 62 845500b07cSRui Ueyama CharVal = 62; 859d2c15efSNico Rieck else if (Str[0] == '/') // 63 865500b07cSRui Ueyama CharVal = 63; 879d2c15efSNico Rieck else 889d2c15efSNico Rieck return true; 899d2c15efSNico Rieck 909d2c15efSNico Rieck Value = (Value * 64) + CharVal; 919d2c15efSNico Rieck Str = Str.substr(1); 929d2c15efSNico Rieck } 939d2c15efSNico Rieck 949d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 959d2c15efSNico Rieck return true; 969d2c15efSNico Rieck 979d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 989d2c15efSNico Rieck return false; 999d2c15efSNico Rieck } 1009d2c15efSNico Rieck 10144f51e51SDavid Majnemer template <typename coff_symbol_type> 10244f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10344f51e51SDavid Majnemer const coff_symbol_type *Addr = 10444f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1051d6167fdSMichael J. Spencer 106236b0ca7SDavid Majnemer assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 1071d6167fdSMichael J. Spencer #ifndef NDEBUG 1081d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1098ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 1101d6167fdSMichael J. Spencer 11144f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11244f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1131d6167fdSMichael J. Spencer #endif 1141d6167fdSMichael J. Spencer 1158ff24d25SRui Ueyama return Addr; 1161d6167fdSMichael J. Spencer } 1171d6167fdSMichael J. Spencer 1188ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1198ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1201d6167fdSMichael J. Spencer 1211d6167fdSMichael J. Spencer #ifndef NDEBUG 1221d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12344f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1241d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1251d6167fdSMichael J. Spencer 1268ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1278ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1281d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1291d6167fdSMichael J. Spencer #endif 1301d6167fdSMichael J. Spencer 1318ff24d25SRui Ueyama return Addr; 1321d6167fdSMichael J. Spencer } 1331d6167fdSMichael J. Spencer 1345e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 135236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 13644f51e51SDavid Majnemer if (SymbolTable16) { 13744f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1388ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 139236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14044f51e51SDavid Majnemer } else if (SymbolTable32) { 14144f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14244f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 143236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14444f51e51SDavid Majnemer } else { 14544f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14644f51e51SDavid Majnemer } 1471d6167fdSMichael J. Spencer } 1481d6167fdSMichael J. Spencer 14981e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 15044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1515d0c2ffaSRafael Espindola StringRef Result; 152efef15a0SEric Beckmann if (std::error_code EC = getSymbolName(Symb, Result)) 15381e8b7d9SKevin Enderby return errorCodeToError(EC); 1545d0c2ffaSRafael Espindola return Result; 1558e90adafSMichael J. Spencer } 1568e90adafSMichael J. Spencer 157be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 158be8b0ea8SRafael Espindola return getCOFFSymbol(Ref).getValue(); 159991af666SRafael Espindola } 160991af666SRafael Espindola 1616b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 1626b2bba14SDavide Italiano // MSVC/link.exe seems to align symbols to the next-power-of-2 1636b2bba14SDavide Italiano // up to 32 bytes. 1646b2bba14SDavide Italiano COFFSymbolRef Symb = getCOFFSymbol(Ref); 16503a85680SDavide Italiano return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 1666b2bba14SDavide Italiano } 1676b2bba14SDavide Italiano 168931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 169ed067c45SRafael Espindola uint64_t Result = getSymbolValue(Ref); 17044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 171c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 172991af666SRafael Espindola 173991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 174991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 175ed067c45SRafael Espindola return Result; 17654c9f3daSRafael Espindola 1772617dcceSCraig Topper const coff_section *Section = nullptr; 178c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 179931cb65dSKevin Enderby return errorCodeToError(EC); 180991af666SRafael Espindola Result += Section->VirtualAddress; 18147ea9eceSReid Kleckner 18247ea9eceSReid Kleckner // The section VirtualAddress does not include ImageBase, and we want to 18347ea9eceSReid Kleckner // return virtual addresses. 18421427adaSReid Kleckner Result += getImageBase(); 18547ea9eceSReid Kleckner 186ed067c45SRafael Espindola return Result; 187c7d7c6fbSDavid Majnemer } 188c7d7c6fbSDavid Majnemer 1897bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 19044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 191c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 19244f51e51SDavid Majnemer 193e834f420SPeter Collingbourne if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 194e834f420SPeter Collingbourne return SymbolRef::ST_Function; 1952fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 1962fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 1972fa80cc5SRafael Espindola if (Symb.isCommon()) 1982fa80cc5SRafael Espindola return SymbolRef::ST_Data; 1992fa80cc5SRafael Espindola if (Symb.isFileRecord()) 2002fa80cc5SRafael Espindola return SymbolRef::ST_File; 2012fa80cc5SRafael Espindola 2021a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 2032fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 2042fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 2052fa80cc5SRafael Espindola 2062fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 2072fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2082fa80cc5SRafael Espindola 2092fa80cc5SRafael Espindola return SymbolRef::ST_Other; 21075d1cf33SBenjamin Kramer } 21175d1cf33SBenjamin Kramer 21220122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 21344f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 21420122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 21575d1cf33SBenjamin Kramer 216c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2179dc0eb42SLang Hames Result |= SymbolRef::SF_Global; 2181df4b84dSDavid Meyer 219a6ffc9c8SMartin Storsjo if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) { 2201df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 221a6ffc9c8SMartin Storsjo if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS) 222a6ffc9c8SMartin Storsjo Result |= SymbolRef::SF_Undefined; 2231079ef8dSMartell Malone } 2241df4b84dSDavid Meyer 22544f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2261df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2271df4b84dSDavid Meyer 228c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 229c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 230c7d7c6fbSDavid Majnemer 231c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 232c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 233c7d7c6fbSDavid Majnemer 234c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 235c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 236c7d7c6fbSDavid Majnemer 237a6ffc9c8SMartin Storsjo if (Symb.isUndefined()) 238c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 239c7d7c6fbSDavid Majnemer 24020122a43SRafael Espindola return Result; 24101759754SMichael J. Spencer } 24201759754SMichael J. Spencer 243d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 244c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2455eb02e45SRafael Espindola return Symb.getValue(); 2468e90adafSMichael J. Spencer } 2478e90adafSMichael J. Spencer 2487bd8d994SKevin Enderby Expected<section_iterator> 2498bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 25044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2518bab889bSRafael Espindola if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2528bab889bSRafael Espindola return section_end(); 2532617dcceSCraig Topper const coff_section *Sec = nullptr; 25444f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 2557bd8d994SKevin Enderby return errorCodeToError(EC); 2568bab889bSRafael Espindola DataRefImpl Ret; 2578bab889bSRafael Espindola Ret.p = reinterpret_cast<uintptr_t>(Sec); 2588bab889bSRafael Espindola return section_iterator(SectionRef(Ret, this)); 25932173153SMichael J. Spencer } 26032173153SMichael J. Spencer 2616bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2626bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2636bf32210SRafael Espindola return Symb.getSectionNumber(); 2646bf32210SRafael Espindola } 2656bf32210SRafael Espindola 2665e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2678ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2688ff24d25SRui Ueyama Sec += 1; 2698ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2708e90adafSMichael J. Spencer } 2718e90adafSMichael J. Spencer 272*8be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const { 2738ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 274*8be28cdcSFangrui Song return getSectionName(Sec); 2758e90adafSMichael J. Spencer } 2768e90adafSMichael J. Spencer 27780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2788ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2797c6a071bSDavid Majnemer uint64_t Result = Sec->VirtualAddress; 2807c6a071bSDavid Majnemer 2817c6a071bSDavid Majnemer // The section VirtualAddress does not include ImageBase, and we want to 2827c6a071bSDavid Majnemer // return virtual addresses. 28321427adaSReid Kleckner Result += getImageBase(); 2847c6a071bSDavid Majnemer return Result; 2858e90adafSMichael J. Spencer } 2868e90adafSMichael J. Spencer 287a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 288a25d329bSGeorge Rimar return toSec(Sec) - SectionTable; 289a25d329bSGeorge Rimar } 290a25d329bSGeorge Rimar 29180291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 292a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2938e90adafSMichael J. Spencer } 2948e90adafSMichael J. Spencer 295db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2961d6167fdSMichael J. Spencer StringRef &Result) const { 2978ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2989da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 299db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3009da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3019da9e693SMichael J. Spencer return EC; 3028e90adafSMichael J. Spencer } 3038e90adafSMichael J. Spencer 30480291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3058ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 306511391feSDavid Majnemer return Sec->getAlignment(); 3077989460aSMichael J. Spencer } 3087989460aSMichael J. Spencer 309401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 310401e4e57SGeorge Rimar return false; 311401e4e57SGeorge Rimar } 312401e4e57SGeorge Rimar 31380291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3148ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31580291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3168e90adafSMichael J. Spencer } 3178e90adafSMichael J. Spencer 31880291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3198ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32080291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 321800619f2SMichael J. Spencer } 322800619f2SMichael J. Spencer 32380291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3248ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3251a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3261a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3271a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3281a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 329800619f2SMichael J. Spencer } 330800619f2SMichael J. Spencer 3316bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3326bf32210SRafael Espindola uintptr_t Offset = 3336bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3346bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3356bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3366bf32210SRafael Espindola } 3376bf32210SRafael Espindola 33880291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3398ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3401a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3411a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3421a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3432138ef6dSPreston Gurd } 3442138ef6dSPreston Gurd 345e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 346e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 347e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 348e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 349e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 350e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 351e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 352e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 353e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 354e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 355e830c60dSDavid Majnemer return 0; 35698fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 35798fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 358e830c60dSDavid Majnemer } 359e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 360e830c60dSDavid Majnemer } 361e830c60dSDavid Majnemer 36294751be7SDavid Majnemer static const coff_relocation * 36394751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 36494751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 36594751be7SDavid Majnemer if (!NumRelocs) 36694751be7SDavid Majnemer return nullptr; 367827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 36894751be7SDavid Majnemer Base + Sec->PointerToRelocations); 369827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 370827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 371827c8a2bSRui Ueyama // relocations. 372827c8a2bSRui Ueyama begin++; 373827c8a2bSRui Ueyama } 374cbc7ee45SBenjamin Kramer if (Binary::checkOffset(M, uintptr_t(begin), 375cbc7ee45SBenjamin Kramer sizeof(coff_relocation) * NumRelocs)) 37694751be7SDavid Majnemer return nullptr; 37794751be7SDavid Majnemer return begin; 378827c8a2bSRui Ueyama } 37994751be7SDavid Majnemer 38094751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 38194751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 38294751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 38376d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 38476d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 38594751be7SDavid Majnemer DataRefImpl Ret; 38694751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3878ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 388e5fd0047SMichael J. Spencer } 389e5fd0047SMichael J. Spencer 3908ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3918ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 39294751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 39394751be7SDavid Majnemer if (I) 39494751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 3958ff24d25SRui Ueyama DataRefImpl Ret; 39694751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 3978ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 398e5fd0047SMichael J. Spencer } 399e5fd0047SMichael J. Spencer 400c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 401db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 40244f51e51SDavid Majnemer if (COFFHeader) 403236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 404236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 405236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 40644f51e51SDavid Majnemer return EC; 40744f51e51SDavid Majnemer 40844f51e51SDavid Majnemer if (COFFBigObjHeader) 409236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 410236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 411236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4128ff24d25SRui Ueyama return EC; 413c2bed429SRui Ueyama 414c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 415c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 416c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 417f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 41844f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 419f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 420c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 42148af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4228ff24d25SRui Ueyama return EC; 423c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 424db4ed0bdSRafael Espindola if (std::error_code EC = 42548af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4268ff24d25SRui Ueyama return EC; 427c2bed429SRui Ueyama 428773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 429773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 430773a5795SNico Rieck if (StringTableSize < 4) 431773a5795SNico Rieck StringTableSize = 4; 432773a5795SNico Rieck 433c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 434773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 435c2bed429SRui Ueyama return object_error::parse_failed; 4367d099195SRui Ueyama return std::error_code(); 437c2bed429SRui Ueyama } 438c2bed429SRui Ueyama 43921427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 440e94fef7bSReid Kleckner if (PE32Header) 44121427adaSReid Kleckner return PE32Header->ImageBase; 442e94fef7bSReid Kleckner else if (PE32PlusHeader) 44321427adaSReid Kleckner return PE32PlusHeader->ImageBase; 44421427adaSReid Kleckner // This actually comes up in practice. 44521427adaSReid Kleckner return 0; 446e94fef7bSReid Kleckner } 447e94fef7bSReid Kleckner 448215a586cSRui Ueyama // Returns the file offset for the given VA. 449db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 45021427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 451b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 452b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 453b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 454215a586cSRui Ueyama } 455215a586cSRui Ueyama 456c2bed429SRui Ueyama // Returns the file offset for the given RVA. 457db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 45827dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 45927dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 460c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 461c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 462215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 463215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 464c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4657d099195SRui Ueyama return std::error_code(); 466c2bed429SRui Ueyama } 467c2bed429SRui Ueyama } 468c2bed429SRui Ueyama return object_error::parse_failed; 469c2bed429SRui Ueyama } 470c2bed429SRui Ueyama 4712da433eaSReid Kleckner std::error_code 4722da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4732da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4742da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4752da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4762da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4772da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4782da433eaSReid Kleckner // overflow. 4792da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4802da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4812da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4822da433eaSReid Kleckner uintptr_t Begin = 4832da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4842da433eaSReid Kleckner Contents = 4852da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4862da433eaSReid Kleckner return std::error_code(); 4872da433eaSReid Kleckner } 4882da433eaSReid Kleckner } 4892da433eaSReid Kleckner return object_error::parse_failed; 4902da433eaSReid Kleckner } 4912da433eaSReid Kleckner 492c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 493c2bed429SRui Ueyama // table entry. 494db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 495db4ed0bdSRafael Espindola StringRef &Name) const { 496c2bed429SRui Ueyama uintptr_t IntPtr = 0; 497db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4988ff24d25SRui Ueyama return EC; 499c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 500c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 501c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5027d099195SRui Ueyama return std::error_code(); 503c2bed429SRui Ueyama } 504c2bed429SRui Ueyama 50501528021SSaleem Abdulrasool std::error_code 50601528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 50701528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5082da433eaSReid Kleckner StringRef &PDBFileName) const { 5092da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5102da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 5112da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5122da433eaSReid Kleckner return EC; 51301528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5142da433eaSReid Kleckner return object_error::parse_failed; 51501528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 51601528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5172da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5182da433eaSReid Kleckner InfoBytes.size()); 5192da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5202da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5212da433eaSReid Kleckner return std::error_code(); 5222da433eaSReid Kleckner } 5232da433eaSReid Kleckner 52401528021SSaleem Abdulrasool std::error_code 52501528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 526f27f3f84SReid Kleckner StringRef &PDBFileName) const { 527f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 528f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 529f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 530f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 531f27f3f84SReid Kleckner PDBInfo = nullptr; 532f27f3f84SReid Kleckner PDBFileName = StringRef(); 533f27f3f84SReid Kleckner return std::error_code(); 534f27f3f84SReid Kleckner } 535f27f3f84SReid Kleckner 536c2bed429SRui Ueyama // Find the import table. 537db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 538c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 539c2bed429SRui Ueyama // the import table, do nothing. 540c2bed429SRui Ueyama const data_directory *DataEntry; 541c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5427d099195SRui Ueyama return std::error_code(); 543c2bed429SRui Ueyama 544c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 545c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5467d099195SRui Ueyama return std::error_code(); 547c2bed429SRui Ueyama 548c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 549c2bed429SRui Ueyama 550c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 551c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 552c2bed429SRui Ueyama uintptr_t IntPtr = 0; 553db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5548ff24d25SRui Ueyama return EC; 555ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 556ad7b7e73SDavid Majnemer return EC; 557c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5581c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5597d099195SRui Ueyama return std::error_code(); 560ad882ba8SRui Ueyama } 561c2bed429SRui Ueyama 56215d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 56315d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 56415d99359SRui Ueyama const data_directory *DataEntry; 56515d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5667d099195SRui Ueyama return std::error_code(); 56715d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5687d099195SRui Ueyama return std::error_code(); 56915d99359SRui Ueyama 57015d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 57115d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 57215d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 57315d99359SRui Ueyama 57415d99359SRui Ueyama uintptr_t IntPtr = 0; 57515d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 57615d99359SRui Ueyama return EC; 57715d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 57815d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5797d099195SRui Ueyama return std::error_code(); 58015d99359SRui Ueyama } 58115d99359SRui Ueyama 582ad882ba8SRui Ueyama // Find the export table. 583db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 584ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 585ad882ba8SRui Ueyama // the export table, do nothing. 586ad882ba8SRui Ueyama const data_directory *DataEntry; 587ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5887d099195SRui Ueyama return std::error_code(); 589ad882ba8SRui Ueyama 590ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 591ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5927d099195SRui Ueyama return std::error_code(); 593ad882ba8SRui Ueyama 594ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 595ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 596db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 597ad882ba8SRui Ueyama return EC; 59824fc2d64SRui Ueyama ExportDirectory = 59924fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6007d099195SRui Ueyama return std::error_code(); 601c2bed429SRui Ueyama } 602c2bed429SRui Ueyama 60374e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 60474e85130SRui Ueyama const data_directory *DataEntry; 60574e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 6067d099195SRui Ueyama return std::error_code(); 60774e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6087d099195SRui Ueyama return std::error_code(); 60974e85130SRui Ueyama 61074e85130SRui Ueyama uintptr_t IntPtr = 0; 61174e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 61274e85130SRui Ueyama return EC; 61374e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 61474e85130SRui Ueyama IntPtr); 61574e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 61674e85130SRui Ueyama IntPtr + DataEntry->Size); 617893c6469SNico Weber // FIXME: Verify the section containing BaseRelocHeader has at least 618893c6469SNico Weber // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6197d099195SRui Ueyama return std::error_code(); 62074e85130SRui Ueyama } 62174e85130SRui Ueyama 6222da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6232da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6242da433eaSReid Kleckner const data_directory *DataEntry; 6252da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6262da433eaSReid Kleckner return std::error_code(); 6272da433eaSReid Kleckner 6282da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6292da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6302da433eaSReid Kleckner return std::error_code(); 6312da433eaSReid Kleckner 6322da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6332da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6342da433eaSReid Kleckner return object_error::parse_failed; 6352da433eaSReid Kleckner 6362da433eaSReid Kleckner uintptr_t IntPtr = 0; 6372da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6382da433eaSReid Kleckner return EC; 6392da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 640893c6469SNico Weber DebugDirectoryEnd = reinterpret_cast<const debug_directory *>( 641893c6469SNico Weber IntPtr + DataEntry->Size); 642893c6469SNico Weber // FIXME: Verify the section containing DebugDirectoryBegin has at least 643893c6469SNico Weber // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6442da433eaSReid Kleckner return std::error_code(); 6452da433eaSReid Kleckner } 6462da433eaSReid Kleckner 647b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() { 648b7d716c0SReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 649b7d716c0SReid Kleckner const data_directory *DataEntry; 650b7d716c0SReid Kleckner if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry)) 651b7d716c0SReid Kleckner return std::error_code(); 652b7d716c0SReid Kleckner 653b7d716c0SReid Kleckner // Do nothing if the RVA is NULL. 654b7d716c0SReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 655b7d716c0SReid Kleckner return std::error_code(); 656b7d716c0SReid Kleckner uintptr_t IntPtr = 0; 657b7d716c0SReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 658b7d716c0SReid Kleckner return EC; 659b7d716c0SReid Kleckner 660b7d716c0SReid Kleckner LoadConfig = (const void *)IntPtr; 661b7d716c0SReid Kleckner return std::error_code(); 662b7d716c0SReid Kleckner } 663b7d716c0SReid Kleckner 66448af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 66548af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 66644f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 66744f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 66844f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 669ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 67015d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6712da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6722da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6731d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 67448af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 675c3f9b5a5SRafael Espindola return; 676ee066fc4SEric Christopher 67782ebd8e3SRui Ueyama // The current location in the file where we are looking at. 67882ebd8e3SRui Ueyama uint64_t CurPtr = 0; 67982ebd8e3SRui Ueyama 68082ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 68182ebd8e3SRui Ueyama // it is placed right after COFF header. 6828ff24d25SRui Ueyama bool HasPEHeader = false; 683ee066fc4SEric Christopher 6841d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 68550267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 686ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 687ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 68850267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 68950267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 69050267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 69182ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 69250267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6938ff24d25SRui Ueyama EC = object_error::parse_failed; 6941d6167fdSMichael J. Spencer return; 6951d6167fdSMichael J. Spencer } 69644f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6978ff24d25SRui Ueyama HasPEHeader = true; 698ee066fc4SEric Christopher } 69950267222SDavid Majnemer } 700ee066fc4SEric Christopher 70148af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 7021d6167fdSMichael J. Spencer return; 70344f51e51SDavid Majnemer 70444f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 70544f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 70644f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 70744f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 70844f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 70944f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 71044f51e51SDavid Majnemer return; 71144f51e51SDavid Majnemer 71244f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 71344f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 71444f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 71544f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 71644f51e51SDavid Majnemer COFFHeader = nullptr; 71744f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 71844f51e51SDavid Majnemer } else { 71944f51e51SDavid Majnemer // It's not a bigobj. 72044f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 72144f51e51SDavid Majnemer } 72244f51e51SDavid Majnemer } 72344f51e51SDavid Majnemer if (COFFHeader) { 72444f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 72544f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7267d099195SRui Ueyama EC = std::error_code(); 72782ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 72882ebd8e3SRui Ueyama 72944f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 73044f51e51SDavid Majnemer return; 73144f51e51SDavid Majnemer } 73244f51e51SDavid Majnemer 7338ff24d25SRui Ueyama if (HasPEHeader) { 73410ed9ddcSRui Ueyama const pe32_header *Header; 73548af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 73682ebd8e3SRui Ueyama return; 73710ed9ddcSRui Ueyama 73810ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 73910ed9ddcSRui Ueyama uint64_t DataDirSize; 74050267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 74110ed9ddcSRui Ueyama PE32Header = Header; 74210ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 74310ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 74450267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 74510ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 74610ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 74710ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 74810ed9ddcSRui Ueyama } else { 74910ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 75010ed9ddcSRui Ueyama EC = object_error::parse_failed; 751ed64342bSRui Ueyama return; 752ed64342bSRui Ueyama } 75348af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 75410ed9ddcSRui Ueyama return; 755f53c8cb4SRui Ueyama } 756776c6828SRui Ueyama 7578950a538SRui Ueyama if (COFFHeader) 7588950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7598950a538SRui Ueyama 76048af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 761236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7621d6167fdSMichael J. Spencer return; 7631d6167fdSMichael J. Spencer 764c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 765236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 766ac8cfab5SDavid Majnemer if ((EC = initSymbolTablePtr())) { 767ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 768ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 769ac8cfab5SDavid Majnemer StringTable = nullptr; 770ac8cfab5SDavid Majnemer StringTableSize = 0; 771ac8cfab5SDavid Majnemer } 772236b0ca7SDavid Majnemer } else { 773236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 774236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 775236b0ca7SDavid Majnemer EC = object_error::parse_failed; 776236b0ca7SDavid Majnemer return; 777236b0ca7SDavid Majnemer } 778236b0ca7SDavid Majnemer } 7798e90adafSMichael J. Spencer 780c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7818ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 782ed64342bSRui Ueyama return; 78315d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 78415d99359SRui Ueyama return; 7851d6167fdSMichael J. Spencer 786ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7878ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 788ad882ba8SRui Ueyama return; 789ad882ba8SRui Ueyama 79074e85130SRui Ueyama // Initialize the pointer to the base relocation table. 79174e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 79274e85130SRui Ueyama return; 79374e85130SRui Ueyama 7942da433eaSReid Kleckner // Initialize the pointer to the export table. 7952da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 7962da433eaSReid Kleckner return; 7972da433eaSReid Kleckner 798b7d716c0SReid Kleckner if ((EC = initLoadConfigPtr())) 799b7d716c0SReid Kleckner return; 800b7d716c0SReid Kleckner 8017d099195SRui Ueyama EC = std::error_code(); 8028e90adafSMichael J. Spencer } 8038e90adafSMichael J. Spencer 804435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 8058ff24d25SRui Ueyama DataRefImpl Ret; 80644f51e51SDavid Majnemer Ret.p = getSymbolTable(); 807f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8088e90adafSMichael J. Spencer } 8098e90adafSMichael J. Spencer 810435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 8118e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 8128ff24d25SRui Ueyama DataRefImpl Ret; 8138ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 814f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8158e90adafSMichael J. Spencer } 8168e90adafSMichael J. Spencer 817bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 818ad7b7e73SDavid Majnemer if (!ImportDirectory) 819ad7b7e73SDavid Majnemer return import_directory_end(); 8201c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 821ad7b7e73SDavid Majnemer return import_directory_end(); 822a045b73aSRui Ueyama return import_directory_iterator( 823a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 824c2bed429SRui Ueyama } 825c2bed429SRui Ueyama 826bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 827a045b73aSRui Ueyama return import_directory_iterator( 828ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 829c2bed429SRui Ueyama } 830c429b80dSDavid Meyer 83115d99359SRui Ueyama delay_import_directory_iterator 83215d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 83315d99359SRui Ueyama return delay_import_directory_iterator( 83415d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 83515d99359SRui Ueyama } 83615d99359SRui Ueyama 83715d99359SRui Ueyama delay_import_directory_iterator 83815d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 83915d99359SRui Ueyama return delay_import_directory_iterator( 84015d99359SRui Ueyama DelayImportDirectoryEntryRef( 84115d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 84215d99359SRui Ueyama } 84315d99359SRui Ueyama 844ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 845ad882ba8SRui Ueyama return export_directory_iterator( 846ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 847ad882ba8SRui Ueyama } 848ad882ba8SRui Ueyama 849ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8502617dcceSCraig Topper if (!ExportDirectory) 8512617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8528ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 853ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8548ff24d25SRui Ueyama return export_directory_iterator(Ref); 855ad882ba8SRui Ueyama } 856ad882ba8SRui Ueyama 857b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8588ff24d25SRui Ueyama DataRefImpl Ret; 8598ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8608ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8618e90adafSMichael J. Spencer } 8628e90adafSMichael J. Spencer 863b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8648ff24d25SRui Ueyama DataRefImpl Ret; 86544f51e51SDavid Majnemer int NumSections = 86644f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8678ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8688ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8698e90adafSMichael J. Spencer } 8708e90adafSMichael J. Spencer 87174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 87274e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 87374e85130SRui Ueyama } 87474e85130SRui Ueyama 87574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 87674e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 87774e85130SRui Ueyama } 87874e85130SRui Ueyama 8798e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 88043c85453SMartin Storsjo return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 8818e90adafSMichael J. Spencer } 8828e90adafSMichael J. Spencer 8838e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 88444f51e51SDavid Majnemer switch(getMachine()) { 8858e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8868e90adafSMichael J. Spencer return "COFF-i386"; 8878e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8888e90adafSMichael J. Spencer return "COFF-x86-64"; 8899b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8909b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8911eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8921eff5c9cSMartell Malone return "COFF-ARM64"; 8938e90adafSMichael J. Spencer default: 8948e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8958e90adafSMichael J. Spencer } 8968e90adafSMichael J. Spencer } 8978e90adafSMichael J. Spencer 898260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const { 89944f51e51SDavid Majnemer switch (getMachine()) { 9008e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9018e90adafSMichael J. Spencer return Triple::x86; 9028e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9038e90adafSMichael J. Spencer return Triple::x86_64; 9049b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9059b7c0af2SSaleem Abdulrasool return Triple::thumb; 9061eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9071eff5c9cSMartell Malone return Triple::aarch64; 9088e90adafSMichael J. Spencer default: 9098e90adafSMichael J. Spencer return Triple::UnknownArch; 9108e90adafSMichael J. Spencer } 9118e90adafSMichael J. Spencer } 9128e90adafSMichael J. Spencer 913d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const { 914d2af4d6fSPaul Semel if (PE32Header) 915d2af4d6fSPaul Semel return PE32Header->AddressOfEntryPoint; 916d2af4d6fSPaul Semel return 0; 917d2af4d6fSPaul Semel } 918d2af4d6fSPaul Semel 919979fb40bSRui Ueyama iterator_range<import_directory_iterator> 920979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 921979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 922979fb40bSRui Ueyama } 923979fb40bSRui Ueyama 924979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 925979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 926979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 927979fb40bSRui Ueyama delay_import_directory_end()); 928979fb40bSRui Ueyama } 929979fb40bSRui Ueyama 930979fb40bSRui Ueyama iterator_range<export_directory_iterator> 931979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 932979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 933979fb40bSRui Ueyama } 934979fb40bSRui Ueyama 93574e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 93674e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 93774e85130SRui Ueyama } 93874e85130SRui Ueyama 939e84a0b5aSMartin Storsjo std::error_code 940e84a0b5aSMartin Storsjo COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 941e84a0b5aSMartin Storsjo Res = COFFHeader; 942e84a0b5aSMartin Storsjo return std::error_code(); 943e84a0b5aSMartin Storsjo } 944e84a0b5aSMartin Storsjo 945e84a0b5aSMartin Storsjo std::error_code 946e84a0b5aSMartin Storsjo COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const { 947e84a0b5aSMartin Storsjo Res = COFFBigObjHeader; 948e84a0b5aSMartin Storsjo return std::error_code(); 949e84a0b5aSMartin Storsjo } 950e84a0b5aSMartin Storsjo 951db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 95282ebd8e3SRui Ueyama Res = PE32Header; 9537d099195SRui Ueyama return std::error_code(); 95489a7a5eaSMichael J. Spencer } 95589a7a5eaSMichael J. Spencer 956db4ed0bdSRafael Espindola std::error_code 95710ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 95810ed9ddcSRui Ueyama Res = PE32PlusHeader; 9597d099195SRui Ueyama return std::error_code(); 96010ed9ddcSRui Ueyama } 96110ed9ddcSRui Ueyama 962db4ed0bdSRafael Espindola std::error_code 963db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 964ed64342bSRui Ueyama const data_directory *&Res) const { 965bcadfee2SHiroshi Inoue // Error if there's no data directory or the index is out of range. 966f69b0585SDavid Majnemer if (!DataDirectory) { 967f69b0585SDavid Majnemer Res = nullptr; 96810ed9ddcSRui Ueyama return object_error::parse_failed; 969f69b0585SDavid Majnemer } 97010ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 97110ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 97210ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 973f69b0585SDavid Majnemer if (Index >= NumEnt) { 974f69b0585SDavid Majnemer Res = nullptr; 975ed64342bSRui Ueyama return object_error::parse_failed; 976f69b0585SDavid Majnemer } 9778ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9787d099195SRui Ueyama return std::error_code(); 979ed64342bSRui Ueyama } 980ed64342bSRui Ueyama 981db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9821d6167fdSMichael J. Spencer const coff_section *&Result) const { 9832617dcceSCraig Topper Result = nullptr; 984236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9857d099195SRui Ueyama return std::error_code(); 986236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9871d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9888ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9897d099195SRui Ueyama return std::error_code(); 9908e90adafSMichael J. Spencer } 991236b0ca7SDavid Majnemer return object_error::parse_failed; 992236b0ca7SDavid Majnemer } 9938e90adafSMichael J. Spencer 994b98f5048SPaul Semel std::error_code COFFObjectFile::getSection(StringRef SectionName, 995b98f5048SPaul Semel const coff_section *&Result) const { 996b98f5048SPaul Semel Result = nullptr; 997b98f5048SPaul Semel StringRef SecName; 998b98f5048SPaul Semel for (const SectionRef &Section : sections()) { 999b98f5048SPaul Semel if (std::error_code E = Section.getName(SecName)) 1000b98f5048SPaul Semel return E; 1001b98f5048SPaul Semel if (SecName == SectionName) { 1002b98f5048SPaul Semel Result = getCOFFSection(Section); 1003b98f5048SPaul Semel return std::error_code(); 1004b98f5048SPaul Semel } 1005b98f5048SPaul Semel } 1006b98f5048SPaul Semel return object_error::parse_failed; 1007b98f5048SPaul Semel } 1008b98f5048SPaul Semel 1009db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 10101d6167fdSMichael J. Spencer StringRef &Result) const { 10111d6167fdSMichael J. Spencer if (StringTableSize <= 4) 10121d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 10131d6167fdSMichael J. Spencer return object_error::parse_failed; 10148ff24d25SRui Ueyama if (Offset >= StringTableSize) 10151d6167fdSMichael J. Spencer return object_error::unexpected_eof; 10168ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 10177d099195SRui Ueyama return std::error_code(); 10188e90adafSMichael J. Spencer } 1019022ecdf2SBenjamin Kramer 102044f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 102189a7a5eaSMichael J. Spencer StringRef &Res) const { 1022e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 1023e40d30f3SRui Ueyama } 1024e40d30f3SRui Ueyama 1025e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 1026e40d30f3SRui Ueyama StringRef &Res) const { 102789a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 1028e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 1029e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 10308ff24d25SRui Ueyama return EC; 10317d099195SRui Ueyama return std::error_code(); 103289a7a5eaSMichael J. Spencer } 103389a7a5eaSMichael J. Spencer 1034e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 103589a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 1036e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 103789a7a5eaSMichael J. Spencer else 103889a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 1039e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 10407d099195SRui Ueyama return std::error_code(); 104189a7a5eaSMichael J. Spencer } 104289a7a5eaSMichael J. Spencer 104344f51e51SDavid Majnemer ArrayRef<uint8_t> 104444f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 10452617dcceSCraig Topper const uint8_t *Aux = nullptr; 104671757ef3SMarshall Clow 104744f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 104844f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 104971757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 105044f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 105171757ef3SMarshall Clow #ifndef NDEBUG 10528ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10538ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 105444f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 105544f51e51SDavid Majnemer Offset >= 105644f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 105771757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 105871757ef3SMarshall Clow 105944f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 106044f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 106171757ef3SMarshall Clow #endif 1062bfb85e67SMarshall Clow } 106344f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 106471757ef3SMarshall Clow } 106571757ef3SMarshall Clow 106674e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { 106774e7d260SMartin Storsjo uintptr_t Offset = 106874e7d260SMartin Storsjo reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable(); 106974e7d260SMartin Storsjo assert(Offset % getSymbolTableEntrySize() == 0 && 107074e7d260SMartin Storsjo "Symbol did not point to the beginning of a symbol"); 107174e7d260SMartin Storsjo size_t Index = Offset / getSymbolTableEntrySize(); 107274e7d260SMartin Storsjo assert(Index < getNumberOfSymbols()); 107374e7d260SMartin Storsjo return Index; 107474e7d260SMartin Storsjo } 107574e7d260SMartin Storsjo 1076*8be28cdcSFangrui Song Expected<StringRef> 1077*8be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const { 107853c2d547SMichael J. Spencer StringRef Name; 107944f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 108053c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 108153c2d547SMichael J. Spencer Name = Sec->Name; 108253c2d547SMichael J. Spencer else 108353c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 108444f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 108553c2d547SMichael J. Spencer 108653c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10872314b3deSDavid Majnemer if (Name.startswith("/")) { 108853c2d547SMichael J. Spencer uint32_t Offset; 10892314b3deSDavid Majnemer if (Name.startswith("//")) { 10909d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 1091*8be28cdcSFangrui Song return createStringError(object_error::parse_failed, 1092*8be28cdcSFangrui Song "inalid section name"); 10939d2c15efSNico Rieck } else { 109453c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 1095*8be28cdcSFangrui Song return createStringError(object_error::parse_failed, 1096*8be28cdcSFangrui Song "invalid section name"); 10979d2c15efSNico Rieck } 1098db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 1099*8be28cdcSFangrui Song return errorCodeToError(EC); 110053c2d547SMichael J. Spencer } 110153c2d547SMichael J. Spencer 1102*8be28cdcSFangrui 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 1121db4ed0bdSRafael Espindola std::error_code 1122db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 11239da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1124e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1125e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1126e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1127ee97c5f0SShoaib Meenai return std::error_code(); 11289da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 11299da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 11309da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 11319da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1132a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1133e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 11349da9e693SMichael J. Spencer return object_error::parse_failed; 1135a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 11367d099195SRui Ueyama return std::error_code(); 11379da9e693SMichael J. Spencer } 11389da9e693SMichael J. Spencer 1139022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1140e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1141022ecdf2SBenjamin Kramer } 11428ff24d25SRui Ueyama 11435e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1144e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1145e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1146022ecdf2SBenjamin Kramer } 11478ff24d25SRui Ueyama 114896d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 114958323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 115096d071cdSRafael Espindola return R->VirtualAddress; 1151cbe72fc9SDanil Malyshev } 11528ff24d25SRui Ueyama 1153806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1154022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 11558ff24d25SRui Ueyama DataRefImpl Ref; 1156236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1157236b0ca7SDavid Majnemer return symbol_end(); 115844f51e51SDavid Majnemer if (SymbolTable16) 115944f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 116044f51e51SDavid Majnemer else if (SymbolTable32) 116144f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 116244f51e51SDavid Majnemer else 1163c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11648ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1165022ecdf2SBenjamin Kramer } 11668ff24d25SRui Ueyama 116799c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1168022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 116999c041b7SRafael Espindola return R->Type; 1170022ecdf2SBenjamin Kramer } 1171e5fd0047SMichael J. Spencer 117227dc8394SAlexey Samsonov const coff_section * 117327dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 117427dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 117571757ef3SMarshall Clow } 117671757ef3SMarshall Clow 117744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 117844f51e51SDavid Majnemer if (SymbolTable16) 117944f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 118044f51e51SDavid Majnemer if (SymbolTable32) 118144f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 118244f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 118344f51e51SDavid Majnemer } 118444f51e51SDavid Majnemer 118544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 118644f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 118771757ef3SMarshall Clow } 118871757ef3SMarshall Clow 1189f12b8282SRafael Espindola const coff_relocation * 119027dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 119127dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1192d3e2a76cSMarshall Clow } 1193d3e2a76cSMarshall Clow 11942f6d0061SPeter Collingbourne ArrayRef<coff_relocation> 11956a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11962f6d0061SPeter Collingbourne return {getFirstReloc(Sec, Data, base()), 11972f6d0061SPeter Collingbourne getNumberOfRelocations(Sec, Data, base())}; 11986a75acb1SRui Ueyama } 11996a75acb1SRui Ueyama 120027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 120127dc8394SAlexey Samsonov case COFF::reloc_type: \ 1202114ebf4aSMartin Storsjo return #reloc_type; 1203e5fd0047SMichael J. Spencer 1204114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { 120544f51e51SDavid Majnemer switch (getMachine()) { 1206e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 1207114ebf4aSMartin Storsjo switch (Type) { 1208e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1209e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1210e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1211e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1212e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1213e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1214e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1215e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1216e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1217e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1218e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1219e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1220e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1221e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1222e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1223e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1224e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1225e5fd0047SMichael J. Spencer default: 1226114ebf4aSMartin Storsjo return "Unknown"; 1227e5fd0047SMichael J. Spencer } 1228e5fd0047SMichael J. Spencer break; 12295c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 1230114ebf4aSMartin Storsjo switch (Type) { 12315c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 12325c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 12335c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 12345c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 12355c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 12365c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 12375c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 12385c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 1239e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32); 12405c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 12415c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 12425c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 12435c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 12445c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 12455c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 12465c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 1247e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR); 12485c503bf4SSaleem Abdulrasool default: 1249114ebf4aSMartin Storsjo return "Unknown"; 12505c503bf4SSaleem Abdulrasool } 12515c503bf4SSaleem Abdulrasool break; 12520c72172eSMandeep Singh Grang case COFF::IMAGE_FILE_MACHINE_ARM64: 1253114ebf4aSMartin Storsjo switch (Type) { 12540c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 12550c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 12560c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 12570c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 12580c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 12590c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 12600c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 12610c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 12620c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 12630c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 12640c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 12650c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 12660c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 12670c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 12680c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 12690c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 12700c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 1271e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32); 12720c72172eSMandeep Singh Grang default: 1273114ebf4aSMartin Storsjo return "Unknown"; 12740c72172eSMandeep Singh Grang } 12750c72172eSMandeep Singh Grang break; 1276e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 1277114ebf4aSMartin Storsjo switch (Type) { 1278e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1279e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1280e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1281e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1282e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1283e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1284e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1285e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1286e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1287e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1288e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1289e5fd0047SMichael J. Spencer default: 1290114ebf4aSMartin Storsjo return "Unknown"; 1291e5fd0047SMichael J. Spencer } 1292e5fd0047SMichael J. Spencer break; 1293e5fd0047SMichael J. Spencer default: 1294114ebf4aSMartin Storsjo return "Unknown"; 1295e5fd0047SMichael J. Spencer } 1296e5fd0047SMichael J. Spencer } 1297e5fd0047SMichael J. Spencer 1298e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1299e5fd0047SMichael J. Spencer 1300114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName( 1301114ebf4aSMartin Storsjo DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1302114ebf4aSMartin Storsjo const coff_relocation *Reloc = toRel(Rel); 1303114ebf4aSMartin Storsjo StringRef Res = getRelocationTypeName(Reloc->Type); 1304114ebf4aSMartin Storsjo Result.append(Res.begin(), Res.end()); 1305114ebf4aSMartin Storsjo } 1306114ebf4aSMartin Storsjo 1307c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1308c66d761bSRafael Espindola return !DataDirectory; 1309c66d761bSRafael Espindola } 1310c66d761bSRafael Espindola 1311e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const { 1312e3093808SMartin Storsjo return StringSwitch<StringRef>(Name) 1313e3093808SMartin Storsjo .Case("eh_fram", "eh_frame") 1314e3093808SMartin Storsjo .Default(Name); 1315e3093808SMartin Storsjo } 1316e3093808SMartin Storsjo 1317c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1318c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1319a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1320c2bed429SRui Ueyama } 1321c2bed429SRui Ueyama 13225e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 13235e812afaSRafael Espindola ++Index; 13241c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1325ad7b7e73SDavid Majnemer Index = -1; 1326ad7b7e73SDavid Majnemer ImportTable = nullptr; 1327ad7b7e73SDavid Majnemer } 1328c2bed429SRui Ueyama } 1329c2bed429SRui Ueyama 1330db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 13311c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1332ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1333c2bed429SRui Ueyama } 1334c2bed429SRui Ueyama 1335861021f9SRui Ueyama static imported_symbol_iterator 133615d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1337861021f9SRui Ueyama uintptr_t Ptr, int Index) { 133815d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1339861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 134015d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1341861021f9SRui Ueyama } 1342861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 134315d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1344861021f9SRui Ueyama } 1345861021f9SRui Ueyama 134615d99359SRui Ueyama static imported_symbol_iterator 134715d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1348861021f9SRui Ueyama uintptr_t IntPtr = 0; 134915d99359SRui Ueyama 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; 135615d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1357861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1358861021f9SRui Ueyama int Index = 0; 135915d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1360861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1361861021f9SRui Ueyama while (*Entry++) 1362861021f9SRui Ueyama ++Index; 1363861021f9SRui Ueyama } else { 1364861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1365861021f9SRui Ueyama while (*Entry++) 1366861021f9SRui Ueyama ++Index; 1367861021f9SRui Ueyama } 136815d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 136915d99359SRui Ueyama } 137015d99359SRui Ueyama 137115d99359SRui Ueyama imported_symbol_iterator 137215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 137360049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 137415d99359SRui Ueyama OwningObject); 137515d99359SRui Ueyama } 137615d99359SRui Ueyama 137715d99359SRui Ueyama imported_symbol_iterator 137815d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 137960049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 138015d99359SRui Ueyama OwningObject); 1381861021f9SRui Ueyama } 1382861021f9SRui Ueyama 1383979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1384979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1385979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1386979fb40bSRui Ueyama } 1387979fb40bSRui Ueyama 138860049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 138960049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 139060049526SDavid Majnemer OwningObject); 139160049526SDavid Majnemer } 139260049526SDavid Majnemer 139360049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 139460049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 139560049526SDavid Majnemer OwningObject); 139660049526SDavid Majnemer } 139760049526SDavid Majnemer 139860049526SDavid Majnemer iterator_range<imported_symbol_iterator> 139960049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 140060049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 140160049526SDavid Majnemer } 140260049526SDavid Majnemer 1403db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1404c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1405db4ed0bdSRafael Espindola if (std::error_code EC = 14061e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1407a045b73aSRui Ueyama return EC; 1408a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14097d099195SRui Ueyama return std::error_code(); 1410c2bed429SRui Ueyama } 1411c2bed429SRui Ueyama 14121e152d5eSRui Ueyama std::error_code 14131e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 14141e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 14157d099195SRui Ueyama return std::error_code(); 14161e152d5eSRui Ueyama } 14171e152d5eSRui Ueyama 14181e152d5eSRui Ueyama std::error_code 14191e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 14201e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 14217d099195SRui Ueyama return std::error_code(); 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 145015d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 145115d99359SRui Ueyama uintptr_t IntPtr = 0; 145215d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 145315d99359SRui Ueyama return EC; 145415d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14557d099195SRui Ueyama return std::error_code(); 145615d99359SRui Ueyama } 145715d99359SRui Ueyama 14581af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 14591af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 14609f598ac7SJoseph Tremoulet Result = &Table[Index]; 14617d099195SRui Ueyama return std::error_code(); 14621af08658SRui Ueyama } 14631af08658SRui Ueyama 1464ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1465ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, 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; 1469ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1470ffa4cebeSRui Ueyama return EC; 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); 14757d099195SRui Ueyama return std::error_code(); 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. 1489db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1490da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1491db4ed0bdSRafael Espindola if (std::error_code EC = 1492db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1493da49d0d4SRui Ueyama return EC; 1494da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14957d099195SRui Ueyama return std::error_code(); 1496da49d0d4SRui Ueyama } 1497da49d0d4SRui Ueyama 1498e5df6095SRui Ueyama // Returns the starting ordinal number. 1499db4ed0bdSRafael Espindola std::error_code 1500db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1501e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 15027d099195SRui Ueyama return std::error_code(); 1503e5df6095SRui Ueyama } 1504e5df6095SRui Ueyama 1505ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1506db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1507ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 15087d099195SRui Ueyama return std::error_code(); 1509ad882ba8SRui Ueyama } 1510ad882ba8SRui Ueyama 1511ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1512db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1513ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1514db4ed0bdSRafael Espindola if (std::error_code EC = 1515db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1516ad882ba8SRui Ueyama return EC; 151724fc2d64SRui Ueyama const export_address_table_entry *entry = 151824fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1519ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 15207d099195SRui Ueyama return std::error_code(); 1521ad882ba8SRui Ueyama } 1522ad882ba8SRui Ueyama 1523ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1524ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1525db4ed0bdSRafael Espindola std::error_code 1526db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1527ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1528db4ed0bdSRafael Espindola if (std::error_code EC = 1529db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1530ad882ba8SRui Ueyama return EC; 1531ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1532ad882ba8SRui Ueyama 1533ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1534ad882ba8SRui Ueyama int Offset = 0; 1535ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1536ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1537ad882ba8SRui Ueyama if (*I != Index) 1538ad882ba8SRui Ueyama continue; 1539db4ed0bdSRafael Espindola if (std::error_code EC = 1540db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1541ad882ba8SRui Ueyama return EC; 1542ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1543db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1544ad882ba8SRui Ueyama return EC; 1545ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15467d099195SRui Ueyama return std::error_code(); 1547ad882ba8SRui Ueyama } 1548ad882ba8SRui Ueyama Result = ""; 15497d099195SRui Ueyama return std::error_code(); 1550ad882ba8SRui Ueyama } 1551ad882ba8SRui Ueyama 15526161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 15536161b38dSRui Ueyama const data_directory *DataEntry; 15546161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 15556161b38dSRui Ueyama return EC; 15566161b38dSRui Ueyama uint32_t RVA; 15576161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15586161b38dSRui Ueyama return EC; 15596161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 15606161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 15616161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 15626161b38dSRui Ueyama return std::error_code(); 15636161b38dSRui Ueyama } 15646161b38dSRui Ueyama 15656161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 15666161b38dSRui Ueyama uint32_t RVA; 15676161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15686161b38dSRui Ueyama return EC; 15696161b38dSRui Ueyama uintptr_t IntPtr = 0; 15706161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 15716161b38dSRui Ueyama return EC; 15726161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15736161b38dSRui Ueyama return std::error_code(); 15746161b38dSRui Ueyama } 15756161b38dSRui Ueyama 1576861021f9SRui Ueyama bool ImportedSymbolRef:: 1577861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1578861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1579861021f9SRui Ueyama && Index == Other.Index; 1580861021f9SRui Ueyama } 1581861021f9SRui Ueyama 1582861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1583861021f9SRui Ueyama ++Index; 1584861021f9SRui Ueyama } 1585861021f9SRui Ueyama 1586861021f9SRui Ueyama std::error_code 1587861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1588861021f9SRui Ueyama uint32_t RVA; 1589861021f9SRui Ueyama if (Entry32) { 1590861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1591861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 15927d099195SRui Ueyama return std::error_code(); 1593861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1594861021f9SRui Ueyama } else { 1595861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 15967d099195SRui Ueyama return std::error_code(); 1597861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1598861021f9SRui Ueyama } 1599861021f9SRui Ueyama uintptr_t IntPtr = 0; 1600861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1601861021f9SRui Ueyama return EC; 1602861021f9SRui Ueyama // +2 because the first two bytes is hint. 1603861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 16047d099195SRui Ueyama return std::error_code(); 1605861021f9SRui Ueyama } 1606861021f9SRui Ueyama 1607ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1608ad7b7e73SDavid Majnemer if (Entry32) 1609ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1610ad7b7e73SDavid Majnemer else 1611ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1612ad7b7e73SDavid Majnemer return std::error_code(); 1613ad7b7e73SDavid Majnemer } 1614ad7b7e73SDavid Majnemer 1615ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1616ad7b7e73SDavid Majnemer if (Entry32) 1617ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1618ad7b7e73SDavid Majnemer else 1619ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1620ad7b7e73SDavid Majnemer return std::error_code(); 1621ad7b7e73SDavid Majnemer } 1622ad7b7e73SDavid Majnemer 1623861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1624861021f9SRui Ueyama uint32_t RVA; 1625861021f9SRui Ueyama if (Entry32) { 1626861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1627861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 16287d099195SRui Ueyama return std::error_code(); 1629861021f9SRui Ueyama } 1630861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1631861021f9SRui Ueyama } else { 1632861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1633861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 16347d099195SRui Ueyama return std::error_code(); 1635861021f9SRui Ueyama } 1636861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1637861021f9SRui Ueyama } 1638861021f9SRui Ueyama uintptr_t IntPtr = 0; 1639861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1640861021f9SRui Ueyama return EC; 1641861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 16427d099195SRui Ueyama return std::error_code(); 1643861021f9SRui Ueyama } 1644861021f9SRui Ueyama 164512db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>> 164648af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1647db4ed0bdSRafael Espindola std::error_code EC; 164848af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1649692410efSRafael Espindola if (EC) 165012db383eSRafael Espindola return errorCodeToError(EC); 1651437b0d58SRafael Espindola return std::move(Ret); 1652686738e2SRui Ueyama } 165374e85130SRui Ueyama 165474e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 165574e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 165674e85130SRui Ueyama } 165774e85130SRui Ueyama 165874e85130SRui Ueyama void BaseRelocRef::moveNext() { 165974e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 166074e85130SRui Ueyama // size of the header itself. 166174e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1662970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 166374e85130SRui Ueyama if (Size == Header->BlockSize) { 166474e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 166574e85130SRui Ueyama // consists of the header followed by entries. The header contains 166674e85130SRui Ueyama // how many entories will follow. When we reach the end of the 166774e85130SRui Ueyama // current block, proceed to the next block. 166874e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 166974e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 167074e85130SRui Ueyama Index = 0; 167174e85130SRui Ueyama } else { 167274e85130SRui Ueyama ++Index; 167374e85130SRui Ueyama } 167474e85130SRui Ueyama } 167574e85130SRui Ueyama 167674e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 167774e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 167874e85130SRui Ueyama Type = Entry[Index].getType(); 16797d099195SRui Ueyama return std::error_code(); 168074e85130SRui Ueyama } 168174e85130SRui Ueyama 168274e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 168374e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 168474e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 16857d099195SRui Ueyama return std::error_code(); 168674e85130SRui Ueyama } 1687efef15a0SEric Beckmann 168887867988SRafael Espindola #define RETURN_IF_ERROR(E) \ 168987867988SRafael Espindola if (E) \ 169087867988SRafael Espindola return E; 1691efef15a0SEric Beckmann 169287867988SRafael Espindola Expected<ArrayRef<UTF16>> 169387867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1694efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1695efef15a0SEric Beckmann Reader.setOffset(Offset); 1696efef15a0SEric Beckmann uint16_t Length; 1697efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1698efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1699efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1700cd704cb6SEric Beckmann return RawDirString; 1701efef15a0SEric Beckmann } 1702efef15a0SEric Beckmann 1703f3404674SRafael Espindola Expected<ArrayRef<UTF16>> 1704efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1705f3404674SRafael Espindola return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1706efef15a0SEric Beckmann } 1707efef15a0SEric Beckmann 170887867988SRafael Espindola Expected<const coff_resource_dir_table &> 1709efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1710efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1711efef15a0SEric Beckmann 1712efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1713efef15a0SEric Beckmann Reader.setOffset(Offset); 1714efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1715efef15a0SEric Beckmann assert(Table != nullptr); 1716efef15a0SEric Beckmann return *Table; 1717efef15a0SEric Beckmann } 1718efef15a0SEric Beckmann 1719f3404674SRafael Espindola Expected<const coff_resource_dir_table &> 1720efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 1721f3404674SRafael Espindola return getTableAtOffset(Entry.Offset.value()); 1722efef15a0SEric Beckmann } 1723efef15a0SEric Beckmann 1724f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1725f3404674SRafael Espindola return getTableAtOffset(0); 1726efef15a0SEric Beckmann } 1727