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 55e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, 5694751be7SDavid Majnemer const uint64_t Size) { 57e830c60dSDavid Majnemer if (Addr + Size < Addr || Addr + Size < Size || 58e830c60dSDavid Majnemer Addr + Size > uintptr_t(M.getBufferEnd()) || 59e830c60dSDavid Majnemer Addr < uintptr_t(M.getBufferStart())) { 60e830c60dSDavid Majnemer return object_error::unexpected_eof; 61e830c60dSDavid Majnemer } 627d099195SRui Ueyama return std::error_code(); 63e830c60dSDavid Majnemer } 64e830c60dSDavid Majnemer 65ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 66ed64342bSRui Ueyama // Returns unexpected_eof if error. 67ed64342bSRui Ueyama template <typename T> 6848af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 6958323a97SDavid Majnemer const void *Ptr, 70236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 71ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 72e830c60dSDavid Majnemer if (std::error_code EC = checkOffset(M, Addr, Size)) 73e830c60dSDavid Majnemer return EC; 74ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 757d099195SRui Ueyama return std::error_code(); 761d6167fdSMichael J. Spencer } 771d6167fdSMichael J. Spencer 789d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 799d2c15efSNico Rieck // prefixed slashes. 809d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 819d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 829d2c15efSNico Rieck if (Str.size() > 6) 839d2c15efSNico Rieck return true; 849d2c15efSNico Rieck 859d2c15efSNico Rieck uint64_t Value = 0; 869d2c15efSNico Rieck while (!Str.empty()) { 879d2c15efSNico Rieck unsigned CharVal; 889d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 899d2c15efSNico Rieck CharVal = Str[0] - 'A'; 909d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 919d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 929d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 939d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 949d2c15efSNico Rieck else if (Str[0] == '+') // 62 955500b07cSRui Ueyama CharVal = 62; 969d2c15efSNico Rieck else if (Str[0] == '/') // 63 975500b07cSRui Ueyama CharVal = 63; 989d2c15efSNico Rieck else 999d2c15efSNico Rieck return true; 1009d2c15efSNico Rieck 1019d2c15efSNico Rieck Value = (Value * 64) + CharVal; 1029d2c15efSNico Rieck Str = Str.substr(1); 1039d2c15efSNico Rieck } 1049d2c15efSNico Rieck 1059d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 1069d2c15efSNico Rieck return true; 1079d2c15efSNico Rieck 1089d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 1099d2c15efSNico Rieck return false; 1109d2c15efSNico Rieck } 1119d2c15efSNico Rieck 11244f51e51SDavid Majnemer template <typename coff_symbol_type> 11344f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 11444f51e51SDavid Majnemer const coff_symbol_type *Addr = 11544f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1161d6167fdSMichael J. Spencer 117236b0ca7SDavid Majnemer assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 1181d6167fdSMichael J. Spencer #ifndef NDEBUG 1191d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1208ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 1211d6167fdSMichael J. Spencer 12244f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 12344f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1241d6167fdSMichael J. Spencer #endif 1251d6167fdSMichael J. Spencer 1268ff24d25SRui Ueyama return Addr; 1271d6167fdSMichael J. Spencer } 1281d6167fdSMichael J. Spencer 1298ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1308ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1311d6167fdSMichael J. Spencer 1321d6167fdSMichael J. Spencer #ifndef NDEBUG 1331d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 13444f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1351d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1361d6167fdSMichael J. Spencer 1378ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1388ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1391d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1401d6167fdSMichael J. Spencer #endif 1411d6167fdSMichael J. Spencer 1428ff24d25SRui Ueyama return Addr; 1431d6167fdSMichael J. Spencer } 1441d6167fdSMichael J. Spencer 1455e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 146236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 14744f51e51SDavid Majnemer if (SymbolTable16) { 14844f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1498ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 150236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 15144f51e51SDavid Majnemer } else if (SymbolTable32) { 15244f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 15344f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 154236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 15544f51e51SDavid Majnemer } else { 15644f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 15744f51e51SDavid Majnemer } 1581d6167fdSMichael J. Spencer } 1591d6167fdSMichael J. Spencer 16081e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 16144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1625d0c2ffaSRafael Espindola StringRef Result; 163efef15a0SEric Beckmann if (std::error_code EC = getSymbolName(Symb, Result)) 16481e8b7d9SKevin Enderby return errorCodeToError(EC); 1655d0c2ffaSRafael Espindola return Result; 1668e90adafSMichael J. Spencer } 1678e90adafSMichael J. Spencer 168be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 169be8b0ea8SRafael Espindola return getCOFFSymbol(Ref).getValue(); 170991af666SRafael Espindola } 171991af666SRafael Espindola 1726b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 1736b2bba14SDavide Italiano // MSVC/link.exe seems to align symbols to the next-power-of-2 1746b2bba14SDavide Italiano // up to 32 bytes. 1756b2bba14SDavide Italiano COFFSymbolRef Symb = getCOFFSymbol(Ref); 17603a85680SDavide Italiano return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 1776b2bba14SDavide Italiano } 1786b2bba14SDavide Italiano 179931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 180ed067c45SRafael Espindola uint64_t Result = getSymbolValue(Ref); 18144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 182c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 183991af666SRafael Espindola 184991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 185991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 186ed067c45SRafael Espindola return Result; 18754c9f3daSRafael Espindola 1882617dcceSCraig Topper const coff_section *Section = nullptr; 189c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 190931cb65dSKevin Enderby return errorCodeToError(EC); 191991af666SRafael Espindola Result += Section->VirtualAddress; 19247ea9eceSReid Kleckner 19347ea9eceSReid Kleckner // The section VirtualAddress does not include ImageBase, and we want to 19447ea9eceSReid Kleckner // return virtual addresses. 19521427adaSReid Kleckner Result += getImageBase(); 19647ea9eceSReid Kleckner 197ed067c45SRafael Espindola return Result; 198c7d7c6fbSDavid Majnemer } 199c7d7c6fbSDavid Majnemer 2007bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 20144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 202c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 20344f51e51SDavid Majnemer 204e834f420SPeter Collingbourne if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 205e834f420SPeter Collingbourne return SymbolRef::ST_Function; 2062fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 2072fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 2082fa80cc5SRafael Espindola if (Symb.isCommon()) 2092fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2102fa80cc5SRafael Espindola if (Symb.isFileRecord()) 2112fa80cc5SRafael Espindola return SymbolRef::ST_File; 2122fa80cc5SRafael Espindola 2131a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 2142fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 2152fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 2162fa80cc5SRafael Espindola 2172fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 2182fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2192fa80cc5SRafael Espindola 2202fa80cc5SRafael Espindola return SymbolRef::ST_Other; 22175d1cf33SBenjamin Kramer } 22275d1cf33SBenjamin Kramer 22320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 22444f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 22520122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 22675d1cf33SBenjamin Kramer 227c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2289dc0eb42SLang Hames Result |= SymbolRef::SF_Global; 2291df4b84dSDavid Meyer 230c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2311df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2321df4b84dSDavid Meyer 23344f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2341df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2351df4b84dSDavid Meyer 236c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 237c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 238c7d7c6fbSDavid Majnemer 239c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 240c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 241c7d7c6fbSDavid Majnemer 242c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 243c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 244c7d7c6fbSDavid Majnemer 245c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 246c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 247c7d7c6fbSDavid Majnemer 24820122a43SRafael Espindola return Result; 24901759754SMichael J. Spencer } 25001759754SMichael J. Spencer 251d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 252c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2535eb02e45SRafael Espindola return Symb.getValue(); 2548e90adafSMichael J. Spencer } 2558e90adafSMichael J. Spencer 2567bd8d994SKevin Enderby Expected<section_iterator> 2578bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 25844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2598bab889bSRafael Espindola if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2608bab889bSRafael Espindola return section_end(); 2612617dcceSCraig Topper const coff_section *Sec = nullptr; 26244f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 2637bd8d994SKevin Enderby return errorCodeToError(EC); 2648bab889bSRafael Espindola DataRefImpl Ret; 2658bab889bSRafael Espindola Ret.p = reinterpret_cast<uintptr_t>(Sec); 2668bab889bSRafael Espindola return section_iterator(SectionRef(Ret, this)); 26732173153SMichael J. Spencer } 26832173153SMichael J. Spencer 2696bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2706bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2716bf32210SRafael Espindola return Symb.getSectionNumber(); 2726bf32210SRafael Espindola } 2736bf32210SRafael Espindola 2745e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2758ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2768ff24d25SRui Ueyama Sec += 1; 2778ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2788e90adafSMichael J. Spencer } 2798e90adafSMichael J. Spencer 280db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2811d6167fdSMichael J. Spencer StringRef &Result) const { 2828ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2838ff24d25SRui Ueyama return getSectionName(Sec, Result); 2848e90adafSMichael J. Spencer } 2858e90adafSMichael J. Spencer 28680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2878ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2887c6a071bSDavid Majnemer uint64_t Result = Sec->VirtualAddress; 2897c6a071bSDavid Majnemer 2907c6a071bSDavid Majnemer // The section VirtualAddress does not include ImageBase, and we want to 2917c6a071bSDavid Majnemer // return virtual addresses. 29221427adaSReid Kleckner Result += getImageBase(); 2937c6a071bSDavid Majnemer return Result; 2948e90adafSMichael J. Spencer } 2958e90adafSMichael J. Spencer 296a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 297a25d329bSGeorge Rimar return toSec(Sec) - SectionTable; 298a25d329bSGeorge Rimar } 299a25d329bSGeorge Rimar 30080291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 301a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 3028e90adafSMichael J. Spencer } 3038e90adafSMichael J. Spencer 304db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 3051d6167fdSMichael J. Spencer StringRef &Result) const { 3068ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3079da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 308db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3099da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3109da9e693SMichael J. Spencer return EC; 3118e90adafSMichael J. Spencer } 3128e90adafSMichael J. Spencer 31380291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3148ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 315511391feSDavid Majnemer return Sec->getAlignment(); 3167989460aSMichael J. Spencer } 3177989460aSMichael J. Spencer 318401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 319401e4e57SGeorge Rimar return false; 320401e4e57SGeorge Rimar } 321401e4e57SGeorge Rimar 32280291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3238ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3258e90adafSMichael J. Spencer } 3268e90adafSMichael J. Spencer 32780291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3288ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32980291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 330800619f2SMichael J. Spencer } 331800619f2SMichael J. Spencer 33280291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3338ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3341a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3351a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3361a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3371a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 338800619f2SMichael J. Spencer } 339800619f2SMichael J. Spencer 3406bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3416bf32210SRafael Espindola uintptr_t Offset = 3426bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3436bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3446bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3456bf32210SRafael Espindola } 3466bf32210SRafael Espindola 34780291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3488ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3491a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3501a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3511a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3522138ef6dSPreston Gurd } 3532138ef6dSPreston Gurd 354e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 355e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 356e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 357e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 358e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 359e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 360e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 361e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 362e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 363e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 364e830c60dSDavid Majnemer return 0; 36598fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 36698fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 367e830c60dSDavid Majnemer } 368e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 369e830c60dSDavid Majnemer } 370e830c60dSDavid Majnemer 37194751be7SDavid Majnemer static const coff_relocation * 37294751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 37394751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 37494751be7SDavid Majnemer if (!NumRelocs) 37594751be7SDavid Majnemer return nullptr; 376827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 37794751be7SDavid Majnemer Base + Sec->PointerToRelocations); 378827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 379827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 380827c8a2bSRui Ueyama // relocations. 381827c8a2bSRui Ueyama begin++; 382827c8a2bSRui Ueyama } 38394751be7SDavid Majnemer if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 38494751be7SDavid Majnemer return nullptr; 38594751be7SDavid Majnemer return begin; 386827c8a2bSRui Ueyama } 38794751be7SDavid Majnemer 38894751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 38994751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 39094751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 39176d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 39276d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 39394751be7SDavid Majnemer DataRefImpl Ret; 39494751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3958ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 396e5fd0047SMichael J. Spencer } 397e5fd0047SMichael J. Spencer 3988ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3998ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 40094751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 40194751be7SDavid Majnemer if (I) 40294751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 4038ff24d25SRui Ueyama DataRefImpl Ret; 40494751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 4058ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 406e5fd0047SMichael J. Spencer } 407e5fd0047SMichael J. Spencer 408c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 409db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 41044f51e51SDavid Majnemer if (COFFHeader) 411236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 412236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 413236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 41444f51e51SDavid Majnemer return EC; 41544f51e51SDavid Majnemer 41644f51e51SDavid Majnemer if (COFFBigObjHeader) 417236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 418236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 419236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4208ff24d25SRui Ueyama return EC; 421c2bed429SRui Ueyama 422c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 423c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 424c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 425f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 42644f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 427f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 428c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 42948af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4308ff24d25SRui Ueyama return EC; 431c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 432db4ed0bdSRafael Espindola if (std::error_code EC = 43348af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4348ff24d25SRui Ueyama return EC; 435c2bed429SRui Ueyama 436773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 437773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 438773a5795SNico Rieck if (StringTableSize < 4) 439773a5795SNico Rieck StringTableSize = 4; 440773a5795SNico Rieck 441c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 442773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 443c2bed429SRui Ueyama return object_error::parse_failed; 4447d099195SRui Ueyama return std::error_code(); 445c2bed429SRui Ueyama } 446c2bed429SRui Ueyama 44721427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 448e94fef7bSReid Kleckner if (PE32Header) 44921427adaSReid Kleckner return PE32Header->ImageBase; 450e94fef7bSReid Kleckner else if (PE32PlusHeader) 45121427adaSReid Kleckner return PE32PlusHeader->ImageBase; 45221427adaSReid Kleckner // This actually comes up in practice. 45321427adaSReid Kleckner return 0; 454e94fef7bSReid Kleckner } 455e94fef7bSReid Kleckner 456215a586cSRui Ueyama // Returns the file offset for the given VA. 457db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 45821427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 459b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 460b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 461b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 462215a586cSRui Ueyama } 463215a586cSRui Ueyama 464c2bed429SRui Ueyama // Returns the file offset for the given RVA. 465db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 46627dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 46727dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 468c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 469c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 470215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 471215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 472c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4737d099195SRui Ueyama return std::error_code(); 474c2bed429SRui Ueyama } 475c2bed429SRui Ueyama } 476c2bed429SRui Ueyama return object_error::parse_failed; 477c2bed429SRui Ueyama } 478c2bed429SRui Ueyama 4792da433eaSReid Kleckner std::error_code 4802da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4812da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4822da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4832da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4842da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4852da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4862da433eaSReid Kleckner // overflow. 4872da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4882da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4892da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4902da433eaSReid Kleckner uintptr_t Begin = 4912da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4922da433eaSReid Kleckner Contents = 4932da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4942da433eaSReid Kleckner return std::error_code(); 4952da433eaSReid Kleckner } 4962da433eaSReid Kleckner } 4972da433eaSReid Kleckner return object_error::parse_failed; 4982da433eaSReid Kleckner } 4992da433eaSReid Kleckner 500c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 501c2bed429SRui Ueyama // table entry. 502db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 503db4ed0bdSRafael Espindola StringRef &Name) const { 504c2bed429SRui Ueyama uintptr_t IntPtr = 0; 505db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 5068ff24d25SRui Ueyama return EC; 507c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 508c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 509c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5107d099195SRui Ueyama return std::error_code(); 511c2bed429SRui Ueyama } 512c2bed429SRui Ueyama 51301528021SSaleem Abdulrasool std::error_code 51401528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 51501528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5162da433eaSReid Kleckner StringRef &PDBFileName) const { 5172da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5182da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 5192da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5202da433eaSReid Kleckner return EC; 52101528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5222da433eaSReid Kleckner return object_error::parse_failed; 52301528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 52401528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5252da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5262da433eaSReid Kleckner InfoBytes.size()); 5272da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5282da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5292da433eaSReid Kleckner return std::error_code(); 5302da433eaSReid Kleckner } 5312da433eaSReid Kleckner 53201528021SSaleem Abdulrasool std::error_code 53301528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 534f27f3f84SReid Kleckner StringRef &PDBFileName) const { 535f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 536f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 537f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 538f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 539f27f3f84SReid Kleckner PDBInfo = nullptr; 540f27f3f84SReid Kleckner PDBFileName = StringRef(); 541f27f3f84SReid Kleckner return std::error_code(); 542f27f3f84SReid Kleckner } 543f27f3f84SReid Kleckner 544c2bed429SRui Ueyama // Find the import table. 545db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 546c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 547c2bed429SRui Ueyama // the import table, do nothing. 548c2bed429SRui Ueyama const data_directory *DataEntry; 549c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5507d099195SRui Ueyama return std::error_code(); 551c2bed429SRui Ueyama 552c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 553c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5547d099195SRui Ueyama return std::error_code(); 555c2bed429SRui Ueyama 556c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 557c2bed429SRui Ueyama 558c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 559c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 560c2bed429SRui Ueyama uintptr_t IntPtr = 0; 561db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5628ff24d25SRui Ueyama return EC; 563ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 564ad7b7e73SDavid Majnemer return EC; 565c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5661c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5677d099195SRui Ueyama return std::error_code(); 568ad882ba8SRui Ueyama } 569c2bed429SRui Ueyama 57015d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 57115d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 57215d99359SRui Ueyama const data_directory *DataEntry; 57315d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5747d099195SRui Ueyama return std::error_code(); 57515d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5767d099195SRui Ueyama return std::error_code(); 57715d99359SRui Ueyama 57815d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 57915d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 58015d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 58115d99359SRui Ueyama 58215d99359SRui Ueyama uintptr_t IntPtr = 0; 58315d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 58415d99359SRui Ueyama return EC; 58515d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 58615d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5877d099195SRui Ueyama return std::error_code(); 58815d99359SRui Ueyama } 58915d99359SRui Ueyama 590ad882ba8SRui Ueyama // Find the export table. 591db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 592ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 593ad882ba8SRui Ueyama // the export table, do nothing. 594ad882ba8SRui Ueyama const data_directory *DataEntry; 595ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5967d099195SRui Ueyama return std::error_code(); 597ad882ba8SRui Ueyama 598ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 599ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6007d099195SRui Ueyama return std::error_code(); 601ad882ba8SRui Ueyama 602ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 603ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 604db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 605ad882ba8SRui Ueyama return EC; 60624fc2d64SRui Ueyama ExportDirectory = 60724fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6087d099195SRui Ueyama return std::error_code(); 609c2bed429SRui Ueyama } 610c2bed429SRui Ueyama 61174e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 61274e85130SRui Ueyama const data_directory *DataEntry; 61374e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 6147d099195SRui Ueyama return std::error_code(); 61574e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6167d099195SRui Ueyama return std::error_code(); 61774e85130SRui Ueyama 61874e85130SRui Ueyama uintptr_t IntPtr = 0; 61974e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 62074e85130SRui Ueyama return EC; 62174e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 62274e85130SRui Ueyama IntPtr); 62374e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 62474e85130SRui Ueyama IntPtr + DataEntry->Size); 6257d099195SRui Ueyama return std::error_code(); 62674e85130SRui Ueyama } 62774e85130SRui Ueyama 6282da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6292da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6302da433eaSReid Kleckner const data_directory *DataEntry; 6312da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6322da433eaSReid Kleckner return std::error_code(); 6332da433eaSReid Kleckner 6342da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6352da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6362da433eaSReid Kleckner return std::error_code(); 6372da433eaSReid Kleckner 6382da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6392da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6402da433eaSReid Kleckner return object_error::parse_failed; 6412da433eaSReid Kleckner 6422da433eaSReid Kleckner uintptr_t IntPtr = 0; 6432da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6442da433eaSReid Kleckner return EC; 6452da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6462da433eaSReid Kleckner if (std::error_code EC = getRvaPtr( 6472da433eaSReid Kleckner DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 6482da433eaSReid Kleckner return EC; 6492da433eaSReid Kleckner DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 6502da433eaSReid Kleckner return std::error_code(); 6512da433eaSReid Kleckner } 6522da433eaSReid Kleckner 653b7d716c0SReid Kleckner std::error_code COFFObjectFile::initLoadConfigPtr() { 654b7d716c0SReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 655b7d716c0SReid Kleckner const data_directory *DataEntry; 656b7d716c0SReid Kleckner if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry)) 657b7d716c0SReid Kleckner return std::error_code(); 658b7d716c0SReid Kleckner 659b7d716c0SReid Kleckner // Do nothing if the RVA is NULL. 660b7d716c0SReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 661b7d716c0SReid Kleckner return std::error_code(); 662b7d716c0SReid Kleckner uintptr_t IntPtr = 0; 663b7d716c0SReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 664b7d716c0SReid Kleckner return EC; 665b7d716c0SReid Kleckner 666b7d716c0SReid Kleckner LoadConfig = (const void *)IntPtr; 667b7d716c0SReid Kleckner return std::error_code(); 668b7d716c0SReid Kleckner } 669b7d716c0SReid Kleckner 67048af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 67148af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 67244f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 67344f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 67444f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 675ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 67615d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6772da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6782da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6791d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 68048af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 681c3f9b5a5SRafael Espindola return; 682ee066fc4SEric Christopher 68382ebd8e3SRui Ueyama // The current location in the file where we are looking at. 68482ebd8e3SRui Ueyama uint64_t CurPtr = 0; 68582ebd8e3SRui Ueyama 68682ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 68782ebd8e3SRui Ueyama // it is placed right after COFF header. 6888ff24d25SRui Ueyama bool HasPEHeader = false; 689ee066fc4SEric Christopher 6901d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 69150267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 692ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 693ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 69450267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 69550267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 69650267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 69782ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 69850267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6998ff24d25SRui Ueyama EC = object_error::parse_failed; 7001d6167fdSMichael J. Spencer return; 7011d6167fdSMichael J. Spencer } 70244f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 7038ff24d25SRui Ueyama HasPEHeader = true; 704ee066fc4SEric Christopher } 70550267222SDavid Majnemer } 706ee066fc4SEric Christopher 70748af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 7081d6167fdSMichael J. Spencer return; 70944f51e51SDavid Majnemer 71044f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 71144f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 71244f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 71344f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 71444f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 71544f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 71644f51e51SDavid Majnemer return; 71744f51e51SDavid Majnemer 71844f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 71944f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 72044f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 72144f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 72244f51e51SDavid Majnemer COFFHeader = nullptr; 72344f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 72444f51e51SDavid Majnemer } else { 72544f51e51SDavid Majnemer // It's not a bigobj. 72644f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 72744f51e51SDavid Majnemer } 72844f51e51SDavid Majnemer } 72944f51e51SDavid Majnemer if (COFFHeader) { 73044f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 73144f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7327d099195SRui Ueyama EC = std::error_code(); 73382ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 73482ebd8e3SRui Ueyama 73544f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 73644f51e51SDavid Majnemer return; 73744f51e51SDavid Majnemer } 73844f51e51SDavid Majnemer 7398ff24d25SRui Ueyama if (HasPEHeader) { 74010ed9ddcSRui Ueyama const pe32_header *Header; 74148af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 74282ebd8e3SRui Ueyama return; 74310ed9ddcSRui Ueyama 74410ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 74510ed9ddcSRui Ueyama uint64_t DataDirSize; 74650267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 74710ed9ddcSRui Ueyama PE32Header = Header; 74810ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 74910ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 75050267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 75110ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 75210ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 75310ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 75410ed9ddcSRui Ueyama } else { 75510ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 75610ed9ddcSRui Ueyama EC = object_error::parse_failed; 757ed64342bSRui Ueyama return; 758ed64342bSRui Ueyama } 75948af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 76010ed9ddcSRui Ueyama return; 761f53c8cb4SRui Ueyama } 762776c6828SRui Ueyama 7638950a538SRui Ueyama if (COFFHeader) 7648950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7658950a538SRui Ueyama 76648af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 767236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7681d6167fdSMichael J. Spencer return; 7691d6167fdSMichael J. Spencer 770c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 771236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 772ac8cfab5SDavid Majnemer if ((EC = initSymbolTablePtr())) { 773ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 774ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 775ac8cfab5SDavid Majnemer StringTable = nullptr; 776ac8cfab5SDavid Majnemer StringTableSize = 0; 777ac8cfab5SDavid Majnemer } 778236b0ca7SDavid Majnemer } else { 779236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 780236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 781236b0ca7SDavid Majnemer EC = object_error::parse_failed; 782236b0ca7SDavid Majnemer return; 783236b0ca7SDavid Majnemer } 784236b0ca7SDavid Majnemer } 7858e90adafSMichael J. Spencer 786c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7878ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 788ed64342bSRui Ueyama return; 78915d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 79015d99359SRui Ueyama return; 7911d6167fdSMichael J. Spencer 792ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7938ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 794ad882ba8SRui Ueyama return; 795ad882ba8SRui Ueyama 79674e85130SRui Ueyama // Initialize the pointer to the base relocation table. 79774e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 79874e85130SRui Ueyama return; 79974e85130SRui Ueyama 8002da433eaSReid Kleckner // Initialize the pointer to the export table. 8012da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 8022da433eaSReid Kleckner return; 8032da433eaSReid Kleckner 804b7d716c0SReid Kleckner if ((EC = initLoadConfigPtr())) 805b7d716c0SReid Kleckner return; 806b7d716c0SReid Kleckner 8077d099195SRui Ueyama EC = std::error_code(); 8088e90adafSMichael J. Spencer } 8098e90adafSMichael J. Spencer 810435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 8118ff24d25SRui Ueyama DataRefImpl Ret; 81244f51e51SDavid Majnemer Ret.p = getSymbolTable(); 813f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8148e90adafSMichael J. Spencer } 8158e90adafSMichael J. Spencer 816435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 8178e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 8188ff24d25SRui Ueyama DataRefImpl Ret; 8198ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 820f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8218e90adafSMichael J. Spencer } 8228e90adafSMichael J. Spencer 823bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 824ad7b7e73SDavid Majnemer if (!ImportDirectory) 825ad7b7e73SDavid Majnemer return import_directory_end(); 8261c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 827ad7b7e73SDavid Majnemer return import_directory_end(); 828a045b73aSRui Ueyama return import_directory_iterator( 829a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 830c2bed429SRui Ueyama } 831c2bed429SRui Ueyama 832bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 833a045b73aSRui Ueyama return import_directory_iterator( 834ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 835c2bed429SRui Ueyama } 836c429b80dSDavid Meyer 83715d99359SRui Ueyama delay_import_directory_iterator 83815d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 83915d99359SRui Ueyama return delay_import_directory_iterator( 84015d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 84115d99359SRui Ueyama } 84215d99359SRui Ueyama 84315d99359SRui Ueyama delay_import_directory_iterator 84415d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 84515d99359SRui Ueyama return delay_import_directory_iterator( 84615d99359SRui Ueyama DelayImportDirectoryEntryRef( 84715d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 84815d99359SRui Ueyama } 84915d99359SRui Ueyama 850ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 851ad882ba8SRui Ueyama return export_directory_iterator( 852ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 853ad882ba8SRui Ueyama } 854ad882ba8SRui Ueyama 855ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8562617dcceSCraig Topper if (!ExportDirectory) 8572617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8588ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 859ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8608ff24d25SRui Ueyama return export_directory_iterator(Ref); 861ad882ba8SRui Ueyama } 862ad882ba8SRui Ueyama 863b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8648ff24d25SRui Ueyama DataRefImpl Ret; 8658ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8668ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8678e90adafSMichael J. Spencer } 8688e90adafSMichael J. Spencer 869b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8708ff24d25SRui Ueyama DataRefImpl Ret; 87144f51e51SDavid Majnemer int NumSections = 87244f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8738ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8748ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8758e90adafSMichael J. Spencer } 8768e90adafSMichael J. Spencer 87774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 87874e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 87974e85130SRui Ueyama } 88074e85130SRui Ueyama 88174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 88274e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 88374e85130SRui Ueyama } 88474e85130SRui Ueyama 8858e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 8860324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 8878e90adafSMichael J. Spencer } 8888e90adafSMichael J. Spencer 8898e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 89044f51e51SDavid Majnemer switch(getMachine()) { 8918e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8928e90adafSMichael J. Spencer return "COFF-i386"; 8938e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8948e90adafSMichael J. Spencer return "COFF-x86-64"; 8959b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8969b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8971eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8981eff5c9cSMartell Malone return "COFF-ARM64"; 8998e90adafSMichael J. Spencer default: 9008e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 9018e90adafSMichael J. Spencer } 9028e90adafSMichael J. Spencer } 9038e90adafSMichael J. Spencer 9048e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 90544f51e51SDavid Majnemer switch (getMachine()) { 9068e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9078e90adafSMichael J. Spencer return Triple::x86; 9088e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9098e90adafSMichael J. Spencer return Triple::x86_64; 9109b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9119b7c0af2SSaleem Abdulrasool return Triple::thumb; 9121eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9131eff5c9cSMartell Malone return Triple::aarch64; 9148e90adafSMichael J. Spencer default: 9158e90adafSMichael J. Spencer return Triple::UnknownArch; 9168e90adafSMichael J. Spencer } 9178e90adafSMichael J. Spencer } 9188e90adafSMichael J. Spencer 919979fb40bSRui Ueyama iterator_range<import_directory_iterator> 920979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 921979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 922979fb40bSRui Ueyama } 923979fb40bSRui Ueyama 924979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 925979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 926979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 927979fb40bSRui Ueyama delay_import_directory_end()); 928979fb40bSRui Ueyama } 929979fb40bSRui Ueyama 930979fb40bSRui Ueyama iterator_range<export_directory_iterator> 931979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 932979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 933979fb40bSRui Ueyama } 934979fb40bSRui Ueyama 93574e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 93674e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 93774e85130SRui Ueyama } 93874e85130SRui Ueyama 939db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 94082ebd8e3SRui Ueyama Res = PE32Header; 9417d099195SRui Ueyama return std::error_code(); 94289a7a5eaSMichael J. Spencer } 94389a7a5eaSMichael J. Spencer 944db4ed0bdSRafael Espindola std::error_code 94510ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 94610ed9ddcSRui Ueyama Res = PE32PlusHeader; 9477d099195SRui Ueyama return std::error_code(); 94810ed9ddcSRui Ueyama } 94910ed9ddcSRui Ueyama 950db4ed0bdSRafael Espindola std::error_code 951db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 952ed64342bSRui Ueyama const data_directory *&Res) const { 953ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 954f69b0585SDavid Majnemer if (!DataDirectory) { 955f69b0585SDavid Majnemer Res = nullptr; 95610ed9ddcSRui Ueyama return object_error::parse_failed; 957f69b0585SDavid Majnemer } 95810ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 95910ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 96010ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 961f69b0585SDavid Majnemer if (Index >= NumEnt) { 962f69b0585SDavid Majnemer Res = nullptr; 963ed64342bSRui Ueyama return object_error::parse_failed; 964f69b0585SDavid Majnemer } 9658ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9667d099195SRui Ueyama return std::error_code(); 967ed64342bSRui Ueyama } 968ed64342bSRui Ueyama 969db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9701d6167fdSMichael J. Spencer const coff_section *&Result) const { 9712617dcceSCraig Topper Result = nullptr; 972236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9737d099195SRui Ueyama return std::error_code(); 974236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9751d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9768ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9777d099195SRui Ueyama return std::error_code(); 9788e90adafSMichael J. Spencer } 979236b0ca7SDavid Majnemer return object_error::parse_failed; 980236b0ca7SDavid Majnemer } 9818e90adafSMichael J. Spencer 982db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9831d6167fdSMichael J. Spencer StringRef &Result) const { 9841d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9851d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9861d6167fdSMichael J. Spencer return object_error::parse_failed; 9878ff24d25SRui Ueyama if (Offset >= StringTableSize) 9881d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9898ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9907d099195SRui Ueyama return std::error_code(); 9918e90adafSMichael J. Spencer } 992022ecdf2SBenjamin Kramer 99344f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 99489a7a5eaSMichael J. Spencer StringRef &Res) const { 995e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 996e40d30f3SRui Ueyama } 997e40d30f3SRui Ueyama 998e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 999e40d30f3SRui Ueyama StringRef &Res) const { 100089a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 1001e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 1002e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 10038ff24d25SRui Ueyama return EC; 10047d099195SRui Ueyama return std::error_code(); 100589a7a5eaSMichael J. Spencer } 100689a7a5eaSMichael J. Spencer 1007e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 100889a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 1009e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 101089a7a5eaSMichael J. Spencer else 101189a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 1012e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 10137d099195SRui Ueyama return std::error_code(); 101489a7a5eaSMichael J. Spencer } 101589a7a5eaSMichael J. Spencer 101644f51e51SDavid Majnemer ArrayRef<uint8_t> 101744f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 10182617dcceSCraig Topper const uint8_t *Aux = nullptr; 101971757ef3SMarshall Clow 102044f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 102144f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 102271757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 102344f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 102471757ef3SMarshall Clow #ifndef NDEBUG 10258ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10268ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 102744f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 102844f51e51SDavid Majnemer Offset >= 102944f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 103071757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 103171757ef3SMarshall Clow 103244f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 103344f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 103471757ef3SMarshall Clow #endif 1035bfb85e67SMarshall Clow } 103644f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 103771757ef3SMarshall Clow } 103871757ef3SMarshall Clow 1039db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 104053c2d547SMichael J. Spencer StringRef &Res) const { 104153c2d547SMichael J. Spencer StringRef Name; 104244f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 104353c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 104453c2d547SMichael J. Spencer Name = Sec->Name; 104553c2d547SMichael J. Spencer else 104653c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 104744f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 104853c2d547SMichael J. Spencer 104953c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10502314b3deSDavid Majnemer if (Name.startswith("/")) { 105153c2d547SMichael J. Spencer uint32_t Offset; 10522314b3deSDavid Majnemer if (Name.startswith("//")) { 10539d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10549d2c15efSNico Rieck return object_error::parse_failed; 10559d2c15efSNico Rieck } else { 105653c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 105753c2d547SMichael J. Spencer return object_error::parse_failed; 10589d2c15efSNico Rieck } 1059db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 10608ff24d25SRui Ueyama return EC; 106153c2d547SMichael J. Spencer } 106253c2d547SMichael J. Spencer 106353c2d547SMichael J. Spencer Res = Name; 10647d099195SRui Ueyama return std::error_code(); 106553c2d547SMichael J. Spencer } 106653c2d547SMichael J. Spencer 1067a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1068a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1069a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1070a9ee5c06SDavid Majnemer // 1071a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1072d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1073a9ee5c06SDavid Majnemer // 1074a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1075a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1076a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1077a9ee5c06SDavid Majnemer // considered to be zero. 1078d5297ee7SRui Ueyama if (getDOSHeader()) 1079d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1080d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1081a9ee5c06SDavid Majnemer } 1082a9ee5c06SDavid Majnemer 1083db4ed0bdSRafael Espindola std::error_code 1084db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10859da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1086e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1087e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1088e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1089ee97c5f0SShoaib Meenai return std::error_code(); 10909da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10919da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10929da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10939da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1094a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1095e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10969da9e693SMichael J. Spencer return object_error::parse_failed; 1097a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10987d099195SRui Ueyama return std::error_code(); 10999da9e693SMichael J. Spencer } 11009da9e693SMichael J. Spencer 1101022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1102e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1103022ecdf2SBenjamin Kramer } 11048ff24d25SRui Ueyama 11055e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1106e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1107e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1108022ecdf2SBenjamin Kramer } 11098ff24d25SRui Ueyama 111096d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 111158323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 111296d071cdSRafael Espindola return R->VirtualAddress; 1113cbe72fc9SDanil Malyshev } 11148ff24d25SRui Ueyama 1115806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1116022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 11178ff24d25SRui Ueyama DataRefImpl Ref; 1118236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1119236b0ca7SDavid Majnemer return symbol_end(); 112044f51e51SDavid Majnemer if (SymbolTable16) 112144f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 112244f51e51SDavid Majnemer else if (SymbolTable32) 112344f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 112444f51e51SDavid Majnemer else 1125c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11268ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1127022ecdf2SBenjamin Kramer } 11288ff24d25SRui Ueyama 112999c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1130022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 113199c041b7SRafael Espindola return R->Type; 1132022ecdf2SBenjamin Kramer } 1133e5fd0047SMichael J. Spencer 113427dc8394SAlexey Samsonov const coff_section * 113527dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 113627dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 113771757ef3SMarshall Clow } 113871757ef3SMarshall Clow 113944f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 114044f51e51SDavid Majnemer if (SymbolTable16) 114144f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 114244f51e51SDavid Majnemer if (SymbolTable32) 114344f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 114444f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 114544f51e51SDavid Majnemer } 114644f51e51SDavid Majnemer 114744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 114844f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 114971757ef3SMarshall Clow } 115071757ef3SMarshall Clow 1151f12b8282SRafael Espindola const coff_relocation * 115227dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 115327dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1154d3e2a76cSMarshall Clow } 1155d3e2a76cSMarshall Clow 11566a75acb1SRui Ueyama iterator_range<const coff_relocation *> 11576a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11586a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 11596a75acb1SRui Ueyama const coff_relocation *E = I; 11606a75acb1SRui Ueyama if (I) 11616a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 11626a75acb1SRui Ueyama return make_range(I, E); 11636a75acb1SRui Ueyama } 11646a75acb1SRui Ueyama 116527dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 116627dc8394SAlexey Samsonov case COFF::reloc_type: \ 116727dc8394SAlexey Samsonov Res = #reloc_type; \ 116827dc8394SAlexey Samsonov break; 1169e5fd0047SMichael J. Spencer 117041bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 117141bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 11728ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11738ff24d25SRui Ueyama StringRef Res; 117444f51e51SDavid Majnemer switch (getMachine()) { 1175e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11768ff24d25SRui Ueyama switch (Reloc->Type) { 1177e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1178e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1179e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1180e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1181e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1182e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1183e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1184e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1185e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1186e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1187e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1188e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1189e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1190e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1191e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1192e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1193e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1194e5fd0047SMichael J. Spencer default: 11958ff24d25SRui Ueyama Res = "Unknown"; 1196e5fd0047SMichael J. Spencer } 1197e5fd0047SMichael J. Spencer break; 11985c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11995c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 12005c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 12015c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 12025c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 12035c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 12045c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 12055c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 12065c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 12075c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 12085c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 12095c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 12105c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 12115c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 12125c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 12135c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 12145c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 12155c503bf4SSaleem Abdulrasool default: 12165c503bf4SSaleem Abdulrasool Res = "Unknown"; 12175c503bf4SSaleem Abdulrasool } 12185c503bf4SSaleem Abdulrasool break; 1219*0c72172eSMandeep Singh Grang case COFF::IMAGE_FILE_MACHINE_ARM64: 1220*0c72172eSMandeep Singh Grang switch (Reloc->Type) { 1221*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 1222*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 1223*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 1224*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 1225*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 1226*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 1227*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 1228*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 1229*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 1230*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 1231*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 1232*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 1233*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 1234*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 1235*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 1236*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 1237*0c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 1238*0c72172eSMandeep Singh Grang default: 1239*0c72172eSMandeep Singh Grang Res = "Unknown"; 1240*0c72172eSMandeep Singh Grang } 1241*0c72172eSMandeep Singh Grang break; 1242e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 12438ff24d25SRui Ueyama switch (Reloc->Type) { 1244e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1245e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1246e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1247e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1248e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1249e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1250e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1251e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1252e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1253e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1254e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1255e5fd0047SMichael J. Spencer default: 12568ff24d25SRui Ueyama Res = "Unknown"; 1257e5fd0047SMichael J. Spencer } 1258e5fd0047SMichael J. Spencer break; 1259e5fd0047SMichael J. Spencer default: 12608ff24d25SRui Ueyama Res = "Unknown"; 1261e5fd0047SMichael J. Spencer } 12628ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1263e5fd0047SMichael J. Spencer } 1264e5fd0047SMichael J. Spencer 1265e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1266e5fd0047SMichael J. Spencer 1267c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1268c66d761bSRafael Espindola return !DataDirectory; 1269c66d761bSRafael Espindola } 1270c66d761bSRafael Espindola 1271c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1272c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1273a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1274c2bed429SRui Ueyama } 1275c2bed429SRui Ueyama 12765e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12775e812afaSRafael Espindola ++Index; 12781c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1279ad7b7e73SDavid Majnemer Index = -1; 1280ad7b7e73SDavid Majnemer ImportTable = nullptr; 1281ad7b7e73SDavid Majnemer } 1282c2bed429SRui Ueyama } 1283c2bed429SRui Ueyama 1284db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 12851c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1286ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1287c2bed429SRui Ueyama } 1288c2bed429SRui Ueyama 1289861021f9SRui Ueyama static imported_symbol_iterator 129015d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1291861021f9SRui Ueyama uintptr_t Ptr, int Index) { 129215d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1293861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 129415d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1295861021f9SRui Ueyama } 1296861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 129715d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1298861021f9SRui Ueyama } 1299861021f9SRui Ueyama 130015d99359SRui Ueyama static imported_symbol_iterator 130115d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1302861021f9SRui Ueyama uintptr_t IntPtr = 0; 130315d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 130415d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1305861021f9SRui Ueyama } 1306861021f9SRui Ueyama 130715d99359SRui Ueyama static imported_symbol_iterator 130815d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1309861021f9SRui Ueyama uintptr_t IntPtr = 0; 131015d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1311861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1312861021f9SRui Ueyama int Index = 0; 131315d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1314861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1315861021f9SRui Ueyama while (*Entry++) 1316861021f9SRui Ueyama ++Index; 1317861021f9SRui Ueyama } else { 1318861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1319861021f9SRui Ueyama while (*Entry++) 1320861021f9SRui Ueyama ++Index; 1321861021f9SRui Ueyama } 132215d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 132315d99359SRui Ueyama } 132415d99359SRui Ueyama 132515d99359SRui Ueyama imported_symbol_iterator 132615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 132760049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 132815d99359SRui Ueyama OwningObject); 132915d99359SRui Ueyama } 133015d99359SRui Ueyama 133115d99359SRui Ueyama imported_symbol_iterator 133215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 133360049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 133415d99359SRui Ueyama OwningObject); 1335861021f9SRui Ueyama } 1336861021f9SRui Ueyama 1337979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1338979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1339979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1340979fb40bSRui Ueyama } 1341979fb40bSRui Ueyama 134260049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 134360049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 134460049526SDavid Majnemer OwningObject); 134560049526SDavid Majnemer } 134660049526SDavid Majnemer 134760049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 134860049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 134960049526SDavid Majnemer OwningObject); 135060049526SDavid Majnemer } 135160049526SDavid Majnemer 135260049526SDavid Majnemer iterator_range<imported_symbol_iterator> 135360049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 135460049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 135560049526SDavid Majnemer } 135660049526SDavid Majnemer 1357db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1358c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1359db4ed0bdSRafael Espindola if (std::error_code EC = 13601e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1361a045b73aSRui Ueyama return EC; 1362a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13637d099195SRui Ueyama return std::error_code(); 1364c2bed429SRui Ueyama } 1365c2bed429SRui Ueyama 13661e152d5eSRui Ueyama std::error_code 13671e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 13681e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 13697d099195SRui Ueyama return std::error_code(); 13701e152d5eSRui Ueyama } 13711e152d5eSRui Ueyama 13721e152d5eSRui Ueyama std::error_code 13731e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 13741e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 13757d099195SRui Ueyama return std::error_code(); 13761e152d5eSRui Ueyama } 13771e152d5eSRui Ueyama 137815d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 137915d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 138015d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 138115d99359SRui Ueyama } 138215d99359SRui Ueyama 138315d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 138415d99359SRui Ueyama ++Index; 138515d99359SRui Ueyama } 138615d99359SRui Ueyama 138715d99359SRui Ueyama imported_symbol_iterator 138815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 138915d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 139015d99359SRui Ueyama OwningObject); 139115d99359SRui Ueyama } 139215d99359SRui Ueyama 139315d99359SRui Ueyama imported_symbol_iterator 139415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 139515d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 139615d99359SRui Ueyama OwningObject); 139715d99359SRui Ueyama } 139815d99359SRui Ueyama 1399979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1400979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1401979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1402979fb40bSRui Ueyama } 1403979fb40bSRui Ueyama 140415d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 140515d99359SRui Ueyama uintptr_t IntPtr = 0; 140615d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 140715d99359SRui Ueyama return EC; 140815d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14097d099195SRui Ueyama return std::error_code(); 141015d99359SRui Ueyama } 141115d99359SRui Ueyama 14121af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 14131af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 14141af08658SRui Ueyama Result = Table; 14157d099195SRui Ueyama return std::error_code(); 14161af08658SRui Ueyama } 14171af08658SRui Ueyama 1418ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1419ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1420ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1421ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1422ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1423ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1424ffa4cebeSRui Ueyama return EC; 1425ffa4cebeSRui Ueyama if (OwningObject->is64()) 14265dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1427ffa4cebeSRui Ueyama else 14285dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 14297d099195SRui Ueyama return std::error_code(); 1430ffa4cebeSRui Ueyama } 1431ffa4cebeSRui Ueyama 1432ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1433ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1434ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1435ad882ba8SRui Ueyama } 1436ad882ba8SRui Ueyama 14375e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 14385e812afaSRafael Espindola ++Index; 1439ad882ba8SRui Ueyama } 1440ad882ba8SRui Ueyama 1441da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1442da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1443db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1444da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1445db4ed0bdSRafael Espindola if (std::error_code EC = 1446db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1447da49d0d4SRui Ueyama return EC; 1448da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14497d099195SRui Ueyama return std::error_code(); 1450da49d0d4SRui Ueyama } 1451da49d0d4SRui Ueyama 1452e5df6095SRui Ueyama // Returns the starting ordinal number. 1453db4ed0bdSRafael Espindola std::error_code 1454db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1455e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 14567d099195SRui Ueyama return std::error_code(); 1457e5df6095SRui Ueyama } 1458e5df6095SRui Ueyama 1459ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1460db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1461ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 14627d099195SRui Ueyama return std::error_code(); 1463ad882ba8SRui Ueyama } 1464ad882ba8SRui Ueyama 1465ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1466db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1467ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1468db4ed0bdSRafael Espindola if (std::error_code EC = 1469db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1470ad882ba8SRui Ueyama return EC; 147124fc2d64SRui Ueyama const export_address_table_entry *entry = 147224fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1473ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 14747d099195SRui Ueyama return std::error_code(); 1475ad882ba8SRui Ueyama } 1476ad882ba8SRui Ueyama 1477ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1478ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1479db4ed0bdSRafael Espindola std::error_code 1480db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1481ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1482db4ed0bdSRafael Espindola if (std::error_code EC = 1483db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1484ad882ba8SRui Ueyama return EC; 1485ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1486ad882ba8SRui Ueyama 1487ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1488ad882ba8SRui Ueyama int Offset = 0; 1489ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1490ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1491ad882ba8SRui Ueyama if (*I != Index) 1492ad882ba8SRui Ueyama continue; 1493db4ed0bdSRafael Espindola if (std::error_code EC = 1494db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1495ad882ba8SRui Ueyama return EC; 1496ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1497db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1498ad882ba8SRui Ueyama return EC; 1499ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15007d099195SRui Ueyama return std::error_code(); 1501ad882ba8SRui Ueyama } 1502ad882ba8SRui Ueyama Result = ""; 15037d099195SRui Ueyama return std::error_code(); 1504ad882ba8SRui Ueyama } 1505ad882ba8SRui Ueyama 15066161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 15076161b38dSRui Ueyama const data_directory *DataEntry; 15086161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 15096161b38dSRui Ueyama return EC; 15106161b38dSRui Ueyama uint32_t RVA; 15116161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15126161b38dSRui Ueyama return EC; 15136161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 15146161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 15156161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 15166161b38dSRui Ueyama return std::error_code(); 15176161b38dSRui Ueyama } 15186161b38dSRui Ueyama 15196161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 15206161b38dSRui Ueyama uint32_t RVA; 15216161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15226161b38dSRui Ueyama return EC; 15236161b38dSRui Ueyama uintptr_t IntPtr = 0; 15246161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 15256161b38dSRui Ueyama return EC; 15266161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15276161b38dSRui Ueyama return std::error_code(); 15286161b38dSRui Ueyama } 15296161b38dSRui Ueyama 1530861021f9SRui Ueyama bool ImportedSymbolRef:: 1531861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1532861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1533861021f9SRui Ueyama && Index == Other.Index; 1534861021f9SRui Ueyama } 1535861021f9SRui Ueyama 1536861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1537861021f9SRui Ueyama ++Index; 1538861021f9SRui Ueyama } 1539861021f9SRui Ueyama 1540861021f9SRui Ueyama std::error_code 1541861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1542861021f9SRui Ueyama uint32_t RVA; 1543861021f9SRui Ueyama if (Entry32) { 1544861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1545861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 15467d099195SRui Ueyama return std::error_code(); 1547861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1548861021f9SRui Ueyama } else { 1549861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 15507d099195SRui Ueyama return std::error_code(); 1551861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1552861021f9SRui Ueyama } 1553861021f9SRui Ueyama uintptr_t IntPtr = 0; 1554861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1555861021f9SRui Ueyama return EC; 1556861021f9SRui Ueyama // +2 because the first two bytes is hint. 1557861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 15587d099195SRui Ueyama return std::error_code(); 1559861021f9SRui Ueyama } 1560861021f9SRui Ueyama 1561ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1562ad7b7e73SDavid Majnemer if (Entry32) 1563ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1564ad7b7e73SDavid Majnemer else 1565ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1566ad7b7e73SDavid Majnemer return std::error_code(); 1567ad7b7e73SDavid Majnemer } 1568ad7b7e73SDavid Majnemer 1569ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1570ad7b7e73SDavid Majnemer if (Entry32) 1571ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1572ad7b7e73SDavid Majnemer else 1573ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1574ad7b7e73SDavid Majnemer return std::error_code(); 1575ad7b7e73SDavid Majnemer } 1576ad7b7e73SDavid Majnemer 1577861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1578861021f9SRui Ueyama uint32_t RVA; 1579861021f9SRui Ueyama if (Entry32) { 1580861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1581861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 15827d099195SRui Ueyama return std::error_code(); 1583861021f9SRui Ueyama } 1584861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1585861021f9SRui Ueyama } else { 1586861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1587861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 15887d099195SRui Ueyama return std::error_code(); 1589861021f9SRui Ueyama } 1590861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1591861021f9SRui Ueyama } 1592861021f9SRui Ueyama uintptr_t IntPtr = 0; 1593861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1594861021f9SRui Ueyama return EC; 1595861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15967d099195SRui Ueyama return std::error_code(); 1597861021f9SRui Ueyama } 1598861021f9SRui Ueyama 1599437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 160048af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1601db4ed0bdSRafael Espindola std::error_code EC; 160248af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1603692410efSRafael Espindola if (EC) 1604692410efSRafael Espindola return EC; 1605437b0d58SRafael Espindola return std::move(Ret); 1606686738e2SRui Ueyama } 160774e85130SRui Ueyama 160874e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 160974e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 161074e85130SRui Ueyama } 161174e85130SRui Ueyama 161274e85130SRui Ueyama void BaseRelocRef::moveNext() { 161374e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 161474e85130SRui Ueyama // size of the header itself. 161574e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1616970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 161774e85130SRui Ueyama if (Size == Header->BlockSize) { 161874e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 161974e85130SRui Ueyama // consists of the header followed by entries. The header contains 162074e85130SRui Ueyama // how many entories will follow. When we reach the end of the 162174e85130SRui Ueyama // current block, proceed to the next block. 162274e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 162374e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 162474e85130SRui Ueyama Index = 0; 162574e85130SRui Ueyama } else { 162674e85130SRui Ueyama ++Index; 162774e85130SRui Ueyama } 162874e85130SRui Ueyama } 162974e85130SRui Ueyama 163074e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 163174e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 163274e85130SRui Ueyama Type = Entry[Index].getType(); 16337d099195SRui Ueyama return std::error_code(); 163474e85130SRui Ueyama } 163574e85130SRui Ueyama 163674e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 163774e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 163874e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 16397d099195SRui Ueyama return std::error_code(); 164074e85130SRui Ueyama } 1641efef15a0SEric Beckmann 1642efef15a0SEric Beckmann #define RETURN_IF_ERROR(X) \ 1643efef15a0SEric Beckmann if (auto EC = errorToErrorCode(X)) \ 1644efef15a0SEric Beckmann return EC; 1645efef15a0SEric Beckmann 1646cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1647efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1648efef15a0SEric Beckmann Reader.setOffset(Offset); 1649efef15a0SEric Beckmann uint16_t Length; 1650efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1651efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1652efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1653cd704cb6SEric Beckmann return RawDirString; 1654efef15a0SEric Beckmann } 1655efef15a0SEric Beckmann 1656cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> 1657efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1658efef15a0SEric Beckmann return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1659efef15a0SEric Beckmann } 1660efef15a0SEric Beckmann 1661efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> 1662efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1663efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1664efef15a0SEric Beckmann 1665efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1666efef15a0SEric Beckmann Reader.setOffset(Offset); 1667efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1668efef15a0SEric Beckmann assert(Table != nullptr); 1669efef15a0SEric Beckmann return *Table; 1670efef15a0SEric Beckmann } 1671efef15a0SEric Beckmann 1672efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> 1673efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 1674efef15a0SEric Beckmann return getTableAtOffset(Entry.Offset.value()); 1675efef15a0SEric Beckmann } 1676efef15a0SEric Beckmann 1677efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1678efef15a0SEric Beckmann return getTableAtOffset(0); 1679efef15a0SEric Beckmann } 1680