1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 28e90adafSMichael J. Spencer // 38e90adafSMichael J. Spencer // The LLVM Compiler Infrastructure 48e90adafSMichael J. Spencer // 58e90adafSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 68e90adafSMichael J. Spencer // License. See LICENSE.TXT for details. 78e90adafSMichael J. Spencer // 88e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 98e90adafSMichael J. Spencer // 108e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 118e90adafSMichael J. Spencer // 128e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 138e90adafSMichael J. Spencer 149da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 15d341c932SEugene Zelenko #include "llvm/ADT/StringRef.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> 5848af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5958323a97SDavid Majnemer const void *Ptr, 60236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 61ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 62*cbc7ee45SBenjamin Kramer if (std::error_code EC = Binary::checkOffset(M, Addr, Size)) 63e830c60dSDavid Majnemer return EC; 64ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 657d099195SRui Ueyama return std::error_code(); 661d6167fdSMichael J. Spencer } 671d6167fdSMichael J. Spencer 689d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 699d2c15efSNico Rieck // prefixed slashes. 709d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 719d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 729d2c15efSNico Rieck if (Str.size() > 6) 739d2c15efSNico Rieck return true; 749d2c15efSNico Rieck 759d2c15efSNico Rieck uint64_t Value = 0; 769d2c15efSNico Rieck while (!Str.empty()) { 779d2c15efSNico Rieck unsigned CharVal; 789d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 799d2c15efSNico Rieck CharVal = Str[0] - 'A'; 809d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 819d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 829d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 839d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 849d2c15efSNico Rieck else if (Str[0] == '+') // 62 855500b07cSRui Ueyama CharVal = 62; 869d2c15efSNico Rieck else if (Str[0] == '/') // 63 875500b07cSRui Ueyama CharVal = 63; 889d2c15efSNico Rieck else 899d2c15efSNico Rieck return true; 909d2c15efSNico Rieck 919d2c15efSNico Rieck Value = (Value * 64) + CharVal; 929d2c15efSNico Rieck Str = Str.substr(1); 939d2c15efSNico Rieck } 949d2c15efSNico Rieck 959d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 969d2c15efSNico Rieck return true; 979d2c15efSNico Rieck 989d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 999d2c15efSNico Rieck return false; 1009d2c15efSNico Rieck } 1019d2c15efSNico Rieck 10244f51e51SDavid Majnemer template <typename coff_symbol_type> 10344f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10444f51e51SDavid Majnemer const coff_symbol_type *Addr = 10544f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1061d6167fdSMichael J. Spencer 107236b0ca7SDavid Majnemer assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 1081d6167fdSMichael J. Spencer #ifndef NDEBUG 1091d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1108ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 1111d6167fdSMichael J. Spencer 11244f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11344f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1141d6167fdSMichael J. Spencer #endif 1151d6167fdSMichael J. Spencer 1168ff24d25SRui Ueyama return Addr; 1171d6167fdSMichael J. Spencer } 1181d6167fdSMichael J. Spencer 1198ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1208ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1211d6167fdSMichael J. Spencer 1221d6167fdSMichael J. Spencer #ifndef NDEBUG 1231d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12444f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1251d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1261d6167fdSMichael J. Spencer 1278ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1288ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1291d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1301d6167fdSMichael J. Spencer #endif 1311d6167fdSMichael J. Spencer 1328ff24d25SRui Ueyama return Addr; 1331d6167fdSMichael J. Spencer } 1341d6167fdSMichael J. Spencer 1355e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 136236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 13744f51e51SDavid Majnemer if (SymbolTable16) { 13844f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1398ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 140236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14144f51e51SDavid Majnemer } else if (SymbolTable32) { 14244f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14344f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 144236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14544f51e51SDavid Majnemer } else { 14644f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14744f51e51SDavid Majnemer } 1481d6167fdSMichael J. Spencer } 1491d6167fdSMichael J. Spencer 15081e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 15144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1525d0c2ffaSRafael Espindola StringRef Result; 153efef15a0SEric Beckmann if (std::error_code EC = getSymbolName(Symb, Result)) 15481e8b7d9SKevin Enderby return errorCodeToError(EC); 1555d0c2ffaSRafael Espindola return Result; 1568e90adafSMichael J. Spencer } 1578e90adafSMichael J. Spencer 158be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 159be8b0ea8SRafael Espindola return getCOFFSymbol(Ref).getValue(); 160991af666SRafael Espindola } 161991af666SRafael Espindola 1626b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 1636b2bba14SDavide Italiano // MSVC/link.exe seems to align symbols to the next-power-of-2 1646b2bba14SDavide Italiano // up to 32 bytes. 1656b2bba14SDavide Italiano COFFSymbolRef Symb = getCOFFSymbol(Ref); 16603a85680SDavide Italiano return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 1676b2bba14SDavide Italiano } 1686b2bba14SDavide Italiano 169931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 170ed067c45SRafael Espindola uint64_t Result = getSymbolValue(Ref); 17144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 172c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 173991af666SRafael Espindola 174991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 175991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 176ed067c45SRafael Espindola return Result; 17754c9f3daSRafael Espindola 1782617dcceSCraig Topper const coff_section *Section = nullptr; 179c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 180931cb65dSKevin Enderby return errorCodeToError(EC); 181991af666SRafael Espindola Result += Section->VirtualAddress; 18247ea9eceSReid Kleckner 18347ea9eceSReid Kleckner // The section VirtualAddress does not include ImageBase, and we want to 18447ea9eceSReid Kleckner // return virtual addresses. 18521427adaSReid Kleckner Result += getImageBase(); 18647ea9eceSReid Kleckner 187ed067c45SRafael Espindola return Result; 188c7d7c6fbSDavid Majnemer } 189c7d7c6fbSDavid Majnemer 1907bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 19144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 192c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 19344f51e51SDavid Majnemer 194e834f420SPeter Collingbourne if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 195e834f420SPeter Collingbourne return SymbolRef::ST_Function; 1962fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 1972fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 1982fa80cc5SRafael Espindola if (Symb.isCommon()) 1992fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2002fa80cc5SRafael Espindola if (Symb.isFileRecord()) 2012fa80cc5SRafael Espindola return SymbolRef::ST_File; 2022fa80cc5SRafael Espindola 2031a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 2042fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 2052fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 2062fa80cc5SRafael Espindola 2072fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 2082fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2092fa80cc5SRafael Espindola 2102fa80cc5SRafael Espindola return SymbolRef::ST_Other; 21175d1cf33SBenjamin Kramer } 21275d1cf33SBenjamin Kramer 21320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 21444f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 21520122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 21675d1cf33SBenjamin Kramer 217c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2189dc0eb42SLang Hames Result |= SymbolRef::SF_Global; 2191df4b84dSDavid Meyer 2201079ef8dSMartell Malone if (Symb.isWeakExternal()) { 2211df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2221079ef8dSMartell Malone // We use indirect to allow the archiver to write weak externs 2231079ef8dSMartell Malone Result |= SymbolRef::SF_Indirect; 2241079ef8dSMartell Malone } 2251df4b84dSDavid Meyer 22644f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2271df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2281df4b84dSDavid Meyer 229c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 230c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 231c7d7c6fbSDavid Majnemer 232c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 233c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 234c7d7c6fbSDavid Majnemer 235c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 236c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 237c7d7c6fbSDavid Majnemer 238c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 239c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 240c7d7c6fbSDavid Majnemer 24120122a43SRafael Espindola return Result; 24201759754SMichael J. Spencer } 24301759754SMichael J. Spencer 244d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 245c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2465eb02e45SRafael Espindola return Symb.getValue(); 2478e90adafSMichael J. Spencer } 2488e90adafSMichael J. Spencer 2497bd8d994SKevin Enderby Expected<section_iterator> 2508bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 25144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2528bab889bSRafael Espindola if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2538bab889bSRafael Espindola return section_end(); 2542617dcceSCraig Topper const coff_section *Sec = nullptr; 25544f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 2567bd8d994SKevin Enderby return errorCodeToError(EC); 2578bab889bSRafael Espindola DataRefImpl Ret; 2588bab889bSRafael Espindola Ret.p = reinterpret_cast<uintptr_t>(Sec); 2598bab889bSRafael Espindola return section_iterator(SectionRef(Ret, this)); 26032173153SMichael J. Spencer } 26132173153SMichael J. Spencer 2626bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2636bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2646bf32210SRafael Espindola return Symb.getSectionNumber(); 2656bf32210SRafael Espindola } 2666bf32210SRafael Espindola 2675e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2688ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2698ff24d25SRui Ueyama Sec += 1; 2708ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2718e90adafSMichael J. Spencer } 2728e90adafSMichael J. Spencer 273db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2741d6167fdSMichael J. Spencer StringRef &Result) const { 2758ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2768ff24d25SRui Ueyama return getSectionName(Sec, Result); 2778e90adafSMichael J. Spencer } 2788e90adafSMichael J. Spencer 27980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2808ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2817c6a071bSDavid Majnemer uint64_t Result = Sec->VirtualAddress; 2827c6a071bSDavid Majnemer 2837c6a071bSDavid Majnemer // The section VirtualAddress does not include ImageBase, and we want to 2847c6a071bSDavid Majnemer // return virtual addresses. 28521427adaSReid Kleckner Result += getImageBase(); 2867c6a071bSDavid Majnemer return Result; 2878e90adafSMichael J. Spencer } 2888e90adafSMichael J. Spencer 289a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 290a25d329bSGeorge Rimar return toSec(Sec) - SectionTable; 291a25d329bSGeorge Rimar } 292a25d329bSGeorge Rimar 29380291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 294a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2958e90adafSMichael J. Spencer } 2968e90adafSMichael J. Spencer 297db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2981d6167fdSMichael J. Spencer StringRef &Result) const { 2998ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3009da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 301db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3029da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3039da9e693SMichael J. Spencer return EC; 3048e90adafSMichael J. Spencer } 3058e90adafSMichael J. Spencer 30680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3078ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 308511391feSDavid Majnemer return Sec->getAlignment(); 3097989460aSMichael J. Spencer } 3107989460aSMichael J. Spencer 311401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 312401e4e57SGeorge Rimar return false; 313401e4e57SGeorge Rimar } 314401e4e57SGeorge Rimar 31580291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3168ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31780291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3188e90adafSMichael J. Spencer } 3198e90adafSMichael J. Spencer 32080291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3218ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32280291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 323800619f2SMichael J. Spencer } 324800619f2SMichael J. Spencer 32580291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3268ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3271a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3281a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3291a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3301a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 331800619f2SMichael J. Spencer } 332800619f2SMichael J. Spencer 3336bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3346bf32210SRafael Espindola uintptr_t Offset = 3356bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3366bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3376bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3386bf32210SRafael Espindola } 3396bf32210SRafael Espindola 34080291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3418ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3421a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3431a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3441a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3452138ef6dSPreston Gurd } 3462138ef6dSPreston Gurd 347e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 348e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 349e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 350e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 351e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 352e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 353e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 354e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 355e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 356e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 357e830c60dSDavid Majnemer return 0; 35898fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 35998fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 360e830c60dSDavid Majnemer } 361e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 362e830c60dSDavid Majnemer } 363e830c60dSDavid Majnemer 36494751be7SDavid Majnemer static const coff_relocation * 36594751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 36694751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 36794751be7SDavid Majnemer if (!NumRelocs) 36894751be7SDavid Majnemer return nullptr; 369827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 37094751be7SDavid Majnemer Base + Sec->PointerToRelocations); 371827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 372827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 373827c8a2bSRui Ueyama // relocations. 374827c8a2bSRui Ueyama begin++; 375827c8a2bSRui Ueyama } 376*cbc7ee45SBenjamin Kramer if (Binary::checkOffset(M, uintptr_t(begin), 377*cbc7ee45SBenjamin Kramer sizeof(coff_relocation) * NumRelocs)) 37894751be7SDavid Majnemer return nullptr; 37994751be7SDavid Majnemer return begin; 380827c8a2bSRui Ueyama } 38194751be7SDavid Majnemer 38294751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 38394751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 38494751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 38576d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 38676d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 38794751be7SDavid Majnemer DataRefImpl Ret; 38894751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3898ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 390e5fd0047SMichael J. Spencer } 391e5fd0047SMichael J. Spencer 3928ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3938ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 39494751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 39594751be7SDavid Majnemer if (I) 39694751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 3978ff24d25SRui Ueyama DataRefImpl Ret; 39894751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 3998ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 400e5fd0047SMichael J. Spencer } 401e5fd0047SMichael J. Spencer 402c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 403db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 40444f51e51SDavid Majnemer if (COFFHeader) 405236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 406236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 407236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 40844f51e51SDavid Majnemer return EC; 40944f51e51SDavid Majnemer 41044f51e51SDavid Majnemer if (COFFBigObjHeader) 411236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 412236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 413236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4148ff24d25SRui Ueyama return EC; 415c2bed429SRui Ueyama 416c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 417c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 418c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 419f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 42044f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 421f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 422c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 42348af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4248ff24d25SRui Ueyama return EC; 425c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 426db4ed0bdSRafael Espindola if (std::error_code EC = 42748af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4288ff24d25SRui Ueyama return EC; 429c2bed429SRui Ueyama 430773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 431773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 432773a5795SNico Rieck if (StringTableSize < 4) 433773a5795SNico Rieck StringTableSize = 4; 434773a5795SNico Rieck 435c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 436773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 437c2bed429SRui Ueyama return object_error::parse_failed; 4387d099195SRui Ueyama return std::error_code(); 439c2bed429SRui Ueyama } 440c2bed429SRui Ueyama 44121427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 442e94fef7bSReid Kleckner if (PE32Header) 44321427adaSReid Kleckner return PE32Header->ImageBase; 444e94fef7bSReid Kleckner else if (PE32PlusHeader) 44521427adaSReid Kleckner return PE32PlusHeader->ImageBase; 44621427adaSReid Kleckner // This actually comes up in practice. 44721427adaSReid Kleckner return 0; 448e94fef7bSReid Kleckner } 449e94fef7bSReid Kleckner 450215a586cSRui Ueyama // Returns the file offset for the given VA. 451db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 45221427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 453b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 454b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 455b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 456215a586cSRui Ueyama } 457215a586cSRui Ueyama 458c2bed429SRui Ueyama // Returns the file offset for the given RVA. 459db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 46027dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 46127dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 462c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 463c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 464215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 465215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 466c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4677d099195SRui Ueyama return std::error_code(); 468c2bed429SRui Ueyama } 469c2bed429SRui Ueyama } 470c2bed429SRui Ueyama return object_error::parse_failed; 471c2bed429SRui Ueyama } 472c2bed429SRui Ueyama 4732da433eaSReid Kleckner std::error_code 4742da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4752da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4762da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4772da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4782da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4792da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4802da433eaSReid Kleckner // overflow. 4812da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4822da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4832da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4842da433eaSReid Kleckner uintptr_t Begin = 4852da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4862da433eaSReid Kleckner Contents = 4872da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4882da433eaSReid Kleckner return std::error_code(); 4892da433eaSReid Kleckner } 4902da433eaSReid Kleckner } 4912da433eaSReid Kleckner return object_error::parse_failed; 4922da433eaSReid Kleckner } 4932da433eaSReid Kleckner 494c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 495c2bed429SRui Ueyama // table entry. 496db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 497db4ed0bdSRafael Espindola StringRef &Name) const { 498c2bed429SRui Ueyama uintptr_t IntPtr = 0; 499db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 5008ff24d25SRui Ueyama return EC; 501c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 502c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 503c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5047d099195SRui Ueyama return std::error_code(); 505c2bed429SRui Ueyama } 506c2bed429SRui Ueyama 50701528021SSaleem Abdulrasool std::error_code 50801528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 50901528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5102da433eaSReid Kleckner StringRef &PDBFileName) const { 5112da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5122da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 5132da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5142da433eaSReid Kleckner return EC; 51501528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5162da433eaSReid Kleckner return object_error::parse_failed; 51701528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 51801528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5192da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5202da433eaSReid Kleckner InfoBytes.size()); 5212da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5222da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5232da433eaSReid Kleckner return std::error_code(); 5242da433eaSReid Kleckner } 5252da433eaSReid Kleckner 52601528021SSaleem Abdulrasool std::error_code 52701528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 528f27f3f84SReid Kleckner StringRef &PDBFileName) const { 529f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 530f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 531f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 532f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 533f27f3f84SReid Kleckner PDBInfo = nullptr; 534f27f3f84SReid Kleckner PDBFileName = StringRef(); 535f27f3f84SReid Kleckner return std::error_code(); 536f27f3f84SReid Kleckner } 537f27f3f84SReid Kleckner 538c2bed429SRui Ueyama // Find the import table. 539db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 540c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 541c2bed429SRui Ueyama // the import table, do nothing. 542c2bed429SRui Ueyama const data_directory *DataEntry; 543c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5447d099195SRui Ueyama return std::error_code(); 545c2bed429SRui Ueyama 546c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 547c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5487d099195SRui Ueyama return std::error_code(); 549c2bed429SRui Ueyama 550c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 551c2bed429SRui Ueyama 552c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 553c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 554c2bed429SRui Ueyama uintptr_t IntPtr = 0; 555db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5568ff24d25SRui Ueyama return EC; 557ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 558ad7b7e73SDavid Majnemer return EC; 559c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5601c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5617d099195SRui Ueyama return std::error_code(); 562ad882ba8SRui Ueyama } 563c2bed429SRui Ueyama 56415d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 56515d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 56615d99359SRui Ueyama const data_directory *DataEntry; 56715d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5687d099195SRui Ueyama return std::error_code(); 56915d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5707d099195SRui Ueyama return std::error_code(); 57115d99359SRui Ueyama 57215d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 57315d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 57415d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 57515d99359SRui Ueyama 57615d99359SRui Ueyama uintptr_t IntPtr = 0; 57715d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 57815d99359SRui Ueyama return EC; 57915d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 58015d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5817d099195SRui Ueyama return std::error_code(); 58215d99359SRui Ueyama } 58315d99359SRui Ueyama 584ad882ba8SRui Ueyama // Find the export table. 585db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 586ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 587ad882ba8SRui Ueyama // the export table, do nothing. 588ad882ba8SRui Ueyama const data_directory *DataEntry; 589ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5907d099195SRui Ueyama return std::error_code(); 591ad882ba8SRui Ueyama 592ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 593ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5947d099195SRui Ueyama return std::error_code(); 595ad882ba8SRui Ueyama 596ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 597ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 598db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 599ad882ba8SRui Ueyama return EC; 60024fc2d64SRui Ueyama ExportDirectory = 60124fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6027d099195SRui Ueyama return std::error_code(); 603c2bed429SRui Ueyama } 604c2bed429SRui Ueyama 60574e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 60674e85130SRui Ueyama const data_directory *DataEntry; 60774e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 6087d099195SRui Ueyama return std::error_code(); 60974e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6107d099195SRui Ueyama return std::error_code(); 61174e85130SRui Ueyama 61274e85130SRui Ueyama uintptr_t IntPtr = 0; 61374e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 61474e85130SRui Ueyama return EC; 61574e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 61674e85130SRui Ueyama IntPtr); 61774e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 61874e85130SRui Ueyama IntPtr + DataEntry->Size); 6197d099195SRui Ueyama return std::error_code(); 62074e85130SRui Ueyama } 62174e85130SRui Ueyama 6222da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6232da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6242da433eaSReid Kleckner const data_directory *DataEntry; 6252da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6262da433eaSReid Kleckner return std::error_code(); 6272da433eaSReid Kleckner 6282da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6292da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6302da433eaSReid Kleckner return std::error_code(); 6312da433eaSReid Kleckner 6322da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6332da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6342da433eaSReid Kleckner return object_error::parse_failed; 6352da433eaSReid Kleckner 6362da433eaSReid Kleckner uintptr_t IntPtr = 0; 6372da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6382da433eaSReid Kleckner return EC; 6392da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6402da433eaSReid Kleckner if (std::error_code EC = getRvaPtr( 6412da433eaSReid Kleckner DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 6422da433eaSReid Kleckner return EC; 6432da433eaSReid Kleckner DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 6442da433eaSReid Kleckner return std::error_code(); 6452da433eaSReid Kleckner } 6462da433eaSReid Kleckner 647b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() { 648b7d716c0SReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 649b7d716c0SReid Kleckner const data_directory *DataEntry; 650b7d716c0SReid Kleckner if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry)) 651b7d716c0SReid Kleckner return std::error_code(); 652b7d716c0SReid Kleckner 653b7d716c0SReid Kleckner // Do nothing if the RVA is NULL. 654b7d716c0SReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 655b7d716c0SReid Kleckner return std::error_code(); 656b7d716c0SReid Kleckner uintptr_t IntPtr = 0; 657b7d716c0SReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 658b7d716c0SReid Kleckner return EC; 659b7d716c0SReid Kleckner 660b7d716c0SReid Kleckner LoadConfig = (const void *)IntPtr; 661b7d716c0SReid Kleckner return std::error_code(); 662b7d716c0SReid Kleckner } 663b7d716c0SReid Kleckner 66448af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 66548af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 66644f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 66744f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 66844f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 669ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 67015d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6712da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6722da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6731d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 67448af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 675c3f9b5a5SRafael Espindola return; 676ee066fc4SEric Christopher 67782ebd8e3SRui Ueyama // The current location in the file where we are looking at. 67882ebd8e3SRui Ueyama uint64_t CurPtr = 0; 67982ebd8e3SRui Ueyama 68082ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 68182ebd8e3SRui Ueyama // it is placed right after COFF header. 6828ff24d25SRui Ueyama bool HasPEHeader = false; 683ee066fc4SEric Christopher 6841d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 68550267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 686ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 687ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 68850267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 68950267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 69050267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 69182ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 69250267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6938ff24d25SRui Ueyama EC = object_error::parse_failed; 6941d6167fdSMichael J. Spencer return; 6951d6167fdSMichael J. Spencer } 69644f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6978ff24d25SRui Ueyama HasPEHeader = true; 698ee066fc4SEric Christopher } 69950267222SDavid Majnemer } 700ee066fc4SEric Christopher 70148af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 7021d6167fdSMichael J. Spencer return; 70344f51e51SDavid Majnemer 70444f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 70544f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 70644f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 70744f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 70844f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 70944f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 71044f51e51SDavid Majnemer return; 71144f51e51SDavid Majnemer 71244f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 71344f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 71444f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 71544f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 71644f51e51SDavid Majnemer COFFHeader = nullptr; 71744f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 71844f51e51SDavid Majnemer } else { 71944f51e51SDavid Majnemer // It's not a bigobj. 72044f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 72144f51e51SDavid Majnemer } 72244f51e51SDavid Majnemer } 72344f51e51SDavid Majnemer if (COFFHeader) { 72444f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 72544f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7267d099195SRui Ueyama EC = std::error_code(); 72782ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 72882ebd8e3SRui Ueyama 72944f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 73044f51e51SDavid Majnemer return; 73144f51e51SDavid Majnemer } 73244f51e51SDavid Majnemer 7338ff24d25SRui Ueyama if (HasPEHeader) { 73410ed9ddcSRui Ueyama const pe32_header *Header; 73548af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 73682ebd8e3SRui Ueyama return; 73710ed9ddcSRui Ueyama 73810ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 73910ed9ddcSRui Ueyama uint64_t DataDirSize; 74050267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 74110ed9ddcSRui Ueyama PE32Header = Header; 74210ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 74310ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 74450267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 74510ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 74610ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 74710ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 74810ed9ddcSRui Ueyama } else { 74910ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 75010ed9ddcSRui Ueyama EC = object_error::parse_failed; 751ed64342bSRui Ueyama return; 752ed64342bSRui Ueyama } 75348af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 75410ed9ddcSRui Ueyama return; 755f53c8cb4SRui Ueyama } 756776c6828SRui Ueyama 7578950a538SRui Ueyama if (COFFHeader) 7588950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7598950a538SRui Ueyama 76048af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 761236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7621d6167fdSMichael J. Spencer return; 7631d6167fdSMichael J. Spencer 764c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 765236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 766ac8cfab5SDavid Majnemer if ((EC = initSymbolTablePtr())) { 767ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 768ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 769ac8cfab5SDavid Majnemer StringTable = nullptr; 770ac8cfab5SDavid Majnemer StringTableSize = 0; 771ac8cfab5SDavid Majnemer } 772236b0ca7SDavid Majnemer } else { 773236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 774236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 775236b0ca7SDavid Majnemer EC = object_error::parse_failed; 776236b0ca7SDavid Majnemer return; 777236b0ca7SDavid Majnemer } 778236b0ca7SDavid Majnemer } 7798e90adafSMichael J. Spencer 780c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7818ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 782ed64342bSRui Ueyama return; 78315d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 78415d99359SRui Ueyama return; 7851d6167fdSMichael J. Spencer 786ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7878ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 788ad882ba8SRui Ueyama return; 789ad882ba8SRui Ueyama 79074e85130SRui Ueyama // Initialize the pointer to the base relocation table. 79174e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 79274e85130SRui Ueyama return; 79374e85130SRui Ueyama 7942da433eaSReid Kleckner // Initialize the pointer to the export table. 7952da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 7962da433eaSReid Kleckner return; 7972da433eaSReid Kleckner 798b7d716c0SReid Kleckner if ((EC = initLoadConfigPtr())) 799b7d716c0SReid Kleckner return; 800b7d716c0SReid Kleckner 8017d099195SRui Ueyama EC = std::error_code(); 8028e90adafSMichael J. Spencer } 8038e90adafSMichael J. Spencer 804435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 8058ff24d25SRui Ueyama DataRefImpl Ret; 80644f51e51SDavid Majnemer Ret.p = getSymbolTable(); 807f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8088e90adafSMichael J. Spencer } 8098e90adafSMichael J. Spencer 810435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 8118e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 8128ff24d25SRui Ueyama DataRefImpl Ret; 8138ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 814f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8158e90adafSMichael J. Spencer } 8168e90adafSMichael J. Spencer 817bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 818ad7b7e73SDavid Majnemer if (!ImportDirectory) 819ad7b7e73SDavid Majnemer return import_directory_end(); 8201c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 821ad7b7e73SDavid Majnemer return import_directory_end(); 822a045b73aSRui Ueyama return import_directory_iterator( 823a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 824c2bed429SRui Ueyama } 825c2bed429SRui Ueyama 826bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 827a045b73aSRui Ueyama return import_directory_iterator( 828ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 829c2bed429SRui Ueyama } 830c429b80dSDavid Meyer 83115d99359SRui Ueyama delay_import_directory_iterator 83215d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 83315d99359SRui Ueyama return delay_import_directory_iterator( 83415d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 83515d99359SRui Ueyama } 83615d99359SRui Ueyama 83715d99359SRui Ueyama delay_import_directory_iterator 83815d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 83915d99359SRui Ueyama return delay_import_directory_iterator( 84015d99359SRui Ueyama DelayImportDirectoryEntryRef( 84115d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 84215d99359SRui Ueyama } 84315d99359SRui Ueyama 844ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 845ad882ba8SRui Ueyama return export_directory_iterator( 846ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 847ad882ba8SRui Ueyama } 848ad882ba8SRui Ueyama 849ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8502617dcceSCraig Topper if (!ExportDirectory) 8512617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8528ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 853ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8548ff24d25SRui Ueyama return export_directory_iterator(Ref); 855ad882ba8SRui Ueyama } 856ad882ba8SRui Ueyama 857b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8588ff24d25SRui Ueyama DataRefImpl Ret; 8598ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8608ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8618e90adafSMichael J. Spencer } 8628e90adafSMichael J. Spencer 863b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8648ff24d25SRui Ueyama DataRefImpl Ret; 86544f51e51SDavid Majnemer int NumSections = 86644f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8678ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8688ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8698e90adafSMichael J. Spencer } 8708e90adafSMichael J. Spencer 87174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 87274e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 87374e85130SRui Ueyama } 87474e85130SRui Ueyama 87574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 87674e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 87774e85130SRui Ueyama } 87874e85130SRui Ueyama 8798e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 88043c85453SMartin Storsjo return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 8818e90adafSMichael J. Spencer } 8828e90adafSMichael J. Spencer 8838e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 88444f51e51SDavid Majnemer switch(getMachine()) { 8858e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8868e90adafSMichael J. Spencer return "COFF-i386"; 8878e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8888e90adafSMichael J. Spencer return "COFF-x86-64"; 8899b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8909b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8911eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8921eff5c9cSMartell Malone return "COFF-ARM64"; 8938e90adafSMichael J. Spencer default: 8948e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8958e90adafSMichael J. Spencer } 8968e90adafSMichael J. Spencer } 8978e90adafSMichael J. Spencer 8988e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 89944f51e51SDavid Majnemer switch (getMachine()) { 9008e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9018e90adafSMichael J. Spencer return Triple::x86; 9028e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9038e90adafSMichael J. Spencer return Triple::x86_64; 9049b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9059b7c0af2SSaleem Abdulrasool return Triple::thumb; 9061eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9071eff5c9cSMartell Malone return Triple::aarch64; 9088e90adafSMichael J. Spencer default: 9098e90adafSMichael J. Spencer return Triple::UnknownArch; 9108e90adafSMichael J. Spencer } 9118e90adafSMichael J. Spencer } 9128e90adafSMichael J. Spencer 913979fb40bSRui Ueyama iterator_range<import_directory_iterator> 914979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 915979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 916979fb40bSRui Ueyama } 917979fb40bSRui Ueyama 918979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 919979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 920979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 921979fb40bSRui Ueyama delay_import_directory_end()); 922979fb40bSRui Ueyama } 923979fb40bSRui Ueyama 924979fb40bSRui Ueyama iterator_range<export_directory_iterator> 925979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 926979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 927979fb40bSRui Ueyama } 928979fb40bSRui Ueyama 92974e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 93074e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 93174e85130SRui Ueyama } 93274e85130SRui Ueyama 933db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 93482ebd8e3SRui Ueyama Res = PE32Header; 9357d099195SRui Ueyama return std::error_code(); 93689a7a5eaSMichael J. Spencer } 93789a7a5eaSMichael J. Spencer 938db4ed0bdSRafael Espindola std::error_code 93910ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 94010ed9ddcSRui Ueyama Res = PE32PlusHeader; 9417d099195SRui Ueyama return std::error_code(); 94210ed9ddcSRui Ueyama } 94310ed9ddcSRui Ueyama 944db4ed0bdSRafael Espindola std::error_code 945db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 946ed64342bSRui Ueyama const data_directory *&Res) const { 947ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 948f69b0585SDavid Majnemer if (!DataDirectory) { 949f69b0585SDavid Majnemer Res = nullptr; 95010ed9ddcSRui Ueyama return object_error::parse_failed; 951f69b0585SDavid Majnemer } 95210ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 95310ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 95410ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 955f69b0585SDavid Majnemer if (Index >= NumEnt) { 956f69b0585SDavid Majnemer Res = nullptr; 957ed64342bSRui Ueyama return object_error::parse_failed; 958f69b0585SDavid Majnemer } 9598ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9607d099195SRui Ueyama return std::error_code(); 961ed64342bSRui Ueyama } 962ed64342bSRui Ueyama 963db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9641d6167fdSMichael J. Spencer const coff_section *&Result) const { 9652617dcceSCraig Topper Result = nullptr; 966236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9677d099195SRui Ueyama return std::error_code(); 968236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9691d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9708ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9717d099195SRui Ueyama return std::error_code(); 9728e90adafSMichael J. Spencer } 973236b0ca7SDavid Majnemer return object_error::parse_failed; 974236b0ca7SDavid Majnemer } 9758e90adafSMichael J. Spencer 976db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9771d6167fdSMichael J. Spencer StringRef &Result) const { 9781d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9791d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9801d6167fdSMichael J. Spencer return object_error::parse_failed; 9818ff24d25SRui Ueyama if (Offset >= StringTableSize) 9821d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9838ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9847d099195SRui Ueyama return std::error_code(); 9858e90adafSMichael J. Spencer } 986022ecdf2SBenjamin Kramer 98744f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 98889a7a5eaSMichael J. Spencer StringRef &Res) const { 989e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 990e40d30f3SRui Ueyama } 991e40d30f3SRui Ueyama 992e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 993e40d30f3SRui Ueyama StringRef &Res) const { 99489a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 995e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 996e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 9978ff24d25SRui Ueyama return EC; 9987d099195SRui Ueyama return std::error_code(); 99989a7a5eaSMichael J. Spencer } 100089a7a5eaSMichael J. Spencer 1001e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 100289a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 1003e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 100489a7a5eaSMichael J. Spencer else 100589a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 1006e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 10077d099195SRui Ueyama return std::error_code(); 100889a7a5eaSMichael J. Spencer } 100989a7a5eaSMichael J. Spencer 101044f51e51SDavid Majnemer ArrayRef<uint8_t> 101144f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 10122617dcceSCraig Topper const uint8_t *Aux = nullptr; 101371757ef3SMarshall Clow 101444f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 101544f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 101671757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 101744f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 101871757ef3SMarshall Clow #ifndef NDEBUG 10198ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10208ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 102144f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 102244f51e51SDavid Majnemer Offset >= 102344f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 102471757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 102571757ef3SMarshall Clow 102644f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 102744f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 102871757ef3SMarshall Clow #endif 1029bfb85e67SMarshall Clow } 103044f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 103171757ef3SMarshall Clow } 103271757ef3SMarshall Clow 1033db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 103453c2d547SMichael J. Spencer StringRef &Res) const { 103553c2d547SMichael J. Spencer StringRef Name; 103644f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 103753c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 103853c2d547SMichael J. Spencer Name = Sec->Name; 103953c2d547SMichael J. Spencer else 104053c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 104144f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 104253c2d547SMichael J. Spencer 104353c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10442314b3deSDavid Majnemer if (Name.startswith("/")) { 104553c2d547SMichael J. Spencer uint32_t Offset; 10462314b3deSDavid Majnemer if (Name.startswith("//")) { 10479d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10489d2c15efSNico Rieck return object_error::parse_failed; 10499d2c15efSNico Rieck } else { 105053c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 105153c2d547SMichael J. Spencer return object_error::parse_failed; 10529d2c15efSNico Rieck } 1053db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 10548ff24d25SRui Ueyama return EC; 105553c2d547SMichael J. Spencer } 105653c2d547SMichael J. Spencer 105753c2d547SMichael J. Spencer Res = Name; 10587d099195SRui Ueyama return std::error_code(); 105953c2d547SMichael J. Spencer } 106053c2d547SMichael J. Spencer 1061a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1062a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1063a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1064a9ee5c06SDavid Majnemer // 1065a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1066d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1067a9ee5c06SDavid Majnemer // 1068a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1069a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1070a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1071a9ee5c06SDavid Majnemer // considered to be zero. 1072d5297ee7SRui Ueyama if (getDOSHeader()) 1073d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1074d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1075a9ee5c06SDavid Majnemer } 1076a9ee5c06SDavid Majnemer 1077db4ed0bdSRafael Espindola std::error_code 1078db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10799da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1080e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1081e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1082e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1083ee97c5f0SShoaib Meenai return std::error_code(); 10849da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10859da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10869da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10879da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1088a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1089e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10909da9e693SMichael J. Spencer return object_error::parse_failed; 1091a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10927d099195SRui Ueyama return std::error_code(); 10939da9e693SMichael J. Spencer } 10949da9e693SMichael J. Spencer 1095022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1096e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1097022ecdf2SBenjamin Kramer } 10988ff24d25SRui Ueyama 10995e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1100e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1101e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1102022ecdf2SBenjamin Kramer } 11038ff24d25SRui Ueyama 110496d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 110558323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 110696d071cdSRafael Espindola return R->VirtualAddress; 1107cbe72fc9SDanil Malyshev } 11088ff24d25SRui Ueyama 1109806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1110022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 11118ff24d25SRui Ueyama DataRefImpl Ref; 1112236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1113236b0ca7SDavid Majnemer return symbol_end(); 111444f51e51SDavid Majnemer if (SymbolTable16) 111544f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 111644f51e51SDavid Majnemer else if (SymbolTable32) 111744f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 111844f51e51SDavid Majnemer else 1119c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11208ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1121022ecdf2SBenjamin Kramer } 11228ff24d25SRui Ueyama 112399c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1124022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 112599c041b7SRafael Espindola return R->Type; 1126022ecdf2SBenjamin Kramer } 1127e5fd0047SMichael J. Spencer 112827dc8394SAlexey Samsonov const coff_section * 112927dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 113027dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 113171757ef3SMarshall Clow } 113271757ef3SMarshall Clow 113344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 113444f51e51SDavid Majnemer if (SymbolTable16) 113544f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 113644f51e51SDavid Majnemer if (SymbolTable32) 113744f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 113844f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 113944f51e51SDavid Majnemer } 114044f51e51SDavid Majnemer 114144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 114244f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 114371757ef3SMarshall Clow } 114471757ef3SMarshall Clow 1145f12b8282SRafael Espindola const coff_relocation * 114627dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 114727dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1148d3e2a76cSMarshall Clow } 1149d3e2a76cSMarshall Clow 11506a75acb1SRui Ueyama iterator_range<const coff_relocation *> 11516a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11526a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 11536a75acb1SRui Ueyama const coff_relocation *E = I; 11546a75acb1SRui Ueyama if (I) 11556a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 11566a75acb1SRui Ueyama return make_range(I, E); 11576a75acb1SRui Ueyama } 11586a75acb1SRui Ueyama 115927dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 116027dc8394SAlexey Samsonov case COFF::reloc_type: \ 116127dc8394SAlexey Samsonov Res = #reloc_type; \ 116227dc8394SAlexey Samsonov break; 1163e5fd0047SMichael J. Spencer 116441bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 116541bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 11668ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11678ff24d25SRui Ueyama StringRef Res; 116844f51e51SDavid Majnemer switch (getMachine()) { 1169e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11708ff24d25SRui Ueyama switch (Reloc->Type) { 1171e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1172e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1173e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1174e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1175e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1176e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1177e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1178e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1179e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1180e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1181e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1182e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1183e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1184e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1185e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1186e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1187e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1188e5fd0047SMichael J. Spencer default: 11898ff24d25SRui Ueyama Res = "Unknown"; 1190e5fd0047SMichael J. Spencer } 1191e5fd0047SMichael J. Spencer break; 11925c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11935c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 11945c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11955c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11965c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11975c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11985c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11995c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 12005c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 12015c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 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); 12095c503bf4SSaleem Abdulrasool default: 12105c503bf4SSaleem Abdulrasool Res = "Unknown"; 12115c503bf4SSaleem Abdulrasool } 12125c503bf4SSaleem Abdulrasool break; 12130c72172eSMandeep Singh Grang case COFF::IMAGE_FILE_MACHINE_ARM64: 12140c72172eSMandeep Singh Grang switch (Reloc->Type) { 12150c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 12160c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 12170c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 12180c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 12190c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 12200c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 12210c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 12220c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 12230c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 12240c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 12250c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 12260c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 12270c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 12280c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 12290c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 12300c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 12310c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 12320c72172eSMandeep Singh Grang default: 12330c72172eSMandeep Singh Grang Res = "Unknown"; 12340c72172eSMandeep Singh Grang } 12350c72172eSMandeep Singh Grang break; 1236e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 12378ff24d25SRui Ueyama switch (Reloc->Type) { 1238e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1239e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1240e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1241e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1242e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1243e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1244e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1245e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1246e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1247e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1248e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1249e5fd0047SMichael J. Spencer default: 12508ff24d25SRui Ueyama Res = "Unknown"; 1251e5fd0047SMichael J. Spencer } 1252e5fd0047SMichael J. Spencer break; 1253e5fd0047SMichael J. Spencer default: 12548ff24d25SRui Ueyama Res = "Unknown"; 1255e5fd0047SMichael J. Spencer } 12568ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1257e5fd0047SMichael J. Spencer } 1258e5fd0047SMichael J. Spencer 1259e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1260e5fd0047SMichael J. Spencer 1261c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1262c66d761bSRafael Espindola return !DataDirectory; 1263c66d761bSRafael Espindola } 1264c66d761bSRafael Espindola 1265c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1266c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1267a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1268c2bed429SRui Ueyama } 1269c2bed429SRui Ueyama 12705e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12715e812afaSRafael Espindola ++Index; 12721c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1273ad7b7e73SDavid Majnemer Index = -1; 1274ad7b7e73SDavid Majnemer ImportTable = nullptr; 1275ad7b7e73SDavid Majnemer } 1276c2bed429SRui Ueyama } 1277c2bed429SRui Ueyama 1278db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 12791c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1280ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1281c2bed429SRui Ueyama } 1282c2bed429SRui Ueyama 1283861021f9SRui Ueyama static imported_symbol_iterator 128415d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1285861021f9SRui Ueyama uintptr_t Ptr, int Index) { 128615d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1287861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 128815d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1289861021f9SRui Ueyama } 1290861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 129115d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1292861021f9SRui Ueyama } 1293861021f9SRui Ueyama 129415d99359SRui Ueyama static imported_symbol_iterator 129515d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1296861021f9SRui Ueyama uintptr_t IntPtr = 0; 129715d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 129815d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1299861021f9SRui Ueyama } 1300861021f9SRui Ueyama 130115d99359SRui Ueyama static imported_symbol_iterator 130215d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1303861021f9SRui Ueyama uintptr_t IntPtr = 0; 130415d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1305861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1306861021f9SRui Ueyama int Index = 0; 130715d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1308861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1309861021f9SRui Ueyama while (*Entry++) 1310861021f9SRui Ueyama ++Index; 1311861021f9SRui Ueyama } else { 1312861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1313861021f9SRui Ueyama while (*Entry++) 1314861021f9SRui Ueyama ++Index; 1315861021f9SRui Ueyama } 131615d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 131715d99359SRui Ueyama } 131815d99359SRui Ueyama 131915d99359SRui Ueyama imported_symbol_iterator 132015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 132160049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 132215d99359SRui Ueyama OwningObject); 132315d99359SRui Ueyama } 132415d99359SRui Ueyama 132515d99359SRui Ueyama imported_symbol_iterator 132615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 132760049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 132815d99359SRui Ueyama OwningObject); 1329861021f9SRui Ueyama } 1330861021f9SRui Ueyama 1331979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1332979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1333979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1334979fb40bSRui Ueyama } 1335979fb40bSRui Ueyama 133660049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 133760049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 133860049526SDavid Majnemer OwningObject); 133960049526SDavid Majnemer } 134060049526SDavid Majnemer 134160049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 134260049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 134360049526SDavid Majnemer OwningObject); 134460049526SDavid Majnemer } 134560049526SDavid Majnemer 134660049526SDavid Majnemer iterator_range<imported_symbol_iterator> 134760049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 134860049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 134960049526SDavid Majnemer } 135060049526SDavid Majnemer 1351db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1352c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1353db4ed0bdSRafael Espindola if (std::error_code EC = 13541e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1355a045b73aSRui Ueyama return EC; 1356a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13577d099195SRui Ueyama return std::error_code(); 1358c2bed429SRui Ueyama } 1359c2bed429SRui Ueyama 13601e152d5eSRui Ueyama std::error_code 13611e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 13621e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 13637d099195SRui Ueyama return std::error_code(); 13641e152d5eSRui Ueyama } 13651e152d5eSRui Ueyama 13661e152d5eSRui Ueyama std::error_code 13671e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 13681e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 13697d099195SRui Ueyama return std::error_code(); 13701e152d5eSRui Ueyama } 13711e152d5eSRui Ueyama 137215d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 137315d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 137415d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 137515d99359SRui Ueyama } 137615d99359SRui Ueyama 137715d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 137815d99359SRui Ueyama ++Index; 137915d99359SRui Ueyama } 138015d99359SRui Ueyama 138115d99359SRui Ueyama imported_symbol_iterator 138215d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 138315d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 138415d99359SRui Ueyama OwningObject); 138515d99359SRui Ueyama } 138615d99359SRui Ueyama 138715d99359SRui Ueyama imported_symbol_iterator 138815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 138915d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 139015d99359SRui Ueyama OwningObject); 139115d99359SRui Ueyama } 139215d99359SRui Ueyama 1393979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1394979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1395979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1396979fb40bSRui Ueyama } 1397979fb40bSRui Ueyama 139815d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 139915d99359SRui Ueyama uintptr_t IntPtr = 0; 140015d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 140115d99359SRui Ueyama return EC; 140215d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14037d099195SRui Ueyama return std::error_code(); 140415d99359SRui Ueyama } 140515d99359SRui Ueyama 14061af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 14071af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 14081af08658SRui Ueyama Result = Table; 14097d099195SRui Ueyama return std::error_code(); 14101af08658SRui Ueyama } 14111af08658SRui Ueyama 1412ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1413ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1414ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1415ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1416ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1417ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1418ffa4cebeSRui Ueyama return EC; 1419ffa4cebeSRui Ueyama if (OwningObject->is64()) 14205dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1421ffa4cebeSRui Ueyama else 14225dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 14237d099195SRui Ueyama return std::error_code(); 1424ffa4cebeSRui Ueyama } 1425ffa4cebeSRui Ueyama 1426ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1427ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1428ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1429ad882ba8SRui Ueyama } 1430ad882ba8SRui Ueyama 14315e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 14325e812afaSRafael Espindola ++Index; 1433ad882ba8SRui Ueyama } 1434ad882ba8SRui Ueyama 1435da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1436da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1437db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1438da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1439db4ed0bdSRafael Espindola if (std::error_code EC = 1440db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1441da49d0d4SRui Ueyama return EC; 1442da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14437d099195SRui Ueyama return std::error_code(); 1444da49d0d4SRui Ueyama } 1445da49d0d4SRui Ueyama 1446e5df6095SRui Ueyama // Returns the starting ordinal number. 1447db4ed0bdSRafael Espindola std::error_code 1448db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1449e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 14507d099195SRui Ueyama return std::error_code(); 1451e5df6095SRui Ueyama } 1452e5df6095SRui Ueyama 1453ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1454db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1455ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 14567d099195SRui Ueyama return std::error_code(); 1457ad882ba8SRui Ueyama } 1458ad882ba8SRui Ueyama 1459ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1460db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1461ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1462db4ed0bdSRafael Espindola if (std::error_code EC = 1463db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1464ad882ba8SRui Ueyama return EC; 146524fc2d64SRui Ueyama const export_address_table_entry *entry = 146624fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1467ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 14687d099195SRui Ueyama return std::error_code(); 1469ad882ba8SRui Ueyama } 1470ad882ba8SRui Ueyama 1471ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1472ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1473db4ed0bdSRafael Espindola std::error_code 1474db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1475ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1476db4ed0bdSRafael Espindola if (std::error_code EC = 1477db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1478ad882ba8SRui Ueyama return EC; 1479ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1480ad882ba8SRui Ueyama 1481ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1482ad882ba8SRui Ueyama int Offset = 0; 1483ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1484ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1485ad882ba8SRui Ueyama if (*I != Index) 1486ad882ba8SRui Ueyama continue; 1487db4ed0bdSRafael Espindola if (std::error_code EC = 1488db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1489ad882ba8SRui Ueyama return EC; 1490ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1491db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1492ad882ba8SRui Ueyama return EC; 1493ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14947d099195SRui Ueyama return std::error_code(); 1495ad882ba8SRui Ueyama } 1496ad882ba8SRui Ueyama Result = ""; 14977d099195SRui Ueyama return std::error_code(); 1498ad882ba8SRui Ueyama } 1499ad882ba8SRui Ueyama 15006161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 15016161b38dSRui Ueyama const data_directory *DataEntry; 15026161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 15036161b38dSRui Ueyama return EC; 15046161b38dSRui Ueyama uint32_t RVA; 15056161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15066161b38dSRui Ueyama return EC; 15076161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 15086161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 15096161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 15106161b38dSRui Ueyama return std::error_code(); 15116161b38dSRui Ueyama } 15126161b38dSRui Ueyama 15136161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 15146161b38dSRui Ueyama uint32_t RVA; 15156161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15166161b38dSRui Ueyama return EC; 15176161b38dSRui Ueyama uintptr_t IntPtr = 0; 15186161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 15196161b38dSRui Ueyama return EC; 15206161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15216161b38dSRui Ueyama return std::error_code(); 15226161b38dSRui Ueyama } 15236161b38dSRui Ueyama 1524861021f9SRui Ueyama bool ImportedSymbolRef:: 1525861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1526861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1527861021f9SRui Ueyama && Index == Other.Index; 1528861021f9SRui Ueyama } 1529861021f9SRui Ueyama 1530861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1531861021f9SRui Ueyama ++Index; 1532861021f9SRui Ueyama } 1533861021f9SRui Ueyama 1534861021f9SRui Ueyama std::error_code 1535861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1536861021f9SRui Ueyama uint32_t RVA; 1537861021f9SRui Ueyama if (Entry32) { 1538861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1539861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 15407d099195SRui Ueyama return std::error_code(); 1541861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1542861021f9SRui Ueyama } else { 1543861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 15447d099195SRui Ueyama return std::error_code(); 1545861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1546861021f9SRui Ueyama } 1547861021f9SRui Ueyama uintptr_t IntPtr = 0; 1548861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1549861021f9SRui Ueyama return EC; 1550861021f9SRui Ueyama // +2 because the first two bytes is hint. 1551861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 15527d099195SRui Ueyama return std::error_code(); 1553861021f9SRui Ueyama } 1554861021f9SRui Ueyama 1555ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1556ad7b7e73SDavid Majnemer if (Entry32) 1557ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1558ad7b7e73SDavid Majnemer else 1559ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1560ad7b7e73SDavid Majnemer return std::error_code(); 1561ad7b7e73SDavid Majnemer } 1562ad7b7e73SDavid Majnemer 1563ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1564ad7b7e73SDavid Majnemer if (Entry32) 1565ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1566ad7b7e73SDavid Majnemer else 1567ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1568ad7b7e73SDavid Majnemer return std::error_code(); 1569ad7b7e73SDavid Majnemer } 1570ad7b7e73SDavid Majnemer 1571861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1572861021f9SRui Ueyama uint32_t RVA; 1573861021f9SRui Ueyama if (Entry32) { 1574861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1575861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 15767d099195SRui Ueyama return std::error_code(); 1577861021f9SRui Ueyama } 1578861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1579861021f9SRui Ueyama } else { 1580861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1581861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 15827d099195SRui Ueyama return std::error_code(); 1583861021f9SRui Ueyama } 1584861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1585861021f9SRui Ueyama } 1586861021f9SRui Ueyama uintptr_t IntPtr = 0; 1587861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1588861021f9SRui Ueyama return EC; 1589861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15907d099195SRui Ueyama return std::error_code(); 1591861021f9SRui Ueyama } 1592861021f9SRui Ueyama 1593437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 159448af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1595db4ed0bdSRafael Espindola std::error_code EC; 159648af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1597692410efSRafael Espindola if (EC) 1598692410efSRafael Espindola return EC; 1599437b0d58SRafael Espindola return std::move(Ret); 1600686738e2SRui Ueyama } 160174e85130SRui Ueyama 160274e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 160374e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 160474e85130SRui Ueyama } 160574e85130SRui Ueyama 160674e85130SRui Ueyama void BaseRelocRef::moveNext() { 160774e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 160874e85130SRui Ueyama // size of the header itself. 160974e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1610970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 161174e85130SRui Ueyama if (Size == Header->BlockSize) { 161274e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 161374e85130SRui Ueyama // consists of the header followed by entries. The header contains 161474e85130SRui Ueyama // how many entories will follow. When we reach the end of the 161574e85130SRui Ueyama // current block, proceed to the next block. 161674e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 161774e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 161874e85130SRui Ueyama Index = 0; 161974e85130SRui Ueyama } else { 162074e85130SRui Ueyama ++Index; 162174e85130SRui Ueyama } 162274e85130SRui Ueyama } 162374e85130SRui Ueyama 162474e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 162574e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 162674e85130SRui Ueyama Type = Entry[Index].getType(); 16277d099195SRui Ueyama return std::error_code(); 162874e85130SRui Ueyama } 162974e85130SRui Ueyama 163074e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 163174e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 163274e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 16337d099195SRui Ueyama return std::error_code(); 163474e85130SRui Ueyama } 1635efef15a0SEric Beckmann 1636efef15a0SEric Beckmann #define RETURN_IF_ERROR(X) \ 1637efef15a0SEric Beckmann if (auto EC = errorToErrorCode(X)) \ 1638efef15a0SEric Beckmann return EC; 1639efef15a0SEric Beckmann 1640cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1641efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1642efef15a0SEric Beckmann Reader.setOffset(Offset); 1643efef15a0SEric Beckmann uint16_t Length; 1644efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1645efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1646efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1647cd704cb6SEric Beckmann return RawDirString; 1648efef15a0SEric Beckmann } 1649efef15a0SEric Beckmann 1650cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> 1651efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1652efef15a0SEric Beckmann return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1653efef15a0SEric Beckmann } 1654efef15a0SEric Beckmann 1655efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> 1656efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1657efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1658efef15a0SEric Beckmann 1659efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1660efef15a0SEric Beckmann Reader.setOffset(Offset); 1661efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1662efef15a0SEric Beckmann assert(Table != nullptr); 1663efef15a0SEric Beckmann return *Table; 1664efef15a0SEric Beckmann } 1665efef15a0SEric Beckmann 1666efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> 1667efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 1668efef15a0SEric Beckmann return getTableAtOffset(Entry.Offset.value()); 1669efef15a0SEric Beckmann } 1670efef15a0SEric Beckmann 1671efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1672efef15a0SEric Beckmann return getTableAtOffset(0); 1673efef15a0SEric Beckmann } 1674