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" 16e5fd0047SMichael J. Spencer #include "llvm/ADT/SmallString.h" 178e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 188e90adafSMichael J. Spencer #include "llvm/ADT/Triple.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 42ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 43ed64342bSRui Ueyama // Returns unexpected_eof if error. 44ed64342bSRui Ueyama template <typename T> 4548af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 46db4ed0bdSRafael Espindola const uint8_t *Ptr, 47db4ed0bdSRafael Espindola const size_t Size = sizeof(T)) { 48ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 49c3f9b5a5SRafael Espindola if (Addr + Size < Addr || Addr + Size < Size || 50c3f9b5a5SRafael Espindola Addr + Size > uintptr_t(M.getBufferEnd())) { 51ed64342bSRui Ueyama return object_error::unexpected_eof; 521d6167fdSMichael J. Spencer } 53ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 54ed64342bSRui Ueyama return object_error::success; 551d6167fdSMichael J. Spencer } 561d6167fdSMichael J. Spencer 579d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 589d2c15efSNico Rieck // prefixed slashes. 599d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 609d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 619d2c15efSNico Rieck if (Str.size() > 6) 629d2c15efSNico Rieck return true; 639d2c15efSNico Rieck 649d2c15efSNico Rieck uint64_t Value = 0; 659d2c15efSNico Rieck while (!Str.empty()) { 669d2c15efSNico Rieck unsigned CharVal; 679d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 689d2c15efSNico Rieck CharVal = Str[0] - 'A'; 699d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 709d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 719d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 729d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 739d2c15efSNico Rieck else if (Str[0] == '+') // 62 745500b07cSRui Ueyama CharVal = 62; 759d2c15efSNico Rieck else if (Str[0] == '/') // 63 765500b07cSRui Ueyama CharVal = 63; 779d2c15efSNico Rieck else 789d2c15efSNico Rieck return true; 799d2c15efSNico Rieck 809d2c15efSNico Rieck Value = (Value * 64) + CharVal; 819d2c15efSNico Rieck Str = Str.substr(1); 829d2c15efSNico Rieck } 839d2c15efSNico Rieck 849d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 859d2c15efSNico Rieck return true; 869d2c15efSNico Rieck 879d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 889d2c15efSNico Rieck return false; 899d2c15efSNico Rieck } 909d2c15efSNico Rieck 9144f51e51SDavid Majnemer template <typename coff_symbol_type> 9244f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 9344f51e51SDavid Majnemer const coff_symbol_type *Addr = 9444f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 951d6167fdSMichael J. Spencer 961d6167fdSMichael J. Spencer #ifndef NDEBUG 971d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 988ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 9944f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 10044f51e51SDavid Majnemer Offset >= getPointerToSymbolTable() + 10144f51e51SDavid Majnemer (getNumberOfSymbols() * sizeof(coff_symbol_type))) 1021d6167fdSMichael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 1031d6167fdSMichael J. Spencer 10444f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 10544f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1061d6167fdSMichael J. Spencer #endif 1071d6167fdSMichael J. Spencer 1088ff24d25SRui Ueyama return Addr; 1091d6167fdSMichael J. Spencer } 1101d6167fdSMichael J. Spencer 1118ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1128ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1131d6167fdSMichael J. Spencer 1141d6167fdSMichael J. Spencer # ifndef NDEBUG 1151d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 11644f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1171d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1181d6167fdSMichael J. Spencer 1198ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1208ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1211d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1221d6167fdSMichael J. Spencer # endif 1231d6167fdSMichael J. Spencer 1248ff24d25SRui Ueyama return Addr; 1251d6167fdSMichael J. Spencer } 1261d6167fdSMichael J. Spencer 1275e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 12844f51e51SDavid Majnemer if (SymbolTable16) { 12944f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1308ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 1318ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Symb); 13244f51e51SDavid Majnemer } else if (SymbolTable32) { 13344f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 13444f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 13544f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(Symb); 13644f51e51SDavid Majnemer } else { 13744f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 13844f51e51SDavid Majnemer } 1391d6167fdSMichael J. Spencer } 1401d6167fdSMichael J. Spencer 141db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, 1421d6167fdSMichael J. Spencer StringRef &Result) const { 14344f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1448ff24d25SRui Ueyama return getSymbolName(Symb, Result); 1458e90adafSMichael J. Spencer } 1468e90adafSMichael J. Spencer 147db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, 14875d1cf33SBenjamin Kramer uint64_t &Result) const { 14944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1502617dcceSCraig Topper const coff_section *Section = nullptr; 15144f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) 1528ff24d25SRui Ueyama return EC; 153e62ab11fSRafael Espindola 15444f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) 15575d1cf33SBenjamin Kramer Result = UnknownAddressOrSize; 15675d1cf33SBenjamin Kramer else if (Section) 15744f51e51SDavid Majnemer Result = Section->VirtualAddress + Symb.getValue(); 15875d1cf33SBenjamin Kramer else 15944f51e51SDavid Majnemer Result = Symb.getValue(); 16075d1cf33SBenjamin Kramer return object_error::success; 16175d1cf33SBenjamin Kramer } 16275d1cf33SBenjamin Kramer 163db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, 164d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 16544f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 16675d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 16744f51e51SDavid Majnemer 16844f51e51SDavid Majnemer if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && 16944f51e51SDavid Majnemer Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { 1707e4b976cSDavid Meyer Result = SymbolRef::ST_Unknown; 17144f51e51SDavid Majnemer } else if (Symb.isFunctionDefinition()) { 17275d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 17375d1cf33SBenjamin Kramer } else { 17406adfac8SRafael Espindola uint32_t Characteristics = 0; 17544f51e51SDavid Majnemer if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 1762617dcceSCraig Topper const coff_section *Section = nullptr; 17744f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) 1788ff24d25SRui Ueyama return EC; 17906adfac8SRafael Espindola Characteristics = Section->Characteristics; 18075d1cf33SBenjamin Kramer } 18106adfac8SRafael Espindola if (Characteristics & COFF::IMAGE_SCN_MEM_READ && 18206adfac8SRafael Espindola ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 18306adfac8SRafael Espindola Result = SymbolRef::ST_Data; 18475d1cf33SBenjamin Kramer } 18575d1cf33SBenjamin Kramer return object_error::success; 18675d1cf33SBenjamin Kramer } 18775d1cf33SBenjamin Kramer 18820122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 18944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 19020122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 19175d1cf33SBenjamin Kramer 192975e115eSRafael Espindola // TODO: Correctly set SF_FormatSpecific, SF_Common 1937e4b976cSDavid Meyer 19444f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { 19544f51e51SDavid Majnemer if (Symb.getValue() == 0) 1967e4b976cSDavid Meyer Result |= SymbolRef::SF_Undefined; 19722fe9c1eSRafael Espindola else 19822fe9c1eSRafael Espindola Result |= SymbolRef::SF_Common; 19922fe9c1eSRafael Espindola } 20022fe9c1eSRafael Espindola 2011df4b84dSDavid Meyer 2021df4b84dSDavid Meyer // TODO: This are certainly too restrictive. 20344f51e51SDavid Majnemer if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL) 2041df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 2051df4b84dSDavid Meyer 20644f51e51SDavid Majnemer if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 2071df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2081df4b84dSDavid Meyer 20944f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2101df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2111df4b84dSDavid Meyer 21220122a43SRafael Espindola return Result; 21301759754SMichael J. Spencer } 21401759754SMichael J. Spencer 215db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, 2161d6167fdSMichael J. Spencer uint64_t &Result) const { 2178e90adafSMichael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 2188e90adafSMichael J. Spencer // in the same section as this symbol, and looking for either the next 2198e90adafSMichael J. Spencer // symbol, or the end of the section. 22044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2212617dcceSCraig Topper const coff_section *Section = nullptr; 22244f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) 2238ff24d25SRui Ueyama return EC; 224e62ab11fSRafael Espindola 2258280fbbfSRafael Espindola if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { 2268280fbbfSRafael Espindola if (Symb.getValue() == 0) 2271d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 2281d6167fdSMichael J. Spencer else 2298280fbbfSRafael Espindola Result = Symb.getValue(); 2308280fbbfSRafael Espindola } else if (Section) { 2318280fbbfSRafael Espindola Result = Section->SizeOfRawData - Symb.getValue(); 2328280fbbfSRafael Espindola } else { 2331d6167fdSMichael J. Spencer Result = 0; 2348280fbbfSRafael Espindola } 2358280fbbfSRafael Espindola 2361d6167fdSMichael J. Spencer return object_error::success; 2378e90adafSMichael J. Spencer } 2388e90adafSMichael J. Spencer 239db4ed0bdSRafael Espindola std::error_code 240db4ed0bdSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref, 24132173153SMichael J. Spencer section_iterator &Result) const { 24244f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 24344f51e51SDavid Majnemer if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 244b5155a57SRafael Espindola Result = section_end(); 245f078eff3SRui Ueyama } else { 2462617dcceSCraig Topper const coff_section *Sec = nullptr; 24744f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 248db4ed0bdSRafael Espindola return EC; 2498ff24d25SRui Ueyama DataRefImpl Ref; 2508ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2518ff24d25SRui Ueyama Result = section_iterator(SectionRef(Ref, this)); 25232173153SMichael J. Spencer } 25332173153SMichael J. Spencer return object_error::success; 25432173153SMichael J. Spencer } 25532173153SMichael J. Spencer 2565e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2578ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2588ff24d25SRui Ueyama Sec += 1; 2598ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2608e90adafSMichael J. Spencer } 2618e90adafSMichael J. Spencer 262db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2631d6167fdSMichael J. Spencer StringRef &Result) const { 2648ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2658ff24d25SRui Ueyama return getSectionName(Sec, Result); 2668e90adafSMichael J. Spencer } 2678e90adafSMichael J. Spencer 26880291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2698ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 27080291274SRafael Espindola return Sec->VirtualAddress; 2718e90adafSMichael J. Spencer } 2728e90adafSMichael J. Spencer 27380291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 274*a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2758e90adafSMichael J. Spencer } 2768e90adafSMichael J. Spencer 277db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2781d6167fdSMichael J. Spencer StringRef &Result) const { 2798ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2809da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 281db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 2829da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2839da9e693SMichael J. Spencer return EC; 2848e90adafSMichael J. Spencer } 2858e90adafSMichael J. Spencer 28680291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 2878ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 28880291274SRafael Espindola return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 2897989460aSMichael J. Spencer } 2907989460aSMichael J. Spencer 29180291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 2928ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 29380291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 2948e90adafSMichael J. Spencer } 2958e90adafSMichael J. Spencer 29680291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 2978ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 29880291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 299800619f2SMichael J. Spencer } 300800619f2SMichael J. Spencer 30180291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3028ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 30380291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 304800619f2SMichael J. Spencer } 305800619f2SMichael J. Spencer 30680291274SRafael Espindola bool COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref) const { 3072138ef6dSPreston Gurd // FIXME: Unimplemented 30880291274SRafael Espindola return true; 3092138ef6dSPreston Gurd } 3102138ef6dSPreston Gurd 31180291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3128ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31380291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3142138ef6dSPreston Gurd } 3152138ef6dSPreston Gurd 31680291274SRafael Espindola bool COFFObjectFile::isSectionZeroInit(DataRefImpl Ref) const { 317b96a320aSAndrew Kaylor // FIXME: Unimplemented. 31880291274SRafael Espindola return false; 3192138ef6dSPreston Gurd } 3202138ef6dSPreston Gurd 32180291274SRafael Espindola bool COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref) const { 3223f31fa05SAndrew Kaylor // FIXME: Unimplemented. 32380291274SRafael Espindola return false; 3243f31fa05SAndrew Kaylor } 3253f31fa05SAndrew Kaylor 32680291274SRafael Espindola bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, 32780291274SRafael Espindola DataRefImpl SymbRef) const { 3288ff24d25SRui Ueyama const coff_section *Sec = toSec(SecRef); 32944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(SymbRef); 330a9260865SRafael Espindola int32_t SecNumber = (Sec - SectionTable) + 1; 33180291274SRafael Espindola return SecNumber == Symb.getSectionNumber(); 332f6f3e81cSBenjamin Kramer } 333f6f3e81cSBenjamin Kramer 3348ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 3358ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3368ff24d25SRui Ueyama DataRefImpl Ret; 337827c8a2bSRui Ueyama if (Sec->NumberOfRelocations == 0) { 3388ff24d25SRui Ueyama Ret.p = 0; 339827c8a2bSRui Ueyama } else { 340827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 341827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 342827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 343827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 344827c8a2bSRui Ueyama // relocations. 345827c8a2bSRui Ueyama begin++; 346827c8a2bSRui Ueyama } 347827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin); 348827c8a2bSRui Ueyama } 3498ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 350e5fd0047SMichael J. Spencer } 351e5fd0047SMichael J. Spencer 352827c8a2bSRui Ueyama static uint32_t getNumberOfRelocations(const coff_section *Sec, 353827c8a2bSRui Ueyama const uint8_t *base) { 354827c8a2bSRui Ueyama // The field for the number of relocations in COFF section table is only 355827c8a2bSRui Ueyama // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 356827c8a2bSRui Ueyama // NumberOfRelocations field, and the actual relocation count is stored in the 357827c8a2bSRui Ueyama // VirtualAddress field in the first relocation entry. 358827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 359827c8a2bSRui Ueyama auto *FirstReloc = reinterpret_cast<const coff_relocation*>( 360827c8a2bSRui Ueyama base + Sec->PointerToRelocations); 361827c8a2bSRui Ueyama return FirstReloc->VirtualAddress; 362827c8a2bSRui Ueyama } 363827c8a2bSRui Ueyama return Sec->NumberOfRelocations; 364827c8a2bSRui Ueyama } 365827c8a2bSRui Ueyama 3668ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3678ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3688ff24d25SRui Ueyama DataRefImpl Ret; 369827c8a2bSRui Ueyama if (Sec->NumberOfRelocations == 0) { 3708ff24d25SRui Ueyama Ret.p = 0; 371827c8a2bSRui Ueyama } else { 372827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 373827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 374827c8a2bSRui Ueyama uint32_t NumReloc = getNumberOfRelocations(Sec, base()); 375827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); 376827c8a2bSRui Ueyama } 3778ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 378e5fd0047SMichael J. Spencer } 379e5fd0047SMichael J. Spencer 380c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 381db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 38244f51e51SDavid Majnemer if (COFFHeader) 38344f51e51SDavid Majnemer if (std::error_code EC = 38444f51e51SDavid Majnemer getObject(SymbolTable16, Data, base() + getPointerToSymbolTable(), 38544f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 38644f51e51SDavid Majnemer return EC; 38744f51e51SDavid Majnemer 38844f51e51SDavid Majnemer if (COFFBigObjHeader) 38944f51e51SDavid Majnemer if (std::error_code EC = 39044f51e51SDavid Majnemer getObject(SymbolTable32, Data, base() + getPointerToSymbolTable(), 39144f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 3928ff24d25SRui Ueyama return EC; 393c2bed429SRui Ueyama 394c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 395c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 396c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 397c2bed429SRui Ueyama const uint8_t *StringTableAddr = 39844f51e51SDavid Majnemer base() + getPointerToSymbolTable() + 39944f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 400c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 40148af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4028ff24d25SRui Ueyama return EC; 403c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 404db4ed0bdSRafael Espindola if (std::error_code EC = 40548af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4068ff24d25SRui Ueyama return EC; 407c2bed429SRui Ueyama 408773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 409773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 410773a5795SNico Rieck if (StringTableSize < 4) 411773a5795SNico Rieck StringTableSize = 4; 412773a5795SNico Rieck 413c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 414773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 415c2bed429SRui Ueyama return object_error::parse_failed; 416c2bed429SRui Ueyama return object_error::success; 417c2bed429SRui Ueyama } 418c2bed429SRui Ueyama 419215a586cSRui Ueyama // Returns the file offset for the given VA. 420db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 421b6eb264aSRui Ueyama uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 422b6eb264aSRui Ueyama : (uint64_t)PE32PlusHeader->ImageBase; 423b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 424b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 425b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 426215a586cSRui Ueyama } 427215a586cSRui Ueyama 428c2bed429SRui Ueyama // Returns the file offset for the given RVA. 429db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 43027dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 43127dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 432c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 433c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 434215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 435215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 436c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 437c2bed429SRui Ueyama return object_error::success; 438c2bed429SRui Ueyama } 439c2bed429SRui Ueyama } 440c2bed429SRui Ueyama return object_error::parse_failed; 441c2bed429SRui Ueyama } 442c2bed429SRui Ueyama 443c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 444c2bed429SRui Ueyama // table entry. 445db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 446db4ed0bdSRafael Espindola StringRef &Name) const { 447c2bed429SRui Ueyama uintptr_t IntPtr = 0; 448db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4498ff24d25SRui Ueyama return EC; 450c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 451c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 452c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 453c2bed429SRui Ueyama return object_error::success; 454c2bed429SRui Ueyama } 455c2bed429SRui Ueyama 456c2bed429SRui Ueyama // Find the import table. 457db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 458c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 459c2bed429SRui Ueyama // the import table, do nothing. 460c2bed429SRui Ueyama const data_directory *DataEntry; 461c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 462c2bed429SRui Ueyama return object_error::success; 463c2bed429SRui Ueyama 464c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 465c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 466c2bed429SRui Ueyama return object_error::success; 467c2bed429SRui Ueyama 468c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 4691e152d5eSRui Ueyama // -1 because the last entry is the null entry. 470c2bed429SRui Ueyama NumberOfImportDirectory = DataEntry->Size / 4711e152d5eSRui Ueyama sizeof(import_directory_table_entry) - 1; 472c2bed429SRui Ueyama 473c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 474c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 475c2bed429SRui Ueyama uintptr_t IntPtr = 0; 476db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 4778ff24d25SRui Ueyama return EC; 478c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 479c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 480ad882ba8SRui Ueyama return object_error::success; 481ad882ba8SRui Ueyama } 482c2bed429SRui Ueyama 48315d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 48415d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 48515d99359SRui Ueyama const data_directory *DataEntry; 48615d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 48715d99359SRui Ueyama return object_error::success; 48815d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 48915d99359SRui Ueyama return object_error::success; 49015d99359SRui Ueyama 49115d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 49215d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 49315d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 49415d99359SRui Ueyama 49515d99359SRui Ueyama uintptr_t IntPtr = 0; 49615d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 49715d99359SRui Ueyama return EC; 49815d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 49915d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 50015d99359SRui Ueyama return object_error::success; 50115d99359SRui Ueyama } 50215d99359SRui Ueyama 503ad882ba8SRui Ueyama // Find the export table. 504db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 505ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 506ad882ba8SRui Ueyama // the export table, do nothing. 507ad882ba8SRui Ueyama const data_directory *DataEntry; 508ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 509ad882ba8SRui Ueyama return object_error::success; 510ad882ba8SRui Ueyama 511ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 512ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 513ad882ba8SRui Ueyama return object_error::success; 514ad882ba8SRui Ueyama 515ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 516ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 517db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 518ad882ba8SRui Ueyama return EC; 51924fc2d64SRui Ueyama ExportDirectory = 52024fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 521ad882ba8SRui Ueyama return object_error::success; 522c2bed429SRui Ueyama } 523c2bed429SRui Ueyama 52448af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 52548af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 52644f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 52744f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 52844f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 52944f51e51SDavid Majnemer ImportDirectory(nullptr), NumberOfImportDirectory(0), 53015d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 5312617dcceSCraig Topper ExportDirectory(nullptr) { 5321d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 53348af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 534c3f9b5a5SRafael Espindola return; 535ee066fc4SEric Christopher 53682ebd8e3SRui Ueyama // The current location in the file where we are looking at. 53782ebd8e3SRui Ueyama uint64_t CurPtr = 0; 53882ebd8e3SRui Ueyama 53982ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 54082ebd8e3SRui Ueyama // it is placed right after COFF header. 5418ff24d25SRui Ueyama bool HasPEHeader = false; 542ee066fc4SEric Christopher 5431d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 544ec29b121SMichael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 545ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 546ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 54748af1c2aSRafael Espindola if (!checkSize(Data, EC, 0x3c + 8)) 548c3f9b5a5SRafael Espindola return; 54982ebd8e3SRui Ueyama CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 55082ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 55144f51e51SDavid Majnemer if (std::memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 55244f51e51SDavid Majnemer 0) { 5538ff24d25SRui Ueyama EC = object_error::parse_failed; 5541d6167fdSMichael J. Spencer return; 5551d6167fdSMichael J. Spencer } 55644f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 5578ff24d25SRui Ueyama HasPEHeader = true; 558ee066fc4SEric Christopher } 559ee066fc4SEric Christopher 56048af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 5611d6167fdSMichael J. Spencer return; 56244f51e51SDavid Majnemer 56344f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 56444f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 56544f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 56644f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 56744f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 56844f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 56944f51e51SDavid Majnemer return; 57044f51e51SDavid Majnemer 57144f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 57244f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 57344f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 57444f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 57544f51e51SDavid Majnemer COFFHeader = nullptr; 57644f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 57744f51e51SDavid Majnemer } else { 57844f51e51SDavid Majnemer // It's not a bigobj. 57944f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 58044f51e51SDavid Majnemer } 58144f51e51SDavid Majnemer } 58244f51e51SDavid Majnemer if (COFFHeader) { 58344f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 58444f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 58544f51e51SDavid Majnemer EC = object_error::success; 58682ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 58782ebd8e3SRui Ueyama 58844f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 58944f51e51SDavid Majnemer return; 59044f51e51SDavid Majnemer } 59144f51e51SDavid Majnemer 5928ff24d25SRui Ueyama if (HasPEHeader) { 59310ed9ddcSRui Ueyama const pe32_header *Header; 59448af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 59582ebd8e3SRui Ueyama return; 59610ed9ddcSRui Ueyama 59710ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 59810ed9ddcSRui Ueyama uint64_t DataDirSize; 59910ed9ddcSRui Ueyama if (Header->Magic == 0x10b) { 60010ed9ddcSRui Ueyama PE32Header = Header; 60110ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 60210ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 60310ed9ddcSRui Ueyama } else if (Header->Magic == 0x20b) { 60410ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 60510ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 60610ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 60710ed9ddcSRui Ueyama } else { 60810ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 60910ed9ddcSRui Ueyama EC = object_error::parse_failed; 610ed64342bSRui Ueyama return; 611ed64342bSRui Ueyama } 61248af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 61310ed9ddcSRui Ueyama return; 61482ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 61582ebd8e3SRui Ueyama } 6161d6167fdSMichael J. Spencer 61748af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 61844f51e51SDavid Majnemer getNumberOfSections() * sizeof(coff_section)))) 6191d6167fdSMichael J. Spencer return; 6201d6167fdSMichael J. Spencer 621c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 62244f51e51SDavid Majnemer if (getPointerToSymbolTable() != 0) 6238ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 6241d6167fdSMichael J. Spencer return; 6258e90adafSMichael J. Spencer 626c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 6278ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 628ed64342bSRui Ueyama return; 62915d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 63015d99359SRui Ueyama return; 6311d6167fdSMichael J. Spencer 632ad882ba8SRui Ueyama // Initialize the pointer to the export table. 6338ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 634ad882ba8SRui Ueyama return; 635ad882ba8SRui Ueyama 6368ff24d25SRui Ueyama EC = object_error::success; 6378e90adafSMichael J. Spencer } 6388e90adafSMichael J. Spencer 639f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 6408ff24d25SRui Ueyama DataRefImpl Ret; 64144f51e51SDavid Majnemer Ret.p = getSymbolTable(); 642f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6438e90adafSMichael J. Spencer } 6448e90adafSMichael J. Spencer 645f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 6468e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 6478ff24d25SRui Ueyama DataRefImpl Ret; 6488ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 649f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6508e90adafSMichael J. Spencer } 6518e90adafSMichael J. Spencer 652bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 653a045b73aSRui Ueyama return import_directory_iterator( 654a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 655c2bed429SRui Ueyama } 656c2bed429SRui Ueyama 657bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 658a045b73aSRui Ueyama return import_directory_iterator( 659a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 660c2bed429SRui Ueyama } 661c429b80dSDavid Meyer 66215d99359SRui Ueyama delay_import_directory_iterator 66315d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 66415d99359SRui Ueyama return delay_import_directory_iterator( 66515d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 66615d99359SRui Ueyama } 66715d99359SRui Ueyama 66815d99359SRui Ueyama delay_import_directory_iterator 66915d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 67015d99359SRui Ueyama return delay_import_directory_iterator( 67115d99359SRui Ueyama DelayImportDirectoryEntryRef( 67215d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 67315d99359SRui Ueyama } 67415d99359SRui Ueyama 675ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 676ad882ba8SRui Ueyama return export_directory_iterator( 677ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 678ad882ba8SRui Ueyama } 679ad882ba8SRui Ueyama 680ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 6812617dcceSCraig Topper if (!ExportDirectory) 6822617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 6838ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 684ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 6858ff24d25SRui Ueyama return export_directory_iterator(Ref); 686ad882ba8SRui Ueyama } 687ad882ba8SRui Ueyama 688b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 6898ff24d25SRui Ueyama DataRefImpl Ret; 6908ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 6918ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 6928e90adafSMichael J. Spencer } 6938e90adafSMichael J. Spencer 694b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 6958ff24d25SRui Ueyama DataRefImpl Ret; 69644f51e51SDavid Majnemer int NumSections = 69744f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 6988ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 6998ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7008e90adafSMichael J. Spencer } 7018e90adafSMichael J. Spencer 7028e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 7030324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 7048e90adafSMichael J. Spencer } 7058e90adafSMichael J. Spencer 7068e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 70744f51e51SDavid Majnemer switch(getMachine()) { 7088e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7098e90adafSMichael J. Spencer return "COFF-i386"; 7108e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7118e90adafSMichael J. Spencer return "COFF-x86-64"; 7129b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7139b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 7148e90adafSMichael J. Spencer default: 7158e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 7168e90adafSMichael J. Spencer } 7178e90adafSMichael J. Spencer } 7188e90adafSMichael J. Spencer 7198e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 72044f51e51SDavid Majnemer switch (getMachine()) { 7218e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7228e90adafSMichael J. Spencer return Triple::x86; 7238e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7248e90adafSMichael J. Spencer return Triple::x86_64; 7259b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7269b7c0af2SSaleem Abdulrasool return Triple::thumb; 7278e90adafSMichael J. Spencer default: 7288e90adafSMichael J. Spencer return Triple::UnknownArch; 7298e90adafSMichael J. Spencer } 7308e90adafSMichael J. Spencer } 7318e90adafSMichael J. Spencer 732979fb40bSRui Ueyama iterator_range<import_directory_iterator> 733979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 734979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 735979fb40bSRui Ueyama } 736979fb40bSRui Ueyama 737979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 738979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 739979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 740979fb40bSRui Ueyama delay_import_directory_end()); 741979fb40bSRui Ueyama } 742979fb40bSRui Ueyama 743979fb40bSRui Ueyama iterator_range<export_directory_iterator> 744979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 745979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 746979fb40bSRui Ueyama } 747979fb40bSRui Ueyama 748db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 74982ebd8e3SRui Ueyama Res = PE32Header; 75089a7a5eaSMichael J. Spencer return object_error::success; 75189a7a5eaSMichael J. Spencer } 75289a7a5eaSMichael J. Spencer 753db4ed0bdSRafael Espindola std::error_code 75410ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 75510ed9ddcSRui Ueyama Res = PE32PlusHeader; 75610ed9ddcSRui Ueyama return object_error::success; 75710ed9ddcSRui Ueyama } 75810ed9ddcSRui Ueyama 759db4ed0bdSRafael Espindola std::error_code 760db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 761ed64342bSRui Ueyama const data_directory *&Res) const { 762ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 76310ed9ddcSRui Ueyama if (!DataDirectory) 76410ed9ddcSRui Ueyama return object_error::parse_failed; 76510ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 76610ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 76710ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 76810ed9ddcSRui Ueyama if (Index > NumEnt) 769ed64342bSRui Ueyama return object_error::parse_failed; 7708ff24d25SRui Ueyama Res = &DataDirectory[Index]; 771ed64342bSRui Ueyama return object_error::success; 772ed64342bSRui Ueyama } 773ed64342bSRui Ueyama 774db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 7751d6167fdSMichael J. Spencer const coff_section *&Result) const { 7761d6167fdSMichael J. Spencer // Check for special index values. 777f078eff3SRui Ueyama if (COFF::isReservedSectionNumber(Index)) 7782617dcceSCraig Topper Result = nullptr; 77944f51e51SDavid Majnemer else if (Index > 0 && static_cast<uint32_t>(Index) <= getNumberOfSections()) 7801d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 7818ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 7821d6167fdSMichael J. Spencer else 7831d6167fdSMichael J. Spencer return object_error::parse_failed; 7841d6167fdSMichael J. Spencer return object_error::success; 7858e90adafSMichael J. Spencer } 7868e90adafSMichael J. Spencer 787db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 7881d6167fdSMichael J. Spencer StringRef &Result) const { 7891d6167fdSMichael J. Spencer if (StringTableSize <= 4) 7901d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 7911d6167fdSMichael J. Spencer return object_error::parse_failed; 7928ff24d25SRui Ueyama if (Offset >= StringTableSize) 7931d6167fdSMichael J. Spencer return object_error::unexpected_eof; 7948ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 7951d6167fdSMichael J. Spencer return object_error::success; 7968e90adafSMichael J. Spencer } 797022ecdf2SBenjamin Kramer 79844f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 79989a7a5eaSMichael J. Spencer StringRef &Res) const { 80089a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 80144f51e51SDavid Majnemer if (Symbol.getStringTableOffset().Zeroes == 0) { 80244f51e51SDavid Majnemer uint32_t Offset = Symbol.getStringTableOffset().Offset; 803db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Res)) 8048ff24d25SRui Ueyama return EC; 80589a7a5eaSMichael J. Spencer return object_error::success; 80689a7a5eaSMichael J. Spencer } 80789a7a5eaSMichael J. Spencer 80844f51e51SDavid Majnemer if (Symbol.getShortName()[COFF::NameSize - 1] == 0) 80989a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 81044f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName()); 81189a7a5eaSMichael J. Spencer else 81289a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 81344f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName(), COFF::NameSize); 81489a7a5eaSMichael J. Spencer return object_error::success; 81589a7a5eaSMichael J. Spencer } 81689a7a5eaSMichael J. Spencer 81744f51e51SDavid Majnemer ArrayRef<uint8_t> 81844f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 8192617dcceSCraig Topper const uint8_t *Aux = nullptr; 82071757ef3SMarshall Clow 82144f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 82244f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 82371757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 82444f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 82571757ef3SMarshall Clow # ifndef NDEBUG 8268ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 8278ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 82844f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 82944f51e51SDavid Majnemer Offset >= 83044f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 83171757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 83271757ef3SMarshall Clow 83344f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 83444f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 83571757ef3SMarshall Clow # endif 836bfb85e67SMarshall Clow } 83744f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 83871757ef3SMarshall Clow } 83971757ef3SMarshall Clow 840db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 84153c2d547SMichael J. Spencer StringRef &Res) const { 84253c2d547SMichael J. Spencer StringRef Name; 84344f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 84453c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 84553c2d547SMichael J. Spencer Name = Sec->Name; 84653c2d547SMichael J. Spencer else 84753c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 84844f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 84953c2d547SMichael J. Spencer 85053c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 85153c2d547SMichael J. Spencer if (Name[0] == '/') { 85253c2d547SMichael J. Spencer uint32_t Offset; 8539d2c15efSNico Rieck if (Name[1] == '/') { 8549d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 8559d2c15efSNico Rieck return object_error::parse_failed; 8569d2c15efSNico Rieck } else { 85753c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 85853c2d547SMichael J. Spencer return object_error::parse_failed; 8599d2c15efSNico Rieck } 860db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 8618ff24d25SRui Ueyama return EC; 86253c2d547SMichael J. Spencer } 86353c2d547SMichael J. Spencer 86453c2d547SMichael J. Spencer Res = Name; 86553c2d547SMichael J. Spencer return object_error::success; 86653c2d547SMichael J. Spencer } 86753c2d547SMichael J. Spencer 868*a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 869*a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 870*a9ee5c06SDavid Majnemer // whether or not we have an executable image. 871*a9ee5c06SDavid Majnemer // 872*a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 873*a9ee5c06SDavid Majnemer // VirtualSize is always zero. 874*a9ee5c06SDavid Majnemer // 875*a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 876*a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 877*a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 878*a9ee5c06SDavid Majnemer // considered to be zero. 879*a9ee5c06SDavid Majnemer uint32_t SectionSize; 880*a9ee5c06SDavid Majnemer if (Sec->VirtualSize) 881*a9ee5c06SDavid Majnemer SectionSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData); 882*a9ee5c06SDavid Majnemer else 883*a9ee5c06SDavid Majnemer SectionSize = Sec->SizeOfRawData; 884*a9ee5c06SDavid Majnemer 885*a9ee5c06SDavid Majnemer return SectionSize; 886*a9ee5c06SDavid Majnemer } 887*a9ee5c06SDavid Majnemer 888db4ed0bdSRafael Espindola std::error_code 889db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 8909da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 891dd9cff2eSDavid Majnemer // PointerToRawData and SizeOfRawData won't make sense for BSS sections, 892dd9cff2eSDavid Majnemer // don't do anything interesting for them. 893dac39857SDavid Majnemer assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && 894dac39857SDavid Majnemer "BSS sections don't have contents!"); 8959da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 8969da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 8979da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 8989da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 899*a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 900*a9ee5c06SDavid Majnemer uintptr_t ConEnd = ConStart + SectionSize; 90148af1c2aSRafael Espindola if (ConEnd > uintptr_t(Data.getBufferEnd())) 9029da9e693SMichael J. Spencer return object_error::parse_failed; 903*a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 9049da9e693SMichael J. Spencer return object_error::success; 9059da9e693SMichael J. Spencer } 9069da9e693SMichael J. Spencer 907022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 908e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 909022ecdf2SBenjamin Kramer } 9108ff24d25SRui Ueyama 9115e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 912e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 913e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 914022ecdf2SBenjamin Kramer } 9158ff24d25SRui Ueyama 916db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 917022ecdf2SBenjamin Kramer uint64_t &Res) const { 9181e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 919022ecdf2SBenjamin Kramer } 9208ff24d25SRui Ueyama 921db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 922cbe72fc9SDanil Malyshev uint64_t &Res) const { 923cbe72fc9SDanil Malyshev Res = toRel(Rel)->VirtualAddress; 924cbe72fc9SDanil Malyshev return object_error::success; 925cbe72fc9SDanil Malyshev } 9268ff24d25SRui Ueyama 927806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 928022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 9298ff24d25SRui Ueyama DataRefImpl Ref; 93044f51e51SDavid Majnemer if (SymbolTable16) 93144f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 93244f51e51SDavid Majnemer else if (SymbolTable32) 93344f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 93444f51e51SDavid Majnemer else 93544f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 9368ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 937022ecdf2SBenjamin Kramer } 9388ff24d25SRui Ueyama 939db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 9407be76590SOwen Anderson uint64_t &Res) const { 941022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 942022ecdf2SBenjamin Kramer Res = R->Type; 943022ecdf2SBenjamin Kramer return object_error::success; 944022ecdf2SBenjamin Kramer } 945e5fd0047SMichael J. Spencer 94627dc8394SAlexey Samsonov const coff_section * 94727dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 94827dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 94971757ef3SMarshall Clow } 95071757ef3SMarshall Clow 95144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 95244f51e51SDavid Majnemer if (SymbolTable16) 95344f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 95444f51e51SDavid Majnemer if (SymbolTable32) 95544f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 95644f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 95744f51e51SDavid Majnemer } 95844f51e51SDavid Majnemer 95944f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 96044f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 96171757ef3SMarshall Clow } 96271757ef3SMarshall Clow 963f12b8282SRafael Espindola const coff_relocation * 96427dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 96527dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 966d3e2a76cSMarshall Clow } 967d3e2a76cSMarshall Clow 96827dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 96927dc8394SAlexey Samsonov case COFF::reloc_type: \ 97027dc8394SAlexey Samsonov Res = #reloc_type; \ 97127dc8394SAlexey Samsonov break; 972e5fd0047SMichael J. Spencer 973db4ed0bdSRafael Espindola std::error_code 974db4ed0bdSRafael Espindola COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 975e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 9768ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 9778ff24d25SRui Ueyama StringRef Res; 97844f51e51SDavid Majnemer switch (getMachine()) { 979e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9808ff24d25SRui Ueyama switch (Reloc->Type) { 981e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 982e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 983e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 984e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 985e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 986e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 987e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 988e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 989e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 990e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 991e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 992e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 993e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 994e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 995e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 996e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 997e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 998e5fd0047SMichael J. Spencer default: 9998ff24d25SRui Ueyama Res = "Unknown"; 1000e5fd0047SMichael J. Spencer } 1001e5fd0047SMichael J. Spencer break; 10025c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 10035c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 10045c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 10055c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 10065c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 10075c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 10085c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 10095c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 10105c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 10115c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 10125c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 10135c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 10145c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 10155c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 10165c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 10175c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 10185c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 10195c503bf4SSaleem Abdulrasool default: 10205c503bf4SSaleem Abdulrasool Res = "Unknown"; 10215c503bf4SSaleem Abdulrasool } 10225c503bf4SSaleem Abdulrasool break; 1023e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 10248ff24d25SRui Ueyama switch (Reloc->Type) { 1025e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1026e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1027e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1028e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1029e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1030e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1031e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1032e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1033e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1034e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1035e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1036e5fd0047SMichael J. Spencer default: 10378ff24d25SRui Ueyama Res = "Unknown"; 1038e5fd0047SMichael J. Spencer } 1039e5fd0047SMichael J. Spencer break; 1040e5fd0047SMichael J. Spencer default: 10418ff24d25SRui Ueyama Res = "Unknown"; 1042e5fd0047SMichael J. Spencer } 10438ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1044e5fd0047SMichael J. Spencer return object_error::success; 1045e5fd0047SMichael J. Spencer } 1046e5fd0047SMichael J. Spencer 1047e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1048e5fd0047SMichael J. Spencer 1049db4ed0bdSRafael Espindola std::error_code 1050db4ed0bdSRafael Espindola COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 1051e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 10528ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 10538ff24d25SRui Ueyama DataRefImpl Sym; 105444f51e51SDavid Majnemer ErrorOr<COFFSymbolRef> Symb = getSymbol(Reloc->SymbolTableIndex); 105544f51e51SDavid Majnemer if (std::error_code EC = Symb.getError()) 105644f51e51SDavid Majnemer return EC; 105744f51e51SDavid Majnemer Sym.p = reinterpret_cast<uintptr_t>(Symb->getRawPtr()); 10588ff24d25SRui Ueyama StringRef SymName; 1059db4ed0bdSRafael Espindola if (std::error_code EC = getSymbolName(Sym, SymName)) 1060db4ed0bdSRafael Espindola return EC; 10618ff24d25SRui Ueyama Result.append(SymName.begin(), SymName.end()); 1062e5fd0047SMichael J. Spencer return object_error::success; 1063022ecdf2SBenjamin Kramer } 10648e90adafSMichael J. Spencer 1065c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1066c66d761bSRafael Espindola return !DataDirectory; 1067c66d761bSRafael Espindola } 1068c66d761bSRafael Espindola 1069c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1070c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1071a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1072c2bed429SRui Ueyama } 1073c2bed429SRui Ueyama 10745e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 10755e812afaSRafael Espindola ++Index; 1076c2bed429SRui Ueyama } 1077c2bed429SRui Ueyama 1078db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1079db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 10801e152d5eSRui Ueyama Result = ImportTable + Index; 1081c2bed429SRui Ueyama return object_error::success; 1082c2bed429SRui Ueyama } 1083c2bed429SRui Ueyama 1084861021f9SRui Ueyama static imported_symbol_iterator 108515d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1086861021f9SRui Ueyama uintptr_t Ptr, int Index) { 108715d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1088861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 108915d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1090861021f9SRui Ueyama } 1091861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 109215d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1093861021f9SRui Ueyama } 1094861021f9SRui Ueyama 109515d99359SRui Ueyama static imported_symbol_iterator 109615d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1097861021f9SRui Ueyama uintptr_t IntPtr = 0; 109815d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 109915d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1100861021f9SRui Ueyama } 1101861021f9SRui Ueyama 110215d99359SRui Ueyama static imported_symbol_iterator 110315d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1104861021f9SRui Ueyama uintptr_t IntPtr = 0; 110515d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1106861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1107861021f9SRui Ueyama int Index = 0; 110815d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1109861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1110861021f9SRui Ueyama while (*Entry++) 1111861021f9SRui Ueyama ++Index; 1112861021f9SRui Ueyama } else { 1113861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1114861021f9SRui Ueyama while (*Entry++) 1115861021f9SRui Ueyama ++Index; 1116861021f9SRui Ueyama } 111715d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 111815d99359SRui Ueyama } 111915d99359SRui Ueyama 112015d99359SRui Ueyama imported_symbol_iterator 112115d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 112215d99359SRui Ueyama return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 112315d99359SRui Ueyama OwningObject); 112415d99359SRui Ueyama } 112515d99359SRui Ueyama 112615d99359SRui Ueyama imported_symbol_iterator 112715d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 112815d99359SRui Ueyama return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 112915d99359SRui Ueyama OwningObject); 1130861021f9SRui Ueyama } 1131861021f9SRui Ueyama 1132979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1133979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1134979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1135979fb40bSRui Ueyama } 1136979fb40bSRui Ueyama 1137db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1138c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1139db4ed0bdSRafael Espindola if (std::error_code EC = 11401e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1141a045b73aSRui Ueyama return EC; 1142a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1143c2bed429SRui Ueyama return object_error::success; 1144c2bed429SRui Ueyama } 1145c2bed429SRui Ueyama 11461e152d5eSRui Ueyama std::error_code 11471e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 11481e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 11491e152d5eSRui Ueyama return object_error::success; 11501e152d5eSRui Ueyama } 11511e152d5eSRui Ueyama 11521e152d5eSRui Ueyama std::error_code 11531e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 11541e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 11551e152d5eSRui Ueyama return object_error::success; 11561e152d5eSRui Ueyama } 11571e152d5eSRui Ueyama 1158db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1159c2bed429SRui Ueyama const import_lookup_table_entry32 *&Result) const { 1160c2bed429SRui Ueyama uintptr_t IntPtr = 0; 11611e152d5eSRui Ueyama uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; 11621e152d5eSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1163a045b73aSRui Ueyama return EC; 1164c2bed429SRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 1165c2bed429SRui Ueyama return object_error::success; 1166c2bed429SRui Ueyama } 1167c2bed429SRui Ueyama 116815d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 116915d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 117015d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 117115d99359SRui Ueyama } 117215d99359SRui Ueyama 117315d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 117415d99359SRui Ueyama ++Index; 117515d99359SRui Ueyama } 117615d99359SRui Ueyama 117715d99359SRui Ueyama imported_symbol_iterator 117815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 117915d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 118015d99359SRui Ueyama OwningObject); 118115d99359SRui Ueyama } 118215d99359SRui Ueyama 118315d99359SRui Ueyama imported_symbol_iterator 118415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 118515d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 118615d99359SRui Ueyama OwningObject); 118715d99359SRui Ueyama } 118815d99359SRui Ueyama 1189979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1190979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1191979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1192979fb40bSRui Ueyama } 1193979fb40bSRui Ueyama 119415d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 119515d99359SRui Ueyama uintptr_t IntPtr = 0; 119615d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 119715d99359SRui Ueyama return EC; 119815d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 119915d99359SRui Ueyama return object_error::success; 120015d99359SRui Ueyama } 120115d99359SRui Ueyama 12021af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 12031af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 12041af08658SRui Ueyama Result = Table; 12051af08658SRui Ueyama return object_error::success; 12061af08658SRui Ueyama } 12071af08658SRui Ueyama 1208ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1209ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1210ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1211ad882ba8SRui Ueyama } 1212ad882ba8SRui Ueyama 12135e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 12145e812afaSRafael Espindola ++Index; 1215ad882ba8SRui Ueyama } 1216ad882ba8SRui Ueyama 1217da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1218da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1219db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1220da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1221db4ed0bdSRafael Espindola if (std::error_code EC = 1222db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1223da49d0d4SRui Ueyama return EC; 1224da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1225da49d0d4SRui Ueyama return object_error::success; 1226da49d0d4SRui Ueyama } 1227da49d0d4SRui Ueyama 1228e5df6095SRui Ueyama // Returns the starting ordinal number. 1229db4ed0bdSRafael Espindola std::error_code 1230db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1231e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 1232e5df6095SRui Ueyama return object_error::success; 1233e5df6095SRui Ueyama } 1234e5df6095SRui Ueyama 1235ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1236db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1237ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 1238ad882ba8SRui Ueyama return object_error::success; 1239ad882ba8SRui Ueyama } 1240ad882ba8SRui Ueyama 1241ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1242db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1243ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1244db4ed0bdSRafael Espindola if (std::error_code EC = 1245db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1246ad882ba8SRui Ueyama return EC; 124724fc2d64SRui Ueyama const export_address_table_entry *entry = 124824fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1249ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 1250ad882ba8SRui Ueyama return object_error::success; 1251ad882ba8SRui Ueyama } 1252ad882ba8SRui Ueyama 1253ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1254ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1255db4ed0bdSRafael Espindola std::error_code 1256db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1257ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1258db4ed0bdSRafael Espindola if (std::error_code EC = 1259db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1260ad882ba8SRui Ueyama return EC; 1261ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1262ad882ba8SRui Ueyama 1263ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1264ad882ba8SRui Ueyama int Offset = 0; 1265ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1266ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1267ad882ba8SRui Ueyama if (*I != Index) 1268ad882ba8SRui Ueyama continue; 1269db4ed0bdSRafael Espindola if (std::error_code EC = 1270db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1271ad882ba8SRui Ueyama return EC; 1272ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1273db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1274ad882ba8SRui Ueyama return EC; 1275ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1276ad882ba8SRui Ueyama return object_error::success; 1277ad882ba8SRui Ueyama } 1278ad882ba8SRui Ueyama Result = ""; 1279ad882ba8SRui Ueyama return object_error::success; 1280ad882ba8SRui Ueyama } 1281ad882ba8SRui Ueyama 1282861021f9SRui Ueyama bool ImportedSymbolRef:: 1283861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1284861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1285861021f9SRui Ueyama && Index == Other.Index; 1286861021f9SRui Ueyama } 1287861021f9SRui Ueyama 1288861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1289861021f9SRui Ueyama ++Index; 1290861021f9SRui Ueyama } 1291861021f9SRui Ueyama 1292861021f9SRui Ueyama std::error_code 1293861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1294861021f9SRui Ueyama uint32_t RVA; 1295861021f9SRui Ueyama if (Entry32) { 1296861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1297861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 1298861021f9SRui Ueyama return object_error::success; 1299861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1300861021f9SRui Ueyama } else { 1301861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 1302861021f9SRui Ueyama return object_error::success; 1303861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1304861021f9SRui Ueyama } 1305861021f9SRui Ueyama uintptr_t IntPtr = 0; 1306861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1307861021f9SRui Ueyama return EC; 1308861021f9SRui Ueyama // +2 because the first two bytes is hint. 1309861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 1310861021f9SRui Ueyama return object_error::success; 1311861021f9SRui Ueyama } 1312861021f9SRui Ueyama 1313861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1314861021f9SRui Ueyama uint32_t RVA; 1315861021f9SRui Ueyama if (Entry32) { 1316861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1317861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 1318861021f9SRui Ueyama return object_error::success; 1319861021f9SRui Ueyama } 1320861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1321861021f9SRui Ueyama } else { 1322861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1323861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 1324861021f9SRui Ueyama return object_error::success; 1325861021f9SRui Ueyama } 1326861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1327861021f9SRui Ueyama } 1328861021f9SRui Ueyama uintptr_t IntPtr = 0; 1329861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1330861021f9SRui Ueyama return EC; 1331861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 1332861021f9SRui Ueyama return object_error::success; 1333861021f9SRui Ueyama } 1334861021f9SRui Ueyama 1335437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 133648af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1337db4ed0bdSRafael Espindola std::error_code EC; 133848af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1339692410efSRafael Espindola if (EC) 1340692410efSRafael Espindola return EC; 1341437b0d58SRafael Espindola return std::move(Ret); 1342686738e2SRui Ueyama } 1343