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); 150*c7d7c6fbSDavid Majnemer 151*c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 152*c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 153*c7d7c6fbSDavid Majnemer return object_error::success; 154*c7d7c6fbSDavid Majnemer } 155*c7d7c6fbSDavid Majnemer if (Symb.isCommon()) { 156*c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 157*c7d7c6fbSDavid Majnemer return object_error::success; 158*c7d7c6fbSDavid Majnemer } 159*c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 160*c7d7c6fbSDavid Majnemer if (!COFF::isReservedSectionNumber(SectionNumber)) { 1612617dcceSCraig Topper const coff_section *Section = nullptr; 162*c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 1638ff24d25SRui Ueyama return EC; 164e62ab11fSRafael Espindola 16544f51e51SDavid Majnemer Result = Section->VirtualAddress + Symb.getValue(); 166*c7d7c6fbSDavid Majnemer return object_error::success; 167*c7d7c6fbSDavid Majnemer } 168*c7d7c6fbSDavid Majnemer 16944f51e51SDavid Majnemer Result = Symb.getValue(); 17075d1cf33SBenjamin Kramer return object_error::success; 17175d1cf33SBenjamin Kramer } 17275d1cf33SBenjamin Kramer 173db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, 174d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 17544f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 176*c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 17775d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 17844f51e51SDavid Majnemer 179*c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 1807e4b976cSDavid Meyer Result = SymbolRef::ST_Unknown; 18144f51e51SDavid Majnemer } else if (Symb.isFunctionDefinition()) { 18275d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 183*c7d7c6fbSDavid Majnemer } else if (Symb.isCommon()) { 184*c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Data; 185*c7d7c6fbSDavid Majnemer } else if (Symb.isFileRecord()) { 186*c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_File; 187*c7d7c6fbSDavid Majnemer } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) { 188*c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Debug; 189*c7d7c6fbSDavid Majnemer } else if (!COFF::isReservedSectionNumber(SectionNumber)) { 1902617dcceSCraig Topper const coff_section *Section = nullptr; 191*c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 1928ff24d25SRui Ueyama return EC; 193*c7d7c6fbSDavid Majnemer uint32_t Characteristics = Section->Characteristics; 194*c7d7c6fbSDavid Majnemer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 195*c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Function; 196*c7d7c6fbSDavid Majnemer else if (Characteristics & (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 197*c7d7c6fbSDavid Majnemer COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) 19806adfac8SRafael Espindola Result = SymbolRef::ST_Data; 19975d1cf33SBenjamin Kramer } 20075d1cf33SBenjamin Kramer return object_error::success; 20175d1cf33SBenjamin Kramer } 20275d1cf33SBenjamin Kramer 20320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 20444f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 20520122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 20675d1cf33SBenjamin Kramer 207*c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2081df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 2091df4b84dSDavid Meyer 210*c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2111df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2121df4b84dSDavid Meyer 21344f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2141df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2151df4b84dSDavid Meyer 216*c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 217*c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 218*c7d7c6fbSDavid Majnemer 219*c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 220*c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 221*c7d7c6fbSDavid Majnemer 222*c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 223*c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 224*c7d7c6fbSDavid Majnemer 225*c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 226*c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 227*c7d7c6fbSDavid Majnemer 22820122a43SRafael Espindola return Result; 22901759754SMichael J. Spencer } 23001759754SMichael J. Spencer 231db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, 2321d6167fdSMichael J. Spencer uint64_t &Result) const { 233*c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 234*c7d7c6fbSDavid Majnemer 235*c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 236*c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 237*c7d7c6fbSDavid Majnemer return object_error::success; 238*c7d7c6fbSDavid Majnemer } 239*c7d7c6fbSDavid Majnemer if (Symb.isCommon()) { 240*c7d7c6fbSDavid Majnemer Result = Symb.getValue(); 241*c7d7c6fbSDavid Majnemer return object_error::success; 242*c7d7c6fbSDavid Majnemer } 243*c7d7c6fbSDavid Majnemer if (Symb.isFunctionDefinition()) { 244*c7d7c6fbSDavid Majnemer ArrayRef<uint8_t> AuxData = getSymbolAuxData(Symb); 245*c7d7c6fbSDavid Majnemer if (!AuxData.empty()) { 246*c7d7c6fbSDavid Majnemer const auto *CAFD = 247*c7d7c6fbSDavid Majnemer reinterpret_cast<const coff_aux_function_definition *>( 248*c7d7c6fbSDavid Majnemer AuxData.data()); 249*c7d7c6fbSDavid Majnemer Result = CAFD->TotalSize; 250*c7d7c6fbSDavid Majnemer return object_error::success; 251*c7d7c6fbSDavid Majnemer } 252*c7d7c6fbSDavid Majnemer } 2538e90adafSMichael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 2548e90adafSMichael J. Spencer // in the same section as this symbol, and looking for either the next 2558e90adafSMichael J. Spencer // symbol, or the end of the section. 256*c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 257*c7d7c6fbSDavid Majnemer if (!COFF::isReservedSectionNumber(SectionNumber)) { 2582617dcceSCraig Topper const coff_section *Section = nullptr; 259*c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 2608ff24d25SRui Ueyama return EC; 261e62ab11fSRafael Espindola 2628280fbbfSRafael Espindola Result = Section->SizeOfRawData - Symb.getValue(); 263*c7d7c6fbSDavid Majnemer return object_error::success; 2648280fbbfSRafael Espindola } 2658280fbbfSRafael Espindola 266*c7d7c6fbSDavid Majnemer Result = 0; 2671d6167fdSMichael J. Spencer return object_error::success; 2688e90adafSMichael J. Spencer } 2698e90adafSMichael J. Spencer 270db4ed0bdSRafael Espindola std::error_code 271db4ed0bdSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref, 27232173153SMichael J. Spencer section_iterator &Result) const { 27344f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 27444f51e51SDavid Majnemer if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 275b5155a57SRafael Espindola Result = section_end(); 276f078eff3SRui Ueyama } else { 2772617dcceSCraig Topper const coff_section *Sec = nullptr; 27844f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 279db4ed0bdSRafael Espindola return EC; 2808ff24d25SRui Ueyama DataRefImpl Ref; 2818ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2828ff24d25SRui Ueyama Result = section_iterator(SectionRef(Ref, this)); 28332173153SMichael J. Spencer } 28432173153SMichael J. Spencer return object_error::success; 28532173153SMichael J. Spencer } 28632173153SMichael J. Spencer 2875e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2888ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2898ff24d25SRui Ueyama Sec += 1; 2908ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2918e90adafSMichael J. Spencer } 2928e90adafSMichael J. Spencer 293db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2941d6167fdSMichael J. Spencer StringRef &Result) const { 2958ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2968ff24d25SRui Ueyama return getSectionName(Sec, Result); 2978e90adafSMichael J. Spencer } 2988e90adafSMichael J. Spencer 29980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 3008ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 30180291274SRafael Espindola return Sec->VirtualAddress; 3028e90adafSMichael J. Spencer } 3038e90adafSMichael J. Spencer 30480291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 305a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 3068e90adafSMichael J. Spencer } 3078e90adafSMichael J. Spencer 308db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 3091d6167fdSMichael J. Spencer StringRef &Result) const { 3108ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3119da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 312db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3139da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3149da9e693SMichael J. Spencer return EC; 3158e90adafSMichael J. Spencer } 3168e90adafSMichael J. Spencer 31780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3188ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31980291274SRafael Espindola return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 3207989460aSMichael J. Spencer } 3217989460aSMichael J. Spencer 32280291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3238ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3258e90adafSMichael J. Spencer } 3268e90adafSMichael J. Spencer 32780291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3288ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32980291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 330800619f2SMichael J. Spencer } 331800619f2SMichael J. Spencer 33280291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3338ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 33480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 335800619f2SMichael J. Spencer } 336800619f2SMichael J. Spencer 33780291274SRafael Espindola bool COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref) const { 3382138ef6dSPreston Gurd // FIXME: Unimplemented 33980291274SRafael Espindola return true; 3402138ef6dSPreston Gurd } 3412138ef6dSPreston Gurd 34280291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3438ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 34480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3452138ef6dSPreston Gurd } 3462138ef6dSPreston Gurd 34780291274SRafael Espindola bool COFFObjectFile::isSectionZeroInit(DataRefImpl Ref) const { 348b96a320aSAndrew Kaylor // FIXME: Unimplemented. 34980291274SRafael Espindola return false; 3502138ef6dSPreston Gurd } 3512138ef6dSPreston Gurd 35280291274SRafael Espindola bool COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref) const { 3533f31fa05SAndrew Kaylor // FIXME: Unimplemented. 35480291274SRafael Espindola return false; 3553f31fa05SAndrew Kaylor } 3563f31fa05SAndrew Kaylor 35780291274SRafael Espindola bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, 35880291274SRafael Espindola DataRefImpl SymbRef) const { 3598ff24d25SRui Ueyama const coff_section *Sec = toSec(SecRef); 36044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(SymbRef); 361a9260865SRafael Espindola int32_t SecNumber = (Sec - SectionTable) + 1; 36280291274SRafael Espindola return SecNumber == Symb.getSectionNumber(); 363f6f3e81cSBenjamin Kramer } 364f6f3e81cSBenjamin Kramer 3658ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 3668ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3678ff24d25SRui Ueyama DataRefImpl Ret; 368827c8a2bSRui Ueyama if (Sec->NumberOfRelocations == 0) { 3698ff24d25SRui Ueyama Ret.p = 0; 370827c8a2bSRui Ueyama } else { 371827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 372827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 373827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 374827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 375827c8a2bSRui Ueyama // relocations. 376827c8a2bSRui Ueyama begin++; 377827c8a2bSRui Ueyama } 378827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin); 379827c8a2bSRui Ueyama } 3808ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 381e5fd0047SMichael J. Spencer } 382e5fd0047SMichael J. Spencer 383827c8a2bSRui Ueyama static uint32_t getNumberOfRelocations(const coff_section *Sec, 384827c8a2bSRui Ueyama const uint8_t *base) { 385827c8a2bSRui Ueyama // The field for the number of relocations in COFF section table is only 386827c8a2bSRui Ueyama // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 387827c8a2bSRui Ueyama // NumberOfRelocations field, and the actual relocation count is stored in the 388827c8a2bSRui Ueyama // VirtualAddress field in the first relocation entry. 389827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 390827c8a2bSRui Ueyama auto *FirstReloc = reinterpret_cast<const coff_relocation*>( 391827c8a2bSRui Ueyama base + Sec->PointerToRelocations); 392827c8a2bSRui Ueyama return FirstReloc->VirtualAddress; 393827c8a2bSRui Ueyama } 394827c8a2bSRui Ueyama return Sec->NumberOfRelocations; 395827c8a2bSRui Ueyama } 396827c8a2bSRui Ueyama 3978ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3988ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3998ff24d25SRui Ueyama DataRefImpl Ret; 400827c8a2bSRui Ueyama if (Sec->NumberOfRelocations == 0) { 4018ff24d25SRui Ueyama Ret.p = 0; 402827c8a2bSRui Ueyama } else { 403827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 404827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 405827c8a2bSRui Ueyama uint32_t NumReloc = getNumberOfRelocations(Sec, base()); 406827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); 407827c8a2bSRui Ueyama } 4088ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 409e5fd0047SMichael J. Spencer } 410e5fd0047SMichael J. Spencer 411c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 412db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 41344f51e51SDavid Majnemer if (COFFHeader) 41444f51e51SDavid Majnemer if (std::error_code EC = 41544f51e51SDavid Majnemer getObject(SymbolTable16, Data, base() + getPointerToSymbolTable(), 41644f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 41744f51e51SDavid Majnemer return EC; 41844f51e51SDavid Majnemer 41944f51e51SDavid Majnemer if (COFFBigObjHeader) 42044f51e51SDavid Majnemer if (std::error_code EC = 42144f51e51SDavid Majnemer getObject(SymbolTable32, Data, base() + getPointerToSymbolTable(), 42244f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 4238ff24d25SRui Ueyama return EC; 424c2bed429SRui Ueyama 425c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 426c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 427c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 428c2bed429SRui Ueyama const uint8_t *StringTableAddr = 42944f51e51SDavid Majnemer base() + getPointerToSymbolTable() + 43044f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 431c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 43248af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4338ff24d25SRui Ueyama return EC; 434c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 435db4ed0bdSRafael Espindola if (std::error_code EC = 43648af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4378ff24d25SRui Ueyama return EC; 438c2bed429SRui Ueyama 439773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 440773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 441773a5795SNico Rieck if (StringTableSize < 4) 442773a5795SNico Rieck StringTableSize = 4; 443773a5795SNico Rieck 444c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 445773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 446c2bed429SRui Ueyama return object_error::parse_failed; 447c2bed429SRui Ueyama return object_error::success; 448c2bed429SRui Ueyama } 449c2bed429SRui Ueyama 450215a586cSRui Ueyama // Returns the file offset for the given VA. 451db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 452b6eb264aSRui Ueyama uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 453b6eb264aSRui Ueyama : (uint64_t)PE32PlusHeader->ImageBase; 454b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 455b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 456b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 457215a586cSRui Ueyama } 458215a586cSRui Ueyama 459c2bed429SRui Ueyama // Returns the file offset for the given RVA. 460db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 46127dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 46227dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 463c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 464c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 465215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 466215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 467c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 468c2bed429SRui Ueyama return object_error::success; 469c2bed429SRui Ueyama } 470c2bed429SRui Ueyama } 471c2bed429SRui Ueyama return object_error::parse_failed; 472c2bed429SRui Ueyama } 473c2bed429SRui Ueyama 474c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 475c2bed429SRui Ueyama // table entry. 476db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 477db4ed0bdSRafael Espindola StringRef &Name) const { 478c2bed429SRui Ueyama uintptr_t IntPtr = 0; 479db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4808ff24d25SRui Ueyama return EC; 481c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 482c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 483c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 484c2bed429SRui Ueyama return object_error::success; 485c2bed429SRui Ueyama } 486c2bed429SRui Ueyama 487c2bed429SRui Ueyama // Find the import table. 488db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 489c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 490c2bed429SRui Ueyama // the import table, do nothing. 491c2bed429SRui Ueyama const data_directory *DataEntry; 492c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 493c2bed429SRui Ueyama return object_error::success; 494c2bed429SRui Ueyama 495c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 496c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 497c2bed429SRui Ueyama return object_error::success; 498c2bed429SRui Ueyama 499c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 5001e152d5eSRui Ueyama // -1 because the last entry is the null entry. 501c2bed429SRui Ueyama NumberOfImportDirectory = DataEntry->Size / 5021e152d5eSRui Ueyama sizeof(import_directory_table_entry) - 1; 503c2bed429SRui Ueyama 504c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 505c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 506c2bed429SRui Ueyama uintptr_t IntPtr = 0; 507db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5088ff24d25SRui Ueyama return EC; 509c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 510c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 511ad882ba8SRui Ueyama return object_error::success; 512ad882ba8SRui Ueyama } 513c2bed429SRui Ueyama 51415d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 51515d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 51615d99359SRui Ueyama const data_directory *DataEntry; 51715d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 51815d99359SRui Ueyama return object_error::success; 51915d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 52015d99359SRui Ueyama return object_error::success; 52115d99359SRui Ueyama 52215d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 52315d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 52415d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 52515d99359SRui Ueyama 52615d99359SRui Ueyama uintptr_t IntPtr = 0; 52715d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 52815d99359SRui Ueyama return EC; 52915d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 53015d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 53115d99359SRui Ueyama return object_error::success; 53215d99359SRui Ueyama } 53315d99359SRui Ueyama 534ad882ba8SRui Ueyama // Find the export table. 535db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 536ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 537ad882ba8SRui Ueyama // the export table, do nothing. 538ad882ba8SRui Ueyama const data_directory *DataEntry; 539ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 540ad882ba8SRui Ueyama return object_error::success; 541ad882ba8SRui Ueyama 542ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 543ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 544ad882ba8SRui Ueyama return object_error::success; 545ad882ba8SRui Ueyama 546ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 547ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 548db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 549ad882ba8SRui Ueyama return EC; 55024fc2d64SRui Ueyama ExportDirectory = 55124fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 552ad882ba8SRui Ueyama return object_error::success; 553c2bed429SRui Ueyama } 554c2bed429SRui Ueyama 55548af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 55648af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 55744f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 55844f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 55944f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 56044f51e51SDavid Majnemer ImportDirectory(nullptr), NumberOfImportDirectory(0), 56115d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 5622617dcceSCraig Topper ExportDirectory(nullptr) { 5631d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 56448af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 565c3f9b5a5SRafael Espindola return; 566ee066fc4SEric Christopher 56782ebd8e3SRui Ueyama // The current location in the file where we are looking at. 56882ebd8e3SRui Ueyama uint64_t CurPtr = 0; 56982ebd8e3SRui Ueyama 57082ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 57182ebd8e3SRui Ueyama // it is placed right after COFF header. 5728ff24d25SRui Ueyama bool HasPEHeader = false; 573ee066fc4SEric Christopher 5741d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 575ec29b121SMichael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 576ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 577ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 57848af1c2aSRafael Espindola if (!checkSize(Data, EC, 0x3c + 8)) 579c3f9b5a5SRafael Espindola return; 58082ebd8e3SRui Ueyama CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 58182ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 58244f51e51SDavid Majnemer if (std::memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 58344f51e51SDavid Majnemer 0) { 5848ff24d25SRui Ueyama EC = object_error::parse_failed; 5851d6167fdSMichael J. Spencer return; 5861d6167fdSMichael J. Spencer } 58744f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 5888ff24d25SRui Ueyama HasPEHeader = true; 589ee066fc4SEric Christopher } 590ee066fc4SEric Christopher 59148af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 5921d6167fdSMichael J. Spencer return; 59344f51e51SDavid Majnemer 59444f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 59544f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 59644f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 59744f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 59844f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 59944f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 60044f51e51SDavid Majnemer return; 60144f51e51SDavid Majnemer 60244f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 60344f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 60444f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 60544f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 60644f51e51SDavid Majnemer COFFHeader = nullptr; 60744f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 60844f51e51SDavid Majnemer } else { 60944f51e51SDavid Majnemer // It's not a bigobj. 61044f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 61144f51e51SDavid Majnemer } 61244f51e51SDavid Majnemer } 61344f51e51SDavid Majnemer if (COFFHeader) { 61444f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 61544f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 61644f51e51SDavid Majnemer EC = object_error::success; 61782ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 61882ebd8e3SRui Ueyama 61944f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 62044f51e51SDavid Majnemer return; 62144f51e51SDavid Majnemer } 62244f51e51SDavid Majnemer 6238ff24d25SRui Ueyama if (HasPEHeader) { 62410ed9ddcSRui Ueyama const pe32_header *Header; 62548af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 62682ebd8e3SRui Ueyama return; 62710ed9ddcSRui Ueyama 62810ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 62910ed9ddcSRui Ueyama uint64_t DataDirSize; 63010ed9ddcSRui Ueyama if (Header->Magic == 0x10b) { 63110ed9ddcSRui Ueyama PE32Header = Header; 63210ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 63310ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 63410ed9ddcSRui Ueyama } else if (Header->Magic == 0x20b) { 63510ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 63610ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 63710ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 63810ed9ddcSRui Ueyama } else { 63910ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 64010ed9ddcSRui Ueyama EC = object_error::parse_failed; 641ed64342bSRui Ueyama return; 642ed64342bSRui Ueyama } 64348af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 64410ed9ddcSRui Ueyama return; 64582ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 64682ebd8e3SRui Ueyama } 6471d6167fdSMichael J. Spencer 64848af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 64944f51e51SDavid Majnemer getNumberOfSections() * sizeof(coff_section)))) 6501d6167fdSMichael J. Spencer return; 6511d6167fdSMichael J. Spencer 652c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 65344f51e51SDavid Majnemer if (getPointerToSymbolTable() != 0) 6548ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 6551d6167fdSMichael J. Spencer return; 6568e90adafSMichael J. Spencer 657c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 6588ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 659ed64342bSRui Ueyama return; 66015d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 66115d99359SRui Ueyama return; 6621d6167fdSMichael J. Spencer 663ad882ba8SRui Ueyama // Initialize the pointer to the export table. 6648ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 665ad882ba8SRui Ueyama return; 666ad882ba8SRui Ueyama 6678ff24d25SRui Ueyama EC = object_error::success; 6688e90adafSMichael J. Spencer } 6698e90adafSMichael J. Spencer 670f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 6718ff24d25SRui Ueyama DataRefImpl Ret; 67244f51e51SDavid Majnemer Ret.p = getSymbolTable(); 673f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6748e90adafSMichael J. Spencer } 6758e90adafSMichael J. Spencer 676f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 6778e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 6788ff24d25SRui Ueyama DataRefImpl Ret; 6798ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 680f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6818e90adafSMichael J. Spencer } 6828e90adafSMichael J. Spencer 683bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 684a045b73aSRui Ueyama return import_directory_iterator( 685a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 686c2bed429SRui Ueyama } 687c2bed429SRui Ueyama 688bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 689a045b73aSRui Ueyama return import_directory_iterator( 690a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 691c2bed429SRui Ueyama } 692c429b80dSDavid Meyer 69315d99359SRui Ueyama delay_import_directory_iterator 69415d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 69515d99359SRui Ueyama return delay_import_directory_iterator( 69615d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 69715d99359SRui Ueyama } 69815d99359SRui Ueyama 69915d99359SRui Ueyama delay_import_directory_iterator 70015d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 70115d99359SRui Ueyama return delay_import_directory_iterator( 70215d99359SRui Ueyama DelayImportDirectoryEntryRef( 70315d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 70415d99359SRui Ueyama } 70515d99359SRui Ueyama 706ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 707ad882ba8SRui Ueyama return export_directory_iterator( 708ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 709ad882ba8SRui Ueyama } 710ad882ba8SRui Ueyama 711ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 7122617dcceSCraig Topper if (!ExportDirectory) 7132617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 7148ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 715ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 7168ff24d25SRui Ueyama return export_directory_iterator(Ref); 717ad882ba8SRui Ueyama } 718ad882ba8SRui Ueyama 719b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 7208ff24d25SRui Ueyama DataRefImpl Ret; 7218ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 7228ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7238e90adafSMichael J. Spencer } 7248e90adafSMichael J. Spencer 725b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 7268ff24d25SRui Ueyama DataRefImpl Ret; 72744f51e51SDavid Majnemer int NumSections = 72844f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 7298ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 7308ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7318e90adafSMichael J. Spencer } 7328e90adafSMichael J. Spencer 7338e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 7340324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 7358e90adafSMichael J. Spencer } 7368e90adafSMichael J. Spencer 7378e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 73844f51e51SDavid Majnemer switch(getMachine()) { 7398e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7408e90adafSMichael J. Spencer return "COFF-i386"; 7418e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7428e90adafSMichael J. Spencer return "COFF-x86-64"; 7439b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7449b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 7458e90adafSMichael J. Spencer default: 7468e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 7478e90adafSMichael J. Spencer } 7488e90adafSMichael J. Spencer } 7498e90adafSMichael J. Spencer 7508e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 75144f51e51SDavid Majnemer switch (getMachine()) { 7528e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7538e90adafSMichael J. Spencer return Triple::x86; 7548e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7558e90adafSMichael J. Spencer return Triple::x86_64; 7569b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7579b7c0af2SSaleem Abdulrasool return Triple::thumb; 7588e90adafSMichael J. Spencer default: 7598e90adafSMichael J. Spencer return Triple::UnknownArch; 7608e90adafSMichael J. Spencer } 7618e90adafSMichael J. Spencer } 7628e90adafSMichael J. Spencer 763979fb40bSRui Ueyama iterator_range<import_directory_iterator> 764979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 765979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 766979fb40bSRui Ueyama } 767979fb40bSRui Ueyama 768979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 769979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 770979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 771979fb40bSRui Ueyama delay_import_directory_end()); 772979fb40bSRui Ueyama } 773979fb40bSRui Ueyama 774979fb40bSRui Ueyama iterator_range<export_directory_iterator> 775979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 776979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 777979fb40bSRui Ueyama } 778979fb40bSRui Ueyama 779db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 78082ebd8e3SRui Ueyama Res = PE32Header; 78189a7a5eaSMichael J. Spencer return object_error::success; 78289a7a5eaSMichael J. Spencer } 78389a7a5eaSMichael J. Spencer 784db4ed0bdSRafael Espindola std::error_code 78510ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 78610ed9ddcSRui Ueyama Res = PE32PlusHeader; 78710ed9ddcSRui Ueyama return object_error::success; 78810ed9ddcSRui Ueyama } 78910ed9ddcSRui Ueyama 790db4ed0bdSRafael Espindola std::error_code 791db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 792ed64342bSRui Ueyama const data_directory *&Res) const { 793ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 79410ed9ddcSRui Ueyama if (!DataDirectory) 79510ed9ddcSRui Ueyama return object_error::parse_failed; 79610ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 79710ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 79810ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 79910ed9ddcSRui Ueyama if (Index > NumEnt) 800ed64342bSRui Ueyama return object_error::parse_failed; 8018ff24d25SRui Ueyama Res = &DataDirectory[Index]; 802ed64342bSRui Ueyama return object_error::success; 803ed64342bSRui Ueyama } 804ed64342bSRui Ueyama 805db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 8061d6167fdSMichael J. Spencer const coff_section *&Result) const { 8071d6167fdSMichael J. Spencer // Check for special index values. 808f078eff3SRui Ueyama if (COFF::isReservedSectionNumber(Index)) 8092617dcceSCraig Topper Result = nullptr; 81044f51e51SDavid Majnemer else if (Index > 0 && static_cast<uint32_t>(Index) <= getNumberOfSections()) 8111d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 8128ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 8131d6167fdSMichael J. Spencer else 8141d6167fdSMichael J. Spencer return object_error::parse_failed; 8151d6167fdSMichael J. Spencer return object_error::success; 8168e90adafSMichael J. Spencer } 8178e90adafSMichael J. Spencer 818db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 8191d6167fdSMichael J. Spencer StringRef &Result) const { 8201d6167fdSMichael J. Spencer if (StringTableSize <= 4) 8211d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 8221d6167fdSMichael J. Spencer return object_error::parse_failed; 8238ff24d25SRui Ueyama if (Offset >= StringTableSize) 8241d6167fdSMichael J. Spencer return object_error::unexpected_eof; 8258ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 8261d6167fdSMichael J. Spencer return object_error::success; 8278e90adafSMichael J. Spencer } 828022ecdf2SBenjamin Kramer 82944f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 83089a7a5eaSMichael J. Spencer StringRef &Res) const { 83189a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 83244f51e51SDavid Majnemer if (Symbol.getStringTableOffset().Zeroes == 0) { 83344f51e51SDavid Majnemer uint32_t Offset = Symbol.getStringTableOffset().Offset; 834db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Res)) 8358ff24d25SRui Ueyama return EC; 83689a7a5eaSMichael J. Spencer return object_error::success; 83789a7a5eaSMichael J. Spencer } 83889a7a5eaSMichael J. Spencer 83944f51e51SDavid Majnemer if (Symbol.getShortName()[COFF::NameSize - 1] == 0) 84089a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 84144f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName()); 84289a7a5eaSMichael J. Spencer else 84389a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 84444f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName(), COFF::NameSize); 84589a7a5eaSMichael J. Spencer return object_error::success; 84689a7a5eaSMichael J. Spencer } 84789a7a5eaSMichael J. Spencer 84844f51e51SDavid Majnemer ArrayRef<uint8_t> 84944f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 8502617dcceSCraig Topper const uint8_t *Aux = nullptr; 85171757ef3SMarshall Clow 85244f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 85344f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 85471757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 85544f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 85671757ef3SMarshall Clow # ifndef NDEBUG 8578ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 8588ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 85944f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 86044f51e51SDavid Majnemer Offset >= 86144f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 86271757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 86371757ef3SMarshall Clow 86444f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 86544f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 86671757ef3SMarshall Clow # endif 867bfb85e67SMarshall Clow } 86844f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 86971757ef3SMarshall Clow } 87071757ef3SMarshall Clow 871db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 87253c2d547SMichael J. Spencer StringRef &Res) const { 87353c2d547SMichael J. Spencer StringRef Name; 87444f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 87553c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 87653c2d547SMichael J. Spencer Name = Sec->Name; 87753c2d547SMichael J. Spencer else 87853c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 87944f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 88053c2d547SMichael J. Spencer 88153c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 88253c2d547SMichael J. Spencer if (Name[0] == '/') { 88353c2d547SMichael J. Spencer uint32_t Offset; 8849d2c15efSNico Rieck if (Name[1] == '/') { 8859d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 8869d2c15efSNico Rieck return object_error::parse_failed; 8879d2c15efSNico Rieck } else { 88853c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 88953c2d547SMichael J. Spencer return object_error::parse_failed; 8909d2c15efSNico Rieck } 891db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 8928ff24d25SRui Ueyama return EC; 89353c2d547SMichael J. Spencer } 89453c2d547SMichael J. Spencer 89553c2d547SMichael J. Spencer Res = Name; 89653c2d547SMichael J. Spencer return object_error::success; 89753c2d547SMichael J. Spencer } 89853c2d547SMichael J. Spencer 899a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 900a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 901a9ee5c06SDavid Majnemer // whether or not we have an executable image. 902a9ee5c06SDavid Majnemer // 903a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 904a9ee5c06SDavid Majnemer // VirtualSize is always zero. 905a9ee5c06SDavid Majnemer // 906a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 907a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 908a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 909a9ee5c06SDavid Majnemer // considered to be zero. 910a9ee5c06SDavid Majnemer uint32_t SectionSize; 911a9ee5c06SDavid Majnemer if (Sec->VirtualSize) 912a9ee5c06SDavid Majnemer SectionSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData); 913a9ee5c06SDavid Majnemer else 914a9ee5c06SDavid Majnemer SectionSize = Sec->SizeOfRawData; 915a9ee5c06SDavid Majnemer 916a9ee5c06SDavid Majnemer return SectionSize; 917a9ee5c06SDavid Majnemer } 918a9ee5c06SDavid Majnemer 919db4ed0bdSRafael Espindola std::error_code 920db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 9219da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 922dd9cff2eSDavid Majnemer // PointerToRawData and SizeOfRawData won't make sense for BSS sections, 923dd9cff2eSDavid Majnemer // don't do anything interesting for them. 924dac39857SDavid Majnemer assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && 925dac39857SDavid Majnemer "BSS sections don't have contents!"); 9269da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 9279da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 9289da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 9299da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 930a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 931a9ee5c06SDavid Majnemer uintptr_t ConEnd = ConStart + SectionSize; 93248af1c2aSRafael Espindola if (ConEnd > uintptr_t(Data.getBufferEnd())) 9339da9e693SMichael J. Spencer return object_error::parse_failed; 934a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 9359da9e693SMichael J. Spencer return object_error::success; 9369da9e693SMichael J. Spencer } 9379da9e693SMichael J. Spencer 938022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 939e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 940022ecdf2SBenjamin Kramer } 9418ff24d25SRui Ueyama 9425e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 943e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 944e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 945022ecdf2SBenjamin Kramer } 9468ff24d25SRui Ueyama 947db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 948022ecdf2SBenjamin Kramer uint64_t &Res) const { 9491e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 950022ecdf2SBenjamin Kramer } 9518ff24d25SRui Ueyama 952db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 953cbe72fc9SDanil Malyshev uint64_t &Res) const { 954cbe72fc9SDanil Malyshev Res = toRel(Rel)->VirtualAddress; 955cbe72fc9SDanil Malyshev return object_error::success; 956cbe72fc9SDanil Malyshev } 9578ff24d25SRui Ueyama 958806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 959022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 9608ff24d25SRui Ueyama DataRefImpl Ref; 96144f51e51SDavid Majnemer if (SymbolTable16) 96244f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 96344f51e51SDavid Majnemer else if (SymbolTable32) 96444f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 96544f51e51SDavid Majnemer else 96644f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 9678ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 968022ecdf2SBenjamin Kramer } 9698ff24d25SRui Ueyama 970db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 9717be76590SOwen Anderson uint64_t &Res) const { 972022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 973022ecdf2SBenjamin Kramer Res = R->Type; 974022ecdf2SBenjamin Kramer return object_error::success; 975022ecdf2SBenjamin Kramer } 976e5fd0047SMichael J. Spencer 97727dc8394SAlexey Samsonov const coff_section * 97827dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 97927dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 98071757ef3SMarshall Clow } 98171757ef3SMarshall Clow 98244f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 98344f51e51SDavid Majnemer if (SymbolTable16) 98444f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 98544f51e51SDavid Majnemer if (SymbolTable32) 98644f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 98744f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 98844f51e51SDavid Majnemer } 98944f51e51SDavid Majnemer 99044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 99144f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 99271757ef3SMarshall Clow } 99371757ef3SMarshall Clow 994f12b8282SRafael Espindola const coff_relocation * 99527dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 99627dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 997d3e2a76cSMarshall Clow } 998d3e2a76cSMarshall Clow 99927dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 100027dc8394SAlexey Samsonov case COFF::reloc_type: \ 100127dc8394SAlexey Samsonov Res = #reloc_type; \ 100227dc8394SAlexey Samsonov break; 1003e5fd0047SMichael J. Spencer 1004db4ed0bdSRafael Espindola std::error_code 1005db4ed0bdSRafael Espindola COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 1006e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 10078ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 10088ff24d25SRui Ueyama StringRef Res; 100944f51e51SDavid Majnemer switch (getMachine()) { 1010e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 10118ff24d25SRui Ueyama switch (Reloc->Type) { 1012e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1013e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1014e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1015e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1016e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1017e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1018e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1019e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1020e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1021e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1022e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1023e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1024e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1025e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1026e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1027e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1028e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1029e5fd0047SMichael J. Spencer default: 10308ff24d25SRui Ueyama Res = "Unknown"; 1031e5fd0047SMichael J. Spencer } 1032e5fd0047SMichael J. Spencer break; 10335c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 10345c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 10355c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 10365c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 10375c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 10385c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 10395c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 10405c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 10415c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 10425c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 10435c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 10445c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 10455c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 10465c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 10475c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 10485c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 10495c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 10505c503bf4SSaleem Abdulrasool default: 10515c503bf4SSaleem Abdulrasool Res = "Unknown"; 10525c503bf4SSaleem Abdulrasool } 10535c503bf4SSaleem Abdulrasool break; 1054e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 10558ff24d25SRui Ueyama switch (Reloc->Type) { 1056e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1057e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1058e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1059e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1060e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1061e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1062e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1063e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1064e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1065e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1066e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1067e5fd0047SMichael J. Spencer default: 10688ff24d25SRui Ueyama Res = "Unknown"; 1069e5fd0047SMichael J. Spencer } 1070e5fd0047SMichael J. Spencer break; 1071e5fd0047SMichael J. Spencer default: 10728ff24d25SRui Ueyama Res = "Unknown"; 1073e5fd0047SMichael J. Spencer } 10748ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1075e5fd0047SMichael J. Spencer return object_error::success; 1076e5fd0047SMichael J. Spencer } 1077e5fd0047SMichael J. Spencer 1078e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1079e5fd0047SMichael J. Spencer 1080db4ed0bdSRafael Espindola std::error_code 1081db4ed0bdSRafael Espindola COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 1082e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 10838ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 10848ff24d25SRui Ueyama DataRefImpl Sym; 108544f51e51SDavid Majnemer ErrorOr<COFFSymbolRef> Symb = getSymbol(Reloc->SymbolTableIndex); 108644f51e51SDavid Majnemer if (std::error_code EC = Symb.getError()) 108744f51e51SDavid Majnemer return EC; 108844f51e51SDavid Majnemer Sym.p = reinterpret_cast<uintptr_t>(Symb->getRawPtr()); 10898ff24d25SRui Ueyama StringRef SymName; 1090db4ed0bdSRafael Espindola if (std::error_code EC = getSymbolName(Sym, SymName)) 1091db4ed0bdSRafael Espindola return EC; 10928ff24d25SRui Ueyama Result.append(SymName.begin(), SymName.end()); 1093e5fd0047SMichael J. Spencer return object_error::success; 1094022ecdf2SBenjamin Kramer } 10958e90adafSMichael J. Spencer 1096c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1097c66d761bSRafael Espindola return !DataDirectory; 1098c66d761bSRafael Espindola } 1099c66d761bSRafael Espindola 1100c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1101c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1102a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1103c2bed429SRui Ueyama } 1104c2bed429SRui Ueyama 11055e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 11065e812afaSRafael Espindola ++Index; 1107c2bed429SRui Ueyama } 1108c2bed429SRui Ueyama 1109db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1110db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 11111e152d5eSRui Ueyama Result = ImportTable + Index; 1112c2bed429SRui Ueyama return object_error::success; 1113c2bed429SRui Ueyama } 1114c2bed429SRui Ueyama 1115861021f9SRui Ueyama static imported_symbol_iterator 111615d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1117861021f9SRui Ueyama uintptr_t Ptr, int Index) { 111815d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1119861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 112015d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1121861021f9SRui Ueyama } 1122861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 112315d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1124861021f9SRui Ueyama } 1125861021f9SRui Ueyama 112615d99359SRui Ueyama static imported_symbol_iterator 112715d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1128861021f9SRui Ueyama uintptr_t IntPtr = 0; 112915d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 113015d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1131861021f9SRui Ueyama } 1132861021f9SRui Ueyama 113315d99359SRui Ueyama static imported_symbol_iterator 113415d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1135861021f9SRui Ueyama uintptr_t IntPtr = 0; 113615d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1137861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1138861021f9SRui Ueyama int Index = 0; 113915d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1140861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1141861021f9SRui Ueyama while (*Entry++) 1142861021f9SRui Ueyama ++Index; 1143861021f9SRui Ueyama } else { 1144861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1145861021f9SRui Ueyama while (*Entry++) 1146861021f9SRui Ueyama ++Index; 1147861021f9SRui Ueyama } 114815d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 114915d99359SRui Ueyama } 115015d99359SRui Ueyama 115115d99359SRui Ueyama imported_symbol_iterator 115215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 115315d99359SRui Ueyama return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 115415d99359SRui Ueyama OwningObject); 115515d99359SRui Ueyama } 115615d99359SRui Ueyama 115715d99359SRui Ueyama imported_symbol_iterator 115815d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 115915d99359SRui Ueyama return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 116015d99359SRui Ueyama OwningObject); 1161861021f9SRui Ueyama } 1162861021f9SRui Ueyama 1163979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1164979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1165979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1166979fb40bSRui Ueyama } 1167979fb40bSRui Ueyama 1168db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1169c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1170db4ed0bdSRafael Espindola if (std::error_code EC = 11711e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1172a045b73aSRui Ueyama return EC; 1173a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1174c2bed429SRui Ueyama return object_error::success; 1175c2bed429SRui Ueyama } 1176c2bed429SRui Ueyama 11771e152d5eSRui Ueyama std::error_code 11781e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 11791e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 11801e152d5eSRui Ueyama return object_error::success; 11811e152d5eSRui Ueyama } 11821e152d5eSRui Ueyama 11831e152d5eSRui Ueyama std::error_code 11841e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 11851e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 11861e152d5eSRui Ueyama return object_error::success; 11871e152d5eSRui Ueyama } 11881e152d5eSRui Ueyama 1189db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1190c2bed429SRui Ueyama const import_lookup_table_entry32 *&Result) const { 1191c2bed429SRui Ueyama uintptr_t IntPtr = 0; 11921e152d5eSRui Ueyama uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; 11931e152d5eSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1194a045b73aSRui Ueyama return EC; 1195c2bed429SRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 1196c2bed429SRui Ueyama return object_error::success; 1197c2bed429SRui Ueyama } 1198c2bed429SRui Ueyama 119915d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 120015d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 120115d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 120215d99359SRui Ueyama } 120315d99359SRui Ueyama 120415d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 120515d99359SRui Ueyama ++Index; 120615d99359SRui Ueyama } 120715d99359SRui Ueyama 120815d99359SRui Ueyama imported_symbol_iterator 120915d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 121015d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 121115d99359SRui Ueyama OwningObject); 121215d99359SRui Ueyama } 121315d99359SRui Ueyama 121415d99359SRui Ueyama imported_symbol_iterator 121515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 121615d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 121715d99359SRui Ueyama OwningObject); 121815d99359SRui Ueyama } 121915d99359SRui Ueyama 1220979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1221979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1222979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1223979fb40bSRui Ueyama } 1224979fb40bSRui Ueyama 122515d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 122615d99359SRui Ueyama uintptr_t IntPtr = 0; 122715d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 122815d99359SRui Ueyama return EC; 122915d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 123015d99359SRui Ueyama return object_error::success; 123115d99359SRui Ueyama } 123215d99359SRui Ueyama 12331af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 12341af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 12351af08658SRui Ueyama Result = Table; 12361af08658SRui Ueyama return object_error::success; 12371af08658SRui Ueyama } 12381af08658SRui Ueyama 1239ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1240ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1241ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1242ad882ba8SRui Ueyama } 1243ad882ba8SRui Ueyama 12445e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 12455e812afaSRafael Espindola ++Index; 1246ad882ba8SRui Ueyama } 1247ad882ba8SRui Ueyama 1248da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1249da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1250db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1251da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1252db4ed0bdSRafael Espindola if (std::error_code EC = 1253db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1254da49d0d4SRui Ueyama return EC; 1255da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1256da49d0d4SRui Ueyama return object_error::success; 1257da49d0d4SRui Ueyama } 1258da49d0d4SRui Ueyama 1259e5df6095SRui Ueyama // Returns the starting ordinal number. 1260db4ed0bdSRafael Espindola std::error_code 1261db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1262e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 1263e5df6095SRui Ueyama return object_error::success; 1264e5df6095SRui Ueyama } 1265e5df6095SRui Ueyama 1266ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1267db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1268ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 1269ad882ba8SRui Ueyama return object_error::success; 1270ad882ba8SRui Ueyama } 1271ad882ba8SRui Ueyama 1272ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1273db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1274ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1275db4ed0bdSRafael Espindola if (std::error_code EC = 1276db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1277ad882ba8SRui Ueyama return EC; 127824fc2d64SRui Ueyama const export_address_table_entry *entry = 127924fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1280ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 1281ad882ba8SRui Ueyama return object_error::success; 1282ad882ba8SRui Ueyama } 1283ad882ba8SRui Ueyama 1284ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1285ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1286db4ed0bdSRafael Espindola std::error_code 1287db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1288ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1289db4ed0bdSRafael Espindola if (std::error_code EC = 1290db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1291ad882ba8SRui Ueyama return EC; 1292ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1293ad882ba8SRui Ueyama 1294ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1295ad882ba8SRui Ueyama int Offset = 0; 1296ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1297ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1298ad882ba8SRui Ueyama if (*I != Index) 1299ad882ba8SRui Ueyama continue; 1300db4ed0bdSRafael Espindola if (std::error_code EC = 1301db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1302ad882ba8SRui Ueyama return EC; 1303ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1304db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1305ad882ba8SRui Ueyama return EC; 1306ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1307ad882ba8SRui Ueyama return object_error::success; 1308ad882ba8SRui Ueyama } 1309ad882ba8SRui Ueyama Result = ""; 1310ad882ba8SRui Ueyama return object_error::success; 1311ad882ba8SRui Ueyama } 1312ad882ba8SRui Ueyama 1313861021f9SRui Ueyama bool ImportedSymbolRef:: 1314861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1315861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1316861021f9SRui Ueyama && Index == Other.Index; 1317861021f9SRui Ueyama } 1318861021f9SRui Ueyama 1319861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1320861021f9SRui Ueyama ++Index; 1321861021f9SRui Ueyama } 1322861021f9SRui Ueyama 1323861021f9SRui Ueyama std::error_code 1324861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1325861021f9SRui Ueyama uint32_t RVA; 1326861021f9SRui Ueyama if (Entry32) { 1327861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1328861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 1329861021f9SRui Ueyama return object_error::success; 1330861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1331861021f9SRui Ueyama } else { 1332861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 1333861021f9SRui Ueyama return object_error::success; 1334861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1335861021f9SRui Ueyama } 1336861021f9SRui Ueyama uintptr_t IntPtr = 0; 1337861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1338861021f9SRui Ueyama return EC; 1339861021f9SRui Ueyama // +2 because the first two bytes is hint. 1340861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 1341861021f9SRui Ueyama return object_error::success; 1342861021f9SRui Ueyama } 1343861021f9SRui Ueyama 1344861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1345861021f9SRui Ueyama uint32_t RVA; 1346861021f9SRui Ueyama if (Entry32) { 1347861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1348861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 1349861021f9SRui Ueyama return object_error::success; 1350861021f9SRui Ueyama } 1351861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1352861021f9SRui Ueyama } else { 1353861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1354861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 1355861021f9SRui Ueyama return object_error::success; 1356861021f9SRui Ueyama } 1357861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1358861021f9SRui Ueyama } 1359861021f9SRui Ueyama uintptr_t IntPtr = 0; 1360861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1361861021f9SRui Ueyama return EC; 1362861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 1363861021f9SRui Ueyama return object_error::success; 1364861021f9SRui Ueyama } 1365861021f9SRui Ueyama 1366437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 136748af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1368db4ed0bdSRafael Espindola std::error_code EC; 136948af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1370692410efSRafael Espindola if (EC) 1371692410efSRafael Espindola return EC; 1372437b0d58SRafael Espindola return std::move(Ret); 1373686738e2SRui Ueyama } 1374