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" 18d341c932SEugene Zelenko #include "llvm/Object/Binary.h" 19d341c932SEugene Zelenko #include "llvm/Object/COFF.h" 20d341c932SEugene Zelenko #include "llvm/Object/Error.h" 21d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h" 22efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h" 23f078eff3SRui Ueyama #include "llvm/Support/COFF.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 29680291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 297a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2988e90adafSMichael J. Spencer } 2998e90adafSMichael J. Spencer 300db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 3011d6167fdSMichael J. Spencer StringRef &Result) const { 3028ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3039da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 304db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3059da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3069da9e693SMichael J. Spencer return EC; 3078e90adafSMichael J. Spencer } 3088e90adafSMichael J. Spencer 30980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3108ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 311511391feSDavid Majnemer return Sec->getAlignment(); 3127989460aSMichael J. Spencer } 3137989460aSMichael J. Spencer 314401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 315401e4e57SGeorge Rimar return false; 316401e4e57SGeorge Rimar } 317401e4e57SGeorge Rimar 31880291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3198ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32080291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3218e90adafSMichael J. Spencer } 3228e90adafSMichael J. Spencer 32380291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3248ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32580291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 326800619f2SMichael J. Spencer } 327800619f2SMichael J. Spencer 32880291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3298ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3301a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3311a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3321a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3331a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 334800619f2SMichael J. Spencer } 335800619f2SMichael J. Spencer 3366bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3376bf32210SRafael Espindola uintptr_t Offset = 3386bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3396bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3406bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3416bf32210SRafael Espindola } 3426bf32210SRafael Espindola 34380291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3448ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3451a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3461a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3471a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3482138ef6dSPreston Gurd } 3492138ef6dSPreston Gurd 350e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 351e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 352e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 353e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 354e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 355e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 356e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 357e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 358e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 359e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 360e830c60dSDavid Majnemer return 0; 36198fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 36298fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 363e830c60dSDavid Majnemer } 364e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 365e830c60dSDavid Majnemer } 366e830c60dSDavid Majnemer 36794751be7SDavid Majnemer static const coff_relocation * 36894751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 36994751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 37094751be7SDavid Majnemer if (!NumRelocs) 37194751be7SDavid Majnemer return nullptr; 372827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 37394751be7SDavid Majnemer Base + Sec->PointerToRelocations); 374827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 375827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 376827c8a2bSRui Ueyama // relocations. 377827c8a2bSRui Ueyama begin++; 378827c8a2bSRui Ueyama } 37994751be7SDavid Majnemer if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 38094751be7SDavid Majnemer return nullptr; 38194751be7SDavid Majnemer return begin; 382827c8a2bSRui Ueyama } 38394751be7SDavid Majnemer 38494751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 38594751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 38694751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 38776d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 38876d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 38994751be7SDavid Majnemer DataRefImpl Ret; 39094751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3918ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 392e5fd0047SMichael J. Spencer } 393e5fd0047SMichael J. Spencer 3948ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3958ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 39694751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 39794751be7SDavid Majnemer if (I) 39894751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 3998ff24d25SRui Ueyama DataRefImpl Ret; 40094751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 4018ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 402e5fd0047SMichael J. Spencer } 403e5fd0047SMichael J. Spencer 404c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 405db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 40644f51e51SDavid Majnemer if (COFFHeader) 407236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 408236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 409236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 41044f51e51SDavid Majnemer return EC; 41144f51e51SDavid Majnemer 41244f51e51SDavid Majnemer if (COFFBigObjHeader) 413236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 414236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 415236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4168ff24d25SRui Ueyama return EC; 417c2bed429SRui Ueyama 418c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 419c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 420c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 421f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 42244f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 423f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 424c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 42548af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4268ff24d25SRui Ueyama return EC; 427c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 428db4ed0bdSRafael Espindola if (std::error_code EC = 42948af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4308ff24d25SRui Ueyama return EC; 431c2bed429SRui Ueyama 432773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 433773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 434773a5795SNico Rieck if (StringTableSize < 4) 435773a5795SNico Rieck StringTableSize = 4; 436773a5795SNico Rieck 437c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 438773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 439c2bed429SRui Ueyama return object_error::parse_failed; 4407d099195SRui Ueyama return std::error_code(); 441c2bed429SRui Ueyama } 442c2bed429SRui Ueyama 44321427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 444e94fef7bSReid Kleckner if (PE32Header) 44521427adaSReid Kleckner return PE32Header->ImageBase; 446e94fef7bSReid Kleckner else if (PE32PlusHeader) 44721427adaSReid Kleckner return PE32PlusHeader->ImageBase; 44821427adaSReid Kleckner // This actually comes up in practice. 44921427adaSReid Kleckner return 0; 450e94fef7bSReid Kleckner } 451e94fef7bSReid Kleckner 452215a586cSRui Ueyama // Returns the file offset for the given VA. 453db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 45421427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 455b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 456b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 457b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 458215a586cSRui Ueyama } 459215a586cSRui Ueyama 460c2bed429SRui Ueyama // Returns the file offset for the given RVA. 461db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 46227dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 46327dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 464c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 465c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 466215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 467215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 468c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4697d099195SRui Ueyama return std::error_code(); 470c2bed429SRui Ueyama } 471c2bed429SRui Ueyama } 472c2bed429SRui Ueyama return object_error::parse_failed; 473c2bed429SRui Ueyama } 474c2bed429SRui Ueyama 4752da433eaSReid Kleckner std::error_code 4762da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4772da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4782da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4792da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4802da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4812da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4822da433eaSReid Kleckner // overflow. 4832da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4842da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4852da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4862da433eaSReid Kleckner uintptr_t Begin = 4872da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4882da433eaSReid Kleckner Contents = 4892da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4902da433eaSReid Kleckner return std::error_code(); 4912da433eaSReid Kleckner } 4922da433eaSReid Kleckner } 4932da433eaSReid Kleckner return object_error::parse_failed; 4942da433eaSReid Kleckner } 4952da433eaSReid Kleckner 496c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 497c2bed429SRui Ueyama // table entry. 498db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 499db4ed0bdSRafael Espindola StringRef &Name) const { 500c2bed429SRui Ueyama uintptr_t IntPtr = 0; 501db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 5028ff24d25SRui Ueyama return EC; 503c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 504c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 505c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5067d099195SRui Ueyama return std::error_code(); 507c2bed429SRui Ueyama } 508c2bed429SRui Ueyama 50901528021SSaleem Abdulrasool std::error_code 51001528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 51101528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5122da433eaSReid Kleckner StringRef &PDBFileName) const { 5132da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5142da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 5152da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5162da433eaSReid Kleckner return EC; 51701528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5182da433eaSReid Kleckner return object_error::parse_failed; 51901528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 52001528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5212da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5222da433eaSReid Kleckner InfoBytes.size()); 5232da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5242da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5252da433eaSReid Kleckner return std::error_code(); 5262da433eaSReid Kleckner } 5272da433eaSReid Kleckner 52801528021SSaleem Abdulrasool std::error_code 52901528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 530f27f3f84SReid Kleckner StringRef &PDBFileName) const { 531f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 532f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 533f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 534f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 535f27f3f84SReid Kleckner PDBInfo = nullptr; 536f27f3f84SReid Kleckner PDBFileName = StringRef(); 537f27f3f84SReid Kleckner return std::error_code(); 538f27f3f84SReid Kleckner } 539f27f3f84SReid Kleckner 540c2bed429SRui Ueyama // Find the import table. 541db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 542c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 543c2bed429SRui Ueyama // the import table, do nothing. 544c2bed429SRui Ueyama const data_directory *DataEntry; 545c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5467d099195SRui Ueyama return std::error_code(); 547c2bed429SRui Ueyama 548c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 549c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5507d099195SRui Ueyama return std::error_code(); 551c2bed429SRui Ueyama 552c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 553c2bed429SRui Ueyama 554c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 555c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 556c2bed429SRui Ueyama uintptr_t IntPtr = 0; 557db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5588ff24d25SRui Ueyama return EC; 559ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 560ad7b7e73SDavid Majnemer return EC; 561c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5621c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5637d099195SRui Ueyama return std::error_code(); 564ad882ba8SRui Ueyama } 565c2bed429SRui Ueyama 56615d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 56715d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 56815d99359SRui Ueyama const data_directory *DataEntry; 56915d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5707d099195SRui Ueyama return std::error_code(); 57115d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5727d099195SRui Ueyama return std::error_code(); 57315d99359SRui Ueyama 57415d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 57515d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 57615d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 57715d99359SRui Ueyama 57815d99359SRui Ueyama uintptr_t IntPtr = 0; 57915d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 58015d99359SRui Ueyama return EC; 58115d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 58215d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5837d099195SRui Ueyama return std::error_code(); 58415d99359SRui Ueyama } 58515d99359SRui Ueyama 586ad882ba8SRui Ueyama // Find the export table. 587db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 588ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 589ad882ba8SRui Ueyama // the export table, do nothing. 590ad882ba8SRui Ueyama const data_directory *DataEntry; 591ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5927d099195SRui Ueyama return std::error_code(); 593ad882ba8SRui Ueyama 594ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 595ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5967d099195SRui Ueyama return std::error_code(); 597ad882ba8SRui Ueyama 598ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 599ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 600db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 601ad882ba8SRui Ueyama return EC; 60224fc2d64SRui Ueyama ExportDirectory = 60324fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6047d099195SRui Ueyama return std::error_code(); 605c2bed429SRui Ueyama } 606c2bed429SRui Ueyama 60774e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 60874e85130SRui Ueyama const data_directory *DataEntry; 60974e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 6107d099195SRui Ueyama return std::error_code(); 61174e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6127d099195SRui Ueyama return std::error_code(); 61374e85130SRui Ueyama 61474e85130SRui Ueyama uintptr_t IntPtr = 0; 61574e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 61674e85130SRui Ueyama return EC; 61774e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 61874e85130SRui Ueyama IntPtr); 61974e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 62074e85130SRui Ueyama IntPtr + DataEntry->Size); 6217d099195SRui Ueyama return std::error_code(); 62274e85130SRui Ueyama } 62374e85130SRui Ueyama 6242da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6252da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6262da433eaSReid Kleckner const data_directory *DataEntry; 6272da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6282da433eaSReid Kleckner return std::error_code(); 6292da433eaSReid Kleckner 6302da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6312da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6322da433eaSReid Kleckner return std::error_code(); 6332da433eaSReid Kleckner 6342da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6352da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6362da433eaSReid Kleckner return object_error::parse_failed; 6372da433eaSReid Kleckner 6382da433eaSReid Kleckner uintptr_t IntPtr = 0; 6392da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6402da433eaSReid Kleckner return EC; 6412da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6422da433eaSReid Kleckner if (std::error_code EC = getRvaPtr( 6432da433eaSReid Kleckner DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 6442da433eaSReid Kleckner return EC; 6452da433eaSReid Kleckner DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 6462da433eaSReid Kleckner return std::error_code(); 6472da433eaSReid Kleckner } 6482da433eaSReid Kleckner 64948af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 65048af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 65144f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 65244f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 65344f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 654ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 65515d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6562da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6572da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6581d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 65948af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 660c3f9b5a5SRafael Espindola return; 661ee066fc4SEric Christopher 66282ebd8e3SRui Ueyama // The current location in the file where we are looking at. 66382ebd8e3SRui Ueyama uint64_t CurPtr = 0; 66482ebd8e3SRui Ueyama 66582ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 66682ebd8e3SRui Ueyama // it is placed right after COFF header. 6678ff24d25SRui Ueyama bool HasPEHeader = false; 668ee066fc4SEric Christopher 6691d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 67050267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 671ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 672ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 67350267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 67450267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 67550267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 67682ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 67750267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6788ff24d25SRui Ueyama EC = object_error::parse_failed; 6791d6167fdSMichael J. Spencer return; 6801d6167fdSMichael J. Spencer } 68144f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6828ff24d25SRui Ueyama HasPEHeader = true; 683ee066fc4SEric Christopher } 68450267222SDavid Majnemer } 685ee066fc4SEric Christopher 68648af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 6871d6167fdSMichael J. Spencer return; 68844f51e51SDavid Majnemer 68944f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 69044f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 69144f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 69244f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 69344f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 69444f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 69544f51e51SDavid Majnemer return; 69644f51e51SDavid Majnemer 69744f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 69844f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 69944f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 70044f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 70144f51e51SDavid Majnemer COFFHeader = nullptr; 70244f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 70344f51e51SDavid Majnemer } else { 70444f51e51SDavid Majnemer // It's not a bigobj. 70544f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 70644f51e51SDavid Majnemer } 70744f51e51SDavid Majnemer } 70844f51e51SDavid Majnemer if (COFFHeader) { 70944f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 71044f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7117d099195SRui Ueyama EC = std::error_code(); 71282ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 71382ebd8e3SRui Ueyama 71444f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 71544f51e51SDavid Majnemer return; 71644f51e51SDavid Majnemer } 71744f51e51SDavid Majnemer 7188ff24d25SRui Ueyama if (HasPEHeader) { 71910ed9ddcSRui Ueyama const pe32_header *Header; 72048af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 72182ebd8e3SRui Ueyama return; 72210ed9ddcSRui Ueyama 72310ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 72410ed9ddcSRui Ueyama uint64_t DataDirSize; 72550267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 72610ed9ddcSRui Ueyama PE32Header = Header; 72710ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 72810ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 72950267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 73010ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 73110ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 73210ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 73310ed9ddcSRui Ueyama } else { 73410ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 73510ed9ddcSRui Ueyama EC = object_error::parse_failed; 736ed64342bSRui Ueyama return; 737ed64342bSRui Ueyama } 73848af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 73910ed9ddcSRui Ueyama return; 740f53c8cb4SRui Ueyama } 741776c6828SRui Ueyama 7428950a538SRui Ueyama if (COFFHeader) 7438950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7448950a538SRui Ueyama 74548af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 746236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7471d6167fdSMichael J. Spencer return; 7481d6167fdSMichael J. Spencer 749c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 750236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 751ac8cfab5SDavid Majnemer if ((EC = initSymbolTablePtr())) { 752ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 753ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 754ac8cfab5SDavid Majnemer StringTable = nullptr; 755ac8cfab5SDavid Majnemer StringTableSize = 0; 756ac8cfab5SDavid Majnemer } 757236b0ca7SDavid Majnemer } else { 758236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 759236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 760236b0ca7SDavid Majnemer EC = object_error::parse_failed; 761236b0ca7SDavid Majnemer return; 762236b0ca7SDavid Majnemer } 763236b0ca7SDavid Majnemer } 7648e90adafSMichael J. Spencer 765c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7668ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 767ed64342bSRui Ueyama return; 76815d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 76915d99359SRui Ueyama return; 7701d6167fdSMichael J. Spencer 771ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7728ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 773ad882ba8SRui Ueyama return; 774ad882ba8SRui Ueyama 77574e85130SRui Ueyama // Initialize the pointer to the base relocation table. 77674e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 77774e85130SRui Ueyama return; 77874e85130SRui Ueyama 7792da433eaSReid Kleckner // Initialize the pointer to the export table. 7802da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 7812da433eaSReid Kleckner return; 7822da433eaSReid Kleckner 7837d099195SRui Ueyama EC = std::error_code(); 7848e90adafSMichael J. Spencer } 7858e90adafSMichael J. Spencer 786435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 7878ff24d25SRui Ueyama DataRefImpl Ret; 78844f51e51SDavid Majnemer Ret.p = getSymbolTable(); 789f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7908e90adafSMichael J. Spencer } 7918e90adafSMichael J. Spencer 792435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 7938e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 7948ff24d25SRui Ueyama DataRefImpl Ret; 7958ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 796f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7978e90adafSMichael J. Spencer } 7988e90adafSMichael J. Spencer 799bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 800ad7b7e73SDavid Majnemer if (!ImportDirectory) 801ad7b7e73SDavid Majnemer return import_directory_end(); 8021c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 803ad7b7e73SDavid Majnemer return import_directory_end(); 804a045b73aSRui Ueyama return import_directory_iterator( 805a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 806c2bed429SRui Ueyama } 807c2bed429SRui Ueyama 808bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 809a045b73aSRui Ueyama return import_directory_iterator( 810ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 811c2bed429SRui Ueyama } 812c429b80dSDavid Meyer 81315d99359SRui Ueyama delay_import_directory_iterator 81415d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 81515d99359SRui Ueyama return delay_import_directory_iterator( 81615d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 81715d99359SRui Ueyama } 81815d99359SRui Ueyama 81915d99359SRui Ueyama delay_import_directory_iterator 82015d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 82115d99359SRui Ueyama return delay_import_directory_iterator( 82215d99359SRui Ueyama DelayImportDirectoryEntryRef( 82315d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 82415d99359SRui Ueyama } 82515d99359SRui Ueyama 826ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 827ad882ba8SRui Ueyama return export_directory_iterator( 828ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 829ad882ba8SRui Ueyama } 830ad882ba8SRui Ueyama 831ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8322617dcceSCraig Topper if (!ExportDirectory) 8332617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8348ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 835ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8368ff24d25SRui Ueyama return export_directory_iterator(Ref); 837ad882ba8SRui Ueyama } 838ad882ba8SRui Ueyama 839b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8408ff24d25SRui Ueyama DataRefImpl Ret; 8418ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8428ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8438e90adafSMichael J. Spencer } 8448e90adafSMichael J. Spencer 845b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8468ff24d25SRui Ueyama DataRefImpl Ret; 84744f51e51SDavid Majnemer int NumSections = 84844f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8498ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8508ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8518e90adafSMichael J. Spencer } 8528e90adafSMichael J. Spencer 85374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 85474e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 85574e85130SRui Ueyama } 85674e85130SRui Ueyama 85774e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 85874e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 85974e85130SRui Ueyama } 86074e85130SRui Ueyama 8618e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 8620324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 8638e90adafSMichael J. Spencer } 8648e90adafSMichael J. Spencer 8658e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 86644f51e51SDavid Majnemer switch(getMachine()) { 8678e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8688e90adafSMichael J. Spencer return "COFF-i386"; 8698e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8708e90adafSMichael J. Spencer return "COFF-x86-64"; 8719b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8729b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8731eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8741eff5c9cSMartell Malone return "COFF-ARM64"; 8758e90adafSMichael J. Spencer default: 8768e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8778e90adafSMichael J. Spencer } 8788e90adafSMichael J. Spencer } 8798e90adafSMichael J. Spencer 8808e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 88144f51e51SDavid Majnemer switch (getMachine()) { 8828e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8838e90adafSMichael J. Spencer return Triple::x86; 8848e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8858e90adafSMichael J. Spencer return Triple::x86_64; 8869b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8879b7c0af2SSaleem Abdulrasool return Triple::thumb; 8881eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8891eff5c9cSMartell Malone return Triple::aarch64; 8908e90adafSMichael J. Spencer default: 8918e90adafSMichael J. Spencer return Triple::UnknownArch; 8928e90adafSMichael J. Spencer } 8938e90adafSMichael J. Spencer } 8948e90adafSMichael J. Spencer 895979fb40bSRui Ueyama iterator_range<import_directory_iterator> 896979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 897979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 898979fb40bSRui Ueyama } 899979fb40bSRui Ueyama 900979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 901979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 902979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 903979fb40bSRui Ueyama delay_import_directory_end()); 904979fb40bSRui Ueyama } 905979fb40bSRui Ueyama 906979fb40bSRui Ueyama iterator_range<export_directory_iterator> 907979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 908979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 909979fb40bSRui Ueyama } 910979fb40bSRui Ueyama 91174e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 91274e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 91374e85130SRui Ueyama } 91474e85130SRui Ueyama 915db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 91682ebd8e3SRui Ueyama Res = PE32Header; 9177d099195SRui Ueyama return std::error_code(); 91889a7a5eaSMichael J. Spencer } 91989a7a5eaSMichael J. Spencer 920db4ed0bdSRafael Espindola std::error_code 92110ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 92210ed9ddcSRui Ueyama Res = PE32PlusHeader; 9237d099195SRui Ueyama return std::error_code(); 92410ed9ddcSRui Ueyama } 92510ed9ddcSRui Ueyama 926db4ed0bdSRafael Espindola std::error_code 927db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 928ed64342bSRui Ueyama const data_directory *&Res) const { 929ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 930f69b0585SDavid Majnemer if (!DataDirectory) { 931f69b0585SDavid Majnemer Res = nullptr; 93210ed9ddcSRui Ueyama return object_error::parse_failed; 933f69b0585SDavid Majnemer } 93410ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 93510ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 93610ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 937f69b0585SDavid Majnemer if (Index >= NumEnt) { 938f69b0585SDavid Majnemer Res = nullptr; 939ed64342bSRui Ueyama return object_error::parse_failed; 940f69b0585SDavid Majnemer } 9418ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9427d099195SRui Ueyama return std::error_code(); 943ed64342bSRui Ueyama } 944ed64342bSRui Ueyama 945db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9461d6167fdSMichael J. Spencer const coff_section *&Result) const { 9472617dcceSCraig Topper Result = nullptr; 948236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9497d099195SRui Ueyama return std::error_code(); 950236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9511d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9528ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9537d099195SRui Ueyama return std::error_code(); 9548e90adafSMichael J. Spencer } 955236b0ca7SDavid Majnemer return object_error::parse_failed; 956236b0ca7SDavid Majnemer } 9578e90adafSMichael J. Spencer 958db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9591d6167fdSMichael J. Spencer StringRef &Result) const { 9601d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9611d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9621d6167fdSMichael J. Spencer return object_error::parse_failed; 9638ff24d25SRui Ueyama if (Offset >= StringTableSize) 9641d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9658ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9667d099195SRui Ueyama return std::error_code(); 9678e90adafSMichael J. Spencer } 968022ecdf2SBenjamin Kramer 96944f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 97089a7a5eaSMichael J. Spencer StringRef &Res) const { 971e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 972e40d30f3SRui Ueyama } 973e40d30f3SRui Ueyama 974e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 975e40d30f3SRui Ueyama StringRef &Res) const { 97689a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 977e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 978e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 9798ff24d25SRui Ueyama return EC; 9807d099195SRui Ueyama return std::error_code(); 98189a7a5eaSMichael J. Spencer } 98289a7a5eaSMichael J. Spencer 983e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 98489a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 985e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 98689a7a5eaSMichael J. Spencer else 98789a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 988e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 9897d099195SRui Ueyama return std::error_code(); 99089a7a5eaSMichael J. Spencer } 99189a7a5eaSMichael J. Spencer 99244f51e51SDavid Majnemer ArrayRef<uint8_t> 99344f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 9942617dcceSCraig Topper const uint8_t *Aux = nullptr; 99571757ef3SMarshall Clow 99644f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 99744f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 99871757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 99944f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 100071757ef3SMarshall Clow #ifndef NDEBUG 10018ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10028ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 100344f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 100444f51e51SDavid Majnemer Offset >= 100544f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 100671757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 100771757ef3SMarshall Clow 100844f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 100944f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 101071757ef3SMarshall Clow #endif 1011bfb85e67SMarshall Clow } 101244f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 101371757ef3SMarshall Clow } 101471757ef3SMarshall Clow 1015db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 101653c2d547SMichael J. Spencer StringRef &Res) const { 101753c2d547SMichael J. Spencer StringRef Name; 101844f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 101953c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 102053c2d547SMichael J. Spencer Name = Sec->Name; 102153c2d547SMichael J. Spencer else 102253c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 102344f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 102453c2d547SMichael J. Spencer 102553c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10262314b3deSDavid Majnemer if (Name.startswith("/")) { 102753c2d547SMichael J. Spencer uint32_t Offset; 10282314b3deSDavid Majnemer if (Name.startswith("//")) { 10299d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10309d2c15efSNico Rieck return object_error::parse_failed; 10319d2c15efSNico Rieck } else { 103253c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 103353c2d547SMichael J. Spencer return object_error::parse_failed; 10349d2c15efSNico Rieck } 1035db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 10368ff24d25SRui Ueyama return EC; 103753c2d547SMichael J. Spencer } 103853c2d547SMichael J. Spencer 103953c2d547SMichael J. Spencer Res = Name; 10407d099195SRui Ueyama return std::error_code(); 104153c2d547SMichael J. Spencer } 104253c2d547SMichael J. Spencer 1043a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1044a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1045a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1046a9ee5c06SDavid Majnemer // 1047a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1048d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1049a9ee5c06SDavid Majnemer // 1050a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1051a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1052a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1053a9ee5c06SDavid Majnemer // considered to be zero. 1054d5297ee7SRui Ueyama if (getDOSHeader()) 1055d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1056d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1057a9ee5c06SDavid Majnemer } 1058a9ee5c06SDavid Majnemer 1059db4ed0bdSRafael Espindola std::error_code 1060db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10619da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1062e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1063e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1064e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1065*ee97c5f0SShoaib Meenai return std::error_code(); 10669da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10679da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10689da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10699da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1070a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1071e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10729da9e693SMichael J. Spencer return object_error::parse_failed; 1073a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10747d099195SRui Ueyama return std::error_code(); 10759da9e693SMichael J. Spencer } 10769da9e693SMichael J. Spencer 1077022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1078e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1079022ecdf2SBenjamin Kramer } 10808ff24d25SRui Ueyama 10815e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1082e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1083e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1084022ecdf2SBenjamin Kramer } 10858ff24d25SRui Ueyama 108696d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 108758323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 108896d071cdSRafael Espindola return R->VirtualAddress; 1089cbe72fc9SDanil Malyshev } 10908ff24d25SRui Ueyama 1091806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1092022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 10938ff24d25SRui Ueyama DataRefImpl Ref; 1094236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1095236b0ca7SDavid Majnemer return symbol_end(); 109644f51e51SDavid Majnemer if (SymbolTable16) 109744f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 109844f51e51SDavid Majnemer else if (SymbolTable32) 109944f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 110044f51e51SDavid Majnemer else 1101c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11028ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1103022ecdf2SBenjamin Kramer } 11048ff24d25SRui Ueyama 110599c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1106022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 110799c041b7SRafael Espindola return R->Type; 1108022ecdf2SBenjamin Kramer } 1109e5fd0047SMichael J. Spencer 111027dc8394SAlexey Samsonov const coff_section * 111127dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 111227dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 111371757ef3SMarshall Clow } 111471757ef3SMarshall Clow 111544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 111644f51e51SDavid Majnemer if (SymbolTable16) 111744f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 111844f51e51SDavid Majnemer if (SymbolTable32) 111944f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 112044f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 112144f51e51SDavid Majnemer } 112244f51e51SDavid Majnemer 112344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 112444f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 112571757ef3SMarshall Clow } 112671757ef3SMarshall Clow 1127f12b8282SRafael Espindola const coff_relocation * 112827dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 112927dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1130d3e2a76cSMarshall Clow } 1131d3e2a76cSMarshall Clow 11326a75acb1SRui Ueyama iterator_range<const coff_relocation *> 11336a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11346a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 11356a75acb1SRui Ueyama const coff_relocation *E = I; 11366a75acb1SRui Ueyama if (I) 11376a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 11386a75acb1SRui Ueyama return make_range(I, E); 11396a75acb1SRui Ueyama } 11406a75acb1SRui Ueyama 114127dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 114227dc8394SAlexey Samsonov case COFF::reloc_type: \ 114327dc8394SAlexey Samsonov Res = #reloc_type; \ 114427dc8394SAlexey Samsonov break; 1145e5fd0047SMichael J. Spencer 114641bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 114741bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 11488ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11498ff24d25SRui Ueyama StringRef Res; 115044f51e51SDavid Majnemer switch (getMachine()) { 1151e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11528ff24d25SRui Ueyama switch (Reloc->Type) { 1153e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1154e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1155e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1156e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1157e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1158e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1159e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1160e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1161e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1162e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1163e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1164e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1165e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1166e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1167e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1168e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1169e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1170e5fd0047SMichael J. Spencer default: 11718ff24d25SRui Ueyama Res = "Unknown"; 1172e5fd0047SMichael J. Spencer } 1173e5fd0047SMichael J. Spencer break; 11745c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11755c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 11765c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11775c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11785c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11795c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11805c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11815c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 11825c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 11835c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 11845c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 11855c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 11865c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 11875c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 11885c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 11895c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 11905c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 11915c503bf4SSaleem Abdulrasool default: 11925c503bf4SSaleem Abdulrasool Res = "Unknown"; 11935c503bf4SSaleem Abdulrasool } 11945c503bf4SSaleem Abdulrasool break; 1195e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 11968ff24d25SRui Ueyama switch (Reloc->Type) { 1197e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1198e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1199e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1200e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1201e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1202e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1203e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1204e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1205e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1206e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1207e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1208e5fd0047SMichael J. Spencer default: 12098ff24d25SRui Ueyama Res = "Unknown"; 1210e5fd0047SMichael J. Spencer } 1211e5fd0047SMichael J. Spencer break; 1212e5fd0047SMichael J. Spencer default: 12138ff24d25SRui Ueyama Res = "Unknown"; 1214e5fd0047SMichael J. Spencer } 12158ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1216e5fd0047SMichael J. Spencer } 1217e5fd0047SMichael J. Spencer 1218e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1219e5fd0047SMichael J. Spencer 1220c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1221c66d761bSRafael Espindola return !DataDirectory; 1222c66d761bSRafael Espindola } 1223c66d761bSRafael Espindola 1224c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1225c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1226a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1227c2bed429SRui Ueyama } 1228c2bed429SRui Ueyama 12295e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12305e812afaSRafael Espindola ++Index; 12311c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1232ad7b7e73SDavid Majnemer Index = -1; 1233ad7b7e73SDavid Majnemer ImportTable = nullptr; 1234ad7b7e73SDavid Majnemer } 1235c2bed429SRui Ueyama } 1236c2bed429SRui Ueyama 1237db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 12381c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1239ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1240c2bed429SRui Ueyama } 1241c2bed429SRui Ueyama 1242861021f9SRui Ueyama static imported_symbol_iterator 124315d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1244861021f9SRui Ueyama uintptr_t Ptr, int Index) { 124515d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1246861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 124715d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1248861021f9SRui Ueyama } 1249861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 125015d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1251861021f9SRui Ueyama } 1252861021f9SRui Ueyama 125315d99359SRui Ueyama static imported_symbol_iterator 125415d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1255861021f9SRui Ueyama uintptr_t IntPtr = 0; 125615d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 125715d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1258861021f9SRui Ueyama } 1259861021f9SRui Ueyama 126015d99359SRui Ueyama static imported_symbol_iterator 126115d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1262861021f9SRui Ueyama uintptr_t IntPtr = 0; 126315d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1264861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1265861021f9SRui Ueyama int Index = 0; 126615d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1267861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1268861021f9SRui Ueyama while (*Entry++) 1269861021f9SRui Ueyama ++Index; 1270861021f9SRui Ueyama } else { 1271861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1272861021f9SRui Ueyama while (*Entry++) 1273861021f9SRui Ueyama ++Index; 1274861021f9SRui Ueyama } 127515d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 127615d99359SRui Ueyama } 127715d99359SRui Ueyama 127815d99359SRui Ueyama imported_symbol_iterator 127915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 128060049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 128115d99359SRui Ueyama OwningObject); 128215d99359SRui Ueyama } 128315d99359SRui Ueyama 128415d99359SRui Ueyama imported_symbol_iterator 128515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 128660049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 128715d99359SRui Ueyama OwningObject); 1288861021f9SRui Ueyama } 1289861021f9SRui Ueyama 1290979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1291979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1292979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1293979fb40bSRui Ueyama } 1294979fb40bSRui Ueyama 129560049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 129660049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 129760049526SDavid Majnemer OwningObject); 129860049526SDavid Majnemer } 129960049526SDavid Majnemer 130060049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 130160049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 130260049526SDavid Majnemer OwningObject); 130360049526SDavid Majnemer } 130460049526SDavid Majnemer 130560049526SDavid Majnemer iterator_range<imported_symbol_iterator> 130660049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 130760049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 130860049526SDavid Majnemer } 130960049526SDavid Majnemer 1310db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1311c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1312db4ed0bdSRafael Espindola if (std::error_code EC = 13131e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1314a045b73aSRui Ueyama return EC; 1315a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13167d099195SRui Ueyama return std::error_code(); 1317c2bed429SRui Ueyama } 1318c2bed429SRui Ueyama 13191e152d5eSRui Ueyama std::error_code 13201e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 13211e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 13227d099195SRui Ueyama return std::error_code(); 13231e152d5eSRui Ueyama } 13241e152d5eSRui Ueyama 13251e152d5eSRui Ueyama std::error_code 13261e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 13271e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 13287d099195SRui Ueyama return std::error_code(); 13291e152d5eSRui Ueyama } 13301e152d5eSRui Ueyama 133115d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 133215d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 133315d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 133415d99359SRui Ueyama } 133515d99359SRui Ueyama 133615d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 133715d99359SRui Ueyama ++Index; 133815d99359SRui Ueyama } 133915d99359SRui Ueyama 134015d99359SRui Ueyama imported_symbol_iterator 134115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 134215d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 134315d99359SRui Ueyama OwningObject); 134415d99359SRui Ueyama } 134515d99359SRui Ueyama 134615d99359SRui Ueyama imported_symbol_iterator 134715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 134815d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 134915d99359SRui Ueyama OwningObject); 135015d99359SRui Ueyama } 135115d99359SRui Ueyama 1352979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1353979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1354979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1355979fb40bSRui Ueyama } 1356979fb40bSRui Ueyama 135715d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 135815d99359SRui Ueyama uintptr_t IntPtr = 0; 135915d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 136015d99359SRui Ueyama return EC; 136115d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13627d099195SRui Ueyama return std::error_code(); 136315d99359SRui Ueyama } 136415d99359SRui Ueyama 13651af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 13661af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 13671af08658SRui Ueyama Result = Table; 13687d099195SRui Ueyama return std::error_code(); 13691af08658SRui Ueyama } 13701af08658SRui Ueyama 1371ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1372ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1373ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1374ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1375ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1376ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1377ffa4cebeSRui Ueyama return EC; 1378ffa4cebeSRui Ueyama if (OwningObject->is64()) 13795dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1380ffa4cebeSRui Ueyama else 13815dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 13827d099195SRui Ueyama return std::error_code(); 1383ffa4cebeSRui Ueyama } 1384ffa4cebeSRui Ueyama 1385ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1386ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1387ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1388ad882ba8SRui Ueyama } 1389ad882ba8SRui Ueyama 13905e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 13915e812afaSRafael Espindola ++Index; 1392ad882ba8SRui Ueyama } 1393ad882ba8SRui Ueyama 1394da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1395da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1396db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1397da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1398db4ed0bdSRafael Espindola if (std::error_code EC = 1399db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1400da49d0d4SRui Ueyama return EC; 1401da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14027d099195SRui Ueyama return std::error_code(); 1403da49d0d4SRui Ueyama } 1404da49d0d4SRui Ueyama 1405e5df6095SRui Ueyama // Returns the starting ordinal number. 1406db4ed0bdSRafael Espindola std::error_code 1407db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1408e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 14097d099195SRui Ueyama return std::error_code(); 1410e5df6095SRui Ueyama } 1411e5df6095SRui Ueyama 1412ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1413db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1414ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 14157d099195SRui Ueyama return std::error_code(); 1416ad882ba8SRui Ueyama } 1417ad882ba8SRui Ueyama 1418ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1419db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1420ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1421db4ed0bdSRafael Espindola if (std::error_code EC = 1422db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1423ad882ba8SRui Ueyama return EC; 142424fc2d64SRui Ueyama const export_address_table_entry *entry = 142524fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1426ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 14277d099195SRui Ueyama return std::error_code(); 1428ad882ba8SRui Ueyama } 1429ad882ba8SRui Ueyama 1430ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1431ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1432db4ed0bdSRafael Espindola std::error_code 1433db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1434ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1435db4ed0bdSRafael Espindola if (std::error_code EC = 1436db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1437ad882ba8SRui Ueyama return EC; 1438ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1439ad882ba8SRui Ueyama 1440ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1441ad882ba8SRui Ueyama int Offset = 0; 1442ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1443ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1444ad882ba8SRui Ueyama if (*I != Index) 1445ad882ba8SRui Ueyama continue; 1446db4ed0bdSRafael Espindola if (std::error_code EC = 1447db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1448ad882ba8SRui Ueyama return EC; 1449ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1450db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1451ad882ba8SRui Ueyama return EC; 1452ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14537d099195SRui Ueyama return std::error_code(); 1454ad882ba8SRui Ueyama } 1455ad882ba8SRui Ueyama Result = ""; 14567d099195SRui Ueyama return std::error_code(); 1457ad882ba8SRui Ueyama } 1458ad882ba8SRui Ueyama 14596161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 14606161b38dSRui Ueyama const data_directory *DataEntry; 14616161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 14626161b38dSRui Ueyama return EC; 14636161b38dSRui Ueyama uint32_t RVA; 14646161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14656161b38dSRui Ueyama return EC; 14666161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 14676161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 14686161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 14696161b38dSRui Ueyama return std::error_code(); 14706161b38dSRui Ueyama } 14716161b38dSRui Ueyama 14726161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 14736161b38dSRui Ueyama uint32_t RVA; 14746161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14756161b38dSRui Ueyama return EC; 14766161b38dSRui Ueyama uintptr_t IntPtr = 0; 14776161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 14786161b38dSRui Ueyama return EC; 14796161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14806161b38dSRui Ueyama return std::error_code(); 14816161b38dSRui Ueyama } 14826161b38dSRui Ueyama 1483861021f9SRui Ueyama bool ImportedSymbolRef:: 1484861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1485861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1486861021f9SRui Ueyama && Index == Other.Index; 1487861021f9SRui Ueyama } 1488861021f9SRui Ueyama 1489861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1490861021f9SRui Ueyama ++Index; 1491861021f9SRui Ueyama } 1492861021f9SRui Ueyama 1493861021f9SRui Ueyama std::error_code 1494861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1495861021f9SRui Ueyama uint32_t RVA; 1496861021f9SRui Ueyama if (Entry32) { 1497861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1498861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 14997d099195SRui Ueyama return std::error_code(); 1500861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1501861021f9SRui Ueyama } else { 1502861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 15037d099195SRui Ueyama return std::error_code(); 1504861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1505861021f9SRui Ueyama } 1506861021f9SRui Ueyama uintptr_t IntPtr = 0; 1507861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1508861021f9SRui Ueyama return EC; 1509861021f9SRui Ueyama // +2 because the first two bytes is hint. 1510861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 15117d099195SRui Ueyama return std::error_code(); 1512861021f9SRui Ueyama } 1513861021f9SRui Ueyama 1514ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1515ad7b7e73SDavid Majnemer if (Entry32) 1516ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1517ad7b7e73SDavid Majnemer else 1518ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1519ad7b7e73SDavid Majnemer return std::error_code(); 1520ad7b7e73SDavid Majnemer } 1521ad7b7e73SDavid Majnemer 1522ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1523ad7b7e73SDavid Majnemer if (Entry32) 1524ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1525ad7b7e73SDavid Majnemer else 1526ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1527ad7b7e73SDavid Majnemer return std::error_code(); 1528ad7b7e73SDavid Majnemer } 1529ad7b7e73SDavid Majnemer 1530861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1531861021f9SRui Ueyama uint32_t RVA; 1532861021f9SRui Ueyama if (Entry32) { 1533861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1534861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 15357d099195SRui Ueyama return std::error_code(); 1536861021f9SRui Ueyama } 1537861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1538861021f9SRui Ueyama } else { 1539861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1540861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 15417d099195SRui Ueyama return std::error_code(); 1542861021f9SRui Ueyama } 1543861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1544861021f9SRui Ueyama } 1545861021f9SRui Ueyama uintptr_t IntPtr = 0; 1546861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1547861021f9SRui Ueyama return EC; 1548861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15497d099195SRui Ueyama return std::error_code(); 1550861021f9SRui Ueyama } 1551861021f9SRui Ueyama 1552437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 155348af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1554db4ed0bdSRafael Espindola std::error_code EC; 155548af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1556692410efSRafael Espindola if (EC) 1557692410efSRafael Espindola return EC; 1558437b0d58SRafael Espindola return std::move(Ret); 1559686738e2SRui Ueyama } 156074e85130SRui Ueyama 156174e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 156274e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 156374e85130SRui Ueyama } 156474e85130SRui Ueyama 156574e85130SRui Ueyama void BaseRelocRef::moveNext() { 156674e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 156774e85130SRui Ueyama // size of the header itself. 156874e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1569970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 157074e85130SRui Ueyama if (Size == Header->BlockSize) { 157174e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 157274e85130SRui Ueyama // consists of the header followed by entries. The header contains 157374e85130SRui Ueyama // how many entories will follow. When we reach the end of the 157474e85130SRui Ueyama // current block, proceed to the next block. 157574e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 157674e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 157774e85130SRui Ueyama Index = 0; 157874e85130SRui Ueyama } else { 157974e85130SRui Ueyama ++Index; 158074e85130SRui Ueyama } 158174e85130SRui Ueyama } 158274e85130SRui Ueyama 158374e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 158474e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 158574e85130SRui Ueyama Type = Entry[Index].getType(); 15867d099195SRui Ueyama return std::error_code(); 158774e85130SRui Ueyama } 158874e85130SRui Ueyama 158974e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 159074e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 159174e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 15927d099195SRui Ueyama return std::error_code(); 159374e85130SRui Ueyama } 1594efef15a0SEric Beckmann 1595efef15a0SEric Beckmann #define RETURN_IF_ERROR(X) \ 1596efef15a0SEric Beckmann if (auto EC = errorToErrorCode(X)) \ 1597efef15a0SEric Beckmann return EC; 1598efef15a0SEric Beckmann 1599cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1600efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1601efef15a0SEric Beckmann Reader.setOffset(Offset); 1602efef15a0SEric Beckmann uint16_t Length; 1603efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1604efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1605efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1606cd704cb6SEric Beckmann return RawDirString; 1607efef15a0SEric Beckmann } 1608efef15a0SEric Beckmann 1609cd704cb6SEric Beckmann ErrorOr<ArrayRef<UTF16>> 1610efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1611efef15a0SEric Beckmann return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1612efef15a0SEric Beckmann } 1613efef15a0SEric Beckmann 1614efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> 1615efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1616efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1617efef15a0SEric Beckmann 1618efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1619efef15a0SEric Beckmann Reader.setOffset(Offset); 1620efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1621efef15a0SEric Beckmann assert(Table != nullptr); 1622efef15a0SEric Beckmann return *Table; 1623efef15a0SEric Beckmann } 1624efef15a0SEric Beckmann 1625efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> 1626efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 1627efef15a0SEric Beckmann return getTableAtOffset(Entry.Offset.value()); 1628efef15a0SEric Beckmann } 1629efef15a0SEric Beckmann 1630efef15a0SEric Beckmann ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1631efef15a0SEric Beckmann return getTableAtOffset(0); 1632efef15a0SEric Beckmann } 1633