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 42*e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, 43*e830c60dSDavid Majnemer const size_t Size) { 44*e830c60dSDavid Majnemer if (Addr + Size < Addr || Addr + Size < Size || 45*e830c60dSDavid Majnemer Addr + Size > uintptr_t(M.getBufferEnd()) || 46*e830c60dSDavid Majnemer Addr < uintptr_t(M.getBufferStart())) { 47*e830c60dSDavid Majnemer return object_error::unexpected_eof; 48*e830c60dSDavid Majnemer } 49*e830c60dSDavid Majnemer return object_error::success; 50*e830c60dSDavid Majnemer } 51*e830c60dSDavid Majnemer 52ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 53ed64342bSRui Ueyama // Returns unexpected_eof if error. 54ed64342bSRui Ueyama template <typename T> 5548af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5658323a97SDavid Majnemer const void *Ptr, 57db4ed0bdSRafael Espindola const size_t Size = sizeof(T)) { 58ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 59*e830c60dSDavid Majnemer if (std::error_code EC = checkOffset(M, Addr, Size)) 60*e830c60dSDavid Majnemer return EC; 61ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 62ed64342bSRui Ueyama return object_error::success; 631d6167fdSMichael J. Spencer } 641d6167fdSMichael J. Spencer 659d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 669d2c15efSNico Rieck // prefixed slashes. 679d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 689d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 699d2c15efSNico Rieck if (Str.size() > 6) 709d2c15efSNico Rieck return true; 719d2c15efSNico Rieck 729d2c15efSNico Rieck uint64_t Value = 0; 739d2c15efSNico Rieck while (!Str.empty()) { 749d2c15efSNico Rieck unsigned CharVal; 759d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 769d2c15efSNico Rieck CharVal = Str[0] - 'A'; 779d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 789d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 799d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 809d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 819d2c15efSNico Rieck else if (Str[0] == '+') // 62 825500b07cSRui Ueyama CharVal = 62; 839d2c15efSNico Rieck else if (Str[0] == '/') // 63 845500b07cSRui Ueyama CharVal = 63; 859d2c15efSNico Rieck else 869d2c15efSNico Rieck return true; 879d2c15efSNico Rieck 889d2c15efSNico Rieck Value = (Value * 64) + CharVal; 899d2c15efSNico Rieck Str = Str.substr(1); 909d2c15efSNico Rieck } 919d2c15efSNico Rieck 929d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 939d2c15efSNico Rieck return true; 949d2c15efSNico Rieck 959d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 969d2c15efSNico Rieck return false; 979d2c15efSNico Rieck } 989d2c15efSNico Rieck 9944f51e51SDavid Majnemer template <typename coff_symbol_type> 10044f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10144f51e51SDavid Majnemer const coff_symbol_type *Addr = 10244f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1031d6167fdSMichael J. Spencer 1041d6167fdSMichael J. Spencer #ifndef NDEBUG 1051d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1068ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 10744f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 10844f51e51SDavid Majnemer Offset >= getPointerToSymbolTable() + 10944f51e51SDavid Majnemer (getNumberOfSymbols() * sizeof(coff_symbol_type))) 1101d6167fdSMichael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 1111d6167fdSMichael J. Spencer 11244f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11344f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1141d6167fdSMichael J. Spencer #endif 1151d6167fdSMichael J. Spencer 1168ff24d25SRui Ueyama return Addr; 1171d6167fdSMichael J. Spencer } 1181d6167fdSMichael J. Spencer 1198ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1208ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1211d6167fdSMichael J. Spencer 1221d6167fdSMichael J. Spencer # ifndef NDEBUG 1231d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12444f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1251d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1261d6167fdSMichael J. Spencer 1278ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1288ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1291d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1301d6167fdSMichael J. Spencer # endif 1311d6167fdSMichael J. Spencer 1328ff24d25SRui Ueyama return Addr; 1331d6167fdSMichael J. Spencer } 1341d6167fdSMichael J. Spencer 1355e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 13644f51e51SDavid Majnemer if (SymbolTable16) { 13744f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1388ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 1398ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Symb); 14044f51e51SDavid Majnemer } else if (SymbolTable32) { 14144f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14244f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 14344f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(Symb); 14444f51e51SDavid Majnemer } else { 14544f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14644f51e51SDavid Majnemer } 1471d6167fdSMichael J. Spencer } 1481d6167fdSMichael J. Spencer 149db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, 1501d6167fdSMichael J. Spencer StringRef &Result) const { 15144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1528ff24d25SRui Ueyama return getSymbolName(Symb, Result); 1538e90adafSMichael J. Spencer } 1548e90adafSMichael J. Spencer 155db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, 15675d1cf33SBenjamin Kramer uint64_t &Result) const { 15744f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 158c7d7c6fbSDavid Majnemer 159c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 160c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 161c7d7c6fbSDavid Majnemer return object_error::success; 162c7d7c6fbSDavid Majnemer } 163c7d7c6fbSDavid Majnemer if (Symb.isCommon()) { 164c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 165c7d7c6fbSDavid Majnemer return object_error::success; 166c7d7c6fbSDavid Majnemer } 167c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 168c7d7c6fbSDavid Majnemer if (!COFF::isReservedSectionNumber(SectionNumber)) { 1692617dcceSCraig Topper const coff_section *Section = nullptr; 170c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 1718ff24d25SRui Ueyama return EC; 172e62ab11fSRafael Espindola 17344f51e51SDavid Majnemer Result = Section->VirtualAddress + Symb.getValue(); 174c7d7c6fbSDavid Majnemer return object_error::success; 175c7d7c6fbSDavid Majnemer } 176c7d7c6fbSDavid Majnemer 17744f51e51SDavid Majnemer Result = Symb.getValue(); 17875d1cf33SBenjamin Kramer return object_error::success; 17975d1cf33SBenjamin Kramer } 18075d1cf33SBenjamin Kramer 181db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, 182d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 18344f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 184c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 18575d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 18644f51e51SDavid Majnemer 187c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 1887e4b976cSDavid Meyer Result = SymbolRef::ST_Unknown; 18944f51e51SDavid Majnemer } else if (Symb.isFunctionDefinition()) { 19075d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 191c7d7c6fbSDavid Majnemer } else if (Symb.isCommon()) { 192c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Data; 193c7d7c6fbSDavid Majnemer } else if (Symb.isFileRecord()) { 194c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_File; 195c7d7c6fbSDavid Majnemer } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) { 196c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Debug; 197c7d7c6fbSDavid Majnemer } else if (!COFF::isReservedSectionNumber(SectionNumber)) { 1982617dcceSCraig Topper const coff_section *Section = nullptr; 199c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 2008ff24d25SRui Ueyama return EC; 201c7d7c6fbSDavid Majnemer uint32_t Characteristics = Section->Characteristics; 202c7d7c6fbSDavid Majnemer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 203c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Function; 204c7d7c6fbSDavid Majnemer else if (Characteristics & (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 205c7d7c6fbSDavid Majnemer COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) 20606adfac8SRafael Espindola Result = SymbolRef::ST_Data; 20775d1cf33SBenjamin Kramer } 20875d1cf33SBenjamin Kramer return object_error::success; 20975d1cf33SBenjamin Kramer } 21075d1cf33SBenjamin Kramer 21120122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 21244f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 21320122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 21475d1cf33SBenjamin Kramer 215c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2161df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 2171df4b84dSDavid Meyer 218c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2191df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2201df4b84dSDavid Meyer 22144f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2221df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2231df4b84dSDavid Meyer 224c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 225c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 226c7d7c6fbSDavid Majnemer 227c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 228c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 229c7d7c6fbSDavid Majnemer 230c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 231c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 232c7d7c6fbSDavid Majnemer 233c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 234c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 235c7d7c6fbSDavid Majnemer 23620122a43SRafael Espindola return Result; 23701759754SMichael J. Spencer } 23801759754SMichael J. Spencer 239db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, 2401d6167fdSMichael J. Spencer uint64_t &Result) const { 241c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 242c7d7c6fbSDavid Majnemer 243c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 244c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 245c7d7c6fbSDavid Majnemer return object_error::success; 246c7d7c6fbSDavid Majnemer } 247c7d7c6fbSDavid Majnemer if (Symb.isCommon()) { 248c7d7c6fbSDavid Majnemer Result = Symb.getValue(); 249c7d7c6fbSDavid Majnemer return object_error::success; 250c7d7c6fbSDavid Majnemer } 25151ff5595SDavid Majnemer 25251ff5595SDavid Majnemer // Let's attempt to get the size of the symbol by looking at the address of 25351ff5595SDavid Majnemer // the symbol after the symbol in question. 25451ff5595SDavid Majnemer uint64_t SymbAddr; 25551ff5595SDavid Majnemer if (std::error_code EC = getSymbolAddress(Ref, SymbAddr)) 25651ff5595SDavid Majnemer return EC; 257c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 25851ff5595SDavid Majnemer if (COFF::isReservedSectionNumber(SectionNumber)) { 25951ff5595SDavid Majnemer // Absolute and debug symbols aren't sorted in any interesting way. 26051ff5595SDavid Majnemer Result = 0; 26151ff5595SDavid Majnemer return object_error::success; 26251ff5595SDavid Majnemer } 26351ff5595SDavid Majnemer const section_iterator SecEnd = section_end(); 26451ff5595SDavid Majnemer uint64_t AfterAddr = UnknownAddressOrSize; 26551ff5595SDavid Majnemer for (const symbol_iterator &SymbI : symbols()) { 26651ff5595SDavid Majnemer section_iterator SecI = SecEnd; 26751ff5595SDavid Majnemer if (std::error_code EC = SymbI->getSection(SecI)) 26851ff5595SDavid Majnemer return EC; 26951ff5595SDavid Majnemer // Check the symbol's section, skip it if it's in the wrong section. 27051ff5595SDavid Majnemer // First, make sure it is in any section. 27151ff5595SDavid Majnemer if (SecI == SecEnd) 27251ff5595SDavid Majnemer continue; 27351ff5595SDavid Majnemer // Second, make sure it is in the same section as the symbol in question. 27451ff5595SDavid Majnemer if (!sectionContainsSymbol(SecI->getRawDataRefImpl(), Ref)) 27551ff5595SDavid Majnemer continue; 27651ff5595SDavid Majnemer uint64_t Addr; 27751ff5595SDavid Majnemer if (std::error_code EC = SymbI->getAddress(Addr)) 27851ff5595SDavid Majnemer return EC; 27951ff5595SDavid Majnemer // We want to compare our symbol in question with the closest possible 28051ff5595SDavid Majnemer // symbol that comes after. 28151ff5595SDavid Majnemer if (AfterAddr > Addr && Addr > SymbAddr) 28251ff5595SDavid Majnemer AfterAddr = Addr; 28351ff5595SDavid Majnemer } 28451ff5595SDavid Majnemer if (AfterAddr == UnknownAddressOrSize) { 28551ff5595SDavid Majnemer // No symbol comes after this one, assume that everything after our symbol 28651ff5595SDavid Majnemer // is part of it. 2872617dcceSCraig Topper const coff_section *Section = nullptr; 288c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 2898ff24d25SRui Ueyama return EC; 2908280fbbfSRafael Espindola Result = Section->SizeOfRawData - Symb.getValue(); 29151ff5595SDavid Majnemer } else { 29251ff5595SDavid Majnemer // Take the difference between our symbol and the symbol that comes after 29351ff5595SDavid Majnemer // our symbol. 29451ff5595SDavid Majnemer Result = AfterAddr - SymbAddr; 2958280fbbfSRafael Espindola } 2968280fbbfSRafael Espindola 2971d6167fdSMichael J. Spencer return object_error::success; 2988e90adafSMichael J. Spencer } 2998e90adafSMichael J. Spencer 300db4ed0bdSRafael Espindola std::error_code 301db4ed0bdSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref, 30232173153SMichael J. Spencer section_iterator &Result) const { 30344f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 30444f51e51SDavid Majnemer if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 305b5155a57SRafael Espindola Result = section_end(); 306f078eff3SRui Ueyama } else { 3072617dcceSCraig Topper const coff_section *Sec = nullptr; 30844f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 309db4ed0bdSRafael Espindola return EC; 3108ff24d25SRui Ueyama DataRefImpl Ref; 3118ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 3128ff24d25SRui Ueyama Result = section_iterator(SectionRef(Ref, this)); 31332173153SMichael J. Spencer } 31432173153SMichael J. Spencer return object_error::success; 31532173153SMichael J. Spencer } 31632173153SMichael J. Spencer 3175e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 3188ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3198ff24d25SRui Ueyama Sec += 1; 3208ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 3218e90adafSMichael J. Spencer } 3228e90adafSMichael J. Spencer 323db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 3241d6167fdSMichael J. Spencer StringRef &Result) const { 3258ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3268ff24d25SRui Ueyama return getSectionName(Sec, Result); 3278e90adafSMichael J. Spencer } 3288e90adafSMichael J. Spencer 32980291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 3308ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 33180291274SRafael Espindola return Sec->VirtualAddress; 3328e90adafSMichael J. Spencer } 3338e90adafSMichael J. Spencer 33480291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 335a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 3368e90adafSMichael J. Spencer } 3378e90adafSMichael J. Spencer 338db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 3391d6167fdSMichael J. Spencer StringRef &Result) const { 3408ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3419da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 342db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3439da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3449da9e693SMichael J. Spencer return EC; 3458e90adafSMichael J. Spencer } 3468e90adafSMichael J. Spencer 34780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3488ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 34980291274SRafael Espindola return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 3507989460aSMichael J. Spencer } 3517989460aSMichael J. Spencer 35280291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3538ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 35480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3558e90adafSMichael J. Spencer } 3568e90adafSMichael J. Spencer 35780291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3588ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 35980291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 360800619f2SMichael J. Spencer } 361800619f2SMichael J. Spencer 36280291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3638ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 36480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 365800619f2SMichael J. Spencer } 366800619f2SMichael J. Spencer 36780291274SRafael Espindola bool COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref) const { 3682138ef6dSPreston Gurd // FIXME: Unimplemented 36980291274SRafael Espindola return true; 3702138ef6dSPreston Gurd } 3712138ef6dSPreston Gurd 37280291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3738ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 37480291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3752138ef6dSPreston Gurd } 3762138ef6dSPreston Gurd 37780291274SRafael Espindola bool COFFObjectFile::isSectionZeroInit(DataRefImpl Ref) const { 378b96a320aSAndrew Kaylor // FIXME: Unimplemented. 37980291274SRafael Espindola return false; 3802138ef6dSPreston Gurd } 3812138ef6dSPreston Gurd 38280291274SRafael Espindola bool COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref) const { 3833f31fa05SAndrew Kaylor // FIXME: Unimplemented. 38480291274SRafael Espindola return false; 3853f31fa05SAndrew Kaylor } 3863f31fa05SAndrew Kaylor 38780291274SRafael Espindola bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, 38880291274SRafael Espindola DataRefImpl SymbRef) const { 3898ff24d25SRui Ueyama const coff_section *Sec = toSec(SecRef); 39044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(SymbRef); 391a9260865SRafael Espindola int32_t SecNumber = (Sec - SectionTable) + 1; 39280291274SRafael Espindola return SecNumber == Symb.getSectionNumber(); 393f6f3e81cSBenjamin Kramer } 394f6f3e81cSBenjamin Kramer 395*e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 396*e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 397*e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 398*e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 399*e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 400*e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 401*e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 402*e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 403*e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 404*e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 405*e830c60dSDavid Majnemer return 0; 406*e830c60dSDavid Majnemer return FirstReloc->VirtualAddress; 407*e830c60dSDavid Majnemer } 408*e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 409*e830c60dSDavid Majnemer } 410*e830c60dSDavid Majnemer 4118ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 4128ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 4138ff24d25SRui Ueyama DataRefImpl Ret; 414*e830c60dSDavid Majnemer if (getNumberOfRelocations(Sec, Data, base()) == 0) { 4158ff24d25SRui Ueyama Ret.p = 0; 416827c8a2bSRui Ueyama } else { 417827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 418827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 419827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 420827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 421827c8a2bSRui Ueyama // relocations. 422827c8a2bSRui Ueyama begin++; 423827c8a2bSRui Ueyama } 424827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin); 425827c8a2bSRui Ueyama } 4268ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 427e5fd0047SMichael J. Spencer } 428e5fd0047SMichael J. Spencer 4298ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 4308ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 4318ff24d25SRui Ueyama DataRefImpl Ret; 432*e830c60dSDavid Majnemer if (getNumberOfRelocations(Sec, Data, base()) == 0) { 4338ff24d25SRui Ueyama Ret.p = 0; 434827c8a2bSRui Ueyama } else { 435827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation*>( 436827c8a2bSRui Ueyama base() + Sec->PointerToRelocations); 43758323a97SDavid Majnemer if (Sec->hasExtendedRelocations()) { 43858323a97SDavid Majnemer // Skip the first relocation entry repurposed to store the number of 43958323a97SDavid Majnemer // relocations. 44058323a97SDavid Majnemer begin++; 44158323a97SDavid Majnemer } 442*e830c60dSDavid Majnemer uint32_t NumReloc = getNumberOfRelocations(Sec, Data, base()); 443827c8a2bSRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); 444827c8a2bSRui Ueyama } 4458ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 446e5fd0047SMichael J. Spencer } 447e5fd0047SMichael J. Spencer 448c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 449db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 45044f51e51SDavid Majnemer if (COFFHeader) 45144f51e51SDavid Majnemer if (std::error_code EC = 45244f51e51SDavid Majnemer getObject(SymbolTable16, Data, base() + getPointerToSymbolTable(), 45344f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 45444f51e51SDavid Majnemer return EC; 45544f51e51SDavid Majnemer 45644f51e51SDavid Majnemer if (COFFBigObjHeader) 45744f51e51SDavid Majnemer if (std::error_code EC = 45844f51e51SDavid Majnemer getObject(SymbolTable32, Data, base() + getPointerToSymbolTable(), 45944f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize())) 4608ff24d25SRui Ueyama return EC; 461c2bed429SRui Ueyama 462c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 463c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 464c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 465c2bed429SRui Ueyama const uint8_t *StringTableAddr = 46644f51e51SDavid Majnemer base() + getPointerToSymbolTable() + 46744f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 468c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 46948af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4708ff24d25SRui Ueyama return EC; 471c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 472db4ed0bdSRafael Espindola if (std::error_code EC = 47348af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4748ff24d25SRui Ueyama return EC; 475c2bed429SRui Ueyama 476773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 477773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 478773a5795SNico Rieck if (StringTableSize < 4) 479773a5795SNico Rieck StringTableSize = 4; 480773a5795SNico Rieck 481c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 482773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 483c2bed429SRui Ueyama return object_error::parse_failed; 484c2bed429SRui Ueyama return object_error::success; 485c2bed429SRui Ueyama } 486c2bed429SRui Ueyama 487215a586cSRui Ueyama // Returns the file offset for the given VA. 488db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 489b6eb264aSRui Ueyama uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 490b6eb264aSRui Ueyama : (uint64_t)PE32PlusHeader->ImageBase; 491b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 492b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 493b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 494215a586cSRui Ueyama } 495215a586cSRui Ueyama 496c2bed429SRui Ueyama // Returns the file offset for the given RVA. 497db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 49827dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 49927dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 500c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 501c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 502215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 503215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 504c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 505c2bed429SRui Ueyama return object_error::success; 506c2bed429SRui Ueyama } 507c2bed429SRui Ueyama } 508c2bed429SRui Ueyama return object_error::parse_failed; 509c2bed429SRui Ueyama } 510c2bed429SRui Ueyama 511c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 512c2bed429SRui Ueyama // table entry. 513db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 514db4ed0bdSRafael Espindola StringRef &Name) const { 515c2bed429SRui Ueyama uintptr_t IntPtr = 0; 516db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 5178ff24d25SRui Ueyama return EC; 518c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 519c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 520c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 521c2bed429SRui Ueyama return object_error::success; 522c2bed429SRui Ueyama } 523c2bed429SRui Ueyama 524c2bed429SRui Ueyama // Find the import table. 525db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 526c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 527c2bed429SRui Ueyama // the import table, do nothing. 528c2bed429SRui Ueyama const data_directory *DataEntry; 529c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 530c2bed429SRui Ueyama return object_error::success; 531c2bed429SRui Ueyama 532c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 533c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 534c2bed429SRui Ueyama return object_error::success; 535c2bed429SRui Ueyama 536c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 5371e152d5eSRui Ueyama // -1 because the last entry is the null entry. 538c2bed429SRui Ueyama NumberOfImportDirectory = DataEntry->Size / 5391e152d5eSRui Ueyama sizeof(import_directory_table_entry) - 1; 540c2bed429SRui Ueyama 541c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 542c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 543c2bed429SRui Ueyama uintptr_t IntPtr = 0; 544db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5458ff24d25SRui Ueyama return EC; 546c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 547c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 548ad882ba8SRui Ueyama return object_error::success; 549ad882ba8SRui Ueyama } 550c2bed429SRui Ueyama 55115d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 55215d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 55315d99359SRui Ueyama const data_directory *DataEntry; 55415d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 55515d99359SRui Ueyama return object_error::success; 55615d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 55715d99359SRui Ueyama return object_error::success; 55815d99359SRui Ueyama 55915d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 56015d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 56115d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 56215d99359SRui Ueyama 56315d99359SRui Ueyama uintptr_t IntPtr = 0; 56415d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 56515d99359SRui Ueyama return EC; 56615d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 56715d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 56815d99359SRui Ueyama return object_error::success; 56915d99359SRui Ueyama } 57015d99359SRui Ueyama 571ad882ba8SRui Ueyama // Find the export table. 572db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 573ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 574ad882ba8SRui Ueyama // the export table, do nothing. 575ad882ba8SRui Ueyama const data_directory *DataEntry; 576ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 577ad882ba8SRui Ueyama return object_error::success; 578ad882ba8SRui Ueyama 579ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 580ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 581ad882ba8SRui Ueyama return object_error::success; 582ad882ba8SRui Ueyama 583ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 584ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 585db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 586ad882ba8SRui Ueyama return EC; 58724fc2d64SRui Ueyama ExportDirectory = 58824fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 589ad882ba8SRui Ueyama return object_error::success; 590c2bed429SRui Ueyama } 591c2bed429SRui Ueyama 59248af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 59348af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 59444f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 59544f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 59644f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 59744f51e51SDavid Majnemer ImportDirectory(nullptr), NumberOfImportDirectory(0), 59815d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 5992617dcceSCraig Topper ExportDirectory(nullptr) { 6001d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 60148af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 602c3f9b5a5SRafael Espindola return; 603ee066fc4SEric Christopher 60482ebd8e3SRui Ueyama // The current location in the file where we are looking at. 60582ebd8e3SRui Ueyama uint64_t CurPtr = 0; 60682ebd8e3SRui Ueyama 60782ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 60882ebd8e3SRui Ueyama // it is placed right after COFF header. 6098ff24d25SRui Ueyama bool HasPEHeader = false; 610ee066fc4SEric Christopher 6111d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 61250267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 613ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 614ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 61550267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 61650267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 61750267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 61882ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 61950267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6208ff24d25SRui Ueyama EC = object_error::parse_failed; 6211d6167fdSMichael J. Spencer return; 6221d6167fdSMichael J. Spencer } 62344f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6248ff24d25SRui Ueyama HasPEHeader = true; 625ee066fc4SEric Christopher } 62650267222SDavid Majnemer } 627ee066fc4SEric Christopher 62848af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 6291d6167fdSMichael J. Spencer return; 63044f51e51SDavid Majnemer 63144f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 63244f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 63344f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 63444f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 63544f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 63644f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 63744f51e51SDavid Majnemer return; 63844f51e51SDavid Majnemer 63944f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 64044f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 64144f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 64244f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 64344f51e51SDavid Majnemer COFFHeader = nullptr; 64444f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 64544f51e51SDavid Majnemer } else { 64644f51e51SDavid Majnemer // It's not a bigobj. 64744f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 64844f51e51SDavid Majnemer } 64944f51e51SDavid Majnemer } 65044f51e51SDavid Majnemer if (COFFHeader) { 65144f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 65244f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 65344f51e51SDavid Majnemer EC = object_error::success; 65482ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 65582ebd8e3SRui Ueyama 65644f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 65744f51e51SDavid Majnemer return; 65844f51e51SDavid Majnemer } 65944f51e51SDavid Majnemer 6608ff24d25SRui Ueyama if (HasPEHeader) { 66110ed9ddcSRui Ueyama const pe32_header *Header; 66248af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 66382ebd8e3SRui Ueyama return; 66410ed9ddcSRui Ueyama 66510ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 66610ed9ddcSRui Ueyama uint64_t DataDirSize; 66750267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 66810ed9ddcSRui Ueyama PE32Header = Header; 66910ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 67010ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 67150267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 67210ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 67310ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 67410ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 67510ed9ddcSRui Ueyama } else { 67610ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 67710ed9ddcSRui Ueyama EC = object_error::parse_failed; 678ed64342bSRui Ueyama return; 679ed64342bSRui Ueyama } 68048af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 68110ed9ddcSRui Ueyama return; 68282ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 68382ebd8e3SRui Ueyama } 6841d6167fdSMichael J. Spencer 68548af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 68644f51e51SDavid Majnemer getNumberOfSections() * sizeof(coff_section)))) 6871d6167fdSMichael J. Spencer return; 6881d6167fdSMichael J. Spencer 689c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 69044f51e51SDavid Majnemer if (getPointerToSymbolTable() != 0) 6918ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 6921d6167fdSMichael J. Spencer return; 6938e90adafSMichael J. Spencer 694c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 6958ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 696ed64342bSRui Ueyama return; 69715d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 69815d99359SRui Ueyama return; 6991d6167fdSMichael J. Spencer 700ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7018ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 702ad882ba8SRui Ueyama return; 703ad882ba8SRui Ueyama 7048ff24d25SRui Ueyama EC = object_error::success; 7058e90adafSMichael J. Spencer } 7068e90adafSMichael J. Spencer 707f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 7088ff24d25SRui Ueyama DataRefImpl Ret; 70944f51e51SDavid Majnemer Ret.p = getSymbolTable(); 710f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7118e90adafSMichael J. Spencer } 7128e90adafSMichael J. Spencer 713f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 7148e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 7158ff24d25SRui Ueyama DataRefImpl Ret; 7168ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 717f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7188e90adafSMichael J. Spencer } 7198e90adafSMichael J. Spencer 720bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 721a045b73aSRui Ueyama return import_directory_iterator( 722a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 723c2bed429SRui Ueyama } 724c2bed429SRui Ueyama 725bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 726a045b73aSRui Ueyama return import_directory_iterator( 727a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 728c2bed429SRui Ueyama } 729c429b80dSDavid Meyer 73015d99359SRui Ueyama delay_import_directory_iterator 73115d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 73215d99359SRui Ueyama return delay_import_directory_iterator( 73315d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 73415d99359SRui Ueyama } 73515d99359SRui Ueyama 73615d99359SRui Ueyama delay_import_directory_iterator 73715d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 73815d99359SRui Ueyama return delay_import_directory_iterator( 73915d99359SRui Ueyama DelayImportDirectoryEntryRef( 74015d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 74115d99359SRui Ueyama } 74215d99359SRui Ueyama 743ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 744ad882ba8SRui Ueyama return export_directory_iterator( 745ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 746ad882ba8SRui Ueyama } 747ad882ba8SRui Ueyama 748ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 7492617dcceSCraig Topper if (!ExportDirectory) 7502617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 7518ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 752ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 7538ff24d25SRui Ueyama return export_directory_iterator(Ref); 754ad882ba8SRui Ueyama } 755ad882ba8SRui Ueyama 756b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 7578ff24d25SRui Ueyama DataRefImpl Ret; 7588ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 7598ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7608e90adafSMichael J. Spencer } 7618e90adafSMichael J. Spencer 762b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 7638ff24d25SRui Ueyama DataRefImpl Ret; 76444f51e51SDavid Majnemer int NumSections = 76544f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 7668ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 7678ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7688e90adafSMichael J. Spencer } 7698e90adafSMichael J. Spencer 7708e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 7710324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 7728e90adafSMichael J. Spencer } 7738e90adafSMichael J. Spencer 7748e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 77544f51e51SDavid Majnemer switch(getMachine()) { 7768e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7778e90adafSMichael J. Spencer return "COFF-i386"; 7788e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7798e90adafSMichael J. Spencer return "COFF-x86-64"; 7809b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7819b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 7828e90adafSMichael J. Spencer default: 7838e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 7848e90adafSMichael J. Spencer } 7858e90adafSMichael J. Spencer } 7868e90adafSMichael J. Spencer 7878e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 78844f51e51SDavid Majnemer switch (getMachine()) { 7898e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7908e90adafSMichael J. Spencer return Triple::x86; 7918e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7928e90adafSMichael J. Spencer return Triple::x86_64; 7939b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7949b7c0af2SSaleem Abdulrasool return Triple::thumb; 7958e90adafSMichael J. Spencer default: 7968e90adafSMichael J. Spencer return Triple::UnknownArch; 7978e90adafSMichael J. Spencer } 7988e90adafSMichael J. Spencer } 7998e90adafSMichael J. Spencer 800979fb40bSRui Ueyama iterator_range<import_directory_iterator> 801979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 802979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 803979fb40bSRui Ueyama } 804979fb40bSRui Ueyama 805979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 806979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 807979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 808979fb40bSRui Ueyama delay_import_directory_end()); 809979fb40bSRui Ueyama } 810979fb40bSRui Ueyama 811979fb40bSRui Ueyama iterator_range<export_directory_iterator> 812979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 813979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 814979fb40bSRui Ueyama } 815979fb40bSRui Ueyama 816db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 81782ebd8e3SRui Ueyama Res = PE32Header; 81889a7a5eaSMichael J. Spencer return object_error::success; 81989a7a5eaSMichael J. Spencer } 82089a7a5eaSMichael J. Spencer 821db4ed0bdSRafael Espindola std::error_code 82210ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 82310ed9ddcSRui Ueyama Res = PE32PlusHeader; 82410ed9ddcSRui Ueyama return object_error::success; 82510ed9ddcSRui Ueyama } 82610ed9ddcSRui Ueyama 827db4ed0bdSRafael Espindola std::error_code 828db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 829ed64342bSRui Ueyama const data_directory *&Res) const { 830ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 83110ed9ddcSRui Ueyama if (!DataDirectory) 83210ed9ddcSRui Ueyama return object_error::parse_failed; 83310ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 83410ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 83510ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 83610ed9ddcSRui Ueyama if (Index > NumEnt) 837ed64342bSRui Ueyama return object_error::parse_failed; 8388ff24d25SRui Ueyama Res = &DataDirectory[Index]; 839ed64342bSRui Ueyama return object_error::success; 840ed64342bSRui Ueyama } 841ed64342bSRui Ueyama 842db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 8431d6167fdSMichael J. Spencer const coff_section *&Result) const { 8441d6167fdSMichael J. Spencer // Check for special index values. 845f078eff3SRui Ueyama if (COFF::isReservedSectionNumber(Index)) 8462617dcceSCraig Topper Result = nullptr; 84744f51e51SDavid Majnemer else if (Index > 0 && static_cast<uint32_t>(Index) <= getNumberOfSections()) 8481d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 8498ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 8501d6167fdSMichael J. Spencer else 8511d6167fdSMichael J. Spencer return object_error::parse_failed; 8521d6167fdSMichael J. Spencer return object_error::success; 8538e90adafSMichael J. Spencer } 8548e90adafSMichael J. Spencer 855db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 8561d6167fdSMichael J. Spencer StringRef &Result) const { 8571d6167fdSMichael J. Spencer if (StringTableSize <= 4) 8581d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 8591d6167fdSMichael J. Spencer return object_error::parse_failed; 8608ff24d25SRui Ueyama if (Offset >= StringTableSize) 8611d6167fdSMichael J. Spencer return object_error::unexpected_eof; 8628ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 8631d6167fdSMichael J. Spencer return object_error::success; 8648e90adafSMichael J. Spencer } 865022ecdf2SBenjamin Kramer 86644f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 86789a7a5eaSMichael J. Spencer StringRef &Res) const { 86889a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 86944f51e51SDavid Majnemer if (Symbol.getStringTableOffset().Zeroes == 0) { 87044f51e51SDavid Majnemer uint32_t Offset = Symbol.getStringTableOffset().Offset; 871db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Res)) 8728ff24d25SRui Ueyama return EC; 87389a7a5eaSMichael J. Spencer return object_error::success; 87489a7a5eaSMichael J. Spencer } 87589a7a5eaSMichael J. Spencer 87644f51e51SDavid Majnemer if (Symbol.getShortName()[COFF::NameSize - 1] == 0) 87789a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 87844f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName()); 87989a7a5eaSMichael J. Spencer else 88089a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 88144f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName(), COFF::NameSize); 88289a7a5eaSMichael J. Spencer return object_error::success; 88389a7a5eaSMichael J. Spencer } 88489a7a5eaSMichael J. Spencer 88544f51e51SDavid Majnemer ArrayRef<uint8_t> 88644f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 8872617dcceSCraig Topper const uint8_t *Aux = nullptr; 88871757ef3SMarshall Clow 88944f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 89044f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 89171757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 89244f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 89371757ef3SMarshall Clow # ifndef NDEBUG 8948ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 8958ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 89644f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 89744f51e51SDavid Majnemer Offset >= 89844f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 89971757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 90071757ef3SMarshall Clow 90144f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 90244f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 90371757ef3SMarshall Clow # endif 904bfb85e67SMarshall Clow } 90544f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 90671757ef3SMarshall Clow } 90771757ef3SMarshall Clow 908db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 90953c2d547SMichael J. Spencer StringRef &Res) const { 91053c2d547SMichael J. Spencer StringRef Name; 91144f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 91253c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 91353c2d547SMichael J. Spencer Name = Sec->Name; 91453c2d547SMichael J. Spencer else 91553c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 91644f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 91753c2d547SMichael J. Spencer 91853c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 9192314b3deSDavid Majnemer if (Name.startswith("/")) { 92053c2d547SMichael J. Spencer uint32_t Offset; 9212314b3deSDavid Majnemer if (Name.startswith("//")) { 9229d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 9239d2c15efSNico Rieck return object_error::parse_failed; 9249d2c15efSNico Rieck } else { 92553c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 92653c2d547SMichael J. Spencer return object_error::parse_failed; 9279d2c15efSNico Rieck } 928db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 9298ff24d25SRui Ueyama return EC; 93053c2d547SMichael J. Spencer } 93153c2d547SMichael J. Spencer 93253c2d547SMichael J. Spencer Res = Name; 93353c2d547SMichael J. Spencer return object_error::success; 93453c2d547SMichael J. Spencer } 93553c2d547SMichael J. Spencer 936a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 937a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 938a9ee5c06SDavid Majnemer // whether or not we have an executable image. 939a9ee5c06SDavid Majnemer // 940a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 941a9ee5c06SDavid Majnemer // VirtualSize is always zero. 942a9ee5c06SDavid Majnemer // 943a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 944a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 945a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 946a9ee5c06SDavid Majnemer // considered to be zero. 947a9ee5c06SDavid Majnemer uint32_t SectionSize; 948a9ee5c06SDavid Majnemer if (Sec->VirtualSize) 949a9ee5c06SDavid Majnemer SectionSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData); 950a9ee5c06SDavid Majnemer else 951a9ee5c06SDavid Majnemer SectionSize = Sec->SizeOfRawData; 952a9ee5c06SDavid Majnemer 953a9ee5c06SDavid Majnemer return SectionSize; 954a9ee5c06SDavid Majnemer } 955a9ee5c06SDavid Majnemer 956db4ed0bdSRafael Espindola std::error_code 957db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 9589da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 959dd9cff2eSDavid Majnemer // PointerToRawData and SizeOfRawData won't make sense for BSS sections, 960dd9cff2eSDavid Majnemer // don't do anything interesting for them. 961dac39857SDavid Majnemer assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && 962dac39857SDavid Majnemer "BSS sections don't have contents!"); 9639da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 9649da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 9659da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 9669da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 967a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 968*e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 9699da9e693SMichael J. Spencer return object_error::parse_failed; 970a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 9719da9e693SMichael J. Spencer return object_error::success; 9729da9e693SMichael J. Spencer } 9739da9e693SMichael J. Spencer 974022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 975e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 976022ecdf2SBenjamin Kramer } 9778ff24d25SRui Ueyama 9785e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 979e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 980e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 981022ecdf2SBenjamin Kramer } 9828ff24d25SRui Ueyama 983db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 984022ecdf2SBenjamin Kramer uint64_t &Res) const { 9851e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 986022ecdf2SBenjamin Kramer } 9878ff24d25SRui Ueyama 988db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 989cbe72fc9SDanil Malyshev uint64_t &Res) const { 99058323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 99158323a97SDavid Majnemer const support::ulittle32_t *VirtualAddressPtr; 99258323a97SDavid Majnemer if (std::error_code EC = 99358323a97SDavid Majnemer getObject(VirtualAddressPtr, Data, &R->VirtualAddress)) 99458323a97SDavid Majnemer return EC; 99558323a97SDavid Majnemer Res = *VirtualAddressPtr; 996cbe72fc9SDanil Malyshev return object_error::success; 997cbe72fc9SDanil Malyshev } 9988ff24d25SRui Ueyama 999806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1000022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 10018ff24d25SRui Ueyama DataRefImpl Ref; 100244f51e51SDavid Majnemer if (SymbolTable16) 100344f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 100444f51e51SDavid Majnemer else if (SymbolTable32) 100544f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 100644f51e51SDavid Majnemer else 10071f80b0a8SDavid Majnemer return symbol_end(); 10088ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1009022ecdf2SBenjamin Kramer } 10108ff24d25SRui Ueyama 1011db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 10127be76590SOwen Anderson uint64_t &Res) const { 1013022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 1014022ecdf2SBenjamin Kramer Res = R->Type; 1015022ecdf2SBenjamin Kramer return object_error::success; 1016022ecdf2SBenjamin Kramer } 1017e5fd0047SMichael J. Spencer 101827dc8394SAlexey Samsonov const coff_section * 101927dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 102027dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 102171757ef3SMarshall Clow } 102271757ef3SMarshall Clow 102344f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 102444f51e51SDavid Majnemer if (SymbolTable16) 102544f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 102644f51e51SDavid Majnemer if (SymbolTable32) 102744f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 102844f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 102944f51e51SDavid Majnemer } 103044f51e51SDavid Majnemer 103144f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 103244f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 103371757ef3SMarshall Clow } 103471757ef3SMarshall Clow 1035f12b8282SRafael Espindola const coff_relocation * 103627dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 103727dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1038d3e2a76cSMarshall Clow } 1039d3e2a76cSMarshall Clow 104027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 104127dc8394SAlexey Samsonov case COFF::reloc_type: \ 104227dc8394SAlexey Samsonov Res = #reloc_type; \ 104327dc8394SAlexey Samsonov break; 1044e5fd0047SMichael J. Spencer 1045db4ed0bdSRafael Espindola std::error_code 1046db4ed0bdSRafael Espindola COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 1047e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 10488ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 10498ff24d25SRui Ueyama StringRef Res; 105044f51e51SDavid Majnemer switch (getMachine()) { 1051e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 10528ff24d25SRui Ueyama switch (Reloc->Type) { 1053e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1054e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1055e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1056e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1057e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1058e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1059e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1060e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1061e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1062e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1063e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1064e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1065e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1066e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1067e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1068e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1069e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1070e5fd0047SMichael J. Spencer default: 10718ff24d25SRui Ueyama Res = "Unknown"; 1072e5fd0047SMichael J. Spencer } 1073e5fd0047SMichael J. Spencer break; 10745c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 10755c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 10765c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 10775c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 10785c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 10795c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 10805c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 10815c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 10825c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 10835c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 10845c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 10855c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 10865c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 10875c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 10885c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 10895c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 10905c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 10915c503bf4SSaleem Abdulrasool default: 10925c503bf4SSaleem Abdulrasool Res = "Unknown"; 10935c503bf4SSaleem Abdulrasool } 10945c503bf4SSaleem Abdulrasool break; 1095e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 10968ff24d25SRui Ueyama switch (Reloc->Type) { 1097e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1098e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1099e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1100e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1101e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1102e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1103e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1104e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1105e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1106e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1107e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1108e5fd0047SMichael J. Spencer default: 11098ff24d25SRui Ueyama Res = "Unknown"; 1110e5fd0047SMichael J. Spencer } 1111e5fd0047SMichael J. Spencer break; 1112e5fd0047SMichael J. Spencer default: 11138ff24d25SRui Ueyama Res = "Unknown"; 1114e5fd0047SMichael J. Spencer } 11158ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1116e5fd0047SMichael J. Spencer return object_error::success; 1117e5fd0047SMichael J. Spencer } 1118e5fd0047SMichael J. Spencer 1119e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1120e5fd0047SMichael J. Spencer 1121db4ed0bdSRafael Espindola std::error_code 1122db4ed0bdSRafael Espindola COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 1123e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 11248ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11258ff24d25SRui Ueyama DataRefImpl Sym; 112644f51e51SDavid Majnemer ErrorOr<COFFSymbolRef> Symb = getSymbol(Reloc->SymbolTableIndex); 112744f51e51SDavid Majnemer if (std::error_code EC = Symb.getError()) 112844f51e51SDavid Majnemer return EC; 112944f51e51SDavid Majnemer Sym.p = reinterpret_cast<uintptr_t>(Symb->getRawPtr()); 11308ff24d25SRui Ueyama StringRef SymName; 1131db4ed0bdSRafael Espindola if (std::error_code EC = getSymbolName(Sym, SymName)) 1132db4ed0bdSRafael Espindola return EC; 11338ff24d25SRui Ueyama Result.append(SymName.begin(), SymName.end()); 1134e5fd0047SMichael J. Spencer return object_error::success; 1135022ecdf2SBenjamin Kramer } 11368e90adafSMichael J. Spencer 1137c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1138c66d761bSRafael Espindola return !DataDirectory; 1139c66d761bSRafael Espindola } 1140c66d761bSRafael Espindola 1141c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1142c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1143a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1144c2bed429SRui Ueyama } 1145c2bed429SRui Ueyama 11465e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 11475e812afaSRafael Espindola ++Index; 1148c2bed429SRui Ueyama } 1149c2bed429SRui Ueyama 1150db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1151db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 11521e152d5eSRui Ueyama Result = ImportTable + Index; 1153c2bed429SRui Ueyama return object_error::success; 1154c2bed429SRui Ueyama } 1155c2bed429SRui Ueyama 1156861021f9SRui Ueyama static imported_symbol_iterator 115715d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1158861021f9SRui Ueyama uintptr_t Ptr, int Index) { 115915d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1160861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 116115d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1162861021f9SRui Ueyama } 1163861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 116415d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1165861021f9SRui Ueyama } 1166861021f9SRui Ueyama 116715d99359SRui Ueyama static imported_symbol_iterator 116815d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1169861021f9SRui Ueyama uintptr_t IntPtr = 0; 117015d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 117115d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1172861021f9SRui Ueyama } 1173861021f9SRui Ueyama 117415d99359SRui Ueyama static imported_symbol_iterator 117515d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1176861021f9SRui Ueyama uintptr_t IntPtr = 0; 117715d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1178861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1179861021f9SRui Ueyama int Index = 0; 118015d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1181861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1182861021f9SRui Ueyama while (*Entry++) 1183861021f9SRui Ueyama ++Index; 1184861021f9SRui Ueyama } else { 1185861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1186861021f9SRui Ueyama while (*Entry++) 1187861021f9SRui Ueyama ++Index; 1188861021f9SRui Ueyama } 118915d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 119015d99359SRui Ueyama } 119115d99359SRui Ueyama 119215d99359SRui Ueyama imported_symbol_iterator 119315d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 119415d99359SRui Ueyama return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 119515d99359SRui Ueyama OwningObject); 119615d99359SRui Ueyama } 119715d99359SRui Ueyama 119815d99359SRui Ueyama imported_symbol_iterator 119915d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 120015d99359SRui Ueyama return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 120115d99359SRui Ueyama OwningObject); 1202861021f9SRui Ueyama } 1203861021f9SRui Ueyama 1204979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1205979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1206979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1207979fb40bSRui Ueyama } 1208979fb40bSRui Ueyama 1209db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1210c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1211db4ed0bdSRafael Espindola if (std::error_code EC = 12121e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1213a045b73aSRui Ueyama return EC; 1214a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1215c2bed429SRui Ueyama return object_error::success; 1216c2bed429SRui Ueyama } 1217c2bed429SRui Ueyama 12181e152d5eSRui Ueyama std::error_code 12191e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 12201e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 12211e152d5eSRui Ueyama return object_error::success; 12221e152d5eSRui Ueyama } 12231e152d5eSRui Ueyama 12241e152d5eSRui Ueyama std::error_code 12251e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 12261e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 12271e152d5eSRui Ueyama return object_error::success; 12281e152d5eSRui Ueyama } 12291e152d5eSRui Ueyama 1230db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1231c2bed429SRui Ueyama const import_lookup_table_entry32 *&Result) const { 1232c2bed429SRui Ueyama uintptr_t IntPtr = 0; 12331e152d5eSRui Ueyama uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; 12341e152d5eSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1235a045b73aSRui Ueyama return EC; 1236c2bed429SRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 1237c2bed429SRui Ueyama return object_error::success; 1238c2bed429SRui Ueyama } 1239c2bed429SRui Ueyama 124015d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 124115d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 124215d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 124315d99359SRui Ueyama } 124415d99359SRui Ueyama 124515d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 124615d99359SRui Ueyama ++Index; 124715d99359SRui Ueyama } 124815d99359SRui Ueyama 124915d99359SRui Ueyama imported_symbol_iterator 125015d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 125115d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 125215d99359SRui Ueyama OwningObject); 125315d99359SRui Ueyama } 125415d99359SRui Ueyama 125515d99359SRui Ueyama imported_symbol_iterator 125615d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 125715d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 125815d99359SRui Ueyama OwningObject); 125915d99359SRui Ueyama } 126015d99359SRui Ueyama 1261979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1262979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1263979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1264979fb40bSRui Ueyama } 1265979fb40bSRui Ueyama 126615d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 126715d99359SRui Ueyama uintptr_t IntPtr = 0; 126815d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 126915d99359SRui Ueyama return EC; 127015d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 127115d99359SRui Ueyama return object_error::success; 127215d99359SRui Ueyama } 127315d99359SRui Ueyama 12741af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 12751af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 12761af08658SRui Ueyama Result = Table; 12771af08658SRui Ueyama return object_error::success; 12781af08658SRui Ueyama } 12791af08658SRui Ueyama 1280ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1281ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1282ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1283ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1284ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1285ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1286ffa4cebeSRui Ueyama return EC; 1287ffa4cebeSRui Ueyama if (OwningObject->is64()) 1288ffa4cebeSRui Ueyama Result = *reinterpret_cast<const uint64_t *>(IntPtr); 1289ffa4cebeSRui Ueyama else 1290ffa4cebeSRui Ueyama Result = *reinterpret_cast<const uint32_t *>(IntPtr); 1291ffa4cebeSRui Ueyama return object_error::success; 1292ffa4cebeSRui Ueyama } 1293ffa4cebeSRui Ueyama 1294ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1295ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1296ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1297ad882ba8SRui Ueyama } 1298ad882ba8SRui Ueyama 12995e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 13005e812afaSRafael Espindola ++Index; 1301ad882ba8SRui Ueyama } 1302ad882ba8SRui Ueyama 1303da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1304da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1305db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1306da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1307db4ed0bdSRafael Espindola if (std::error_code EC = 1308db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1309da49d0d4SRui Ueyama return EC; 1310da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1311da49d0d4SRui Ueyama return object_error::success; 1312da49d0d4SRui Ueyama } 1313da49d0d4SRui Ueyama 1314e5df6095SRui Ueyama // Returns the starting ordinal number. 1315db4ed0bdSRafael Espindola std::error_code 1316db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1317e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 1318e5df6095SRui Ueyama return object_error::success; 1319e5df6095SRui Ueyama } 1320e5df6095SRui Ueyama 1321ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1322db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1323ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 1324ad882ba8SRui Ueyama return object_error::success; 1325ad882ba8SRui Ueyama } 1326ad882ba8SRui Ueyama 1327ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1328db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1329ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1330db4ed0bdSRafael Espindola if (std::error_code EC = 1331db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1332ad882ba8SRui Ueyama return EC; 133324fc2d64SRui Ueyama const export_address_table_entry *entry = 133424fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1335ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 1336ad882ba8SRui Ueyama return object_error::success; 1337ad882ba8SRui Ueyama } 1338ad882ba8SRui Ueyama 1339ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1340ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1341db4ed0bdSRafael Espindola std::error_code 1342db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1343ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1344db4ed0bdSRafael Espindola if (std::error_code EC = 1345db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1346ad882ba8SRui Ueyama return EC; 1347ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1348ad882ba8SRui Ueyama 1349ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1350ad882ba8SRui Ueyama int Offset = 0; 1351ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1352ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1353ad882ba8SRui Ueyama if (*I != Index) 1354ad882ba8SRui Ueyama continue; 1355db4ed0bdSRafael Espindola if (std::error_code EC = 1356db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1357ad882ba8SRui Ueyama return EC; 1358ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1359db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1360ad882ba8SRui Ueyama return EC; 1361ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1362ad882ba8SRui Ueyama return object_error::success; 1363ad882ba8SRui Ueyama } 1364ad882ba8SRui Ueyama Result = ""; 1365ad882ba8SRui Ueyama return object_error::success; 1366ad882ba8SRui Ueyama } 1367ad882ba8SRui Ueyama 1368861021f9SRui Ueyama bool ImportedSymbolRef:: 1369861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1370861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1371861021f9SRui Ueyama && Index == Other.Index; 1372861021f9SRui Ueyama } 1373861021f9SRui Ueyama 1374861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1375861021f9SRui Ueyama ++Index; 1376861021f9SRui Ueyama } 1377861021f9SRui Ueyama 1378861021f9SRui Ueyama std::error_code 1379861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1380861021f9SRui Ueyama uint32_t RVA; 1381861021f9SRui Ueyama if (Entry32) { 1382861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1383861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 1384861021f9SRui Ueyama return object_error::success; 1385861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1386861021f9SRui Ueyama } else { 1387861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 1388861021f9SRui Ueyama return object_error::success; 1389861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1390861021f9SRui Ueyama } 1391861021f9SRui Ueyama uintptr_t IntPtr = 0; 1392861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1393861021f9SRui Ueyama return EC; 1394861021f9SRui Ueyama // +2 because the first two bytes is hint. 1395861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 1396861021f9SRui Ueyama return object_error::success; 1397861021f9SRui Ueyama } 1398861021f9SRui Ueyama 1399861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1400861021f9SRui Ueyama uint32_t RVA; 1401861021f9SRui Ueyama if (Entry32) { 1402861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1403861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 1404861021f9SRui Ueyama return object_error::success; 1405861021f9SRui Ueyama } 1406861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1407861021f9SRui Ueyama } else { 1408861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1409861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 1410861021f9SRui Ueyama return object_error::success; 1411861021f9SRui Ueyama } 1412861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1413861021f9SRui Ueyama } 1414861021f9SRui Ueyama uintptr_t IntPtr = 0; 1415861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1416861021f9SRui Ueyama return EC; 1417861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 1418861021f9SRui Ueyama return object_error::success; 1419861021f9SRui Ueyama } 1420861021f9SRui Ueyama 1421437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 142248af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1423db4ed0bdSRafael Espindola std::error_code EC; 142448af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1425692410efSRafael Espindola if (EC) 1426692410efSRafael Espindola return EC; 1427437b0d58SRafael Espindola return std::move(Ret); 1428686738e2SRui Ueyama } 1429