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 42e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, 4394751be7SDavid Majnemer const uint64_t Size) { 44e830c60dSDavid Majnemer if (Addr + Size < Addr || Addr + Size < Size || 45e830c60dSDavid Majnemer Addr + Size > uintptr_t(M.getBufferEnd()) || 46e830c60dSDavid Majnemer Addr < uintptr_t(M.getBufferStart())) { 47e830c60dSDavid Majnemer return object_error::unexpected_eof; 48e830c60dSDavid Majnemer } 49e830c60dSDavid Majnemer return object_error::success; 50e830c60dSDavid Majnemer } 51e830c60dSDavid Majnemer 52ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 53ed64342bSRui Ueyama // Returns unexpected_eof if error. 54ed64342bSRui Ueyama template <typename T> 5548af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5658323a97SDavid Majnemer const void *Ptr, 57236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 58ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 59e830c60dSDavid Majnemer if (std::error_code EC = checkOffset(M, Addr, Size)) 60e830c60dSDavid Majnemer return EC; 61ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 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 104236b0ca7SDavid Majnemer assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 1051d6167fdSMichael J. Spencer #ifndef NDEBUG 1061d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1078ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 1081d6167fdSMichael J. Spencer 10944f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11044f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1111d6167fdSMichael J. Spencer #endif 1121d6167fdSMichael J. Spencer 1138ff24d25SRui Ueyama return Addr; 1141d6167fdSMichael J. Spencer } 1151d6167fdSMichael J. Spencer 1168ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1178ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1181d6167fdSMichael J. Spencer 1191d6167fdSMichael J. Spencer # ifndef NDEBUG 1201d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12144f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1221d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1231d6167fdSMichael J. Spencer 1248ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1258ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1261d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1271d6167fdSMichael J. Spencer # endif 1281d6167fdSMichael J. Spencer 1298ff24d25SRui Ueyama return Addr; 1301d6167fdSMichael J. Spencer } 1311d6167fdSMichael J. Spencer 1325e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 133236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 13444f51e51SDavid Majnemer if (SymbolTable16) { 13544f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1368ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 137236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 13844f51e51SDavid Majnemer } else if (SymbolTable32) { 13944f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14044f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 141236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14244f51e51SDavid Majnemer } else { 14344f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14444f51e51SDavid Majnemer } 1451d6167fdSMichael J. Spencer } 1461d6167fdSMichael J. Spencer 147db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, 1481d6167fdSMichael J. Spencer StringRef &Result) const { 14944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1508ff24d25SRui Ueyama return getSymbolName(Symb, Result); 1518e90adafSMichael J. Spencer } 1528e90adafSMichael J. Spencer 153db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, 15475d1cf33SBenjamin Kramer uint64_t &Result) const { 15544f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 156c7d7c6fbSDavid Majnemer 157c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 158c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 159c7d7c6fbSDavid Majnemer return object_error::success; 160c7d7c6fbSDavid Majnemer } 161c7d7c6fbSDavid Majnemer if (Symb.isCommon()) { 162c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 163c7d7c6fbSDavid Majnemer return object_error::success; 164c7d7c6fbSDavid Majnemer } 165c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 166c7d7c6fbSDavid Majnemer if (!COFF::isReservedSectionNumber(SectionNumber)) { 1672617dcceSCraig Topper const coff_section *Section = nullptr; 168c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 1698ff24d25SRui Ueyama return EC; 170e62ab11fSRafael Espindola 17144f51e51SDavid Majnemer Result = Section->VirtualAddress + Symb.getValue(); 172c7d7c6fbSDavid Majnemer return object_error::success; 173c7d7c6fbSDavid Majnemer } 174c7d7c6fbSDavid Majnemer 17544f51e51SDavid Majnemer Result = Symb.getValue(); 17675d1cf33SBenjamin Kramer return object_error::success; 17775d1cf33SBenjamin Kramer } 17875d1cf33SBenjamin Kramer 179db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, 180d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 18144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 182c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 18375d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 18444f51e51SDavid Majnemer 185c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 1867e4b976cSDavid Meyer Result = SymbolRef::ST_Unknown; 18744f51e51SDavid Majnemer } else if (Symb.isFunctionDefinition()) { 18875d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 189c7d7c6fbSDavid Majnemer } else if (Symb.isCommon()) { 190c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Data; 191c7d7c6fbSDavid Majnemer } else if (Symb.isFileRecord()) { 192c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_File; 193c7d7c6fbSDavid Majnemer } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) { 194c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Debug; 195c7d7c6fbSDavid Majnemer } else if (!COFF::isReservedSectionNumber(SectionNumber)) { 1962617dcceSCraig Topper const coff_section *Section = nullptr; 197c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 1988ff24d25SRui Ueyama return EC; 199c7d7c6fbSDavid Majnemer uint32_t Characteristics = Section->Characteristics; 200c7d7c6fbSDavid Majnemer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 201c7d7c6fbSDavid Majnemer Result = SymbolRef::ST_Function; 202c7d7c6fbSDavid Majnemer else if (Characteristics & (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 203c7d7c6fbSDavid Majnemer COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) 20406adfac8SRafael Espindola Result = SymbolRef::ST_Data; 20575d1cf33SBenjamin Kramer } 20675d1cf33SBenjamin Kramer return object_error::success; 20775d1cf33SBenjamin Kramer } 20875d1cf33SBenjamin Kramer 20920122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 21044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 21120122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 21275d1cf33SBenjamin Kramer 213c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2141df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 2151df4b84dSDavid Meyer 216c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2171df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2181df4b84dSDavid Meyer 21944f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2201df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2211df4b84dSDavid Meyer 222c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 223c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 224c7d7c6fbSDavid Majnemer 225c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 226c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 227c7d7c6fbSDavid Majnemer 228c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 229c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 230c7d7c6fbSDavid Majnemer 231c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 232c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 233c7d7c6fbSDavid Majnemer 23420122a43SRafael Espindola return Result; 23501759754SMichael J. Spencer } 23601759754SMichael J. Spencer 237db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, 2381d6167fdSMichael J. Spencer uint64_t &Result) const { 239c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 240c7d7c6fbSDavid Majnemer 241c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) { 242c7d7c6fbSDavid Majnemer Result = UnknownAddressOrSize; 243c7d7c6fbSDavid Majnemer return object_error::success; 244c7d7c6fbSDavid Majnemer } 245c7d7c6fbSDavid Majnemer if (Symb.isCommon()) { 246c7d7c6fbSDavid Majnemer Result = Symb.getValue(); 247c7d7c6fbSDavid Majnemer return object_error::success; 248c7d7c6fbSDavid Majnemer } 24951ff5595SDavid Majnemer 25051ff5595SDavid Majnemer // Let's attempt to get the size of the symbol by looking at the address of 25151ff5595SDavid Majnemer // the symbol after the symbol in question. 25251ff5595SDavid Majnemer uint64_t SymbAddr; 25351ff5595SDavid Majnemer if (std::error_code EC = getSymbolAddress(Ref, SymbAddr)) 25451ff5595SDavid Majnemer return EC; 255c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 25651ff5595SDavid Majnemer if (COFF::isReservedSectionNumber(SectionNumber)) { 25751ff5595SDavid Majnemer // Absolute and debug symbols aren't sorted in any interesting way. 25851ff5595SDavid Majnemer Result = 0; 25951ff5595SDavid Majnemer return object_error::success; 26051ff5595SDavid Majnemer } 26151ff5595SDavid Majnemer const section_iterator SecEnd = section_end(); 26251ff5595SDavid Majnemer uint64_t AfterAddr = UnknownAddressOrSize; 26351ff5595SDavid Majnemer for (const symbol_iterator &SymbI : symbols()) { 26451ff5595SDavid Majnemer section_iterator SecI = SecEnd; 26551ff5595SDavid Majnemer if (std::error_code EC = SymbI->getSection(SecI)) 26651ff5595SDavid Majnemer return EC; 26751ff5595SDavid Majnemer // Check the symbol's section, skip it if it's in the wrong section. 26851ff5595SDavid Majnemer // First, make sure it is in any section. 26951ff5595SDavid Majnemer if (SecI == SecEnd) 27051ff5595SDavid Majnemer continue; 27151ff5595SDavid Majnemer // Second, make sure it is in the same section as the symbol in question. 27251ff5595SDavid Majnemer if (!sectionContainsSymbol(SecI->getRawDataRefImpl(), Ref)) 27351ff5595SDavid Majnemer continue; 27451ff5595SDavid Majnemer uint64_t Addr; 27551ff5595SDavid Majnemer if (std::error_code EC = SymbI->getAddress(Addr)) 27651ff5595SDavid Majnemer return EC; 27751ff5595SDavid Majnemer // We want to compare our symbol in question with the closest possible 27851ff5595SDavid Majnemer // symbol that comes after. 27951ff5595SDavid Majnemer if (AfterAddr > Addr && Addr > SymbAddr) 28051ff5595SDavid Majnemer AfterAddr = Addr; 28151ff5595SDavid Majnemer } 28251ff5595SDavid Majnemer if (AfterAddr == UnknownAddressOrSize) { 28351ff5595SDavid Majnemer // No symbol comes after this one, assume that everything after our symbol 28451ff5595SDavid Majnemer // is part of it. 2852617dcceSCraig Topper const coff_section *Section = nullptr; 286c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 2878ff24d25SRui Ueyama return EC; 2888280fbbfSRafael Espindola Result = Section->SizeOfRawData - Symb.getValue(); 28951ff5595SDavid Majnemer } else { 29051ff5595SDavid Majnemer // Take the difference between our symbol and the symbol that comes after 29151ff5595SDavid Majnemer // our symbol. 29251ff5595SDavid Majnemer Result = AfterAddr - SymbAddr; 2938280fbbfSRafael Espindola } 2948280fbbfSRafael Espindola 2951d6167fdSMichael J. Spencer return object_error::success; 2968e90adafSMichael J. Spencer } 2978e90adafSMichael J. Spencer 298db4ed0bdSRafael Espindola std::error_code 299db4ed0bdSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref, 30032173153SMichael J. Spencer section_iterator &Result) const { 30144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 30244f51e51SDavid Majnemer if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 303b5155a57SRafael Espindola Result = section_end(); 304f078eff3SRui Ueyama } else { 3052617dcceSCraig Topper const coff_section *Sec = nullptr; 30644f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 307db4ed0bdSRafael Espindola return EC; 3088ff24d25SRui Ueyama DataRefImpl Ref; 3098ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 3108ff24d25SRui Ueyama Result = section_iterator(SectionRef(Ref, this)); 31132173153SMichael J. Spencer } 31232173153SMichael J. Spencer return object_error::success; 31332173153SMichael J. Spencer } 31432173153SMichael J. Spencer 3155e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 3168ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3178ff24d25SRui Ueyama Sec += 1; 3188ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 3198e90adafSMichael J. Spencer } 3208e90adafSMichael J. Spencer 321db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 3221d6167fdSMichael J. Spencer StringRef &Result) const { 3238ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3248ff24d25SRui Ueyama return getSectionName(Sec, Result); 3258e90adafSMichael J. Spencer } 3268e90adafSMichael J. Spencer 32780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 3288ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 32980291274SRafael Espindola return Sec->VirtualAddress; 3308e90adafSMichael J. Spencer } 3318e90adafSMichael J. Spencer 33280291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 333a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 3348e90adafSMichael J. Spencer } 3358e90adafSMichael J. Spencer 336db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 3371d6167fdSMichael J. Spencer StringRef &Result) const { 3388ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3399da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 340db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 3419da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3429da9e693SMichael J. Spencer return EC; 3438e90adafSMichael J. Spencer } 3448e90adafSMichael J. Spencer 34580291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3468ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 34780291274SRafael Espindola return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 3487989460aSMichael J. Spencer } 3497989460aSMichael J. Spencer 35080291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3518ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 35280291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3538e90adafSMichael J. Spencer } 3548e90adafSMichael J. Spencer 35580291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3568ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 35780291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 358800619f2SMichael J. Spencer } 359800619f2SMichael J. Spencer 36080291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3618ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 36280291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 363800619f2SMichael J. Spencer } 364800619f2SMichael J. Spencer 36580291274SRafael Espindola bool COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref) const { 366236b0ca7SDavid Majnemer // Sections marked 'Info', 'Remove', or 'Discardable' aren't required for 367236b0ca7SDavid Majnemer // execution. 368236b0ca7SDavid Majnemer const coff_section *Sec = toSec(Ref); 369236b0ca7SDavid Majnemer return !(Sec->Characteristics & 370236b0ca7SDavid Majnemer (COFF::IMAGE_SCN_LNK_INFO | COFF::IMAGE_SCN_LNK_REMOVE | 371236b0ca7SDavid Majnemer COFF::IMAGE_SCN_MEM_DISCARDABLE)); 3722138ef6dSPreston Gurd } 3732138ef6dSPreston Gurd 37480291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3758ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 37680291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3772138ef6dSPreston Gurd } 3782138ef6dSPreston Gurd 37980291274SRafael Espindola bool COFFObjectFile::isSectionZeroInit(DataRefImpl Ref) const { 380236b0ca7SDavid Majnemer const coff_section *Sec = toSec(Ref); 381236b0ca7SDavid Majnemer return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3822138ef6dSPreston Gurd } 3832138ef6dSPreston Gurd 38480291274SRafael Espindola bool COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref) const { 385236b0ca7SDavid Majnemer const coff_section *Sec = toSec(Ref); 386236b0ca7SDavid Majnemer // Check if it's any sort of data section. 387236b0ca7SDavid Majnemer if (!(Sec->Characteristics & (COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 388236b0ca7SDavid Majnemer COFF::IMAGE_SCN_CNT_INITIALIZED_DATA))) 38980291274SRafael Espindola return false; 390236b0ca7SDavid Majnemer // If it's writable or executable or contains code, it isn't read-only data. 391236b0ca7SDavid Majnemer if (Sec->Characteristics & 392236b0ca7SDavid Majnemer (COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | 393236b0ca7SDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE)) 394236b0ca7SDavid Majnemer return false; 395236b0ca7SDavid Majnemer return true; 3963f31fa05SAndrew Kaylor } 3973f31fa05SAndrew Kaylor 39880291274SRafael Espindola bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, 39980291274SRafael Espindola DataRefImpl SymbRef) const { 4008ff24d25SRui Ueyama const coff_section *Sec = toSec(SecRef); 40144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(SymbRef); 402a9260865SRafael Espindola int32_t SecNumber = (Sec - SectionTable) + 1; 40380291274SRafael Espindola return SecNumber == Symb.getSectionNumber(); 404f6f3e81cSBenjamin Kramer } 405f6f3e81cSBenjamin Kramer 406e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 407e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 408e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 409e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 410e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 411e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 412e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 413e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 414e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 415e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 416e830c60dSDavid Majnemer return 0; 417*98fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 418*98fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 419e830c60dSDavid Majnemer } 420e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 421e830c60dSDavid Majnemer } 422e830c60dSDavid Majnemer 42394751be7SDavid Majnemer static const coff_relocation * 42494751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 42594751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 42694751be7SDavid Majnemer if (!NumRelocs) 42794751be7SDavid Majnemer return nullptr; 428827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 42994751be7SDavid Majnemer Base + Sec->PointerToRelocations); 430827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 431827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 432827c8a2bSRui Ueyama // relocations. 433827c8a2bSRui Ueyama begin++; 434827c8a2bSRui Ueyama } 43594751be7SDavid Majnemer if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 43694751be7SDavid Majnemer return nullptr; 43794751be7SDavid Majnemer return begin; 438827c8a2bSRui Ueyama } 43994751be7SDavid Majnemer 44094751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 44194751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 44294751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 44394751be7SDavid Majnemer DataRefImpl Ret; 44494751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 4458ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 446e5fd0047SMichael J. Spencer } 447e5fd0047SMichael J. Spencer 4488ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 4498ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 45094751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 45194751be7SDavid Majnemer if (I) 45294751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 4538ff24d25SRui Ueyama DataRefImpl Ret; 45494751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 4558ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 456e5fd0047SMichael J. Spencer } 457e5fd0047SMichael J. Spencer 458c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 459db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 46044f51e51SDavid Majnemer if (COFFHeader) 461236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 462236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 463236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 46444f51e51SDavid Majnemer return EC; 46544f51e51SDavid Majnemer 46644f51e51SDavid Majnemer if (COFFBigObjHeader) 467236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 468236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 469236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4708ff24d25SRui Ueyama return EC; 471c2bed429SRui Ueyama 472c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 473c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 474c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 475f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 47644f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 477f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 478c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 47948af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4808ff24d25SRui Ueyama return EC; 481c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 482db4ed0bdSRafael Espindola if (std::error_code EC = 48348af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4848ff24d25SRui Ueyama return EC; 485c2bed429SRui Ueyama 486773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 487773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 488773a5795SNico Rieck if (StringTableSize < 4) 489773a5795SNico Rieck StringTableSize = 4; 490773a5795SNico Rieck 491c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 492773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 493c2bed429SRui Ueyama return object_error::parse_failed; 494c2bed429SRui Ueyama return object_error::success; 495c2bed429SRui Ueyama } 496c2bed429SRui Ueyama 497215a586cSRui Ueyama // Returns the file offset for the given VA. 498db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 499b6eb264aSRui Ueyama uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 500b6eb264aSRui Ueyama : (uint64_t)PE32PlusHeader->ImageBase; 501b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 502b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 503b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 504215a586cSRui Ueyama } 505215a586cSRui Ueyama 506c2bed429SRui Ueyama // Returns the file offset for the given RVA. 507db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 50827dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 50927dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 510c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 511c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 512215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 513215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 514c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 515c2bed429SRui Ueyama return object_error::success; 516c2bed429SRui Ueyama } 517c2bed429SRui Ueyama } 518c2bed429SRui Ueyama return object_error::parse_failed; 519c2bed429SRui Ueyama } 520c2bed429SRui Ueyama 521c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 522c2bed429SRui Ueyama // table entry. 523db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 524db4ed0bdSRafael Espindola StringRef &Name) const { 525c2bed429SRui Ueyama uintptr_t IntPtr = 0; 526db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 5278ff24d25SRui Ueyama return EC; 528c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 529c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 530c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 531c2bed429SRui Ueyama return object_error::success; 532c2bed429SRui Ueyama } 533c2bed429SRui Ueyama 534c2bed429SRui Ueyama // Find the import table. 535db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 536c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 537c2bed429SRui Ueyama // the import table, do nothing. 538c2bed429SRui Ueyama const data_directory *DataEntry; 539c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 540c2bed429SRui Ueyama return object_error::success; 541c2bed429SRui Ueyama 542c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 543c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 544c2bed429SRui Ueyama return object_error::success; 545c2bed429SRui Ueyama 546c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 5471e152d5eSRui Ueyama // -1 because the last entry is the null entry. 548c2bed429SRui Ueyama NumberOfImportDirectory = DataEntry->Size / 5491e152d5eSRui Ueyama sizeof(import_directory_table_entry) - 1; 550c2bed429SRui Ueyama 551c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 552c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 553c2bed429SRui Ueyama uintptr_t IntPtr = 0; 554db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5558ff24d25SRui Ueyama return EC; 556c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 557c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 558ad882ba8SRui Ueyama return object_error::success; 559ad882ba8SRui Ueyama } 560c2bed429SRui Ueyama 56115d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 56215d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 56315d99359SRui Ueyama const data_directory *DataEntry; 56415d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 56515d99359SRui Ueyama return object_error::success; 56615d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 56715d99359SRui Ueyama return object_error::success; 56815d99359SRui Ueyama 56915d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 57015d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 57115d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 57215d99359SRui Ueyama 57315d99359SRui Ueyama uintptr_t IntPtr = 0; 57415d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 57515d99359SRui Ueyama return EC; 57615d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 57715d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 57815d99359SRui Ueyama return object_error::success; 57915d99359SRui Ueyama } 58015d99359SRui Ueyama 581ad882ba8SRui Ueyama // Find the export table. 582db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 583ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 584ad882ba8SRui Ueyama // the export table, do nothing. 585ad882ba8SRui Ueyama const data_directory *DataEntry; 586ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 587ad882ba8SRui Ueyama return object_error::success; 588ad882ba8SRui Ueyama 589ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 590ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 591ad882ba8SRui Ueyama return object_error::success; 592ad882ba8SRui Ueyama 593ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 594ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 595db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 596ad882ba8SRui Ueyama return EC; 59724fc2d64SRui Ueyama ExportDirectory = 59824fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 599ad882ba8SRui Ueyama return object_error::success; 600c2bed429SRui Ueyama } 601c2bed429SRui Ueyama 60274e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 60374e85130SRui Ueyama const data_directory *DataEntry; 60474e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 60574e85130SRui Ueyama return object_error::success; 60674e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 60774e85130SRui Ueyama return object_error::success; 60874e85130SRui Ueyama 60974e85130SRui Ueyama uintptr_t IntPtr = 0; 61074e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 61174e85130SRui Ueyama return EC; 61274e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 61374e85130SRui Ueyama IntPtr); 61474e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 61574e85130SRui Ueyama IntPtr + DataEntry->Size); 61674e85130SRui Ueyama return object_error::success; 61774e85130SRui Ueyama } 61874e85130SRui Ueyama 61948af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 62048af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 62144f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 62244f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 62344f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 62444f51e51SDavid Majnemer ImportDirectory(nullptr), NumberOfImportDirectory(0), 62515d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 62674e85130SRui Ueyama ExportDirectory(nullptr), BaseRelocHeader(nullptr), 62774e85130SRui Ueyama BaseRelocEnd(nullptr) { 6281d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 62948af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 630c3f9b5a5SRafael Espindola return; 631ee066fc4SEric Christopher 63282ebd8e3SRui Ueyama // The current location in the file where we are looking at. 63382ebd8e3SRui Ueyama uint64_t CurPtr = 0; 63482ebd8e3SRui Ueyama 63582ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 63682ebd8e3SRui Ueyama // it is placed right after COFF header. 6378ff24d25SRui Ueyama bool HasPEHeader = false; 638ee066fc4SEric Christopher 6391d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 64050267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 641ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 642ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 64350267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 64450267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 64550267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 64682ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 64750267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6488ff24d25SRui Ueyama EC = object_error::parse_failed; 6491d6167fdSMichael J. Spencer return; 6501d6167fdSMichael J. Spencer } 65144f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6528ff24d25SRui Ueyama HasPEHeader = true; 653ee066fc4SEric Christopher } 65450267222SDavid Majnemer } 655ee066fc4SEric Christopher 65648af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 6571d6167fdSMichael J. Spencer return; 65844f51e51SDavid Majnemer 65944f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 66044f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 66144f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 66244f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 66344f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 66444f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 66544f51e51SDavid Majnemer return; 66644f51e51SDavid Majnemer 66744f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 66844f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 66944f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 67044f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 67144f51e51SDavid Majnemer COFFHeader = nullptr; 67244f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 67344f51e51SDavid Majnemer } else { 67444f51e51SDavid Majnemer // It's not a bigobj. 67544f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 67644f51e51SDavid Majnemer } 67744f51e51SDavid Majnemer } 67844f51e51SDavid Majnemer if (COFFHeader) { 67944f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 68044f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 68144f51e51SDavid Majnemer EC = object_error::success; 68282ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 68382ebd8e3SRui Ueyama 68444f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 68544f51e51SDavid Majnemer return; 68644f51e51SDavid Majnemer } 68744f51e51SDavid Majnemer 6888ff24d25SRui Ueyama if (HasPEHeader) { 68910ed9ddcSRui Ueyama const pe32_header *Header; 69048af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 69182ebd8e3SRui Ueyama return; 69210ed9ddcSRui Ueyama 69310ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 69410ed9ddcSRui Ueyama uint64_t DataDirSize; 69550267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 69610ed9ddcSRui Ueyama PE32Header = Header; 69710ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 69810ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 69950267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 70010ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 70110ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 70210ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 70310ed9ddcSRui Ueyama } else { 70410ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 70510ed9ddcSRui Ueyama EC = object_error::parse_failed; 706ed64342bSRui Ueyama return; 707ed64342bSRui Ueyama } 70848af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 70910ed9ddcSRui Ueyama return; 71082ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 71182ebd8e3SRui Ueyama } 7121d6167fdSMichael J. Spencer 71348af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 714236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7151d6167fdSMichael J. Spencer return; 7161d6167fdSMichael J. Spencer 717c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 718236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 7198ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 7201d6167fdSMichael J. Spencer return; 721236b0ca7SDavid Majnemer } else { 722236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 723236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 724236b0ca7SDavid Majnemer EC = object_error::parse_failed; 725236b0ca7SDavid Majnemer return; 726236b0ca7SDavid Majnemer } 727236b0ca7SDavid Majnemer } 7288e90adafSMichael J. Spencer 729c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7308ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 731ed64342bSRui Ueyama return; 73215d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 73315d99359SRui Ueyama return; 7341d6167fdSMichael J. Spencer 735ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7368ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 737ad882ba8SRui Ueyama return; 738ad882ba8SRui Ueyama 73974e85130SRui Ueyama // Initialize the pointer to the base relocation table. 74074e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 74174e85130SRui Ueyama return; 74274e85130SRui Ueyama 7438ff24d25SRui Ueyama EC = object_error::success; 7448e90adafSMichael J. Spencer } 7458e90adafSMichael J. Spencer 746f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 7478ff24d25SRui Ueyama DataRefImpl Ret; 74844f51e51SDavid Majnemer Ret.p = getSymbolTable(); 749f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7508e90adafSMichael J. Spencer } 7518e90adafSMichael J. Spencer 752f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 7538e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 7548ff24d25SRui Ueyama DataRefImpl Ret; 7558ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 756f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7578e90adafSMichael J. Spencer } 7588e90adafSMichael J. Spencer 759bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 760a045b73aSRui Ueyama return import_directory_iterator( 761a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 762c2bed429SRui Ueyama } 763c2bed429SRui Ueyama 764bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 765a045b73aSRui Ueyama return import_directory_iterator( 766a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 767c2bed429SRui Ueyama } 768c429b80dSDavid Meyer 76915d99359SRui Ueyama delay_import_directory_iterator 77015d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 77115d99359SRui Ueyama return delay_import_directory_iterator( 77215d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 77315d99359SRui Ueyama } 77415d99359SRui Ueyama 77515d99359SRui Ueyama delay_import_directory_iterator 77615d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 77715d99359SRui Ueyama return delay_import_directory_iterator( 77815d99359SRui Ueyama DelayImportDirectoryEntryRef( 77915d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 78015d99359SRui Ueyama } 78115d99359SRui Ueyama 782ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 783ad882ba8SRui Ueyama return export_directory_iterator( 784ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 785ad882ba8SRui Ueyama } 786ad882ba8SRui Ueyama 787ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 7882617dcceSCraig Topper if (!ExportDirectory) 7892617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 7908ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 791ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 7928ff24d25SRui Ueyama return export_directory_iterator(Ref); 793ad882ba8SRui Ueyama } 794ad882ba8SRui Ueyama 795b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 7968ff24d25SRui Ueyama DataRefImpl Ret; 7978ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 7988ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7998e90adafSMichael J. Spencer } 8008e90adafSMichael J. Spencer 801b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8028ff24d25SRui Ueyama DataRefImpl Ret; 80344f51e51SDavid Majnemer int NumSections = 80444f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8058ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8068ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8078e90adafSMichael J. Spencer } 8088e90adafSMichael J. Spencer 80974e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 81074e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 81174e85130SRui Ueyama } 81274e85130SRui Ueyama 81374e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 81474e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 81574e85130SRui Ueyama } 81674e85130SRui Ueyama 8178e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 8180324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 8198e90adafSMichael J. Spencer } 8208e90adafSMichael J. Spencer 8218e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 82244f51e51SDavid Majnemer switch(getMachine()) { 8238e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8248e90adafSMichael J. Spencer return "COFF-i386"; 8258e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8268e90adafSMichael J. Spencer return "COFF-x86-64"; 8279b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8289b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8298e90adafSMichael J. Spencer default: 8308e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8318e90adafSMichael J. Spencer } 8328e90adafSMichael J. Spencer } 8338e90adafSMichael J. Spencer 8348e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 83544f51e51SDavid Majnemer switch (getMachine()) { 8368e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8378e90adafSMichael J. Spencer return Triple::x86; 8388e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8398e90adafSMichael J. Spencer return Triple::x86_64; 8409b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8419b7c0af2SSaleem Abdulrasool return Triple::thumb; 8428e90adafSMichael J. Spencer default: 8438e90adafSMichael J. Spencer return Triple::UnknownArch; 8448e90adafSMichael J. Spencer } 8458e90adafSMichael J. Spencer } 8468e90adafSMichael J. Spencer 847979fb40bSRui Ueyama iterator_range<import_directory_iterator> 848979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 849979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 850979fb40bSRui Ueyama } 851979fb40bSRui Ueyama 852979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 853979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 854979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 855979fb40bSRui Ueyama delay_import_directory_end()); 856979fb40bSRui Ueyama } 857979fb40bSRui Ueyama 858979fb40bSRui Ueyama iterator_range<export_directory_iterator> 859979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 860979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 861979fb40bSRui Ueyama } 862979fb40bSRui Ueyama 86374e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 86474e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 86574e85130SRui Ueyama } 86674e85130SRui Ueyama 867db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 86882ebd8e3SRui Ueyama Res = PE32Header; 86989a7a5eaSMichael J. Spencer return object_error::success; 87089a7a5eaSMichael J. Spencer } 87189a7a5eaSMichael J. Spencer 872db4ed0bdSRafael Espindola std::error_code 87310ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 87410ed9ddcSRui Ueyama Res = PE32PlusHeader; 87510ed9ddcSRui Ueyama return object_error::success; 87610ed9ddcSRui Ueyama } 87710ed9ddcSRui Ueyama 878db4ed0bdSRafael Espindola std::error_code 879db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 880ed64342bSRui Ueyama const data_directory *&Res) const { 881ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 882f69b0585SDavid Majnemer if (!DataDirectory) { 883f69b0585SDavid Majnemer Res = nullptr; 88410ed9ddcSRui Ueyama return object_error::parse_failed; 885f69b0585SDavid Majnemer } 88610ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 88710ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 88810ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 889f69b0585SDavid Majnemer if (Index >= NumEnt) { 890f69b0585SDavid Majnemer Res = nullptr; 891ed64342bSRui Ueyama return object_error::parse_failed; 892f69b0585SDavid Majnemer } 8938ff24d25SRui Ueyama Res = &DataDirectory[Index]; 894ed64342bSRui Ueyama return object_error::success; 895ed64342bSRui Ueyama } 896ed64342bSRui Ueyama 897db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 8981d6167fdSMichael J. Spencer const coff_section *&Result) const { 8992617dcceSCraig Topper Result = nullptr; 900236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 901236b0ca7SDavid Majnemer return object_error::success; 902236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9031d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9048ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9051d6167fdSMichael J. Spencer return object_error::success; 9068e90adafSMichael J. Spencer } 907236b0ca7SDavid Majnemer return object_error::parse_failed; 908236b0ca7SDavid Majnemer } 9098e90adafSMichael J. Spencer 910db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9111d6167fdSMichael J. Spencer StringRef &Result) const { 9121d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9131d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9141d6167fdSMichael J. Spencer return object_error::parse_failed; 9158ff24d25SRui Ueyama if (Offset >= StringTableSize) 9161d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9178ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9181d6167fdSMichael J. Spencer return object_error::success; 9198e90adafSMichael J. Spencer } 920022ecdf2SBenjamin Kramer 92144f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 92289a7a5eaSMichael J. Spencer StringRef &Res) const { 92389a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 92444f51e51SDavid Majnemer if (Symbol.getStringTableOffset().Zeroes == 0) { 92544f51e51SDavid Majnemer uint32_t Offset = Symbol.getStringTableOffset().Offset; 926db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Res)) 9278ff24d25SRui Ueyama return EC; 92889a7a5eaSMichael J. Spencer return object_error::success; 92989a7a5eaSMichael J. Spencer } 93089a7a5eaSMichael J. Spencer 93144f51e51SDavid Majnemer if (Symbol.getShortName()[COFF::NameSize - 1] == 0) 93289a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 93344f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName()); 93489a7a5eaSMichael J. Spencer else 93589a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 93644f51e51SDavid Majnemer Res = StringRef(Symbol.getShortName(), COFF::NameSize); 93789a7a5eaSMichael J. Spencer return object_error::success; 93889a7a5eaSMichael J. Spencer } 93989a7a5eaSMichael J. Spencer 94044f51e51SDavid Majnemer ArrayRef<uint8_t> 94144f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 9422617dcceSCraig Topper const uint8_t *Aux = nullptr; 94371757ef3SMarshall Clow 94444f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 94544f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 94671757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 94744f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 94871757ef3SMarshall Clow # ifndef NDEBUG 9498ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 9508ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 95144f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 95244f51e51SDavid Majnemer Offset >= 95344f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 95471757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 95571757ef3SMarshall Clow 95644f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 95744f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 95871757ef3SMarshall Clow # endif 959bfb85e67SMarshall Clow } 96044f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 96171757ef3SMarshall Clow } 96271757ef3SMarshall Clow 963db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 96453c2d547SMichael J. Spencer StringRef &Res) const { 96553c2d547SMichael J. Spencer StringRef Name; 96644f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 96753c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 96853c2d547SMichael J. Spencer Name = Sec->Name; 96953c2d547SMichael J. Spencer else 97053c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 97144f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 97253c2d547SMichael J. Spencer 97353c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 9742314b3deSDavid Majnemer if (Name.startswith("/")) { 97553c2d547SMichael J. Spencer uint32_t Offset; 9762314b3deSDavid Majnemer if (Name.startswith("//")) { 9779d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 9789d2c15efSNico Rieck return object_error::parse_failed; 9799d2c15efSNico Rieck } else { 98053c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 98153c2d547SMichael J. Spencer return object_error::parse_failed; 9829d2c15efSNico Rieck } 983db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 9848ff24d25SRui Ueyama return EC; 98553c2d547SMichael J. Spencer } 98653c2d547SMichael J. Spencer 98753c2d547SMichael J. Spencer Res = Name; 98853c2d547SMichael J. Spencer return object_error::success; 98953c2d547SMichael J. Spencer } 99053c2d547SMichael J. Spencer 991a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 992a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 993a9ee5c06SDavid Majnemer // whether or not we have an executable image. 994a9ee5c06SDavid Majnemer // 995a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 996a9ee5c06SDavid Majnemer // VirtualSize is always zero. 997a9ee5c06SDavid Majnemer // 998a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 999a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1000a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1001a9ee5c06SDavid Majnemer // considered to be zero. 1002a9ee5c06SDavid Majnemer uint32_t SectionSize; 1003a9ee5c06SDavid Majnemer if (Sec->VirtualSize) 1004a9ee5c06SDavid Majnemer SectionSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1005a9ee5c06SDavid Majnemer else 1006a9ee5c06SDavid Majnemer SectionSize = Sec->SizeOfRawData; 1007a9ee5c06SDavid Majnemer 1008a9ee5c06SDavid Majnemer return SectionSize; 1009a9ee5c06SDavid Majnemer } 1010a9ee5c06SDavid Majnemer 1011db4ed0bdSRafael Espindola std::error_code 1012db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10139da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1014dd9cff2eSDavid Majnemer // PointerToRawData and SizeOfRawData won't make sense for BSS sections, 1015dd9cff2eSDavid Majnemer // don't do anything interesting for them. 1016dac39857SDavid Majnemer assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && 1017dac39857SDavid Majnemer "BSS sections don't have contents!"); 10189da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10199da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10209da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10219da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1022a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1023e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10249da9e693SMichael J. Spencer return object_error::parse_failed; 1025a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10269da9e693SMichael J. Spencer return object_error::success; 10279da9e693SMichael J. Spencer } 10289da9e693SMichael J. Spencer 1029022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1030e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1031022ecdf2SBenjamin Kramer } 10328ff24d25SRui Ueyama 10335e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1034e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1035e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1036022ecdf2SBenjamin Kramer } 10378ff24d25SRui Ueyama 1038db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 1039022ecdf2SBenjamin Kramer uint64_t &Res) const { 10401e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 1041022ecdf2SBenjamin Kramer } 10428ff24d25SRui Ueyama 1043db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 1044cbe72fc9SDanil Malyshev uint64_t &Res) const { 104558323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 104658323a97SDavid Majnemer const support::ulittle32_t *VirtualAddressPtr; 104758323a97SDavid Majnemer if (std::error_code EC = 104858323a97SDavid Majnemer getObject(VirtualAddressPtr, Data, &R->VirtualAddress)) 104958323a97SDavid Majnemer return EC; 105058323a97SDavid Majnemer Res = *VirtualAddressPtr; 1051cbe72fc9SDanil Malyshev return object_error::success; 1052cbe72fc9SDanil Malyshev } 10538ff24d25SRui Ueyama 1054806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1055022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 10568ff24d25SRui Ueyama DataRefImpl Ref; 1057236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1058236b0ca7SDavid Majnemer return symbol_end(); 105944f51e51SDavid Majnemer if (SymbolTable16) 106044f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 106144f51e51SDavid Majnemer else if (SymbolTable32) 106244f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 106344f51e51SDavid Majnemer else 1064c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 10658ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1066022ecdf2SBenjamin Kramer } 10678ff24d25SRui Ueyama 1068db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 10697be76590SOwen Anderson uint64_t &Res) const { 1070022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 1071022ecdf2SBenjamin Kramer Res = R->Type; 1072022ecdf2SBenjamin Kramer return object_error::success; 1073022ecdf2SBenjamin Kramer } 1074e5fd0047SMichael J. Spencer 107527dc8394SAlexey Samsonov const coff_section * 107627dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 107727dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 107871757ef3SMarshall Clow } 107971757ef3SMarshall Clow 108044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 108144f51e51SDavid Majnemer if (SymbolTable16) 108244f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 108344f51e51SDavid Majnemer if (SymbolTable32) 108444f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 108544f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 108644f51e51SDavid Majnemer } 108744f51e51SDavid Majnemer 108844f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 108944f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 109071757ef3SMarshall Clow } 109171757ef3SMarshall Clow 1092f12b8282SRafael Espindola const coff_relocation * 109327dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 109427dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1095d3e2a76cSMarshall Clow } 1096d3e2a76cSMarshall Clow 109727dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 109827dc8394SAlexey Samsonov case COFF::reloc_type: \ 109927dc8394SAlexey Samsonov Res = #reloc_type; \ 110027dc8394SAlexey Samsonov break; 1101e5fd0047SMichael J. Spencer 1102db4ed0bdSRafael Espindola std::error_code 1103db4ed0bdSRafael Espindola COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 1104e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 11058ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11068ff24d25SRui Ueyama StringRef Res; 110744f51e51SDavid Majnemer switch (getMachine()) { 1108e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11098ff24d25SRui Ueyama switch (Reloc->Type) { 1110e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1111e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1112e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1113e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1114e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1115e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1116e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1117e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1118e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1119e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1120e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1121e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1122e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1123e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1124e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1125e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1126e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1127e5fd0047SMichael J. Spencer default: 11288ff24d25SRui Ueyama Res = "Unknown"; 1129e5fd0047SMichael J. Spencer } 1130e5fd0047SMichael J. Spencer break; 11315c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11325c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 11335c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11345c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11355c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11365c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11375c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11385c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 11395c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 11405c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 11415c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 11425c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 11435c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 11445c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 11455c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 11465c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 11475c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 11485c503bf4SSaleem Abdulrasool default: 11495c503bf4SSaleem Abdulrasool Res = "Unknown"; 11505c503bf4SSaleem Abdulrasool } 11515c503bf4SSaleem Abdulrasool break; 1152e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 11538ff24d25SRui Ueyama switch (Reloc->Type) { 1154e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1155e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1156e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1157e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1158e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1159e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1160e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1161e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1162e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1163e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1164e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1165e5fd0047SMichael J. Spencer default: 11668ff24d25SRui Ueyama Res = "Unknown"; 1167e5fd0047SMichael J. Spencer } 1168e5fd0047SMichael J. Spencer break; 1169e5fd0047SMichael J. Spencer default: 11708ff24d25SRui Ueyama Res = "Unknown"; 1171e5fd0047SMichael J. Spencer } 11728ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1173e5fd0047SMichael J. Spencer return object_error::success; 1174e5fd0047SMichael J. Spencer } 1175e5fd0047SMichael J. Spencer 1176e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1177e5fd0047SMichael J. Spencer 1178db4ed0bdSRafael Espindola std::error_code 1179db4ed0bdSRafael Espindola COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 1180e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 11818ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11828ff24d25SRui Ueyama DataRefImpl Sym; 118344f51e51SDavid Majnemer ErrorOr<COFFSymbolRef> Symb = getSymbol(Reloc->SymbolTableIndex); 118444f51e51SDavid Majnemer if (std::error_code EC = Symb.getError()) 118544f51e51SDavid Majnemer return EC; 118644f51e51SDavid Majnemer Sym.p = reinterpret_cast<uintptr_t>(Symb->getRawPtr()); 11878ff24d25SRui Ueyama StringRef SymName; 1188db4ed0bdSRafael Espindola if (std::error_code EC = getSymbolName(Sym, SymName)) 1189db4ed0bdSRafael Espindola return EC; 11908ff24d25SRui Ueyama Result.append(SymName.begin(), SymName.end()); 1191e5fd0047SMichael J. Spencer return object_error::success; 1192022ecdf2SBenjamin Kramer } 11938e90adafSMichael J. Spencer 1194c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1195c66d761bSRafael Espindola return !DataDirectory; 1196c66d761bSRafael Espindola } 1197c66d761bSRafael Espindola 1198c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1199c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1200a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1201c2bed429SRui Ueyama } 1202c2bed429SRui Ueyama 12035e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12045e812afaSRafael Espindola ++Index; 1205c2bed429SRui Ueyama } 1206c2bed429SRui Ueyama 1207db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1208db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 12091e152d5eSRui Ueyama Result = ImportTable + Index; 1210c2bed429SRui Ueyama return object_error::success; 1211c2bed429SRui Ueyama } 1212c2bed429SRui Ueyama 1213861021f9SRui Ueyama static imported_symbol_iterator 121415d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1215861021f9SRui Ueyama uintptr_t Ptr, int Index) { 121615d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1217861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 121815d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1219861021f9SRui Ueyama } 1220861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 122115d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1222861021f9SRui Ueyama } 1223861021f9SRui Ueyama 122415d99359SRui Ueyama static imported_symbol_iterator 122515d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1226861021f9SRui Ueyama uintptr_t IntPtr = 0; 122715d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 122815d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1229861021f9SRui Ueyama } 1230861021f9SRui Ueyama 123115d99359SRui Ueyama static imported_symbol_iterator 123215d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1233861021f9SRui Ueyama uintptr_t IntPtr = 0; 123415d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1235861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1236861021f9SRui Ueyama int Index = 0; 123715d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1238861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1239861021f9SRui Ueyama while (*Entry++) 1240861021f9SRui Ueyama ++Index; 1241861021f9SRui Ueyama } else { 1242861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1243861021f9SRui Ueyama while (*Entry++) 1244861021f9SRui Ueyama ++Index; 1245861021f9SRui Ueyama } 124615d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 124715d99359SRui Ueyama } 124815d99359SRui Ueyama 124915d99359SRui Ueyama imported_symbol_iterator 125015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 125115d99359SRui Ueyama return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 125215d99359SRui Ueyama OwningObject); 125315d99359SRui Ueyama } 125415d99359SRui Ueyama 125515d99359SRui Ueyama imported_symbol_iterator 125615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 125715d99359SRui Ueyama return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 125815d99359SRui Ueyama OwningObject); 1259861021f9SRui Ueyama } 1260861021f9SRui Ueyama 1261979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1262979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1263979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1264979fb40bSRui Ueyama } 1265979fb40bSRui Ueyama 1266db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1267c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1268db4ed0bdSRafael Espindola if (std::error_code EC = 12691e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1270a045b73aSRui Ueyama return EC; 1271a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1272c2bed429SRui Ueyama return object_error::success; 1273c2bed429SRui Ueyama } 1274c2bed429SRui Ueyama 12751e152d5eSRui Ueyama std::error_code 12761e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 12771e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 12781e152d5eSRui Ueyama return object_error::success; 12791e152d5eSRui Ueyama } 12801e152d5eSRui Ueyama 12811e152d5eSRui Ueyama std::error_code 12821e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 12831e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 12841e152d5eSRui Ueyama return object_error::success; 12851e152d5eSRui Ueyama } 12861e152d5eSRui Ueyama 1287db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1288c2bed429SRui Ueyama const import_lookup_table_entry32 *&Result) const { 1289c2bed429SRui Ueyama uintptr_t IntPtr = 0; 12901e152d5eSRui Ueyama uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; 12911e152d5eSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1292a045b73aSRui Ueyama return EC; 1293c2bed429SRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 1294c2bed429SRui Ueyama return object_error::success; 1295c2bed429SRui Ueyama } 1296c2bed429SRui Ueyama 129715d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 129815d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 129915d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 130015d99359SRui Ueyama } 130115d99359SRui Ueyama 130215d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 130315d99359SRui Ueyama ++Index; 130415d99359SRui Ueyama } 130515d99359SRui Ueyama 130615d99359SRui Ueyama imported_symbol_iterator 130715d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 130815d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 130915d99359SRui Ueyama OwningObject); 131015d99359SRui Ueyama } 131115d99359SRui Ueyama 131215d99359SRui Ueyama imported_symbol_iterator 131315d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 131415d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 131515d99359SRui Ueyama OwningObject); 131615d99359SRui Ueyama } 131715d99359SRui Ueyama 1318979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1319979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1320979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1321979fb40bSRui Ueyama } 1322979fb40bSRui Ueyama 132315d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 132415d99359SRui Ueyama uintptr_t IntPtr = 0; 132515d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 132615d99359SRui Ueyama return EC; 132715d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 132815d99359SRui Ueyama return object_error::success; 132915d99359SRui Ueyama } 133015d99359SRui Ueyama 13311af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 13321af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 13331af08658SRui Ueyama Result = Table; 13341af08658SRui Ueyama return object_error::success; 13351af08658SRui Ueyama } 13361af08658SRui Ueyama 1337ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1338ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1339ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1340ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1341ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1342ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1343ffa4cebeSRui Ueyama return EC; 1344ffa4cebeSRui Ueyama if (OwningObject->is64()) 13455dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1346ffa4cebeSRui Ueyama else 13475dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 1348ffa4cebeSRui Ueyama return object_error::success; 1349ffa4cebeSRui Ueyama } 1350ffa4cebeSRui Ueyama 1351ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1352ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1353ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1354ad882ba8SRui Ueyama } 1355ad882ba8SRui Ueyama 13565e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 13575e812afaSRafael Espindola ++Index; 1358ad882ba8SRui Ueyama } 1359ad882ba8SRui Ueyama 1360da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1361da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1362db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1363da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1364db4ed0bdSRafael Espindola if (std::error_code EC = 1365db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1366da49d0d4SRui Ueyama return EC; 1367da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1368da49d0d4SRui Ueyama return object_error::success; 1369da49d0d4SRui Ueyama } 1370da49d0d4SRui Ueyama 1371e5df6095SRui Ueyama // Returns the starting ordinal number. 1372db4ed0bdSRafael Espindola std::error_code 1373db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1374e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 1375e5df6095SRui Ueyama return object_error::success; 1376e5df6095SRui Ueyama } 1377e5df6095SRui Ueyama 1378ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1379db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1380ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 1381ad882ba8SRui Ueyama return object_error::success; 1382ad882ba8SRui Ueyama } 1383ad882ba8SRui Ueyama 1384ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1385db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1386ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1387db4ed0bdSRafael Espindola if (std::error_code EC = 1388db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1389ad882ba8SRui Ueyama return EC; 139024fc2d64SRui Ueyama const export_address_table_entry *entry = 139124fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1392ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 1393ad882ba8SRui Ueyama return object_error::success; 1394ad882ba8SRui Ueyama } 1395ad882ba8SRui Ueyama 1396ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1397ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1398db4ed0bdSRafael Espindola std::error_code 1399db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1400ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1401db4ed0bdSRafael Espindola if (std::error_code EC = 1402db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1403ad882ba8SRui Ueyama return EC; 1404ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1405ad882ba8SRui Ueyama 1406ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1407ad882ba8SRui Ueyama int Offset = 0; 1408ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1409ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1410ad882ba8SRui Ueyama if (*I != Index) 1411ad882ba8SRui Ueyama continue; 1412db4ed0bdSRafael Espindola if (std::error_code EC = 1413db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1414ad882ba8SRui Ueyama return EC; 1415ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1416db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1417ad882ba8SRui Ueyama return EC; 1418ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1419ad882ba8SRui Ueyama return object_error::success; 1420ad882ba8SRui Ueyama } 1421ad882ba8SRui Ueyama Result = ""; 1422ad882ba8SRui Ueyama return object_error::success; 1423ad882ba8SRui Ueyama } 1424ad882ba8SRui Ueyama 1425861021f9SRui Ueyama bool ImportedSymbolRef:: 1426861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1427861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1428861021f9SRui Ueyama && Index == Other.Index; 1429861021f9SRui Ueyama } 1430861021f9SRui Ueyama 1431861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1432861021f9SRui Ueyama ++Index; 1433861021f9SRui Ueyama } 1434861021f9SRui Ueyama 1435861021f9SRui Ueyama std::error_code 1436861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1437861021f9SRui Ueyama uint32_t RVA; 1438861021f9SRui Ueyama if (Entry32) { 1439861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1440861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 1441861021f9SRui Ueyama return object_error::success; 1442861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1443861021f9SRui Ueyama } else { 1444861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 1445861021f9SRui Ueyama return object_error::success; 1446861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1447861021f9SRui Ueyama } 1448861021f9SRui Ueyama uintptr_t IntPtr = 0; 1449861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1450861021f9SRui Ueyama return EC; 1451861021f9SRui Ueyama // +2 because the first two bytes is hint. 1452861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 1453861021f9SRui Ueyama return object_error::success; 1454861021f9SRui Ueyama } 1455861021f9SRui Ueyama 1456861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1457861021f9SRui Ueyama uint32_t RVA; 1458861021f9SRui Ueyama if (Entry32) { 1459861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1460861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 1461861021f9SRui Ueyama return object_error::success; 1462861021f9SRui Ueyama } 1463861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1464861021f9SRui Ueyama } else { 1465861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1466861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 1467861021f9SRui Ueyama return object_error::success; 1468861021f9SRui Ueyama } 1469861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1470861021f9SRui Ueyama } 1471861021f9SRui Ueyama uintptr_t IntPtr = 0; 1472861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1473861021f9SRui Ueyama return EC; 1474861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 1475861021f9SRui Ueyama return object_error::success; 1476861021f9SRui Ueyama } 1477861021f9SRui Ueyama 1478437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 147948af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1480db4ed0bdSRafael Espindola std::error_code EC; 148148af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1482692410efSRafael Espindola if (EC) 1483692410efSRafael Espindola return EC; 1484437b0d58SRafael Espindola return std::move(Ret); 1485686738e2SRui Ueyama } 148674e85130SRui Ueyama 148774e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 148874e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 148974e85130SRui Ueyama } 149074e85130SRui Ueyama 149174e85130SRui Ueyama void BaseRelocRef::moveNext() { 149274e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 149374e85130SRui Ueyama // size of the header itself. 149474e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1495970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 149674e85130SRui Ueyama if (Size == Header->BlockSize) { 149774e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 149874e85130SRui Ueyama // consists of the header followed by entries. The header contains 149974e85130SRui Ueyama // how many entories will follow. When we reach the end of the 150074e85130SRui Ueyama // current block, proceed to the next block. 150174e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 150274e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 150374e85130SRui Ueyama Index = 0; 150474e85130SRui Ueyama } else { 150574e85130SRui Ueyama ++Index; 150674e85130SRui Ueyama } 150774e85130SRui Ueyama } 150874e85130SRui Ueyama 150974e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 151074e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 151174e85130SRui Ueyama Type = Entry[Index].getType(); 151274e85130SRui Ueyama return object_error::success; 151374e85130SRui Ueyama } 151474e85130SRui Ueyama 151574e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 151674e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 151774e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 151874e85130SRui Ueyama return object_error::success; 151974e85130SRui Ueyama } 1520