18e90adafSMichael J. Spencer //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 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 14ec29b121SMichael J. Spencer #include "llvm/Object/COFF.h" 159da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 168e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 178e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 186a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h" 19f078eff3SRui Ueyama #include "llvm/Support/COFF.h" 20c2bed429SRui Ueyama #include "llvm/Support/Debug.h" 21c2bed429SRui Ueyama #include "llvm/Support/raw_ostream.h" 22981af002SWill Dietz #include <cctype> 239d2c15efSNico Rieck #include <limits> 248e90adafSMichael J. Spencer 258e90adafSMichael J. Spencer using namespace llvm; 268e90adafSMichael J. Spencer using namespace object; 278e90adafSMichael J. Spencer 288e90adafSMichael J. Spencer using support::ulittle16_t; 298e90adafSMichael J. Spencer using support::ulittle32_t; 30861021f9SRui Ueyama using support::ulittle64_t; 318e90adafSMichael J. Spencer using support::little16_t; 328e90adafSMichael J. Spencer 331d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 3448af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 35c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 368ff24d25SRui Ueyama EC = object_error::unexpected_eof; 371d6167fdSMichael J. Spencer return false; 381d6167fdSMichael J. Spencer } 391d6167fdSMichael J. Spencer return true; 408e90adafSMichael J. Spencer } 418e90adafSMichael J. Spencer 42e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, 4394751be7SDavid Majnemer const uint64_t Size) { 44e830c60dSDavid Majnemer if (Addr + Size < Addr || Addr + Size < Size || 45e830c60dSDavid Majnemer Addr + Size > uintptr_t(M.getBufferEnd()) || 46e830c60dSDavid Majnemer Addr < uintptr_t(M.getBufferStart())) { 47e830c60dSDavid Majnemer return object_error::unexpected_eof; 48e830c60dSDavid Majnemer } 497d099195SRui Ueyama return std::error_code(); 50e830c60dSDavid Majnemer } 51e830c60dSDavid Majnemer 52ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 53ed64342bSRui Ueyama // Returns unexpected_eof if error. 54ed64342bSRui Ueyama template <typename T> 5548af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5658323a97SDavid Majnemer const void *Ptr, 57236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 58ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 59e830c60dSDavid Majnemer if (std::error_code EC = checkOffset(M, Addr, Size)) 60e830c60dSDavid Majnemer return EC; 61ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 627d099195SRui Ueyama return std::error_code(); 631d6167fdSMichael J. Spencer } 641d6167fdSMichael J. Spencer 659d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 669d2c15efSNico Rieck // prefixed slashes. 679d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 689d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 699d2c15efSNico Rieck if (Str.size() > 6) 709d2c15efSNico Rieck return true; 719d2c15efSNico Rieck 729d2c15efSNico Rieck uint64_t Value = 0; 739d2c15efSNico Rieck while (!Str.empty()) { 749d2c15efSNico Rieck unsigned CharVal; 759d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 769d2c15efSNico Rieck CharVal = Str[0] - 'A'; 779d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 789d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 799d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 809d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 819d2c15efSNico Rieck else if (Str[0] == '+') // 62 825500b07cSRui Ueyama CharVal = 62; 839d2c15efSNico Rieck else if (Str[0] == '/') // 63 845500b07cSRui Ueyama CharVal = 63; 859d2c15efSNico Rieck else 869d2c15efSNico Rieck return true; 879d2c15efSNico Rieck 889d2c15efSNico Rieck Value = (Value * 64) + CharVal; 899d2c15efSNico Rieck Str = Str.substr(1); 909d2c15efSNico Rieck } 919d2c15efSNico Rieck 929d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 939d2c15efSNico Rieck return true; 949d2c15efSNico Rieck 959d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 969d2c15efSNico Rieck return false; 979d2c15efSNico Rieck } 989d2c15efSNico Rieck 9944f51e51SDavid Majnemer template <typename coff_symbol_type> 10044f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10144f51e51SDavid Majnemer const coff_symbol_type *Addr = 10244f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1031d6167fdSMichael J. Spencer 104236b0ca7SDavid Majnemer assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 1051d6167fdSMichael J. Spencer #ifndef NDEBUG 1061d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1078ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 1081d6167fdSMichael J. Spencer 10944f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11044f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1111d6167fdSMichael J. Spencer #endif 1121d6167fdSMichael J. Spencer 1138ff24d25SRui Ueyama return Addr; 1141d6167fdSMichael J. Spencer } 1151d6167fdSMichael J. Spencer 1168ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1178ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1181d6167fdSMichael J. Spencer 1191d6167fdSMichael J. Spencer # ifndef NDEBUG 1201d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12144f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1221d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1231d6167fdSMichael J. Spencer 1248ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1258ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1261d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1271d6167fdSMichael J. Spencer # endif 1281d6167fdSMichael J. Spencer 1298ff24d25SRui Ueyama return Addr; 1301d6167fdSMichael J. Spencer } 1311d6167fdSMichael J. Spencer 1325e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 133236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 13444f51e51SDavid Majnemer if (SymbolTable16) { 13544f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1368ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 137236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 13844f51e51SDavid Majnemer } else if (SymbolTable32) { 13944f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14044f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 141236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14244f51e51SDavid Majnemer } else { 14344f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14444f51e51SDavid Majnemer } 1451d6167fdSMichael J. Spencer } 1461d6167fdSMichael J. Spencer 14781e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 14844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1495d0c2ffaSRafael Espindola StringRef Result; 1505d0c2ffaSRafael Espindola std::error_code EC = getSymbolName(Symb, Result); 1515d0c2ffaSRafael Espindola if (EC) 15281e8b7d9SKevin Enderby return errorCodeToError(EC); 1535d0c2ffaSRafael Espindola return Result; 1548e90adafSMichael J. Spencer } 1558e90adafSMichael J. Spencer 156be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 157be8b0ea8SRafael Espindola return getCOFFSymbol(Ref).getValue(); 158991af666SRafael Espindola } 159991af666SRafael Espindola 1606b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 1616b2bba14SDavide Italiano // MSVC/link.exe seems to align symbols to the next-power-of-2 1626b2bba14SDavide Italiano // up to 32 bytes. 1636b2bba14SDavide Italiano COFFSymbolRef Symb = getCOFFSymbol(Ref); 164*03a85680SDavide Italiano return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 1656b2bba14SDavide Italiano } 1666b2bba14SDavide Italiano 167931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 168ed067c45SRafael Espindola uint64_t Result = getSymbolValue(Ref); 16944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 170c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 171991af666SRafael Espindola 172991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 173991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 174ed067c45SRafael Espindola return Result; 17554c9f3daSRafael Espindola 1762617dcceSCraig Topper const coff_section *Section = nullptr; 177c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 178931cb65dSKevin Enderby return errorCodeToError(EC); 179991af666SRafael Espindola Result += Section->VirtualAddress; 18047ea9eceSReid Kleckner 18147ea9eceSReid Kleckner // The section VirtualAddress does not include ImageBase, and we want to 18247ea9eceSReid Kleckner // return virtual addresses. 18321427adaSReid Kleckner Result += getImageBase(); 18447ea9eceSReid Kleckner 185ed067c45SRafael Espindola return Result; 186c7d7c6fbSDavid Majnemer } 187c7d7c6fbSDavid Majnemer 1887bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 18944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 190c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 19144f51e51SDavid Majnemer 192e834f420SPeter Collingbourne if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 193e834f420SPeter Collingbourne return SymbolRef::ST_Function; 1942fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 1952fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 1962fa80cc5SRafael Espindola if (Symb.isCommon()) 1972fa80cc5SRafael Espindola return SymbolRef::ST_Data; 1982fa80cc5SRafael Espindola if (Symb.isFileRecord()) 1992fa80cc5SRafael Espindola return SymbolRef::ST_File; 2002fa80cc5SRafael Espindola 2011a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 2022fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 2032fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 2042fa80cc5SRafael Espindola 2052fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 2062fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2072fa80cc5SRafael Espindola 2082fa80cc5SRafael Espindola return SymbolRef::ST_Other; 20975d1cf33SBenjamin Kramer } 21075d1cf33SBenjamin Kramer 21120122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 21244f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 21320122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 21475d1cf33SBenjamin Kramer 215c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2169dc0eb42SLang Hames Result |= SymbolRef::SF_Global; 2171df4b84dSDavid Meyer 218c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2191df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2201df4b84dSDavid Meyer 22144f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2221df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2231df4b84dSDavid Meyer 224c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 225c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 226c7d7c6fbSDavid Majnemer 227c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 228c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 229c7d7c6fbSDavid Majnemer 230c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 231c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 232c7d7c6fbSDavid Majnemer 233c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 234c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 235c7d7c6fbSDavid Majnemer 23620122a43SRafael Espindola return Result; 23701759754SMichael J. Spencer } 23801759754SMichael J. Spencer 239d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 240c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2415eb02e45SRafael Espindola return Symb.getValue(); 2428e90adafSMichael J. Spencer } 2438e90adafSMichael J. Spencer 2447bd8d994SKevin Enderby Expected<section_iterator> 2458bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 24644f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2478bab889bSRafael Espindola if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2488bab889bSRafael Espindola return section_end(); 2492617dcceSCraig Topper const coff_section *Sec = nullptr; 25044f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 2517bd8d994SKevin Enderby return errorCodeToError(EC); 2528bab889bSRafael Espindola DataRefImpl Ret; 2538bab889bSRafael Espindola Ret.p = reinterpret_cast<uintptr_t>(Sec); 2548bab889bSRafael Espindola return section_iterator(SectionRef(Ret, this)); 25532173153SMichael J. Spencer } 25632173153SMichael J. Spencer 2576bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2586bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2596bf32210SRafael Espindola return Symb.getSectionNumber(); 2606bf32210SRafael Espindola } 2616bf32210SRafael Espindola 2625e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2638ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2648ff24d25SRui Ueyama Sec += 1; 2658ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2668e90adafSMichael J. Spencer } 2678e90adafSMichael J. Spencer 268db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2691d6167fdSMichael J. Spencer StringRef &Result) const { 2708ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2718ff24d25SRui Ueyama return getSectionName(Sec, Result); 2728e90adafSMichael J. Spencer } 2738e90adafSMichael J. Spencer 27480291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2758ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2767c6a071bSDavid Majnemer uint64_t Result = Sec->VirtualAddress; 2777c6a071bSDavid Majnemer 2787c6a071bSDavid Majnemer // The section VirtualAddress does not include ImageBase, and we want to 2797c6a071bSDavid Majnemer // return virtual addresses. 28021427adaSReid Kleckner Result += getImageBase(); 2817c6a071bSDavid Majnemer return Result; 2828e90adafSMichael J. Spencer } 2838e90adafSMichael J. Spencer 28480291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 285a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2868e90adafSMichael J. Spencer } 2878e90adafSMichael J. Spencer 288db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2891d6167fdSMichael J. Spencer StringRef &Result) const { 2908ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2919da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 292db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 2939da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2949da9e693SMichael J. Spencer return EC; 2958e90adafSMichael J. Spencer } 2968e90adafSMichael J. Spencer 29780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 2988ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 299511391feSDavid Majnemer return Sec->getAlignment(); 3007989460aSMichael J. Spencer } 3017989460aSMichael J. Spencer 302401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 303401e4e57SGeorge Rimar return false; 304401e4e57SGeorge Rimar } 305401e4e57SGeorge Rimar 30680291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3078ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 30880291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3098e90adafSMichael J. Spencer } 3108e90adafSMichael J. Spencer 31180291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3128ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31380291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 314800619f2SMichael J. Spencer } 315800619f2SMichael J. Spencer 31680291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3178ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3181a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3191a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3201a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3211a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 322800619f2SMichael J. Spencer } 323800619f2SMichael J. Spencer 3246bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3256bf32210SRafael Espindola uintptr_t Offset = 3266bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3276bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3286bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3296bf32210SRafael Espindola } 3306bf32210SRafael Espindola 33180291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3328ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3331a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3341a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3351a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3362138ef6dSPreston Gurd } 3372138ef6dSPreston Gurd 338e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 339e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 340e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 341e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 342e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 343e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 344e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 345e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 346e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 347e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 348e830c60dSDavid Majnemer return 0; 34998fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 35098fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 351e830c60dSDavid Majnemer } 352e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 353e830c60dSDavid Majnemer } 354e830c60dSDavid Majnemer 35594751be7SDavid Majnemer static const coff_relocation * 35694751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 35794751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 35894751be7SDavid Majnemer if (!NumRelocs) 35994751be7SDavid Majnemer return nullptr; 360827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 36194751be7SDavid Majnemer Base + Sec->PointerToRelocations); 362827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 363827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 364827c8a2bSRui Ueyama // relocations. 365827c8a2bSRui Ueyama begin++; 366827c8a2bSRui Ueyama } 36794751be7SDavid Majnemer if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 36894751be7SDavid Majnemer return nullptr; 36994751be7SDavid Majnemer return begin; 370827c8a2bSRui Ueyama } 37194751be7SDavid Majnemer 37294751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 37394751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 37494751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 37576d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 37676d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 37794751be7SDavid Majnemer DataRefImpl Ret; 37894751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3798ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 380e5fd0047SMichael J. Spencer } 381e5fd0047SMichael J. Spencer 3828ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3838ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 38494751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 38594751be7SDavid Majnemer if (I) 38694751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 3878ff24d25SRui Ueyama DataRefImpl Ret; 38894751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 3898ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 390e5fd0047SMichael J. Spencer } 391e5fd0047SMichael J. Spencer 392c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 393db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 39444f51e51SDavid Majnemer if (COFFHeader) 395236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 396236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 397236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 39844f51e51SDavid Majnemer return EC; 39944f51e51SDavid Majnemer 40044f51e51SDavid Majnemer if (COFFBigObjHeader) 401236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 402236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 403236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4048ff24d25SRui Ueyama return EC; 405c2bed429SRui Ueyama 406c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 407c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 408c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 409f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 41044f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 411f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 412c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 41348af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4148ff24d25SRui Ueyama return EC; 415c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 416db4ed0bdSRafael Espindola if (std::error_code EC = 41748af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4188ff24d25SRui Ueyama return EC; 419c2bed429SRui Ueyama 420773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 421773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 422773a5795SNico Rieck if (StringTableSize < 4) 423773a5795SNico Rieck StringTableSize = 4; 424773a5795SNico Rieck 425c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 426773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 427c2bed429SRui Ueyama return object_error::parse_failed; 4287d099195SRui Ueyama return std::error_code(); 429c2bed429SRui Ueyama } 430c2bed429SRui Ueyama 43121427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 432e94fef7bSReid Kleckner if (PE32Header) 43321427adaSReid Kleckner return PE32Header->ImageBase; 434e94fef7bSReid Kleckner else if (PE32PlusHeader) 43521427adaSReid Kleckner return PE32PlusHeader->ImageBase; 43621427adaSReid Kleckner // This actually comes up in practice. 43721427adaSReid Kleckner return 0; 438e94fef7bSReid Kleckner } 439e94fef7bSReid Kleckner 440215a586cSRui Ueyama // Returns the file offset for the given VA. 441db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 44221427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 443b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 444b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 445b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 446215a586cSRui Ueyama } 447215a586cSRui Ueyama 448c2bed429SRui Ueyama // Returns the file offset for the given RVA. 449db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 45027dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 45127dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 452c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 453c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 454215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 455215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 456c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4577d099195SRui Ueyama return std::error_code(); 458c2bed429SRui Ueyama } 459c2bed429SRui Ueyama } 460c2bed429SRui Ueyama return object_error::parse_failed; 461c2bed429SRui Ueyama } 462c2bed429SRui Ueyama 4632da433eaSReid Kleckner std::error_code 4642da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4652da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4662da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4672da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4682da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4692da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4702da433eaSReid Kleckner // overflow. 4712da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4722da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4732da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4742da433eaSReid Kleckner uintptr_t Begin = 4752da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4762da433eaSReid Kleckner Contents = 4772da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4782da433eaSReid Kleckner return std::error_code(); 4792da433eaSReid Kleckner } 4802da433eaSReid Kleckner } 4812da433eaSReid Kleckner return object_error::parse_failed; 4822da433eaSReid Kleckner } 4832da433eaSReid Kleckner 484c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 485c2bed429SRui Ueyama // table entry. 486db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 487db4ed0bdSRafael Espindola StringRef &Name) const { 488c2bed429SRui Ueyama uintptr_t IntPtr = 0; 489db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4908ff24d25SRui Ueyama return EC; 491c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 492c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 493c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 4947d099195SRui Ueyama return std::error_code(); 495c2bed429SRui Ueyama } 496c2bed429SRui Ueyama 49701528021SSaleem Abdulrasool std::error_code 49801528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 49901528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5002da433eaSReid Kleckner StringRef &PDBFileName) const { 5012da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5022da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 5032da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5042da433eaSReid Kleckner return EC; 50501528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5062da433eaSReid Kleckner return object_error::parse_failed; 50701528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 50801528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5092da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5102da433eaSReid Kleckner InfoBytes.size()); 5112da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5122da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5132da433eaSReid Kleckner return std::error_code(); 5142da433eaSReid Kleckner } 5152da433eaSReid Kleckner 51601528021SSaleem Abdulrasool std::error_code 51701528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 518f27f3f84SReid Kleckner StringRef &PDBFileName) const { 519f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 520f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 521f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 522f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 523f27f3f84SReid Kleckner PDBInfo = nullptr; 524f27f3f84SReid Kleckner PDBFileName = StringRef(); 525f27f3f84SReid Kleckner return std::error_code(); 526f27f3f84SReid Kleckner } 527f27f3f84SReid Kleckner 528c2bed429SRui Ueyama // Find the import table. 529db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 530c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 531c2bed429SRui Ueyama // the import table, do nothing. 532c2bed429SRui Ueyama const data_directory *DataEntry; 533c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5347d099195SRui Ueyama return std::error_code(); 535c2bed429SRui Ueyama 536c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 537c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5387d099195SRui Ueyama return std::error_code(); 539c2bed429SRui Ueyama 540c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 541c2bed429SRui Ueyama 542c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 543c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 544c2bed429SRui Ueyama uintptr_t IntPtr = 0; 545db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5468ff24d25SRui Ueyama return EC; 547ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 548ad7b7e73SDavid Majnemer return EC; 549c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5501c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5517d099195SRui Ueyama return std::error_code(); 552ad882ba8SRui Ueyama } 553c2bed429SRui Ueyama 55415d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 55515d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 55615d99359SRui Ueyama const data_directory *DataEntry; 55715d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5587d099195SRui Ueyama return std::error_code(); 55915d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5607d099195SRui Ueyama return std::error_code(); 56115d99359SRui Ueyama 56215d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 56315d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 56415d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 56515d99359SRui Ueyama 56615d99359SRui Ueyama uintptr_t IntPtr = 0; 56715d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 56815d99359SRui Ueyama return EC; 56915d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 57015d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5717d099195SRui Ueyama return std::error_code(); 57215d99359SRui Ueyama } 57315d99359SRui Ueyama 574ad882ba8SRui Ueyama // Find the export table. 575db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 576ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 577ad882ba8SRui Ueyama // the export table, do nothing. 578ad882ba8SRui Ueyama const data_directory *DataEntry; 579ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5807d099195SRui Ueyama return std::error_code(); 581ad882ba8SRui Ueyama 582ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 583ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5847d099195SRui Ueyama return std::error_code(); 585ad882ba8SRui Ueyama 586ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 587ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 588db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 589ad882ba8SRui Ueyama return EC; 59024fc2d64SRui Ueyama ExportDirectory = 59124fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 5927d099195SRui Ueyama return std::error_code(); 593c2bed429SRui Ueyama } 594c2bed429SRui Ueyama 59574e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 59674e85130SRui Ueyama const data_directory *DataEntry; 59774e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 5987d099195SRui Ueyama return std::error_code(); 59974e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6007d099195SRui Ueyama return std::error_code(); 60174e85130SRui Ueyama 60274e85130SRui Ueyama uintptr_t IntPtr = 0; 60374e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 60474e85130SRui Ueyama return EC; 60574e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 60674e85130SRui Ueyama IntPtr); 60774e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 60874e85130SRui Ueyama IntPtr + DataEntry->Size); 6097d099195SRui Ueyama return std::error_code(); 61074e85130SRui Ueyama } 61174e85130SRui Ueyama 6122da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6132da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6142da433eaSReid Kleckner const data_directory *DataEntry; 6152da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6162da433eaSReid Kleckner return std::error_code(); 6172da433eaSReid Kleckner 6182da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6192da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6202da433eaSReid Kleckner return std::error_code(); 6212da433eaSReid Kleckner 6222da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6232da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6242da433eaSReid Kleckner return object_error::parse_failed; 6252da433eaSReid Kleckner 6262da433eaSReid Kleckner uintptr_t IntPtr = 0; 6272da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6282da433eaSReid Kleckner return EC; 6292da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6302da433eaSReid Kleckner if (std::error_code EC = getRvaPtr( 6312da433eaSReid Kleckner DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 6322da433eaSReid Kleckner return EC; 6332da433eaSReid Kleckner DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 6342da433eaSReid Kleckner return std::error_code(); 6352da433eaSReid Kleckner } 6362da433eaSReid Kleckner 63748af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 63848af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 63944f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 64044f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 64144f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 642ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 64315d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6442da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6452da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6461d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 64748af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 648c3f9b5a5SRafael Espindola return; 649ee066fc4SEric Christopher 65082ebd8e3SRui Ueyama // The current location in the file where we are looking at. 65182ebd8e3SRui Ueyama uint64_t CurPtr = 0; 65282ebd8e3SRui Ueyama 65382ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 65482ebd8e3SRui Ueyama // it is placed right after COFF header. 6558ff24d25SRui Ueyama bool HasPEHeader = false; 656ee066fc4SEric Christopher 6571d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 65850267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 659ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 660ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 66150267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 66250267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 66350267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 66482ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 66550267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6668ff24d25SRui Ueyama EC = object_error::parse_failed; 6671d6167fdSMichael J. Spencer return; 6681d6167fdSMichael J. Spencer } 66944f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6708ff24d25SRui Ueyama HasPEHeader = true; 671ee066fc4SEric Christopher } 67250267222SDavid Majnemer } 673ee066fc4SEric Christopher 67448af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 6751d6167fdSMichael J. Spencer return; 67644f51e51SDavid Majnemer 67744f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 67844f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 67944f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 68044f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 68144f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 68244f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 68344f51e51SDavid Majnemer return; 68444f51e51SDavid Majnemer 68544f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 68644f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 68744f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 68844f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 68944f51e51SDavid Majnemer COFFHeader = nullptr; 69044f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 69144f51e51SDavid Majnemer } else { 69244f51e51SDavid Majnemer // It's not a bigobj. 69344f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 69444f51e51SDavid Majnemer } 69544f51e51SDavid Majnemer } 69644f51e51SDavid Majnemer if (COFFHeader) { 69744f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 69844f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 6997d099195SRui Ueyama EC = std::error_code(); 70082ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 70182ebd8e3SRui Ueyama 70244f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 70344f51e51SDavid Majnemer return; 70444f51e51SDavid Majnemer } 70544f51e51SDavid Majnemer 7068ff24d25SRui Ueyama if (HasPEHeader) { 70710ed9ddcSRui Ueyama const pe32_header *Header; 70848af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 70982ebd8e3SRui Ueyama return; 71010ed9ddcSRui Ueyama 71110ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 71210ed9ddcSRui Ueyama uint64_t DataDirSize; 71350267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 71410ed9ddcSRui Ueyama PE32Header = Header; 71510ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 71610ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 71750267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 71810ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 71910ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 72010ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 72110ed9ddcSRui Ueyama } else { 72210ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 72310ed9ddcSRui Ueyama EC = object_error::parse_failed; 724ed64342bSRui Ueyama return; 725ed64342bSRui Ueyama } 72648af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 72710ed9ddcSRui Ueyama return; 728f53c8cb4SRui Ueyama } 729776c6828SRui Ueyama 7308950a538SRui Ueyama if (COFFHeader) 7318950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7328950a538SRui Ueyama 73348af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 734236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7351d6167fdSMichael J. Spencer return; 7361d6167fdSMichael J. Spencer 737c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 738236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 739ac8cfab5SDavid Majnemer if ((EC = initSymbolTablePtr())) { 740ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 741ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 742ac8cfab5SDavid Majnemer StringTable = nullptr; 743ac8cfab5SDavid Majnemer StringTableSize = 0; 744ac8cfab5SDavid Majnemer } 745236b0ca7SDavid Majnemer } else { 746236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 747236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 748236b0ca7SDavid Majnemer EC = object_error::parse_failed; 749236b0ca7SDavid Majnemer return; 750236b0ca7SDavid Majnemer } 751236b0ca7SDavid Majnemer } 7528e90adafSMichael J. Spencer 753c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7548ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 755ed64342bSRui Ueyama return; 75615d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 75715d99359SRui Ueyama return; 7581d6167fdSMichael J. Spencer 759ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7608ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 761ad882ba8SRui Ueyama return; 762ad882ba8SRui Ueyama 76374e85130SRui Ueyama // Initialize the pointer to the base relocation table. 76474e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 76574e85130SRui Ueyama return; 76674e85130SRui Ueyama 7672da433eaSReid Kleckner // Initialize the pointer to the export table. 7682da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 7692da433eaSReid Kleckner return; 7702da433eaSReid Kleckner 7717d099195SRui Ueyama EC = std::error_code(); 7728e90adafSMichael J. Spencer } 7738e90adafSMichael J. Spencer 774f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 7758ff24d25SRui Ueyama DataRefImpl Ret; 77644f51e51SDavid Majnemer Ret.p = getSymbolTable(); 777f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7788e90adafSMichael J. Spencer } 7798e90adafSMichael J. Spencer 780f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 7818e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 7828ff24d25SRui Ueyama DataRefImpl Ret; 7838ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 784f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7858e90adafSMichael J. Spencer } 7868e90adafSMichael J. Spencer 787bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 788ad7b7e73SDavid Majnemer if (!ImportDirectory) 789ad7b7e73SDavid Majnemer return import_directory_end(); 7901c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 791ad7b7e73SDavid Majnemer return import_directory_end(); 792a045b73aSRui Ueyama return import_directory_iterator( 793a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 794c2bed429SRui Ueyama } 795c2bed429SRui Ueyama 796bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 797a045b73aSRui Ueyama return import_directory_iterator( 798ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 799c2bed429SRui Ueyama } 800c429b80dSDavid Meyer 80115d99359SRui Ueyama delay_import_directory_iterator 80215d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 80315d99359SRui Ueyama return delay_import_directory_iterator( 80415d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 80515d99359SRui Ueyama } 80615d99359SRui Ueyama 80715d99359SRui Ueyama delay_import_directory_iterator 80815d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 80915d99359SRui Ueyama return delay_import_directory_iterator( 81015d99359SRui Ueyama DelayImportDirectoryEntryRef( 81115d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 81215d99359SRui Ueyama } 81315d99359SRui Ueyama 814ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 815ad882ba8SRui Ueyama return export_directory_iterator( 816ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 817ad882ba8SRui Ueyama } 818ad882ba8SRui Ueyama 819ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8202617dcceSCraig Topper if (!ExportDirectory) 8212617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8228ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 823ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8248ff24d25SRui Ueyama return export_directory_iterator(Ref); 825ad882ba8SRui Ueyama } 826ad882ba8SRui Ueyama 827b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8288ff24d25SRui Ueyama DataRefImpl Ret; 8298ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8308ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8318e90adafSMichael J. Spencer } 8328e90adafSMichael J. Spencer 833b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8348ff24d25SRui Ueyama DataRefImpl Ret; 83544f51e51SDavid Majnemer int NumSections = 83644f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8378ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8388ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8398e90adafSMichael J. Spencer } 8408e90adafSMichael J. Spencer 84174e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 84274e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 84374e85130SRui Ueyama } 84474e85130SRui Ueyama 84574e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 84674e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 84774e85130SRui Ueyama } 84874e85130SRui Ueyama 8498e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 8500324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 8518e90adafSMichael J. Spencer } 8528e90adafSMichael J. Spencer 8538e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 85444f51e51SDavid Majnemer switch(getMachine()) { 8558e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8568e90adafSMichael J. Spencer return "COFF-i386"; 8578e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8588e90adafSMichael J. Spencer return "COFF-x86-64"; 8599b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8609b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8611eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8621eff5c9cSMartell Malone return "COFF-ARM64"; 8638e90adafSMichael J. Spencer default: 8648e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8658e90adafSMichael J. Spencer } 8668e90adafSMichael J. Spencer } 8678e90adafSMichael J. Spencer 8688e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 86944f51e51SDavid Majnemer switch (getMachine()) { 8708e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8718e90adafSMichael J. Spencer return Triple::x86; 8728e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8738e90adafSMichael J. Spencer return Triple::x86_64; 8749b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8759b7c0af2SSaleem Abdulrasool return Triple::thumb; 8761eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8771eff5c9cSMartell Malone return Triple::aarch64; 8788e90adafSMichael J. Spencer default: 8798e90adafSMichael J. Spencer return Triple::UnknownArch; 8808e90adafSMichael J. Spencer } 8818e90adafSMichael J. Spencer } 8828e90adafSMichael J. Spencer 883979fb40bSRui Ueyama iterator_range<import_directory_iterator> 884979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 885979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 886979fb40bSRui Ueyama } 887979fb40bSRui Ueyama 888979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 889979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 890979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 891979fb40bSRui Ueyama delay_import_directory_end()); 892979fb40bSRui Ueyama } 893979fb40bSRui Ueyama 894979fb40bSRui Ueyama iterator_range<export_directory_iterator> 895979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 896979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 897979fb40bSRui Ueyama } 898979fb40bSRui Ueyama 89974e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 90074e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 90174e85130SRui Ueyama } 90274e85130SRui Ueyama 903db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 90482ebd8e3SRui Ueyama Res = PE32Header; 9057d099195SRui Ueyama return std::error_code(); 90689a7a5eaSMichael J. Spencer } 90789a7a5eaSMichael J. Spencer 908db4ed0bdSRafael Espindola std::error_code 90910ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 91010ed9ddcSRui Ueyama Res = PE32PlusHeader; 9117d099195SRui Ueyama return std::error_code(); 91210ed9ddcSRui Ueyama } 91310ed9ddcSRui Ueyama 914db4ed0bdSRafael Espindola std::error_code 915db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 916ed64342bSRui Ueyama const data_directory *&Res) const { 917ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 918f69b0585SDavid Majnemer if (!DataDirectory) { 919f69b0585SDavid Majnemer Res = nullptr; 92010ed9ddcSRui Ueyama return object_error::parse_failed; 921f69b0585SDavid Majnemer } 92210ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 92310ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 92410ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 925f69b0585SDavid Majnemer if (Index >= NumEnt) { 926f69b0585SDavid Majnemer Res = nullptr; 927ed64342bSRui Ueyama return object_error::parse_failed; 928f69b0585SDavid Majnemer } 9298ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9307d099195SRui Ueyama return std::error_code(); 931ed64342bSRui Ueyama } 932ed64342bSRui Ueyama 933db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9341d6167fdSMichael J. Spencer const coff_section *&Result) const { 9352617dcceSCraig Topper Result = nullptr; 936236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9377d099195SRui Ueyama return std::error_code(); 938236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9391d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9408ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9417d099195SRui Ueyama return std::error_code(); 9428e90adafSMichael J. Spencer } 943236b0ca7SDavid Majnemer return object_error::parse_failed; 944236b0ca7SDavid Majnemer } 9458e90adafSMichael J. Spencer 946db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9471d6167fdSMichael J. Spencer StringRef &Result) const { 9481d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9491d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9501d6167fdSMichael J. Spencer return object_error::parse_failed; 9518ff24d25SRui Ueyama if (Offset >= StringTableSize) 9521d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9538ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9547d099195SRui Ueyama return std::error_code(); 9558e90adafSMichael J. Spencer } 956022ecdf2SBenjamin Kramer 95744f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 95889a7a5eaSMichael J. Spencer StringRef &Res) const { 959e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 960e40d30f3SRui Ueyama } 961e40d30f3SRui Ueyama 962e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 963e40d30f3SRui Ueyama StringRef &Res) const { 96489a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 965e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 966e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 9678ff24d25SRui Ueyama return EC; 9687d099195SRui Ueyama return std::error_code(); 96989a7a5eaSMichael J. Spencer } 97089a7a5eaSMichael J. Spencer 971e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 97289a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 973e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 97489a7a5eaSMichael J. Spencer else 97589a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 976e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 9777d099195SRui Ueyama return std::error_code(); 97889a7a5eaSMichael J. Spencer } 97989a7a5eaSMichael J. Spencer 98044f51e51SDavid Majnemer ArrayRef<uint8_t> 98144f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 9822617dcceSCraig Topper const uint8_t *Aux = nullptr; 98371757ef3SMarshall Clow 98444f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 98544f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 98671757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 98744f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 98871757ef3SMarshall Clow # ifndef NDEBUG 9898ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 9908ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 99144f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 99244f51e51SDavid Majnemer Offset >= 99344f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 99471757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 99571757ef3SMarshall Clow 99644f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 99744f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 99871757ef3SMarshall Clow # endif 999bfb85e67SMarshall Clow } 100044f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 100171757ef3SMarshall Clow } 100271757ef3SMarshall Clow 1003db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 100453c2d547SMichael J. Spencer StringRef &Res) const { 100553c2d547SMichael J. Spencer StringRef Name; 100644f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 100753c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 100853c2d547SMichael J. Spencer Name = Sec->Name; 100953c2d547SMichael J. Spencer else 101053c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 101144f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 101253c2d547SMichael J. Spencer 101353c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10142314b3deSDavid Majnemer if (Name.startswith("/")) { 101553c2d547SMichael J. Spencer uint32_t Offset; 10162314b3deSDavid Majnemer if (Name.startswith("//")) { 10179d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10189d2c15efSNico Rieck return object_error::parse_failed; 10199d2c15efSNico Rieck } else { 102053c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 102153c2d547SMichael J. Spencer return object_error::parse_failed; 10229d2c15efSNico Rieck } 1023db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 10248ff24d25SRui Ueyama return EC; 102553c2d547SMichael J. Spencer } 102653c2d547SMichael J. Spencer 102753c2d547SMichael J. Spencer Res = Name; 10287d099195SRui Ueyama return std::error_code(); 102953c2d547SMichael J. Spencer } 103053c2d547SMichael J. Spencer 1031a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1032a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1033a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1034a9ee5c06SDavid Majnemer // 1035a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1036d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1037a9ee5c06SDavid Majnemer // 1038a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1039a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1040a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1041a9ee5c06SDavid Majnemer // considered to be zero. 1042d5297ee7SRui Ueyama if (getDOSHeader()) 1043d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1044d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1045a9ee5c06SDavid Majnemer } 1046a9ee5c06SDavid Majnemer 1047db4ed0bdSRafael Espindola std::error_code 1048db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10499da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1050e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1051e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1052e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1053e2129662SDavid Majnemer return object_error::parse_failed; 10549da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10559da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10569da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10579da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1058a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1059e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10609da9e693SMichael J. Spencer return object_error::parse_failed; 1061a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10627d099195SRui Ueyama return std::error_code(); 10639da9e693SMichael J. Spencer } 10649da9e693SMichael J. Spencer 1065022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1066e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1067022ecdf2SBenjamin Kramer } 10688ff24d25SRui Ueyama 10695e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1070e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1071e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1072022ecdf2SBenjamin Kramer } 10738ff24d25SRui Ueyama 107496d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 107558323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 107696d071cdSRafael Espindola return R->VirtualAddress; 1077cbe72fc9SDanil Malyshev } 10788ff24d25SRui Ueyama 1079806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1080022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 10818ff24d25SRui Ueyama DataRefImpl Ref; 1082236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1083236b0ca7SDavid Majnemer return symbol_end(); 108444f51e51SDavid Majnemer if (SymbolTable16) 108544f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 108644f51e51SDavid Majnemer else if (SymbolTable32) 108744f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 108844f51e51SDavid Majnemer else 1089c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 10908ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1091022ecdf2SBenjamin Kramer } 10928ff24d25SRui Ueyama 109399c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1094022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 109599c041b7SRafael Espindola return R->Type; 1096022ecdf2SBenjamin Kramer } 1097e5fd0047SMichael J. Spencer 109827dc8394SAlexey Samsonov const coff_section * 109927dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 110027dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 110171757ef3SMarshall Clow } 110271757ef3SMarshall Clow 110344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 110444f51e51SDavid Majnemer if (SymbolTable16) 110544f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 110644f51e51SDavid Majnemer if (SymbolTable32) 110744f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 110844f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 110944f51e51SDavid Majnemer } 111044f51e51SDavid Majnemer 111144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 111244f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 111371757ef3SMarshall Clow } 111471757ef3SMarshall Clow 1115f12b8282SRafael Espindola const coff_relocation * 111627dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 111727dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1118d3e2a76cSMarshall Clow } 1119d3e2a76cSMarshall Clow 11206a75acb1SRui Ueyama iterator_range<const coff_relocation *> 11216a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11226a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 11236a75acb1SRui Ueyama const coff_relocation *E = I; 11246a75acb1SRui Ueyama if (I) 11256a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 11266a75acb1SRui Ueyama return make_range(I, E); 11276a75acb1SRui Ueyama } 11286a75acb1SRui Ueyama 112927dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 113027dc8394SAlexey Samsonov case COFF::reloc_type: \ 113127dc8394SAlexey Samsonov Res = #reloc_type; \ 113227dc8394SAlexey Samsonov break; 1133e5fd0047SMichael J. Spencer 113441bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 113541bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 11368ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11378ff24d25SRui Ueyama StringRef Res; 113844f51e51SDavid Majnemer switch (getMachine()) { 1139e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11408ff24d25SRui Ueyama switch (Reloc->Type) { 1141e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1142e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1143e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1144e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1145e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1146e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1147e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1148e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1149e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1150e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1151e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1152e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1153e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1154e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1155e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1156e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1157e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1158e5fd0047SMichael J. Spencer default: 11598ff24d25SRui Ueyama Res = "Unknown"; 1160e5fd0047SMichael J. Spencer } 1161e5fd0047SMichael J. Spencer break; 11625c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11635c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 11645c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11655c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11665c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11675c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11685c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11695c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 11705c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 11715c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 11725c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 11735c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 11745c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 11755c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 11765c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 11775c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 11785c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 11795c503bf4SSaleem Abdulrasool default: 11805c503bf4SSaleem Abdulrasool Res = "Unknown"; 11815c503bf4SSaleem Abdulrasool } 11825c503bf4SSaleem Abdulrasool break; 1183e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 11848ff24d25SRui Ueyama switch (Reloc->Type) { 1185e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1186e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1187e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1188e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1189e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1190e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1191e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1192e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1193e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1194e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1195e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1196e5fd0047SMichael J. Spencer default: 11978ff24d25SRui Ueyama Res = "Unknown"; 1198e5fd0047SMichael J. Spencer } 1199e5fd0047SMichael J. Spencer break; 1200e5fd0047SMichael J. Spencer default: 12018ff24d25SRui Ueyama Res = "Unknown"; 1202e5fd0047SMichael J. Spencer } 12038ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1204e5fd0047SMichael J. Spencer } 1205e5fd0047SMichael J. Spencer 1206e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1207e5fd0047SMichael J. Spencer 1208c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1209c66d761bSRafael Espindola return !DataDirectory; 1210c66d761bSRafael Espindola } 1211c66d761bSRafael Espindola 1212c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1213c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1214a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1215c2bed429SRui Ueyama } 1216c2bed429SRui Ueyama 12175e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12185e812afaSRafael Espindola ++Index; 12191c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1220ad7b7e73SDavid Majnemer Index = -1; 1221ad7b7e73SDavid Majnemer ImportTable = nullptr; 1222ad7b7e73SDavid Majnemer } 1223c2bed429SRui Ueyama } 1224c2bed429SRui Ueyama 1225db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 12261c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1227ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1228c2bed429SRui Ueyama } 1229c2bed429SRui Ueyama 1230861021f9SRui Ueyama static imported_symbol_iterator 123115d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1232861021f9SRui Ueyama uintptr_t Ptr, int Index) { 123315d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1234861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 123515d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1236861021f9SRui Ueyama } 1237861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 123815d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1239861021f9SRui Ueyama } 1240861021f9SRui Ueyama 124115d99359SRui Ueyama static imported_symbol_iterator 124215d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1243861021f9SRui Ueyama uintptr_t IntPtr = 0; 124415d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 124515d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1246861021f9SRui Ueyama } 1247861021f9SRui Ueyama 124815d99359SRui Ueyama static imported_symbol_iterator 124915d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1250861021f9SRui Ueyama uintptr_t IntPtr = 0; 125115d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1252861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1253861021f9SRui Ueyama int Index = 0; 125415d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1255861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1256861021f9SRui Ueyama while (*Entry++) 1257861021f9SRui Ueyama ++Index; 1258861021f9SRui Ueyama } else { 1259861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1260861021f9SRui Ueyama while (*Entry++) 1261861021f9SRui Ueyama ++Index; 1262861021f9SRui Ueyama } 126315d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 126415d99359SRui Ueyama } 126515d99359SRui Ueyama 126615d99359SRui Ueyama imported_symbol_iterator 126715d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 126860049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 126915d99359SRui Ueyama OwningObject); 127015d99359SRui Ueyama } 127115d99359SRui Ueyama 127215d99359SRui Ueyama imported_symbol_iterator 127315d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 127460049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 127515d99359SRui Ueyama OwningObject); 1276861021f9SRui Ueyama } 1277861021f9SRui Ueyama 1278979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1279979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1280979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1281979fb40bSRui Ueyama } 1282979fb40bSRui Ueyama 128360049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 128460049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 128560049526SDavid Majnemer OwningObject); 128660049526SDavid Majnemer } 128760049526SDavid Majnemer 128860049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 128960049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 129060049526SDavid Majnemer OwningObject); 129160049526SDavid Majnemer } 129260049526SDavid Majnemer 129360049526SDavid Majnemer iterator_range<imported_symbol_iterator> 129460049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 129560049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 129660049526SDavid Majnemer } 129760049526SDavid Majnemer 1298db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1299c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1300db4ed0bdSRafael Espindola if (std::error_code EC = 13011e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1302a045b73aSRui Ueyama return EC; 1303a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13047d099195SRui Ueyama return std::error_code(); 1305c2bed429SRui Ueyama } 1306c2bed429SRui Ueyama 13071e152d5eSRui Ueyama std::error_code 13081e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 13091e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 13107d099195SRui Ueyama return std::error_code(); 13111e152d5eSRui Ueyama } 13121e152d5eSRui Ueyama 13131e152d5eSRui Ueyama std::error_code 13141e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 13151e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 13167d099195SRui Ueyama return std::error_code(); 13171e152d5eSRui Ueyama } 13181e152d5eSRui Ueyama 131915d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 132015d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 132115d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 132215d99359SRui Ueyama } 132315d99359SRui Ueyama 132415d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 132515d99359SRui Ueyama ++Index; 132615d99359SRui Ueyama } 132715d99359SRui Ueyama 132815d99359SRui Ueyama imported_symbol_iterator 132915d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 133015d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 133115d99359SRui Ueyama OwningObject); 133215d99359SRui Ueyama } 133315d99359SRui Ueyama 133415d99359SRui Ueyama imported_symbol_iterator 133515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 133615d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 133715d99359SRui Ueyama OwningObject); 133815d99359SRui Ueyama } 133915d99359SRui Ueyama 1340979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1341979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1342979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1343979fb40bSRui Ueyama } 1344979fb40bSRui Ueyama 134515d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 134615d99359SRui Ueyama uintptr_t IntPtr = 0; 134715d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 134815d99359SRui Ueyama return EC; 134915d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13507d099195SRui Ueyama return std::error_code(); 135115d99359SRui Ueyama } 135215d99359SRui Ueyama 13531af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 13541af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 13551af08658SRui Ueyama Result = Table; 13567d099195SRui Ueyama return std::error_code(); 13571af08658SRui Ueyama } 13581af08658SRui Ueyama 1359ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1360ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1361ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1362ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1363ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1364ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1365ffa4cebeSRui Ueyama return EC; 1366ffa4cebeSRui Ueyama if (OwningObject->is64()) 13675dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1368ffa4cebeSRui Ueyama else 13695dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 13707d099195SRui Ueyama return std::error_code(); 1371ffa4cebeSRui Ueyama } 1372ffa4cebeSRui Ueyama 1373ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1374ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1375ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1376ad882ba8SRui Ueyama } 1377ad882ba8SRui Ueyama 13785e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 13795e812afaSRafael Espindola ++Index; 1380ad882ba8SRui Ueyama } 1381ad882ba8SRui Ueyama 1382da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1383da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1384db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1385da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1386db4ed0bdSRafael Espindola if (std::error_code EC = 1387db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1388da49d0d4SRui Ueyama return EC; 1389da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13907d099195SRui Ueyama return std::error_code(); 1391da49d0d4SRui Ueyama } 1392da49d0d4SRui Ueyama 1393e5df6095SRui Ueyama // Returns the starting ordinal number. 1394db4ed0bdSRafael Espindola std::error_code 1395db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1396e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 13977d099195SRui Ueyama return std::error_code(); 1398e5df6095SRui Ueyama } 1399e5df6095SRui Ueyama 1400ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1401db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1402ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 14037d099195SRui Ueyama return std::error_code(); 1404ad882ba8SRui Ueyama } 1405ad882ba8SRui Ueyama 1406ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1407db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1408ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1409db4ed0bdSRafael Espindola if (std::error_code EC = 1410db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1411ad882ba8SRui Ueyama return EC; 141224fc2d64SRui Ueyama const export_address_table_entry *entry = 141324fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1414ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 14157d099195SRui Ueyama return std::error_code(); 1416ad882ba8SRui Ueyama } 1417ad882ba8SRui Ueyama 1418ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1419ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1420db4ed0bdSRafael Espindola std::error_code 1421db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1422ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1423db4ed0bdSRafael Espindola if (std::error_code EC = 1424db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1425ad882ba8SRui Ueyama return EC; 1426ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1427ad882ba8SRui Ueyama 1428ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1429ad882ba8SRui Ueyama int Offset = 0; 1430ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1431ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1432ad882ba8SRui Ueyama if (*I != Index) 1433ad882ba8SRui Ueyama continue; 1434db4ed0bdSRafael Espindola if (std::error_code EC = 1435db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1436ad882ba8SRui Ueyama return EC; 1437ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1438db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1439ad882ba8SRui Ueyama return EC; 1440ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14417d099195SRui Ueyama return std::error_code(); 1442ad882ba8SRui Ueyama } 1443ad882ba8SRui Ueyama Result = ""; 14447d099195SRui Ueyama return std::error_code(); 1445ad882ba8SRui Ueyama } 1446ad882ba8SRui Ueyama 14476161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 14486161b38dSRui Ueyama const data_directory *DataEntry; 14496161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 14506161b38dSRui Ueyama return EC; 14516161b38dSRui Ueyama uint32_t RVA; 14526161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14536161b38dSRui Ueyama return EC; 14546161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 14556161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 14566161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 14576161b38dSRui Ueyama return std::error_code(); 14586161b38dSRui Ueyama } 14596161b38dSRui Ueyama 14606161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 14616161b38dSRui Ueyama uint32_t RVA; 14626161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14636161b38dSRui Ueyama return EC; 14646161b38dSRui Ueyama uintptr_t IntPtr = 0; 14656161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 14666161b38dSRui Ueyama return EC; 14676161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14686161b38dSRui Ueyama return std::error_code(); 14696161b38dSRui Ueyama } 14706161b38dSRui Ueyama 1471861021f9SRui Ueyama bool ImportedSymbolRef:: 1472861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1473861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1474861021f9SRui Ueyama && Index == Other.Index; 1475861021f9SRui Ueyama } 1476861021f9SRui Ueyama 1477861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1478861021f9SRui Ueyama ++Index; 1479861021f9SRui Ueyama } 1480861021f9SRui Ueyama 1481861021f9SRui Ueyama std::error_code 1482861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1483861021f9SRui Ueyama uint32_t RVA; 1484861021f9SRui Ueyama if (Entry32) { 1485861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1486861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 14877d099195SRui Ueyama return std::error_code(); 1488861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1489861021f9SRui Ueyama } else { 1490861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 14917d099195SRui Ueyama return std::error_code(); 1492861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1493861021f9SRui Ueyama } 1494861021f9SRui Ueyama uintptr_t IntPtr = 0; 1495861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1496861021f9SRui Ueyama return EC; 1497861021f9SRui Ueyama // +2 because the first two bytes is hint. 1498861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 14997d099195SRui Ueyama return std::error_code(); 1500861021f9SRui Ueyama } 1501861021f9SRui Ueyama 1502ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1503ad7b7e73SDavid Majnemer if (Entry32) 1504ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1505ad7b7e73SDavid Majnemer else 1506ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1507ad7b7e73SDavid Majnemer return std::error_code(); 1508ad7b7e73SDavid Majnemer } 1509ad7b7e73SDavid Majnemer 1510ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1511ad7b7e73SDavid Majnemer if (Entry32) 1512ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1513ad7b7e73SDavid Majnemer else 1514ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1515ad7b7e73SDavid Majnemer return std::error_code(); 1516ad7b7e73SDavid Majnemer } 1517ad7b7e73SDavid Majnemer 1518861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1519861021f9SRui Ueyama uint32_t RVA; 1520861021f9SRui Ueyama if (Entry32) { 1521861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1522861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 15237d099195SRui Ueyama return std::error_code(); 1524861021f9SRui Ueyama } 1525861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1526861021f9SRui Ueyama } else { 1527861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1528861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 15297d099195SRui Ueyama return std::error_code(); 1530861021f9SRui Ueyama } 1531861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1532861021f9SRui Ueyama } 1533861021f9SRui Ueyama uintptr_t IntPtr = 0; 1534861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1535861021f9SRui Ueyama return EC; 1536861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15377d099195SRui Ueyama return std::error_code(); 1538861021f9SRui Ueyama } 1539861021f9SRui Ueyama 1540437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 154148af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1542db4ed0bdSRafael Espindola std::error_code EC; 154348af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1544692410efSRafael Espindola if (EC) 1545692410efSRafael Espindola return EC; 1546437b0d58SRafael Espindola return std::move(Ret); 1547686738e2SRui Ueyama } 154874e85130SRui Ueyama 154974e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 155074e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 155174e85130SRui Ueyama } 155274e85130SRui Ueyama 155374e85130SRui Ueyama void BaseRelocRef::moveNext() { 155474e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 155574e85130SRui Ueyama // size of the header itself. 155674e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1557970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 155874e85130SRui Ueyama if (Size == Header->BlockSize) { 155974e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 156074e85130SRui Ueyama // consists of the header followed by entries. The header contains 156174e85130SRui Ueyama // how many entories will follow. When we reach the end of the 156274e85130SRui Ueyama // current block, proceed to the next block. 156374e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 156474e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 156574e85130SRui Ueyama Index = 0; 156674e85130SRui Ueyama } else { 156774e85130SRui Ueyama ++Index; 156874e85130SRui Ueyama } 156974e85130SRui Ueyama } 157074e85130SRui Ueyama 157174e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 157274e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 157374e85130SRui Ueyama Type = Entry[Index].getType(); 15747d099195SRui Ueyama return std::error_code(); 157574e85130SRui Ueyama } 157674e85130SRui Ueyama 157774e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 157874e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 157974e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 15807d099195SRui Ueyama return std::error_code(); 158174e85130SRui Ueyama } 1582