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