1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 28e90adafSMichael J. Spencer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68e90adafSMichael J. Spencer // 78e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 88e90adafSMichael J. Spencer // 98e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 108e90adafSMichael J. Spencer // 118e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 128e90adafSMichael J. Spencer 139da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h" 150ea52537SSimon Pilgrim #include "llvm/ADT/StringSwitch.h" 168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 176a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h" 18264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h" 19d341c932SEugene Zelenko #include "llvm/Object/Binary.h" 20d341c932SEugene Zelenko #include "llvm/Object/COFF.h" 21d341c932SEugene Zelenko #include "llvm/Object/Error.h" 22d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h" 23efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h" 24d341c932SEugene Zelenko #include "llvm/Support/Endian.h" 25d341c932SEugene Zelenko #include "llvm/Support/Error.h" 26d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 27d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h" 28d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h" 29d341c932SEugene Zelenko #include <algorithm> 30d341c932SEugene Zelenko #include <cassert> 31d341c932SEugene Zelenko #include <cstddef> 32d341c932SEugene Zelenko #include <cstdint> 33d341c932SEugene Zelenko #include <cstring> 349d2c15efSNico Rieck #include <limits> 35d341c932SEugene Zelenko #include <memory> 36d341c932SEugene Zelenko #include <system_error> 378e90adafSMichael J. Spencer 388e90adafSMichael J. Spencer using namespace llvm; 398e90adafSMichael J. Spencer using namespace object; 408e90adafSMichael J. Spencer 418e90adafSMichael J. Spencer using support::ulittle16_t; 428e90adafSMichael J. Spencer using support::ulittle32_t; 43861021f9SRui Ueyama using support::ulittle64_t; 448e90adafSMichael J. Spencer using support::little16_t; 458e90adafSMichael J. Spencer 461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 48c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 498ff24d25SRui Ueyama EC = object_error::unexpected_eof; 501d6167fdSMichael J. Spencer return false; 511d6167fdSMichael J. Spencer } 521d6167fdSMichael J. Spencer return true; 538e90adafSMichael J. Spencer } 548e90adafSMichael J. Spencer 55ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 56ed64342bSRui Ueyama // Returns unexpected_eof if error. 57ed64342bSRui Ueyama template <typename T> 58*1c03389cSReid 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)) 62*1c03389cSReid Kleckner return E; 63ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 64*1c03389cSReid 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; 355*1c03389cSReid Kleckner if (Error E = getObject(FirstReloc, M, 356*1c03389cSReid Kleckner reinterpret_cast<const coff_relocation *>( 357*1c03389cSReid Kleckner base + Sec->PointerToRelocations))) { 358*1c03389cSReid Kleckner consumeError(std::move(E)); 359e830c60dSDavid Majnemer return 0; 360*1c03389cSReid 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. 408*1c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() { 40944f51e51SDavid Majnemer if (COFFHeader) 410*1c03389cSReid Kleckner if (Error E = getObject( 411236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 412236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 413*1c03389cSReid Kleckner return E; 41444f51e51SDavid Majnemer 41544f51e51SDavid Majnemer if (COFFBigObjHeader) 416*1c03389cSReid Kleckner if (Error E = getObject( 417236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 418236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 419*1c03389cSReid 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; 428*1c03389cSReid Kleckner if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr)) 429*1c03389cSReid Kleckner return E; 430c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 431*1c03389cSReid Kleckner if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize)) 432*1c03389cSReid 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) 441*1c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 442*1c03389cSReid 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. 455*1c03389cSReid 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. 463*1c03389cSReid 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; 471*1c03389cSReid Kleckner return Error::success(); 472c2bed429SRui Ueyama } 473c2bed429SRui Ueyama } 474*1c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 475c2bed429SRui Ueyama } 476c2bed429SRui Ueyama 477*1c03389cSReid 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); 491*1c03389cSReid Kleckner return Error::success(); 4922da433eaSReid Kleckner } 4932da433eaSReid Kleckner } 494*1c03389cSReid 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. 499*1c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 500db4ed0bdSRafael Espindola StringRef &Name) const { 501c2bed429SRui Ueyama uintptr_t IntPtr = 0; 502*1c03389cSReid Kleckner if (Error E = getRvaPtr(Rva, IntPtr)) 503*1c03389cSReid 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)); 507*1c03389cSReid Kleckner return Error::success(); 508c2bed429SRui Ueyama } 509c2bed429SRui Ueyama 510*1c03389cSReid 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; 514*1c03389cSReid Kleckner if (Error E = getRvaAndSizeAsBytes( 5152da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 516*1c03389cSReid Kleckner return E; 51701528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 518*1c03389cSReid 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; 525*1c03389cSReid Kleckner return Error::success(); 5262da433eaSReid Kleckner } 5272da433eaSReid Kleckner 528*1c03389cSReid 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(); 536*1c03389cSReid Kleckner return Error::success(); 537f27f3f84SReid Kleckner } 538f27f3f84SReid Kleckner 539c2bed429SRui Ueyama // Find the import table. 540*1c03389cSReid 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. 543*1c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE); 544*1c03389cSReid Kleckner if (!DataEntry) 545*1c03389cSReid Kleckner return Error::success(); 546c2bed429SRui Ueyama 547c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 548c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 549*1c03389cSReid 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; 556*1c03389cSReid Kleckner if (Error E = getRvaPtr(ImportTableRva, IntPtr)) 557*1c03389cSReid Kleckner return E; 558e03a135bSReid Kleckner if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 559*1c03389cSReid Kleckner return E; 560c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5611c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 562*1c03389cSReid Kleckner return Error::success(); 563ad882ba8SRui Ueyama } 564c2bed429SRui Ueyama 56515d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 566*1c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() { 567*1c03389cSReid Kleckner const data_directory *DataEntry = 568*1c03389cSReid Kleckner getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR); 569*1c03389cSReid Kleckner if (!DataEntry) 570*1c03389cSReid Kleckner return Error::success(); 57115d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 572*1c03389cSReid 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; 579*1c03389cSReid Kleckner if (Error E = getRvaPtr(RVA, IntPtr)) 580*1c03389cSReid Kleckner return E; 58115d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 58215d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 583*1c03389cSReid Kleckner return Error::success(); 58415d99359SRui Ueyama } 58515d99359SRui Ueyama 586ad882ba8SRui Ueyama // Find the export table. 587*1c03389cSReid 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. 590*1c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE); 591*1c03389cSReid Kleckner if (!DataEntry) 592*1c03389cSReid Kleckner return Error::success(); 593ad882ba8SRui Ueyama 594ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 595ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 596*1c03389cSReid Kleckner return Error::success(); 597ad882ba8SRui Ueyama 598ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 599ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 600*1c03389cSReid Kleckner if (Error E = getRvaPtr(ExportTableRva, IntPtr)) 601*1c03389cSReid Kleckner return E; 60224fc2d64SRui Ueyama ExportDirectory = 60324fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 604*1c03389cSReid Kleckner return Error::success(); 605c2bed429SRui Ueyama } 606c2bed429SRui Ueyama 607*1c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() { 608*1c03389cSReid Kleckner const data_directory *DataEntry = 609*1c03389cSReid Kleckner getDataDirectory(COFF::BASE_RELOCATION_TABLE); 610*1c03389cSReid Kleckner if (!DataEntry) 611*1c03389cSReid Kleckner return Error::success(); 61274e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 613*1c03389cSReid Kleckner return Error::success(); 61474e85130SRui Ueyama 61574e85130SRui Ueyama uintptr_t IntPtr = 0; 616*1c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 617*1c03389cSReid 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. 624*1c03389cSReid Kleckner return Error::success(); 62574e85130SRui Ueyama } 62674e85130SRui Ueyama 627*1c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() { 6282da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 629*1c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY); 630*1c03389cSReid Kleckner if (!DataEntry) 631*1c03389cSReid Kleckner return Error::success(); 6322da433eaSReid Kleckner 6332da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6342da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 635*1c03389cSReid 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) 639*1c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 6402da433eaSReid Kleckner 6412da433eaSReid Kleckner uintptr_t IntPtr = 0; 642*1c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 643*1c03389cSReid 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. 649*1c03389cSReid Kleckner return Error::success(); 6502da433eaSReid Kleckner } 6512da433eaSReid Kleckner 652*1c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() { 653b7d716c0SReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 654*1c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE); 655*1c03389cSReid Kleckner if (!DataEntry) 656*1c03389cSReid Kleckner return Error::success(); 657b7d716c0SReid Kleckner 658b7d716c0SReid Kleckner // Do nothing if the RVA is NULL. 659b7d716c0SReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 660*1c03389cSReid Kleckner return Error::success(); 661b7d716c0SReid Kleckner uintptr_t IntPtr = 0; 662*1c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 663*1c03389cSReid Kleckner return E; 664b7d716c0SReid Kleckner 665b7d716c0SReid Kleckner LoadConfig = (const void *)IntPtr; 666*1c03389cSReid Kleckner return Error::success(); 667b7d716c0SReid Kleckner } 668b7d716c0SReid Kleckner 66939772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>> 67039772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) { 67139772063SReid Kleckner std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object))); 67239772063SReid Kleckner if (Error E = Obj->initialize()) 67339772063SReid Kleckner return std::move(E); 67439772063SReid Kleckner return std::move(Obj); 67539772063SReid Kleckner } 67639772063SReid Kleckner 67739772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object) 67848af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 67944f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 68044f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 68144f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 68239772063SReid Kleckner ImportDirectory(nullptr), DelayImportDirectory(nullptr), 68339772063SReid Kleckner NumberOfDelayImportDirectory(0), ExportDirectory(nullptr), 68439772063SReid Kleckner BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 68539772063SReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {} 68639772063SReid Kleckner 687101fbc01SNico Weber Error COFFObjectFile::initialize() { 6881d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 68939772063SReid Kleckner std::error_code EC; 69048af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 69139772063SReid Kleckner return errorCodeToError(EC); 692ee066fc4SEric Christopher 69382ebd8e3SRui Ueyama // The current location in the file where we are looking at. 69482ebd8e3SRui Ueyama uint64_t CurPtr = 0; 69582ebd8e3SRui Ueyama 69682ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 69782ebd8e3SRui Ueyama // it is placed right after COFF header. 6988ff24d25SRui Ueyama bool HasPEHeader = false; 699ee066fc4SEric Christopher 7001d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 70150267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 702ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 703ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 70450267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 70550267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 70650267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 70782ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 70850267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 70939772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 7101d6167fdSMichael J. Spencer } 71144f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 7128ff24d25SRui Ueyama HasPEHeader = true; 713ee066fc4SEric Christopher } 71450267222SDavid Majnemer } 715ee066fc4SEric Christopher 716*1c03389cSReid Kleckner if (Error E = getObject(COFFHeader, Data, base() + CurPtr)) 717*1c03389cSReid Kleckner return E; 71844f51e51SDavid Majnemer 71944f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 72044f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 72144f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 72244f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 72344f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 724*1c03389cSReid Kleckner if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr)) 725*1c03389cSReid Kleckner return E; 72644f51e51SDavid Majnemer 72744f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 72844f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 72944f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 73044f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 73144f51e51SDavid Majnemer COFFHeader = nullptr; 73244f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 73344f51e51SDavid Majnemer } else { 73444f51e51SDavid Majnemer // It's not a bigobj. 73544f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 73644f51e51SDavid Majnemer } 73744f51e51SDavid Majnemer } 73844f51e51SDavid Majnemer if (COFFHeader) { 73944f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 74044f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7417d099195SRui Ueyama EC = std::error_code(); 74282ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 74382ebd8e3SRui Ueyama 74444f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 74539772063SReid Kleckner return errorCodeToError(EC); 74644f51e51SDavid Majnemer } 74744f51e51SDavid Majnemer 7488ff24d25SRui Ueyama if (HasPEHeader) { 74910ed9ddcSRui Ueyama const pe32_header *Header; 750*1c03389cSReid Kleckner if (Error E = getObject(Header, Data, base() + CurPtr)) 751*1c03389cSReid Kleckner return E; 75210ed9ddcSRui Ueyama 75310ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 75410ed9ddcSRui Ueyama uint64_t DataDirSize; 75550267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 75610ed9ddcSRui Ueyama PE32Header = Header; 75710ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 75810ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 75950267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 76010ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 76110ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 76210ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 76310ed9ddcSRui Ueyama } else { 76410ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 76539772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 766ed64342bSRui Ueyama } 767*1c03389cSReid Kleckner if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)) 768*1c03389cSReid Kleckner return E; 769f53c8cb4SRui Ueyama } 770776c6828SRui Ueyama 7718950a538SRui Ueyama if (COFFHeader) 7728950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7738950a538SRui Ueyama 774*1c03389cSReid Kleckner assert(COFFHeader || COFFBigObjHeader); 775*1c03389cSReid Kleckner 776*1c03389cSReid Kleckner if (Error E = 777*1c03389cSReid Kleckner getObject(SectionTable, Data, base() + CurPtr, 778*1c03389cSReid Kleckner (uint64_t)getNumberOfSections() * sizeof(coff_section))) 779*1c03389cSReid Kleckner return E; 7801d6167fdSMichael J. Spencer 781c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 782236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 783*1c03389cSReid Kleckner if (Error E = initSymbolTablePtr()) { 784*1c03389cSReid Kleckner // Recover from errors reading the symbol table. 785*1c03389cSReid Kleckner consumeError(std::move(E)); 786ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 787ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 788ac8cfab5SDavid Majnemer StringTable = nullptr; 789ac8cfab5SDavid Majnemer StringTableSize = 0; 790ac8cfab5SDavid Majnemer } 791236b0ca7SDavid Majnemer } else { 792236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 793236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 79439772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 795236b0ca7SDavid Majnemer } 796236b0ca7SDavid Majnemer } 7978e90adafSMichael J. Spencer 798c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 799*1c03389cSReid Kleckner if (Error E = initImportTablePtr()) 800*1c03389cSReid Kleckner return E; 801*1c03389cSReid Kleckner if (Error E = initDelayImportTablePtr()) 802*1c03389cSReid Kleckner return E; 8031d6167fdSMichael J. Spencer 804ad882ba8SRui Ueyama // Initialize the pointer to the export table. 805*1c03389cSReid Kleckner if (Error E = initExportTablePtr()) 806*1c03389cSReid Kleckner return E; 807ad882ba8SRui Ueyama 80874e85130SRui Ueyama // Initialize the pointer to the base relocation table. 809*1c03389cSReid Kleckner if (Error E = initBaseRelocPtr()) 810*1c03389cSReid Kleckner return E; 81174e85130SRui Ueyama 8122da433eaSReid Kleckner // Initialize the pointer to the export table. 813*1c03389cSReid Kleckner if (Error E = initDebugDirectoryPtr()) 814*1c03389cSReid Kleckner return E; 8152da433eaSReid Kleckner 816*1c03389cSReid Kleckner if (Error E = initLoadConfigPtr()) 817*1c03389cSReid Kleckner return E; 818b7d716c0SReid Kleckner 81939772063SReid Kleckner return Error::success(); 8208e90adafSMichael J. Spencer } 8218e90adafSMichael J. Spencer 822435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 8238ff24d25SRui Ueyama DataRefImpl Ret; 82444f51e51SDavid Majnemer Ret.p = getSymbolTable(); 825f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8268e90adafSMichael J. Spencer } 8278e90adafSMichael J. Spencer 828435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 8298e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 8308ff24d25SRui Ueyama DataRefImpl Ret; 8318ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 832f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8338e90adafSMichael J. Spencer } 8348e90adafSMichael J. Spencer 835bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 836ad7b7e73SDavid Majnemer if (!ImportDirectory) 837ad7b7e73SDavid Majnemer return import_directory_end(); 8381c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 839ad7b7e73SDavid Majnemer return import_directory_end(); 840a045b73aSRui Ueyama return import_directory_iterator( 841a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 842c2bed429SRui Ueyama } 843c2bed429SRui Ueyama 844bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 845a045b73aSRui Ueyama return import_directory_iterator( 846ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 847c2bed429SRui Ueyama } 848c429b80dSDavid Meyer 84915d99359SRui Ueyama delay_import_directory_iterator 85015d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 85115d99359SRui Ueyama return delay_import_directory_iterator( 85215d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 85315d99359SRui Ueyama } 85415d99359SRui Ueyama 85515d99359SRui Ueyama delay_import_directory_iterator 85615d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 85715d99359SRui Ueyama return delay_import_directory_iterator( 85815d99359SRui Ueyama DelayImportDirectoryEntryRef( 85915d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 86015d99359SRui Ueyama } 86115d99359SRui Ueyama 862ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 863ad882ba8SRui Ueyama return export_directory_iterator( 864ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 865ad882ba8SRui Ueyama } 866ad882ba8SRui Ueyama 867ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8682617dcceSCraig Topper if (!ExportDirectory) 8692617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8708ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 871ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8728ff24d25SRui Ueyama return export_directory_iterator(Ref); 873ad882ba8SRui Ueyama } 874ad882ba8SRui Ueyama 875b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8768ff24d25SRui Ueyama DataRefImpl Ret; 8778ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8788ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8798e90adafSMichael J. Spencer } 8808e90adafSMichael J. Spencer 881b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8828ff24d25SRui Ueyama DataRefImpl Ret; 88344f51e51SDavid Majnemer int NumSections = 88444f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8858ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8868ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8878e90adafSMichael J. Spencer } 8888e90adafSMichael J. Spencer 88974e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 89074e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 89174e85130SRui Ueyama } 89274e85130SRui Ueyama 89374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 89474e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 89574e85130SRui Ueyama } 89674e85130SRui Ueyama 8978e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 89843c85453SMartin Storsjo return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 8998e90adafSMichael J. Spencer } 9008e90adafSMichael J. Spencer 9018e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 90244f51e51SDavid Majnemer switch(getMachine()) { 9038e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9048e90adafSMichael J. Spencer return "COFF-i386"; 9058e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9068e90adafSMichael J. Spencer return "COFF-x86-64"; 9079b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9089b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 9091eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9101eff5c9cSMartell Malone return "COFF-ARM64"; 9118e90adafSMichael J. Spencer default: 9128e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 9138e90adafSMichael J. Spencer } 9148e90adafSMichael J. Spencer } 9158e90adafSMichael J. Spencer 916260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const { 91744f51e51SDavid Majnemer switch (getMachine()) { 9188e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9198e90adafSMichael J. Spencer return Triple::x86; 9208e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9218e90adafSMichael J. Spencer return Triple::x86_64; 9229b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9239b7c0af2SSaleem Abdulrasool return Triple::thumb; 9241eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9251eff5c9cSMartell Malone return Triple::aarch64; 9268e90adafSMichael J. Spencer default: 9278e90adafSMichael J. Spencer return Triple::UnknownArch; 9288e90adafSMichael J. Spencer } 9298e90adafSMichael J. Spencer } 9308e90adafSMichael J. Spencer 931d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const { 932d2af4d6fSPaul Semel if (PE32Header) 933d2af4d6fSPaul Semel return PE32Header->AddressOfEntryPoint; 934d2af4d6fSPaul Semel return 0; 935d2af4d6fSPaul Semel } 936d2af4d6fSPaul Semel 937979fb40bSRui Ueyama iterator_range<import_directory_iterator> 938979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 939979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 940979fb40bSRui Ueyama } 941979fb40bSRui Ueyama 942979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 943979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 944979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 945979fb40bSRui Ueyama delay_import_directory_end()); 946979fb40bSRui Ueyama } 947979fb40bSRui Ueyama 948979fb40bSRui Ueyama iterator_range<export_directory_iterator> 949979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 950979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 951979fb40bSRui Ueyama } 952979fb40bSRui Ueyama 95374e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 95474e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 95574e85130SRui Ueyama } 95674e85130SRui Ueyama 957*1c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const { 958*1c03389cSReid Kleckner if (!DataDirectory) 959*1c03389cSReid Kleckner return nullptr; 96010ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 96110ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 96210ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 963*1c03389cSReid Kleckner if (Index >= NumEnt) 964*1c03389cSReid Kleckner return nullptr; 965*1c03389cSReid Kleckner return &DataDirectory[Index]; 966ed64342bSRui Ueyama } 967ed64342bSRui Ueyama 96877ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const { 96977ecf90cSReid Kleckner // Perhaps getting the section of a reserved section index should be an error, 97077ecf90cSReid Kleckner // but callers rely on this to return null. 971236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 97277ecf90cSReid Kleckner return (const coff_section *)nullptr; 973236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9741d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 97577ecf90cSReid Kleckner return SectionTable + (Index - 1); 9768e90adafSMichael J. Spencer } 97777ecf90cSReid Kleckner return errorCodeToError(object_error::parse_failed); 978236b0ca7SDavid Majnemer } 9798e90adafSMichael J. Spencer 98077ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const { 9811d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9821d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 98377ecf90cSReid Kleckner return errorCodeToError(object_error::parse_failed); 9848ff24d25SRui Ueyama if (Offset >= StringTableSize) 98577ecf90cSReid Kleckner return errorCodeToError(object_error::unexpected_eof); 98677ecf90cSReid Kleckner return StringRef(StringTable + Offset); 9878e90adafSMichael J. Spencer } 988022ecdf2SBenjamin Kramer 98977ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const { 99077ecf90cSReid Kleckner return getSymbolName(Symbol.getGeneric()); 991e40d30f3SRui Ueyama } 992e40d30f3SRui Ueyama 99377ecf90cSReid Kleckner Expected<StringRef> 99477ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const { 99589a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 99677ecf90cSReid Kleckner if (Symbol->Name.Offset.Zeroes == 0) 99777ecf90cSReid Kleckner return getString(Symbol->Name.Offset.Offset); 99889a7a5eaSMichael J. Spencer 99989a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 100077ecf90cSReid Kleckner if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 100177ecf90cSReid Kleckner return StringRef(Symbol->Name.ShortName); 100277ecf90cSReid Kleckner 100389a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 100477ecf90cSReid Kleckner return StringRef(Symbol->Name.ShortName, COFF::NameSize); 100589a7a5eaSMichael J. Spencer } 100689a7a5eaSMichael J. Spencer 100744f51e51SDavid Majnemer ArrayRef<uint8_t> 100844f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 10092617dcceSCraig Topper const uint8_t *Aux = nullptr; 101071757ef3SMarshall Clow 101144f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 101244f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 101371757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 101444f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 101571757ef3SMarshall Clow #ifndef NDEBUG 10168ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10178ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 101844f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 101944f51e51SDavid Majnemer Offset >= 102044f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 102171757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 102271757ef3SMarshall Clow 102344f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 102444f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 102571757ef3SMarshall Clow #endif 1026bfb85e67SMarshall Clow } 102744f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 102871757ef3SMarshall Clow } 102971757ef3SMarshall Clow 103074e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { 103174e7d260SMartin Storsjo uintptr_t Offset = 103274e7d260SMartin Storsjo reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable(); 103374e7d260SMartin Storsjo assert(Offset % getSymbolTableEntrySize() == 0 && 103474e7d260SMartin Storsjo "Symbol did not point to the beginning of a symbol"); 103574e7d260SMartin Storsjo size_t Index = Offset / getSymbolTableEntrySize(); 103674e7d260SMartin Storsjo assert(Index < getNumberOfSymbols()); 103774e7d260SMartin Storsjo return Index; 103874e7d260SMartin Storsjo } 103974e7d260SMartin Storsjo 10408be28cdcSFangrui Song Expected<StringRef> 10418be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const { 104253c2d547SMichael J. Spencer StringRef Name; 104344f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 104453c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 104553c2d547SMichael J. Spencer Name = Sec->Name; 104653c2d547SMichael J. Spencer else 104753c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 104844f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 104953c2d547SMichael J. Spencer 105053c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10512314b3deSDavid Majnemer if (Name.startswith("/")) { 105253c2d547SMichael J. Spencer uint32_t Offset; 10532314b3deSDavid Majnemer if (Name.startswith("//")) { 10549d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10558be28cdcSFangrui Song return createStringError(object_error::parse_failed, 1056400b6c08Sserge-sans-paille "invalid section name"); 10579d2c15efSNico Rieck } else { 105853c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 10598be28cdcSFangrui Song return createStringError(object_error::parse_failed, 10608be28cdcSFangrui Song "invalid section name"); 10619d2c15efSNico Rieck } 106277ecf90cSReid Kleckner return getString(Offset); 106353c2d547SMichael J. Spencer } 106453c2d547SMichael J. Spencer 10658be28cdcSFangrui Song return Name; 106653c2d547SMichael J. Spencer } 106753c2d547SMichael J. Spencer 1068a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1069a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1070a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1071a9ee5c06SDavid Majnemer // 1072a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1073d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1074a9ee5c06SDavid Majnemer // 1075a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1076a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1077a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1078a9ee5c06SDavid Majnemer // considered to be zero. 1079d5297ee7SRui Ueyama if (getDOSHeader()) 1080d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1081d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1082a9ee5c06SDavid Majnemer } 1083a9ee5c06SDavid Majnemer 1084e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec, 10859da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1086e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1087e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1088e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1089e1cb2c0fSFangrui Song return Error::success(); 10909da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10919da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10929da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10939da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1094a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1095e03a135bSReid Kleckner if (Error E = checkOffset(Data, ConStart, SectionSize)) 1096e03a135bSReid Kleckner return E; 1097a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 1098e1cb2c0fSFangrui Song return Error::success(); 10999da9e693SMichael J. Spencer } 11009da9e693SMichael J. Spencer 1101022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1102e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1103022ecdf2SBenjamin Kramer } 11048ff24d25SRui Ueyama 11055e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1106e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1107e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1108022ecdf2SBenjamin Kramer } 11098ff24d25SRui Ueyama 111096d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 111158323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 111296d071cdSRafael Espindola return R->VirtualAddress; 1113cbe72fc9SDanil Malyshev } 11148ff24d25SRui Ueyama 1115806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1116022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 11178ff24d25SRui Ueyama DataRefImpl Ref; 1118236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1119236b0ca7SDavid Majnemer return symbol_end(); 112044f51e51SDavid Majnemer if (SymbolTable16) 112144f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 112244f51e51SDavid Majnemer else if (SymbolTable32) 112344f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 112444f51e51SDavid Majnemer else 1125c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11268ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1127022ecdf2SBenjamin Kramer } 11288ff24d25SRui Ueyama 112999c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1130022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 113199c041b7SRafael Espindola return R->Type; 1132022ecdf2SBenjamin Kramer } 1133e5fd0047SMichael J. Spencer 113427dc8394SAlexey Samsonov const coff_section * 113527dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 113627dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 113771757ef3SMarshall Clow } 113871757ef3SMarshall Clow 113944f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 114044f51e51SDavid Majnemer if (SymbolTable16) 114144f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 114244f51e51SDavid Majnemer if (SymbolTable32) 114344f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 114444f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 114544f51e51SDavid Majnemer } 114644f51e51SDavid Majnemer 114744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 114844f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 114971757ef3SMarshall Clow } 115071757ef3SMarshall Clow 1151f12b8282SRafael Espindola const coff_relocation * 115227dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 115327dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1154d3e2a76cSMarshall Clow } 1155d3e2a76cSMarshall Clow 11562f6d0061SPeter Collingbourne ArrayRef<coff_relocation> 11576a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11582f6d0061SPeter Collingbourne return {getFirstReloc(Sec, Data, base()), 11592f6d0061SPeter Collingbourne getNumberOfRelocations(Sec, Data, base())}; 11606a75acb1SRui Ueyama } 11616a75acb1SRui Ueyama 116227dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 116327dc8394SAlexey Samsonov case COFF::reloc_type: \ 1164114ebf4aSMartin Storsjo return #reloc_type; 1165e5fd0047SMichael J. Spencer 1166114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { 116744f51e51SDavid Majnemer switch (getMachine()) { 1168e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 1169114ebf4aSMartin Storsjo switch (Type) { 1170e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1171e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1172e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1173e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1174e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1175e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1176e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1177e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1178e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1179e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1180e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1181e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1182e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1183e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1184e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1185e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1186e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1187e5fd0047SMichael J. Spencer default: 1188114ebf4aSMartin Storsjo return "Unknown"; 1189e5fd0047SMichael J. Spencer } 1190e5fd0047SMichael J. Spencer break; 11915c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 1192114ebf4aSMartin Storsjo switch (Type) { 11935c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11945c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11955c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11965c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11975c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11985c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 11995c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 12005c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 1201e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32); 12025c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 12035c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 12045c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 12055c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 12065c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 12075c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 12085c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 1209e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR); 12105c503bf4SSaleem Abdulrasool default: 1211114ebf4aSMartin Storsjo return "Unknown"; 12125c503bf4SSaleem Abdulrasool } 12135c503bf4SSaleem Abdulrasool break; 12140c72172eSMandeep Singh Grang case COFF::IMAGE_FILE_MACHINE_ARM64: 1215114ebf4aSMartin Storsjo switch (Type) { 12160c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 12170c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 12180c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 12190c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 12200c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 12210c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 12220c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 12230c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 12240c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 12250c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 12260c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 12270c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 12280c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 12290c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 12300c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 12310c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 12320c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 1233e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32); 12340c72172eSMandeep Singh Grang default: 1235114ebf4aSMartin Storsjo return "Unknown"; 12360c72172eSMandeep Singh Grang } 12370c72172eSMandeep Singh Grang break; 1238e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 1239114ebf4aSMartin Storsjo switch (Type) { 1240e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1241e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1242e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1243e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1244e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1245e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1246e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1247e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1248e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1249e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1250e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1251e5fd0047SMichael J. Spencer default: 1252114ebf4aSMartin Storsjo return "Unknown"; 1253e5fd0047SMichael J. Spencer } 1254e5fd0047SMichael J. Spencer break; 1255e5fd0047SMichael J. Spencer default: 1256114ebf4aSMartin Storsjo return "Unknown"; 1257e5fd0047SMichael J. Spencer } 1258e5fd0047SMichael J. Spencer } 1259e5fd0047SMichael J. Spencer 1260e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1261e5fd0047SMichael J. Spencer 1262114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName( 1263114ebf4aSMartin Storsjo DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1264114ebf4aSMartin Storsjo const coff_relocation *Reloc = toRel(Rel); 1265114ebf4aSMartin Storsjo StringRef Res = getRelocationTypeName(Reloc->Type); 1266114ebf4aSMartin Storsjo Result.append(Res.begin(), Res.end()); 1267114ebf4aSMartin Storsjo } 1268114ebf4aSMartin Storsjo 1269c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1270c66d761bSRafael Espindola return !DataDirectory; 1271c66d761bSRafael Espindola } 1272c66d761bSRafael Espindola 1273e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const { 1274e3093808SMartin Storsjo return StringSwitch<StringRef>(Name) 1275e3093808SMartin Storsjo .Case("eh_fram", "eh_frame") 1276e3093808SMartin Storsjo .Default(Name); 1277e3093808SMartin Storsjo } 1278e3093808SMartin Storsjo 1279c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1280c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1281a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1282c2bed429SRui Ueyama } 1283c2bed429SRui Ueyama 12845e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12855e812afaSRafael Espindola ++Index; 12861c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1287ad7b7e73SDavid Majnemer Index = -1; 1288ad7b7e73SDavid Majnemer ImportTable = nullptr; 1289ad7b7e73SDavid Majnemer } 1290c2bed429SRui Ueyama } 1291c2bed429SRui Ueyama 1292*1c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry( 12931c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1294ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1295c2bed429SRui Ueyama } 1296c2bed429SRui Ueyama 1297861021f9SRui Ueyama static imported_symbol_iterator 129815d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1299861021f9SRui Ueyama uintptr_t Ptr, int Index) { 130015d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1301861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 130215d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1303861021f9SRui Ueyama } 1304861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 130515d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1306861021f9SRui Ueyama } 1307861021f9SRui Ueyama 130815d99359SRui Ueyama static imported_symbol_iterator 130915d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1310861021f9SRui Ueyama uintptr_t IntPtr = 0; 1311*1c03389cSReid Kleckner // FIXME: Handle errors. 1312*1c03389cSReid Kleckner cantFail(Object->getRvaPtr(RVA, IntPtr)); 131315d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1314861021f9SRui Ueyama } 1315861021f9SRui Ueyama 131615d99359SRui Ueyama static imported_symbol_iterator 131715d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1318861021f9SRui Ueyama uintptr_t IntPtr = 0; 1319*1c03389cSReid Kleckner // FIXME: Handle errors. 1320*1c03389cSReid Kleckner cantFail(Object->getRvaPtr(RVA, IntPtr)); 1321861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1322861021f9SRui Ueyama int Index = 0; 132315d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1324861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1325861021f9SRui Ueyama while (*Entry++) 1326861021f9SRui Ueyama ++Index; 1327861021f9SRui Ueyama } else { 1328861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1329861021f9SRui Ueyama while (*Entry++) 1330861021f9SRui Ueyama ++Index; 1331861021f9SRui Ueyama } 133215d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 133315d99359SRui Ueyama } 133415d99359SRui Ueyama 133515d99359SRui Ueyama imported_symbol_iterator 133615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 133760049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 133815d99359SRui Ueyama OwningObject); 133915d99359SRui Ueyama } 134015d99359SRui Ueyama 134115d99359SRui Ueyama imported_symbol_iterator 134215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 134360049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 134415d99359SRui Ueyama OwningObject); 1345861021f9SRui Ueyama } 1346861021f9SRui Ueyama 1347979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1348979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1349979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1350979fb40bSRui Ueyama } 1351979fb40bSRui Ueyama 135260049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 135360049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 135460049526SDavid Majnemer OwningObject); 135560049526SDavid Majnemer } 135660049526SDavid Majnemer 135760049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 135860049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 135960049526SDavid Majnemer OwningObject); 136060049526SDavid Majnemer } 136160049526SDavid Majnemer 136260049526SDavid Majnemer iterator_range<imported_symbol_iterator> 136360049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 136460049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 136560049526SDavid Majnemer } 136660049526SDavid Majnemer 1367*1c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const { 1368c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1369*1c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1370*1c03389cSReid Kleckner return E; 1371a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1372*1c03389cSReid Kleckner return Error::success(); 1373c2bed429SRui Ueyama } 1374c2bed429SRui Ueyama 1375*1c03389cSReid Kleckner Error 13761e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 13771e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 1378*1c03389cSReid Kleckner return Error::success(); 13791e152d5eSRui Ueyama } 13801e152d5eSRui Ueyama 1381*1c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA( 1382*1c03389cSReid Kleckner uint32_t &Result) const { 13831e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 1384*1c03389cSReid Kleckner return Error::success(); 13851e152d5eSRui Ueyama } 13861e152d5eSRui Ueyama 138715d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 138815d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 138915d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 139015d99359SRui Ueyama } 139115d99359SRui Ueyama 139215d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 139315d99359SRui Ueyama ++Index; 139415d99359SRui Ueyama } 139515d99359SRui Ueyama 139615d99359SRui Ueyama imported_symbol_iterator 139715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 139815d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 139915d99359SRui Ueyama OwningObject); 140015d99359SRui Ueyama } 140115d99359SRui Ueyama 140215d99359SRui Ueyama imported_symbol_iterator 140315d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 140415d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 140515d99359SRui Ueyama OwningObject); 140615d99359SRui Ueyama } 140715d99359SRui Ueyama 1408979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1409979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1410979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1411979fb40bSRui Ueyama } 1412979fb40bSRui Ueyama 1413*1c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 141415d99359SRui Ueyama uintptr_t IntPtr = 0; 1415*1c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 1416*1c03389cSReid Kleckner return E; 141715d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1418*1c03389cSReid Kleckner return Error::success(); 141915d99359SRui Ueyama } 142015d99359SRui Ueyama 1421*1c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable( 1422*1c03389cSReid Kleckner const delay_import_directory_table_entry *&Result) const { 14239f598ac7SJoseph Tremoulet Result = &Table[Index]; 1424*1c03389cSReid Kleckner return Error::success(); 14251af08658SRui Ueyama } 14261af08658SRui Ueyama 1427*1c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex, 1428*1c03389cSReid Kleckner uint64_t &Result) const { 1429ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1430ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1431ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1432*1c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(RVA, IntPtr)) 1433*1c03389cSReid Kleckner return E; 1434ffa4cebeSRui Ueyama if (OwningObject->is64()) 14355dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1436ffa4cebeSRui Ueyama else 14375dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 1438*1c03389cSReid Kleckner return Error::success(); 1439ffa4cebeSRui Ueyama } 1440ffa4cebeSRui Ueyama 1441ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1442ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1443ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1444ad882ba8SRui Ueyama } 1445ad882ba8SRui Ueyama 14465e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 14475e812afaSRafael Espindola ++Index; 1448ad882ba8SRui Ueyama } 1449ad882ba8SRui Ueyama 1450da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1451da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1452*1c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1453da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1454*1c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1455*1c03389cSReid Kleckner return E; 1456da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1457*1c03389cSReid Kleckner return Error::success(); 1458da49d0d4SRui Ueyama } 1459da49d0d4SRui Ueyama 1460e5df6095SRui Ueyama // Returns the starting ordinal number. 1461*1c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1462e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 1463*1c03389cSReid Kleckner return Error::success(); 1464e5df6095SRui Ueyama } 1465e5df6095SRui Ueyama 1466ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1467*1c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1468ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 1469*1c03389cSReid Kleckner return Error::success(); 1470ad882ba8SRui Ueyama } 1471ad882ba8SRui Ueyama 1472ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1473*1c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1474ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1475*1c03389cSReid Kleckner if (Error EC = 1476db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1477ad882ba8SRui Ueyama return EC; 147824fc2d64SRui Ueyama const export_address_table_entry *entry = 147924fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1480ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 1481*1c03389cSReid Kleckner return Error::success(); 1482ad882ba8SRui Ueyama } 1483ad882ba8SRui Ueyama 1484ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1485ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1486*1c03389cSReid Kleckner Error 1487db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1488ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1489*1c03389cSReid Kleckner if (Error EC = 1490db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1491ad882ba8SRui Ueyama return EC; 1492ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1493ad882ba8SRui Ueyama 1494ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1495ad882ba8SRui Ueyama int Offset = 0; 1496ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1497ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1498ad882ba8SRui Ueyama if (*I != Index) 1499ad882ba8SRui Ueyama continue; 1500*1c03389cSReid Kleckner if (Error EC = 1501db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1502ad882ba8SRui Ueyama return EC; 1503ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1504*1c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1505ad882ba8SRui Ueyama return EC; 1506ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1507*1c03389cSReid Kleckner return Error::success(); 1508ad882ba8SRui Ueyama } 1509ad882ba8SRui Ueyama Result = ""; 1510*1c03389cSReid Kleckner return Error::success(); 1511ad882ba8SRui Ueyama } 1512ad882ba8SRui Ueyama 1513*1c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const { 1514*1c03389cSReid Kleckner const data_directory *DataEntry = 1515*1c03389cSReid Kleckner OwningObject->getDataDirectory(COFF::EXPORT_TABLE); 1516*1c03389cSReid Kleckner if (!DataEntry) 1517*1c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 15186161b38dSRui Ueyama uint32_t RVA; 15196161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15206161b38dSRui Ueyama return EC; 15216161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 15226161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 15236161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 1524*1c03389cSReid Kleckner return Error::success(); 15256161b38dSRui Ueyama } 15266161b38dSRui Ueyama 1527*1c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 15286161b38dSRui Ueyama uint32_t RVA; 15296161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15306161b38dSRui Ueyama return EC; 15316161b38dSRui Ueyama uintptr_t IntPtr = 0; 15326161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 15336161b38dSRui Ueyama return EC; 15346161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1535*1c03389cSReid Kleckner return Error::success(); 15366161b38dSRui Ueyama } 15376161b38dSRui Ueyama 1538861021f9SRui Ueyama bool ImportedSymbolRef:: 1539861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1540861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1541861021f9SRui Ueyama && Index == Other.Index; 1542861021f9SRui Ueyama } 1543861021f9SRui Ueyama 1544861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1545861021f9SRui Ueyama ++Index; 1546861021f9SRui Ueyama } 1547861021f9SRui Ueyama 1548*1c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1549861021f9SRui Ueyama uint32_t RVA; 1550861021f9SRui Ueyama if (Entry32) { 1551861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1552861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 1553*1c03389cSReid Kleckner return Error::success(); 1554861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1555861021f9SRui Ueyama } else { 1556861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 1557*1c03389cSReid Kleckner return Error::success(); 1558861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1559861021f9SRui Ueyama } 1560861021f9SRui Ueyama uintptr_t IntPtr = 0; 1561*1c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1562861021f9SRui Ueyama return EC; 1563861021f9SRui Ueyama // +2 because the first two bytes is hint. 1564861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 1565*1c03389cSReid Kleckner return Error::success(); 1566861021f9SRui Ueyama } 1567861021f9SRui Ueyama 1568*1c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const { 1569ad7b7e73SDavid Majnemer if (Entry32) 1570ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1571ad7b7e73SDavid Majnemer else 1572ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1573*1c03389cSReid Kleckner return Error::success(); 1574ad7b7e73SDavid Majnemer } 1575ad7b7e73SDavid Majnemer 1576*1c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1577ad7b7e73SDavid Majnemer if (Entry32) 1578ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1579ad7b7e73SDavid Majnemer else 1580ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1581*1c03389cSReid Kleckner return Error::success(); 1582ad7b7e73SDavid Majnemer } 1583ad7b7e73SDavid Majnemer 1584*1c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1585861021f9SRui Ueyama uint32_t RVA; 1586861021f9SRui Ueyama if (Entry32) { 1587861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1588861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 1589*1c03389cSReid Kleckner return Error::success(); 1590861021f9SRui Ueyama } 1591861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1592861021f9SRui Ueyama } else { 1593861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1594861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 1595*1c03389cSReid Kleckner return Error::success(); 1596861021f9SRui Ueyama } 1597861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1598861021f9SRui Ueyama } 1599861021f9SRui Ueyama uintptr_t IntPtr = 0; 1600*1c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1601861021f9SRui Ueyama return EC; 1602861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 1603*1c03389cSReid Kleckner return Error::success(); 1604861021f9SRui Ueyama } 1605861021f9SRui Ueyama 160612db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>> 160748af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 160839772063SReid Kleckner return COFFObjectFile::create(Object); 1609686738e2SRui Ueyama } 161074e85130SRui Ueyama 161174e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 161274e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 161374e85130SRui Ueyama } 161474e85130SRui Ueyama 161574e85130SRui Ueyama void BaseRelocRef::moveNext() { 161674e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 161774e85130SRui Ueyama // size of the header itself. 161874e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1619970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 162074e85130SRui Ueyama if (Size == Header->BlockSize) { 162174e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 162274e85130SRui Ueyama // consists of the header followed by entries. The header contains 162374e85130SRui Ueyama // how many entories will follow. When we reach the end of the 162474e85130SRui Ueyama // current block, proceed to the next block. 162574e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 162674e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 162774e85130SRui Ueyama Index = 0; 162874e85130SRui Ueyama } else { 162974e85130SRui Ueyama ++Index; 163074e85130SRui Ueyama } 163174e85130SRui Ueyama } 163274e85130SRui Ueyama 1633*1c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const { 163474e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 163574e85130SRui Ueyama Type = Entry[Index].getType(); 1636*1c03389cSReid Kleckner return Error::success(); 163774e85130SRui Ueyama } 163874e85130SRui Ueyama 1639*1c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const { 164074e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 164174e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 1642*1c03389cSReid Kleckner return Error::success(); 164374e85130SRui Ueyama } 1644efef15a0SEric Beckmann 1645357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr) \ 1646357a40ecSMartin Storsjo do { \ 1647357a40ecSMartin Storsjo Error E = (Expr); \ 164887867988SRafael Espindola if (E) \ 1649c55cf4afSBill Wendling return std::move(E); \ 1650357a40ecSMartin Storsjo } while (0) 1651efef15a0SEric Beckmann 165287867988SRafael Espindola Expected<ArrayRef<UTF16>> 165387867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1654efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1655efef15a0SEric Beckmann Reader.setOffset(Offset); 1656efef15a0SEric Beckmann uint16_t Length; 1657efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1658efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1659efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1660cd704cb6SEric Beckmann return RawDirString; 1661efef15a0SEric Beckmann } 1662efef15a0SEric Beckmann 1663f3404674SRafael Espindola Expected<ArrayRef<UTF16>> 1664efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1665f3404674SRafael Espindola return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1666efef15a0SEric Beckmann } 1667efef15a0SEric Beckmann 166887867988SRafael Espindola Expected<const coff_resource_dir_table &> 1669efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1670efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1671efef15a0SEric Beckmann 1672efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1673efef15a0SEric Beckmann Reader.setOffset(Offset); 1674efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1675efef15a0SEric Beckmann assert(Table != nullptr); 1676efef15a0SEric Beckmann return *Table; 1677efef15a0SEric Beckmann } 1678efef15a0SEric Beckmann 1679edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &> 1680edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) { 1681edb6ab9bSMartin Storsjo const coff_resource_dir_entry *Entry = nullptr; 1682edb6ab9bSMartin Storsjo 1683edb6ab9bSMartin Storsjo BinaryStreamReader Reader(BBS); 1684edb6ab9bSMartin Storsjo Reader.setOffset(Offset); 1685edb6ab9bSMartin Storsjo RETURN_IF_ERROR(Reader.readObject(Entry)); 1686edb6ab9bSMartin Storsjo assert(Entry != nullptr); 1687edb6ab9bSMartin Storsjo return *Entry; 1688edb6ab9bSMartin Storsjo } 1689edb6ab9bSMartin Storsjo 16907ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &> 16917ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) { 16927ba81d95SMartin Storsjo const coff_resource_data_entry *Entry = nullptr; 16937ba81d95SMartin Storsjo 16947ba81d95SMartin Storsjo BinaryStreamReader Reader(BBS); 16957ba81d95SMartin Storsjo Reader.setOffset(Offset); 16967ba81d95SMartin Storsjo RETURN_IF_ERROR(Reader.readObject(Entry)); 16977ba81d95SMartin Storsjo assert(Entry != nullptr); 16987ba81d95SMartin Storsjo return *Entry; 16997ba81d95SMartin Storsjo } 17007ba81d95SMartin Storsjo 1701f3404674SRafael Espindola Expected<const coff_resource_dir_table &> 1702efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 17037ba81d95SMartin Storsjo assert(Entry.Offset.isSubDir()); 1704f3404674SRafael Espindola return getTableAtOffset(Entry.Offset.value()); 1705efef15a0SEric Beckmann } 1706efef15a0SEric Beckmann 17077ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &> 17087ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) { 17097ba81d95SMartin Storsjo assert(!Entry.Offset.isSubDir()); 17107ba81d95SMartin Storsjo return getDataEntryAtOffset(Entry.Offset.value()); 17117ba81d95SMartin Storsjo } 17127ba81d95SMartin Storsjo 1713f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1714f3404674SRafael Espindola return getTableAtOffset(0); 1715efef15a0SEric Beckmann } 1716edb6ab9bSMartin Storsjo 1717edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &> 1718edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table, 1719edb6ab9bSMartin Storsjo uint32_t Index) { 1720edb6ab9bSMartin Storsjo if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) 1721edb6ab9bSMartin Storsjo return createStringError(object_error::parse_failed, "index out of range"); 1722edb6ab9bSMartin Storsjo const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table); 1723edb6ab9bSMartin Storsjo ptrdiff_t TableOffset = TablePtr - BBS.data().data(); 1724edb6ab9bSMartin Storsjo return getTableEntryAtOffset(TableOffset + sizeof(Table) + 1725edb6ab9bSMartin Storsjo Index * sizeof(coff_resource_dir_entry)); 1726edb6ab9bSMartin Storsjo } 172794382217SMartin Storsjo 172894382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) { 172994382217SMartin Storsjo for (const SectionRef &S : O->sections()) { 173094382217SMartin Storsjo Expected<StringRef> Name = S.getName(); 173194382217SMartin Storsjo if (!Name) 173294382217SMartin Storsjo return Name.takeError(); 173394382217SMartin Storsjo 173494382217SMartin Storsjo if (*Name == ".rsrc" || *Name == ".rsrc$01") 173594382217SMartin Storsjo return load(O, S); 173694382217SMartin Storsjo } 173794382217SMartin Storsjo return createStringError(object_error::parse_failed, 173894382217SMartin Storsjo "no resource section found"); 173994382217SMartin Storsjo } 174094382217SMartin Storsjo 174194382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) { 174294382217SMartin Storsjo Obj = O; 174394382217SMartin Storsjo Section = S; 174494382217SMartin Storsjo Expected<StringRef> Contents = Section.getContents(); 174594382217SMartin Storsjo if (!Contents) 174694382217SMartin Storsjo return Contents.takeError(); 174794382217SMartin Storsjo BBS = BinaryByteStream(*Contents, support::little); 174894382217SMartin Storsjo const coff_section *COFFSect = Obj->getCOFFSection(Section); 174994382217SMartin Storsjo ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect); 175094382217SMartin Storsjo Relocs.reserve(OrigRelocs.size()); 175194382217SMartin Storsjo for (const coff_relocation &R : OrigRelocs) 175294382217SMartin Storsjo Relocs.push_back(&R); 175394382217SMartin Storsjo std::sort(Relocs.begin(), Relocs.end(), 175494382217SMartin Storsjo [](const coff_relocation *A, const coff_relocation *B) { 175594382217SMartin Storsjo return A->VirtualAddress < B->VirtualAddress; 175694382217SMartin Storsjo }); 175794382217SMartin Storsjo return Error::success(); 175894382217SMartin Storsjo } 175994382217SMartin Storsjo 176094382217SMartin Storsjo Expected<StringRef> 176194382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { 176294382217SMartin Storsjo if (!Obj) 176394382217SMartin Storsjo return createStringError(object_error::parse_failed, "no object provided"); 176494382217SMartin Storsjo 176594382217SMartin Storsjo // Find a potential relocation at the DataRVA field (first member of 176694382217SMartin Storsjo // the coff_resource_data_entry struct). 176794382217SMartin Storsjo const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry); 176894382217SMartin Storsjo ptrdiff_t EntryOffset = EntryPtr - BBS.data().data(); 176994382217SMartin Storsjo coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0), 177094382217SMartin Storsjo ulittle16_t(0)}; 177194382217SMartin Storsjo auto RelocsForOffset = 177294382217SMartin Storsjo std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget, 177394382217SMartin Storsjo [](const coff_relocation *A, const coff_relocation *B) { 177494382217SMartin Storsjo return A->VirtualAddress < B->VirtualAddress; 177594382217SMartin Storsjo }); 177694382217SMartin Storsjo 177794382217SMartin Storsjo if (RelocsForOffset.first != RelocsForOffset.second) { 177894382217SMartin Storsjo // We found a relocation with the right offset. Check that it does have 177994382217SMartin Storsjo // the expected type. 178094382217SMartin Storsjo const coff_relocation &R = **RelocsForOffset.first; 178194382217SMartin Storsjo uint16_t RVAReloc; 178294382217SMartin Storsjo switch (Obj->getMachine()) { 178394382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_I386: 178494382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_I386_DIR32NB; 178594382217SMartin Storsjo break; 178694382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_AMD64: 178794382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB; 178894382217SMartin Storsjo break; 178994382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_ARMNT: 179094382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB; 179194382217SMartin Storsjo break; 179294382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_ARM64: 179394382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB; 179494382217SMartin Storsjo break; 179594382217SMartin Storsjo default: 179694382217SMartin Storsjo return createStringError(object_error::parse_failed, 179794382217SMartin Storsjo "unsupported architecture"); 179894382217SMartin Storsjo } 179994382217SMartin Storsjo if (R.Type != RVAReloc) 180094382217SMartin Storsjo return createStringError(object_error::parse_failed, 180194382217SMartin Storsjo "unexpected relocation type"); 180294382217SMartin Storsjo // Get the relocation's symbol 180394382217SMartin Storsjo Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex); 180494382217SMartin Storsjo if (!Sym) 180594382217SMartin Storsjo return Sym.takeError(); 180694382217SMartin Storsjo // And the symbol's section 180777ecf90cSReid Kleckner Expected<const coff_section *> Section = 180877ecf90cSReid Kleckner Obj->getSection(Sym->getSectionNumber()); 180977ecf90cSReid Kleckner if (!Section) 181077ecf90cSReid Kleckner return Section.takeError(); 181194382217SMartin Storsjo // Add the initial value of DataRVA to the symbol's offset to find the 181294382217SMartin Storsjo // data it points at. 181394382217SMartin Storsjo uint64_t Offset = Entry.DataRVA + Sym->getValue(); 181494382217SMartin Storsjo ArrayRef<uint8_t> Contents; 181577ecf90cSReid Kleckner if (Error E = Obj->getSectionContents(*Section, Contents)) 1816c55cf4afSBill Wendling return std::move(E); 181794382217SMartin Storsjo if (Offset + Entry.DataSize > Contents.size()) 181894382217SMartin Storsjo return createStringError(object_error::parse_failed, 181994382217SMartin Storsjo "data outside of section"); 182094382217SMartin Storsjo // Return a reference to the data inside the section. 182194382217SMartin Storsjo return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset, 182294382217SMartin Storsjo Entry.DataSize); 182394382217SMartin Storsjo } else { 182494382217SMartin Storsjo // Relocatable objects need a relocation for the DataRVA field. 182594382217SMartin Storsjo if (Obj->isRelocatableObject()) 182694382217SMartin Storsjo return createStringError(object_error::parse_failed, 182794382217SMartin Storsjo "no relocation found for DataRVA"); 182894382217SMartin Storsjo 182994382217SMartin Storsjo // Locate the section that contains the address that DataRVA points at. 183094382217SMartin Storsjo uint64_t VA = Entry.DataRVA + Obj->getImageBase(); 183194382217SMartin Storsjo for (const SectionRef &S : Obj->sections()) { 183294382217SMartin Storsjo if (VA >= S.getAddress() && 183394382217SMartin Storsjo VA + Entry.DataSize <= S.getAddress() + S.getSize()) { 183494382217SMartin Storsjo uint64_t Offset = VA - S.getAddress(); 183594382217SMartin Storsjo Expected<StringRef> Contents = S.getContents(); 183694382217SMartin Storsjo if (!Contents) 183794382217SMartin Storsjo return Contents.takeError(); 183894382217SMartin Storsjo return Contents->slice(Offset, Offset + Entry.DataSize); 183994382217SMartin Storsjo } 184094382217SMartin Storsjo } 184194382217SMartin Storsjo return createStringError(object_error::parse_failed, 184294382217SMartin Storsjo "address not found in image"); 184394382217SMartin Storsjo } 184494382217SMartin Storsjo } 1845