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" 196a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h" 20f078eff3SRui Ueyama #include "llvm/Support/COFF.h" 21c2bed429SRui Ueyama #include "llvm/Support/Debug.h" 22c2bed429SRui Ueyama #include "llvm/Support/raw_ostream.h" 23981af002SWill Dietz #include <cctype> 249d2c15efSNico Rieck #include <limits> 258e90adafSMichael J. Spencer 268e90adafSMichael J. Spencer using namespace llvm; 278e90adafSMichael J. Spencer using namespace object; 288e90adafSMichael J. Spencer 298e90adafSMichael J. Spencer using support::ulittle16_t; 308e90adafSMichael J. Spencer using support::ulittle32_t; 31861021f9SRui Ueyama using support::ulittle64_t; 328e90adafSMichael J. Spencer using support::little16_t; 338e90adafSMichael J. Spencer 341d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 3548af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 36c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 378ff24d25SRui Ueyama EC = object_error::unexpected_eof; 381d6167fdSMichael J. Spencer return false; 391d6167fdSMichael J. Spencer } 401d6167fdSMichael J. Spencer return true; 418e90adafSMichael J. Spencer } 428e90adafSMichael J. Spencer 43e830c60dSDavid Majnemer static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, 4494751be7SDavid Majnemer const uint64_t Size) { 45e830c60dSDavid Majnemer if (Addr + Size < Addr || Addr + Size < Size || 46e830c60dSDavid Majnemer Addr + Size > uintptr_t(M.getBufferEnd()) || 47e830c60dSDavid Majnemer Addr < uintptr_t(M.getBufferStart())) { 48e830c60dSDavid Majnemer return object_error::unexpected_eof; 49e830c60dSDavid Majnemer } 507d099195SRui Ueyama return std::error_code(); 51e830c60dSDavid Majnemer } 52e830c60dSDavid Majnemer 53ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 54ed64342bSRui Ueyama // Returns unexpected_eof if error. 55ed64342bSRui Ueyama template <typename T> 5648af1c2aSRafael Espindola static std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5758323a97SDavid Majnemer const void *Ptr, 58236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 59ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 60e830c60dSDavid Majnemer if (std::error_code EC = checkOffset(M, Addr, Size)) 61e830c60dSDavid Majnemer return EC; 62ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 637d099195SRui Ueyama return std::error_code(); 641d6167fdSMichael J. Spencer } 651d6167fdSMichael J. Spencer 669d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 679d2c15efSNico Rieck // prefixed slashes. 689d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 699d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 709d2c15efSNico Rieck if (Str.size() > 6) 719d2c15efSNico Rieck return true; 729d2c15efSNico Rieck 739d2c15efSNico Rieck uint64_t Value = 0; 749d2c15efSNico Rieck while (!Str.empty()) { 759d2c15efSNico Rieck unsigned CharVal; 769d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 779d2c15efSNico Rieck CharVal = Str[0] - 'A'; 789d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 799d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 809d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 819d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 829d2c15efSNico Rieck else if (Str[0] == '+') // 62 835500b07cSRui Ueyama CharVal = 62; 849d2c15efSNico Rieck else if (Str[0] == '/') // 63 855500b07cSRui Ueyama CharVal = 63; 869d2c15efSNico Rieck else 879d2c15efSNico Rieck return true; 889d2c15efSNico Rieck 899d2c15efSNico Rieck Value = (Value * 64) + CharVal; 909d2c15efSNico Rieck Str = Str.substr(1); 919d2c15efSNico Rieck } 929d2c15efSNico Rieck 939d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 949d2c15efSNico Rieck return true; 959d2c15efSNico Rieck 969d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 979d2c15efSNico Rieck return false; 989d2c15efSNico Rieck } 999d2c15efSNico Rieck 10044f51e51SDavid Majnemer template <typename coff_symbol_type> 10144f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10244f51e51SDavid Majnemer const coff_symbol_type *Addr = 10344f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1041d6167fdSMichael J. Spencer 105236b0ca7SDavid Majnemer assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 1061d6167fdSMichael J. Spencer #ifndef NDEBUG 1071d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 1088ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 1091d6167fdSMichael J. Spencer 11044f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11144f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1121d6167fdSMichael J. Spencer #endif 1131d6167fdSMichael J. Spencer 1148ff24d25SRui Ueyama return Addr; 1151d6167fdSMichael J. Spencer } 1161d6167fdSMichael J. Spencer 1178ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1188ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1191d6167fdSMichael J. Spencer 1201d6167fdSMichael J. Spencer # ifndef NDEBUG 1211d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12244f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1231d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1241d6167fdSMichael J. Spencer 1258ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 1268ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1271d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1281d6167fdSMichael J. Spencer # endif 1291d6167fdSMichael J. Spencer 1308ff24d25SRui Ueyama return Addr; 1311d6167fdSMichael J. Spencer } 1321d6167fdSMichael J. Spencer 1335e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 134236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 13544f51e51SDavid Majnemer if (SymbolTable16) { 13644f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1378ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 138236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 13944f51e51SDavid Majnemer } else if (SymbolTable32) { 14044f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14144f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 142236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14344f51e51SDavid Majnemer } else { 14444f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14544f51e51SDavid Majnemer } 1461d6167fdSMichael J. Spencer } 1471d6167fdSMichael J. Spencer 148db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, 1491d6167fdSMichael J. Spencer StringRef &Result) const { 15044f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1518ff24d25SRui Ueyama return getSymbolName(Symb, Result); 1528e90adafSMichael J. Spencer } 1538e90adafSMichael J. Spencer 154991af666SRafael Espindola uint64_t COFFObjectFile::getSymbolValue(DataRefImpl Ref) const { 155991af666SRafael Espindola COFFSymbolRef Sym = getCOFFSymbol(Ref); 156991af666SRafael Espindola 157991af666SRafael Espindola if (Sym.isAnyUndefined() || Sym.isCommon()) 158991af666SRafael Espindola return UnknownAddress; 159991af666SRafael Espindola 160991af666SRafael Espindola return Sym.getValue(); 161991af666SRafael Espindola } 162991af666SRafael Espindola 163db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, 16475d1cf33SBenjamin Kramer uint64_t &Result) const { 165991af666SRafael Espindola Result = getSymbolValue(Ref); 16644f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 167c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 168991af666SRafael Espindola 169991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 170991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 17154c9f3daSRafael Espindola return std::error_code(); 17254c9f3daSRafael Espindola 1732617dcceSCraig Topper const coff_section *Section = nullptr; 174c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 1758ff24d25SRui Ueyama return EC; 176991af666SRafael Espindola Result += Section->VirtualAddress; 1777d099195SRui Ueyama return std::error_code(); 178c7d7c6fbSDavid Majnemer } 179c7d7c6fbSDavid Majnemer 1802fa80cc5SRafael Espindola SymbolRef::Type COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 18144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 182c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 18344f51e51SDavid Majnemer 1842fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 1852fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 1862fa80cc5SRafael Espindola if (Symb.isFunctionDefinition()) 1872fa80cc5SRafael Espindola return SymbolRef::ST_Function; 1882fa80cc5SRafael Espindola if (Symb.isCommon()) 1892fa80cc5SRafael Espindola return SymbolRef::ST_Data; 1902fa80cc5SRafael Espindola if (Symb.isFileRecord()) 1912fa80cc5SRafael Espindola return SymbolRef::ST_File; 1922fa80cc5SRafael Espindola 1931a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 1942fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 1952fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 1962fa80cc5SRafael Espindola 1972fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 1982fa80cc5SRafael Espindola return SymbolRef::ST_Data; 1992fa80cc5SRafael Espindola 2002fa80cc5SRafael Espindola return SymbolRef::ST_Other; 20175d1cf33SBenjamin Kramer } 20275d1cf33SBenjamin Kramer 20320122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 20444f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 20520122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 20675d1cf33SBenjamin Kramer 207c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2081df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 2091df4b84dSDavid Meyer 210c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2111df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2121df4b84dSDavid Meyer 21344f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2141df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2151df4b84dSDavid Meyer 216c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 217c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 218c7d7c6fbSDavid Majnemer 219c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 220c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 221c7d7c6fbSDavid Majnemer 222c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 223c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 224c7d7c6fbSDavid Majnemer 225c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 226c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 227c7d7c6fbSDavid Majnemer 22820122a43SRafael Espindola return Result; 22901759754SMichael J. Spencer } 23001759754SMichael J. Spencer 231d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 232c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2335eb02e45SRafael Espindola return Symb.getValue(); 2348e90adafSMichael J. Spencer } 2358e90adafSMichael J. Spencer 236db4ed0bdSRafael Espindola std::error_code 237db4ed0bdSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref, 23832173153SMichael J. Spencer section_iterator &Result) const { 23944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 24044f51e51SDavid Majnemer if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 241b5155a57SRafael Espindola Result = section_end(); 242f078eff3SRui Ueyama } else { 2432617dcceSCraig Topper const coff_section *Sec = nullptr; 24444f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 245db4ed0bdSRafael Espindola return EC; 2468ff24d25SRui Ueyama DataRefImpl Ref; 2478ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2488ff24d25SRui Ueyama Result = section_iterator(SectionRef(Ref, this)); 24932173153SMichael J. Spencer } 2507d099195SRui Ueyama return std::error_code(); 25132173153SMichael J. Spencer } 25232173153SMichael J. Spencer 2536bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2546bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2556bf32210SRafael Espindola return Symb.getSectionNumber(); 2566bf32210SRafael Espindola } 2576bf32210SRafael Espindola 2585e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2598ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2608ff24d25SRui Ueyama Sec += 1; 2618ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2628e90adafSMichael J. Spencer } 2638e90adafSMichael J. Spencer 264db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2651d6167fdSMichael J. Spencer StringRef &Result) const { 2668ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2678ff24d25SRui Ueyama return getSectionName(Sec, Result); 2688e90adafSMichael J. Spencer } 2698e90adafSMichael J. Spencer 27080291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2718ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 27280291274SRafael Espindola return Sec->VirtualAddress; 2738e90adafSMichael J. Spencer } 2748e90adafSMichael J. Spencer 27580291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 276a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2778e90adafSMichael J. Spencer } 2788e90adafSMichael J. Spencer 279db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2801d6167fdSMichael J. Spencer StringRef &Result) const { 2818ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2829da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 283db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 2849da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2859da9e693SMichael J. Spencer return EC; 2868e90adafSMichael J. Spencer } 2878e90adafSMichael J. Spencer 28880291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 2898ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 29080291274SRafael Espindola return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 2917989460aSMichael J. Spencer } 2927989460aSMichael J. Spencer 29380291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 2948ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 29580291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 2968e90adafSMichael J. Spencer } 2978e90adafSMichael J. Spencer 29880291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 2998ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 30080291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 301800619f2SMichael J. Spencer } 302800619f2SMichael J. Spencer 30380291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3048ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3051a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3061a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3071a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3081a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 309800619f2SMichael J. Spencer } 310800619f2SMichael J. Spencer 3116bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3126bf32210SRafael Espindola uintptr_t Offset = 3136bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3146bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3156bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3166bf32210SRafael Espindola } 3176bf32210SRafael Espindola 31880291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3198ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3201a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3211a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3221a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3232138ef6dSPreston Gurd } 3242138ef6dSPreston Gurd 325e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 326e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 327e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 328e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 329e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 330e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 331e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 332e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 333e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 334e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 335e830c60dSDavid Majnemer return 0; 33698fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 33798fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 338e830c60dSDavid Majnemer } 339e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 340e830c60dSDavid Majnemer } 341e830c60dSDavid Majnemer 34294751be7SDavid Majnemer static const coff_relocation * 34394751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 34494751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 34594751be7SDavid Majnemer if (!NumRelocs) 34694751be7SDavid Majnemer return nullptr; 347827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 34894751be7SDavid Majnemer Base + Sec->PointerToRelocations); 349827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 350827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 351827c8a2bSRui Ueyama // relocations. 352827c8a2bSRui Ueyama begin++; 353827c8a2bSRui Ueyama } 35494751be7SDavid Majnemer if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 35594751be7SDavid Majnemer return nullptr; 35694751be7SDavid Majnemer return begin; 357827c8a2bSRui Ueyama } 35894751be7SDavid Majnemer 35994751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 36094751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 36194751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 36294751be7SDavid Majnemer DataRefImpl Ret; 36394751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3648ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 365e5fd0047SMichael J. Spencer } 366e5fd0047SMichael J. Spencer 3678ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3688ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 36994751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 37094751be7SDavid Majnemer if (I) 37194751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 3728ff24d25SRui Ueyama DataRefImpl Ret; 37394751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 3748ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 375e5fd0047SMichael J. Spencer } 376e5fd0047SMichael J. Spencer 377c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 378db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 37944f51e51SDavid Majnemer if (COFFHeader) 380236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 381236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 382236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 38344f51e51SDavid Majnemer return EC; 38444f51e51SDavid Majnemer 38544f51e51SDavid Majnemer if (COFFBigObjHeader) 386236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 387236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 388236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 3898ff24d25SRui Ueyama return EC; 390c2bed429SRui Ueyama 391c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 392c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 393c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 394f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 39544f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 396f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 397c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 39848af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 3998ff24d25SRui Ueyama return EC; 400c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 401db4ed0bdSRafael Espindola if (std::error_code EC = 40248af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4038ff24d25SRui Ueyama return EC; 404c2bed429SRui Ueyama 405773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 406773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 407773a5795SNico Rieck if (StringTableSize < 4) 408773a5795SNico Rieck StringTableSize = 4; 409773a5795SNico Rieck 410c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 411773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 412c2bed429SRui Ueyama return object_error::parse_failed; 4137d099195SRui Ueyama return std::error_code(); 414c2bed429SRui Ueyama } 415c2bed429SRui Ueyama 416215a586cSRui Ueyama // Returns the file offset for the given VA. 417db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 418b6eb264aSRui Ueyama uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 419b6eb264aSRui Ueyama : (uint64_t)PE32PlusHeader->ImageBase; 420b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 421b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 422b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 423215a586cSRui Ueyama } 424215a586cSRui Ueyama 425c2bed429SRui Ueyama // Returns the file offset for the given RVA. 426db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 42727dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 42827dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 429c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 430c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 431215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 432215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 433c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4347d099195SRui Ueyama return std::error_code(); 435c2bed429SRui Ueyama } 436c2bed429SRui Ueyama } 437c2bed429SRui Ueyama return object_error::parse_failed; 438c2bed429SRui Ueyama } 439c2bed429SRui Ueyama 440c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 441c2bed429SRui Ueyama // table entry. 442db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 443db4ed0bdSRafael Espindola StringRef &Name) const { 444c2bed429SRui Ueyama uintptr_t IntPtr = 0; 445db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4468ff24d25SRui Ueyama return EC; 447c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 448c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 449c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 4507d099195SRui Ueyama return std::error_code(); 451c2bed429SRui Ueyama } 452c2bed429SRui Ueyama 453c2bed429SRui Ueyama // Find the import table. 454db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 455c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 456c2bed429SRui Ueyama // the import table, do nothing. 457c2bed429SRui Ueyama const data_directory *DataEntry; 458c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 4597d099195SRui Ueyama return std::error_code(); 460c2bed429SRui Ueyama 461c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 462c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 4637d099195SRui Ueyama return std::error_code(); 464c2bed429SRui Ueyama 465c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 4661e152d5eSRui Ueyama // -1 because the last entry is the null entry. 467c2bed429SRui Ueyama NumberOfImportDirectory = DataEntry->Size / 4681e152d5eSRui Ueyama sizeof(import_directory_table_entry) - 1; 469c2bed429SRui Ueyama 470c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 471c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 472c2bed429SRui Ueyama uintptr_t IntPtr = 0; 473db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 4748ff24d25SRui Ueyama return EC; 475c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 476c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 4777d099195SRui Ueyama return std::error_code(); 478ad882ba8SRui Ueyama } 479c2bed429SRui Ueyama 48015d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 48115d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 48215d99359SRui Ueyama const data_directory *DataEntry; 48315d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 4847d099195SRui Ueyama return std::error_code(); 48515d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 4867d099195SRui Ueyama return std::error_code(); 48715d99359SRui Ueyama 48815d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 48915d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 49015d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 49115d99359SRui Ueyama 49215d99359SRui Ueyama uintptr_t IntPtr = 0; 49315d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 49415d99359SRui Ueyama return EC; 49515d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 49615d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 4977d099195SRui Ueyama return std::error_code(); 49815d99359SRui Ueyama } 49915d99359SRui Ueyama 500ad882ba8SRui Ueyama // Find the export table. 501db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 502ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 503ad882ba8SRui Ueyama // the export table, do nothing. 504ad882ba8SRui Ueyama const data_directory *DataEntry; 505ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5067d099195SRui Ueyama return std::error_code(); 507ad882ba8SRui Ueyama 508ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 509ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5107d099195SRui Ueyama return std::error_code(); 511ad882ba8SRui Ueyama 512ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 513ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 514db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 515ad882ba8SRui Ueyama return EC; 51624fc2d64SRui Ueyama ExportDirectory = 51724fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 5187d099195SRui Ueyama return std::error_code(); 519c2bed429SRui Ueyama } 520c2bed429SRui Ueyama 52174e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 52274e85130SRui Ueyama const data_directory *DataEntry; 52374e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 5247d099195SRui Ueyama return std::error_code(); 52574e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5267d099195SRui Ueyama return std::error_code(); 52774e85130SRui Ueyama 52874e85130SRui Ueyama uintptr_t IntPtr = 0; 52974e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 53074e85130SRui Ueyama return EC; 53174e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 53274e85130SRui Ueyama IntPtr); 53374e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 53474e85130SRui Ueyama IntPtr + DataEntry->Size); 5357d099195SRui Ueyama return std::error_code(); 53674e85130SRui Ueyama } 53774e85130SRui Ueyama 53848af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 53948af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 54044f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 54144f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 54244f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 54344f51e51SDavid Majnemer ImportDirectory(nullptr), NumberOfImportDirectory(0), 54415d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 54574e85130SRui Ueyama ExportDirectory(nullptr), BaseRelocHeader(nullptr), 54674e85130SRui Ueyama BaseRelocEnd(nullptr) { 5471d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 54848af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 549c3f9b5a5SRafael Espindola return; 550ee066fc4SEric Christopher 55182ebd8e3SRui Ueyama // The current location in the file where we are looking at. 55282ebd8e3SRui Ueyama uint64_t CurPtr = 0; 55382ebd8e3SRui Ueyama 55482ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 55582ebd8e3SRui Ueyama // it is placed right after COFF header. 5568ff24d25SRui Ueyama bool HasPEHeader = false; 557ee066fc4SEric Christopher 5581d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 55950267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 560ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 561ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 56250267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 56350267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 56450267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 56582ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 56650267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 5678ff24d25SRui Ueyama EC = object_error::parse_failed; 5681d6167fdSMichael J. Spencer return; 5691d6167fdSMichael J. Spencer } 57044f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 5718ff24d25SRui Ueyama HasPEHeader = true; 572ee066fc4SEric Christopher } 57350267222SDavid Majnemer } 574ee066fc4SEric Christopher 57548af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 5761d6167fdSMichael J. Spencer return; 57744f51e51SDavid Majnemer 57844f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 57944f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 58044f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 58144f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 58244f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 58344f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 58444f51e51SDavid Majnemer return; 58544f51e51SDavid Majnemer 58644f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 58744f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 58844f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 58944f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 59044f51e51SDavid Majnemer COFFHeader = nullptr; 59144f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 59244f51e51SDavid Majnemer } else { 59344f51e51SDavid Majnemer // It's not a bigobj. 59444f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 59544f51e51SDavid Majnemer } 59644f51e51SDavid Majnemer } 59744f51e51SDavid Majnemer if (COFFHeader) { 59844f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 59944f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 6007d099195SRui Ueyama EC = std::error_code(); 60182ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 60282ebd8e3SRui Ueyama 60344f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 60444f51e51SDavid Majnemer return; 60544f51e51SDavid Majnemer } 60644f51e51SDavid Majnemer 6078ff24d25SRui Ueyama if (HasPEHeader) { 60810ed9ddcSRui Ueyama const pe32_header *Header; 60948af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 61082ebd8e3SRui Ueyama return; 61110ed9ddcSRui Ueyama 61210ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 61310ed9ddcSRui Ueyama uint64_t DataDirSize; 61450267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 61510ed9ddcSRui Ueyama PE32Header = Header; 61610ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 61710ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 61850267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 61910ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 62010ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 62110ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 62210ed9ddcSRui Ueyama } else { 62310ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 62410ed9ddcSRui Ueyama EC = object_error::parse_failed; 625ed64342bSRui Ueyama return; 626ed64342bSRui Ueyama } 62748af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 62810ed9ddcSRui Ueyama return; 62982ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 63082ebd8e3SRui Ueyama } 6311d6167fdSMichael J. Spencer 63248af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 633236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 6341d6167fdSMichael J. Spencer return; 6351d6167fdSMichael J. Spencer 636c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 637236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 6388ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 6391d6167fdSMichael J. Spencer return; 640236b0ca7SDavid Majnemer } else { 641236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 642236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 643236b0ca7SDavid Majnemer EC = object_error::parse_failed; 644236b0ca7SDavid Majnemer return; 645236b0ca7SDavid Majnemer } 646236b0ca7SDavid Majnemer } 6478e90adafSMichael J. Spencer 648c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 6498ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 650ed64342bSRui Ueyama return; 65115d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 65215d99359SRui Ueyama return; 6531d6167fdSMichael J. Spencer 654ad882ba8SRui Ueyama // Initialize the pointer to the export table. 6558ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 656ad882ba8SRui Ueyama return; 657ad882ba8SRui Ueyama 65874e85130SRui Ueyama // Initialize the pointer to the base relocation table. 65974e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 66074e85130SRui Ueyama return; 66174e85130SRui Ueyama 6627d099195SRui Ueyama EC = std::error_code(); 6638e90adafSMichael J. Spencer } 6648e90adafSMichael J. Spencer 665f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 6668ff24d25SRui Ueyama DataRefImpl Ret; 66744f51e51SDavid Majnemer Ret.p = getSymbolTable(); 668f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6698e90adafSMichael J. Spencer } 6708e90adafSMichael J. Spencer 671f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 6728e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 6738ff24d25SRui Ueyama DataRefImpl Ret; 6748ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 675f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 6768e90adafSMichael J. Spencer } 6778e90adafSMichael J. Spencer 678bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 679a045b73aSRui Ueyama return import_directory_iterator( 680a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 681c2bed429SRui Ueyama } 682c2bed429SRui Ueyama 683bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 684a045b73aSRui Ueyama return import_directory_iterator( 685a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 686c2bed429SRui Ueyama } 687c429b80dSDavid Meyer 68815d99359SRui Ueyama delay_import_directory_iterator 68915d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 69015d99359SRui Ueyama return delay_import_directory_iterator( 69115d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 69215d99359SRui Ueyama } 69315d99359SRui Ueyama 69415d99359SRui Ueyama delay_import_directory_iterator 69515d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 69615d99359SRui Ueyama return delay_import_directory_iterator( 69715d99359SRui Ueyama DelayImportDirectoryEntryRef( 69815d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 69915d99359SRui Ueyama } 70015d99359SRui Ueyama 701ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 702ad882ba8SRui Ueyama return export_directory_iterator( 703ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 704ad882ba8SRui Ueyama } 705ad882ba8SRui Ueyama 706ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 7072617dcceSCraig Topper if (!ExportDirectory) 7082617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 7098ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 710ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 7118ff24d25SRui Ueyama return export_directory_iterator(Ref); 712ad882ba8SRui Ueyama } 713ad882ba8SRui Ueyama 714b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 7158ff24d25SRui Ueyama DataRefImpl Ret; 7168ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 7178ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7188e90adafSMichael J. Spencer } 7198e90adafSMichael J. Spencer 720b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 7218ff24d25SRui Ueyama DataRefImpl Ret; 72244f51e51SDavid Majnemer int NumSections = 72344f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 7248ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 7258ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 7268e90adafSMichael J. Spencer } 7278e90adafSMichael J. Spencer 72874e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 72974e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 73074e85130SRui Ueyama } 73174e85130SRui Ueyama 73274e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 73374e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 73474e85130SRui Ueyama } 73574e85130SRui Ueyama 7368e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 7370324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 7388e90adafSMichael J. Spencer } 7398e90adafSMichael J. Spencer 7408e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 74144f51e51SDavid Majnemer switch(getMachine()) { 7428e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7438e90adafSMichael J. Spencer return "COFF-i386"; 7448e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7458e90adafSMichael J. Spencer return "COFF-x86-64"; 7469b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7479b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 7488e90adafSMichael J. Spencer default: 7498e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 7508e90adafSMichael J. Spencer } 7518e90adafSMichael J. Spencer } 7528e90adafSMichael J. Spencer 7538e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 75444f51e51SDavid Majnemer switch (getMachine()) { 7558e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7568e90adafSMichael J. Spencer return Triple::x86; 7578e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 7588e90adafSMichael J. Spencer return Triple::x86_64; 7599b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 7609b7c0af2SSaleem Abdulrasool return Triple::thumb; 7618e90adafSMichael J. Spencer default: 7628e90adafSMichael J. Spencer return Triple::UnknownArch; 7638e90adafSMichael J. Spencer } 7648e90adafSMichael J. Spencer } 7658e90adafSMichael J. Spencer 766979fb40bSRui Ueyama iterator_range<import_directory_iterator> 767979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 768979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 769979fb40bSRui Ueyama } 770979fb40bSRui Ueyama 771979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 772979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 773979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 774979fb40bSRui Ueyama delay_import_directory_end()); 775979fb40bSRui Ueyama } 776979fb40bSRui Ueyama 777979fb40bSRui Ueyama iterator_range<export_directory_iterator> 778979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 779979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 780979fb40bSRui Ueyama } 781979fb40bSRui Ueyama 78274e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 78374e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 78474e85130SRui Ueyama } 78574e85130SRui Ueyama 786db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 78782ebd8e3SRui Ueyama Res = PE32Header; 7887d099195SRui Ueyama return std::error_code(); 78989a7a5eaSMichael J. Spencer } 79089a7a5eaSMichael J. Spencer 791db4ed0bdSRafael Espindola std::error_code 79210ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 79310ed9ddcSRui Ueyama Res = PE32PlusHeader; 7947d099195SRui Ueyama return std::error_code(); 79510ed9ddcSRui Ueyama } 79610ed9ddcSRui Ueyama 797db4ed0bdSRafael Espindola std::error_code 798db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 799ed64342bSRui Ueyama const data_directory *&Res) const { 800ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 801f69b0585SDavid Majnemer if (!DataDirectory) { 802f69b0585SDavid Majnemer Res = nullptr; 80310ed9ddcSRui Ueyama return object_error::parse_failed; 804f69b0585SDavid Majnemer } 80510ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 80610ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 80710ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 808f69b0585SDavid Majnemer if (Index >= NumEnt) { 809f69b0585SDavid Majnemer Res = nullptr; 810ed64342bSRui Ueyama return object_error::parse_failed; 811f69b0585SDavid Majnemer } 8128ff24d25SRui Ueyama Res = &DataDirectory[Index]; 8137d099195SRui Ueyama return std::error_code(); 814ed64342bSRui Ueyama } 815ed64342bSRui Ueyama 816db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 8171d6167fdSMichael J. Spencer const coff_section *&Result) const { 8182617dcceSCraig Topper Result = nullptr; 819236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 8207d099195SRui Ueyama return std::error_code(); 821236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 8221d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 8238ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 8247d099195SRui Ueyama return std::error_code(); 8258e90adafSMichael J. Spencer } 826236b0ca7SDavid Majnemer return object_error::parse_failed; 827236b0ca7SDavid Majnemer } 8288e90adafSMichael J. Spencer 829db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 8301d6167fdSMichael J. Spencer StringRef &Result) const { 8311d6167fdSMichael J. Spencer if (StringTableSize <= 4) 8321d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 8331d6167fdSMichael J. Spencer return object_error::parse_failed; 8348ff24d25SRui Ueyama if (Offset >= StringTableSize) 8351d6167fdSMichael J. Spencer return object_error::unexpected_eof; 8368ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 8377d099195SRui Ueyama return std::error_code(); 8388e90adafSMichael J. Spencer } 839022ecdf2SBenjamin Kramer 84044f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 84189a7a5eaSMichael J. Spencer StringRef &Res) const { 842e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 843e40d30f3SRui Ueyama } 844e40d30f3SRui Ueyama 845e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 846e40d30f3SRui Ueyama StringRef &Res) const { 84789a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 848e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 849e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 8508ff24d25SRui Ueyama return EC; 8517d099195SRui Ueyama return std::error_code(); 85289a7a5eaSMichael J. Spencer } 85389a7a5eaSMichael J. Spencer 854e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 85589a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 856e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 85789a7a5eaSMichael J. Spencer else 85889a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 859e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 8607d099195SRui Ueyama return std::error_code(); 86189a7a5eaSMichael J. Spencer } 86289a7a5eaSMichael J. Spencer 86344f51e51SDavid Majnemer ArrayRef<uint8_t> 86444f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 8652617dcceSCraig Topper const uint8_t *Aux = nullptr; 86671757ef3SMarshall Clow 86744f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 86844f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 86971757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 87044f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 87171757ef3SMarshall Clow # ifndef NDEBUG 8728ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 8738ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 87444f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 87544f51e51SDavid Majnemer Offset >= 87644f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 87771757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 87871757ef3SMarshall Clow 87944f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 88044f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 88171757ef3SMarshall Clow # endif 882bfb85e67SMarshall Clow } 88344f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 88471757ef3SMarshall Clow } 88571757ef3SMarshall Clow 886db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 88753c2d547SMichael J. Spencer StringRef &Res) const { 88853c2d547SMichael J. Spencer StringRef Name; 88944f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 89053c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 89153c2d547SMichael J. Spencer Name = Sec->Name; 89253c2d547SMichael J. Spencer else 89353c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 89444f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 89553c2d547SMichael J. Spencer 89653c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 8972314b3deSDavid Majnemer if (Name.startswith("/")) { 89853c2d547SMichael J. Spencer uint32_t Offset; 8992314b3deSDavid Majnemer if (Name.startswith("//")) { 9009d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 9019d2c15efSNico Rieck return object_error::parse_failed; 9029d2c15efSNico Rieck } else { 90353c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 90453c2d547SMichael J. Spencer return object_error::parse_failed; 9059d2c15efSNico Rieck } 906db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 9078ff24d25SRui Ueyama return EC; 90853c2d547SMichael J. Spencer } 90953c2d547SMichael J. Spencer 91053c2d547SMichael J. Spencer Res = Name; 9117d099195SRui Ueyama return std::error_code(); 91253c2d547SMichael J. Spencer } 91353c2d547SMichael J. Spencer 914a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 915a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 916a9ee5c06SDavid Majnemer // whether or not we have an executable image. 917a9ee5c06SDavid Majnemer // 918a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 919a9ee5c06SDavid Majnemer // VirtualSize is always zero. 920a9ee5c06SDavid Majnemer // 921a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 922a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 923a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 924a9ee5c06SDavid Majnemer // considered to be zero. 925a9ee5c06SDavid Majnemer uint32_t SectionSize; 926a9ee5c06SDavid Majnemer if (Sec->VirtualSize) 927a9ee5c06SDavid Majnemer SectionSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData); 928a9ee5c06SDavid Majnemer else 929a9ee5c06SDavid Majnemer SectionSize = Sec->SizeOfRawData; 930a9ee5c06SDavid Majnemer 931a9ee5c06SDavid Majnemer return SectionSize; 932a9ee5c06SDavid Majnemer } 933a9ee5c06SDavid Majnemer 934db4ed0bdSRafael Espindola std::error_code 935db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 9369da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 937dd9cff2eSDavid Majnemer // PointerToRawData and SizeOfRawData won't make sense for BSS sections, 938dd9cff2eSDavid Majnemer // don't do anything interesting for them. 939dac39857SDavid Majnemer assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && 940dac39857SDavid Majnemer "BSS sections don't have contents!"); 9419da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 9429da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 9439da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 9449da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 945a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 946e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 9479da9e693SMichael J. Spencer return object_error::parse_failed; 948a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 9497d099195SRui Ueyama return std::error_code(); 9509da9e693SMichael J. Spencer } 9519da9e693SMichael J. Spencer 952022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 953e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 954022ecdf2SBenjamin Kramer } 9558ff24d25SRui Ueyama 9565e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 957e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 958e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 959022ecdf2SBenjamin Kramer } 9608ff24d25SRui Ueyama 961*10fcac7bSRafael Espindola ErrorOr<uint64_t> COFFObjectFile::getRelocationAddress(DataRefImpl Rel) const { 9621e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 963022ecdf2SBenjamin Kramer } 9648ff24d25SRui Ueyama 96596d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 96658323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 96796d071cdSRafael Espindola return R->VirtualAddress; 968cbe72fc9SDanil Malyshev } 9698ff24d25SRui Ueyama 970806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 971022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 9728ff24d25SRui Ueyama DataRefImpl Ref; 973236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 974236b0ca7SDavid Majnemer return symbol_end(); 97544f51e51SDavid Majnemer if (SymbolTable16) 97644f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 97744f51e51SDavid Majnemer else if (SymbolTable32) 97844f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 97944f51e51SDavid Majnemer else 980c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 9818ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 982022ecdf2SBenjamin Kramer } 9838ff24d25SRui Ueyama 98499c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 985022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 98699c041b7SRafael Espindola return R->Type; 987022ecdf2SBenjamin Kramer } 988e5fd0047SMichael J. Spencer 98927dc8394SAlexey Samsonov const coff_section * 99027dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 99127dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 99271757ef3SMarshall Clow } 99371757ef3SMarshall Clow 99444f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 99544f51e51SDavid Majnemer if (SymbolTable16) 99644f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 99744f51e51SDavid Majnemer if (SymbolTable32) 99844f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 99944f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 100044f51e51SDavid Majnemer } 100144f51e51SDavid Majnemer 100244f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 100344f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 100471757ef3SMarshall Clow } 100571757ef3SMarshall Clow 1006f12b8282SRafael Espindola const coff_relocation * 100727dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 100827dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1009d3e2a76cSMarshall Clow } 1010d3e2a76cSMarshall Clow 10116a75acb1SRui Ueyama iterator_range<const coff_relocation *> 10126a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 10136a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 10146a75acb1SRui Ueyama const coff_relocation *E = I; 10156a75acb1SRui Ueyama if (I) 10166a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 10176a75acb1SRui Ueyama return make_range(I, E); 10186a75acb1SRui Ueyama } 10196a75acb1SRui Ueyama 102027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 102127dc8394SAlexey Samsonov case COFF::reloc_type: \ 102227dc8394SAlexey Samsonov Res = #reloc_type; \ 102327dc8394SAlexey Samsonov break; 1024e5fd0047SMichael J. Spencer 102541bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 102641bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 10278ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 10288ff24d25SRui Ueyama StringRef Res; 102944f51e51SDavid Majnemer switch (getMachine()) { 1030e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 10318ff24d25SRui Ueyama switch (Reloc->Type) { 1032e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1033e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1034e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1035e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1036e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1037e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1038e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1039e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1040e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1041e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1042e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1043e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1044e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1045e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1046e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1047e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1048e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1049e5fd0047SMichael J. Spencer default: 10508ff24d25SRui Ueyama Res = "Unknown"; 1051e5fd0047SMichael J. Spencer } 1052e5fd0047SMichael J. Spencer break; 10535c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 10545c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 10555c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 10565c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 10575c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 10585c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 10595c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 10605c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 10615c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 10625c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 10635c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 10645c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 10655c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 10665c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 10675c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 10685c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 10695c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 10705c503bf4SSaleem Abdulrasool default: 10715c503bf4SSaleem Abdulrasool Res = "Unknown"; 10725c503bf4SSaleem Abdulrasool } 10735c503bf4SSaleem Abdulrasool break; 1074e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 10758ff24d25SRui Ueyama switch (Reloc->Type) { 1076e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1077e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1078e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1079e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1080e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1081e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1082e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1083e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1084e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1085e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1086e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1087e5fd0047SMichael J. Spencer default: 10888ff24d25SRui Ueyama Res = "Unknown"; 1089e5fd0047SMichael J. Spencer } 1090e5fd0047SMichael J. Spencer break; 1091e5fd0047SMichael J. Spencer default: 10928ff24d25SRui Ueyama Res = "Unknown"; 1093e5fd0047SMichael J. Spencer } 10948ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1095e5fd0047SMichael J. Spencer } 1096e5fd0047SMichael J. Spencer 1097e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1098e5fd0047SMichael J. Spencer 1099c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1100c66d761bSRafael Espindola return !DataDirectory; 1101c66d761bSRafael Espindola } 1102c66d761bSRafael Espindola 1103c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1104c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1105a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1106c2bed429SRui Ueyama } 1107c2bed429SRui Ueyama 11085e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 11095e812afaSRafael Espindola ++Index; 1110c2bed429SRui Ueyama } 1111c2bed429SRui Ueyama 1112db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1113db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 11141e152d5eSRui Ueyama Result = ImportTable + Index; 11157d099195SRui Ueyama return std::error_code(); 1116c2bed429SRui Ueyama } 1117c2bed429SRui Ueyama 1118861021f9SRui Ueyama static imported_symbol_iterator 111915d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1120861021f9SRui Ueyama uintptr_t Ptr, int Index) { 112115d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1122861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 112315d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1124861021f9SRui Ueyama } 1125861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 112615d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1127861021f9SRui Ueyama } 1128861021f9SRui Ueyama 112915d99359SRui Ueyama static imported_symbol_iterator 113015d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1131861021f9SRui Ueyama uintptr_t IntPtr = 0; 113215d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 113315d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1134861021f9SRui Ueyama } 1135861021f9SRui Ueyama 113615d99359SRui Ueyama static imported_symbol_iterator 113715d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1138861021f9SRui Ueyama uintptr_t IntPtr = 0; 113915d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1140861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1141861021f9SRui Ueyama int Index = 0; 114215d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1143861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1144861021f9SRui Ueyama while (*Entry++) 1145861021f9SRui Ueyama ++Index; 1146861021f9SRui Ueyama } else { 1147861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1148861021f9SRui Ueyama while (*Entry++) 1149861021f9SRui Ueyama ++Index; 1150861021f9SRui Ueyama } 115115d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 115215d99359SRui Ueyama } 115315d99359SRui Ueyama 115415d99359SRui Ueyama imported_symbol_iterator 115515d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 115615d99359SRui Ueyama return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 115715d99359SRui Ueyama OwningObject); 115815d99359SRui Ueyama } 115915d99359SRui Ueyama 116015d99359SRui Ueyama imported_symbol_iterator 116115d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 116215d99359SRui Ueyama return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 116315d99359SRui Ueyama OwningObject); 1164861021f9SRui Ueyama } 1165861021f9SRui Ueyama 1166979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1167979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1168979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1169979fb40bSRui Ueyama } 1170979fb40bSRui Ueyama 1171db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1172c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1173db4ed0bdSRafael Espindola if (std::error_code EC = 11741e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1175a045b73aSRui Ueyama return EC; 1176a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 11777d099195SRui Ueyama return std::error_code(); 1178c2bed429SRui Ueyama } 1179c2bed429SRui Ueyama 11801e152d5eSRui Ueyama std::error_code 11811e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 11821e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 11837d099195SRui Ueyama return std::error_code(); 11841e152d5eSRui Ueyama } 11851e152d5eSRui Ueyama 11861e152d5eSRui Ueyama std::error_code 11871e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 11881e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 11897d099195SRui Ueyama return std::error_code(); 11901e152d5eSRui Ueyama } 11911e152d5eSRui Ueyama 1192db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1193c2bed429SRui Ueyama const import_lookup_table_entry32 *&Result) const { 1194c2bed429SRui Ueyama uintptr_t IntPtr = 0; 11951e152d5eSRui Ueyama uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; 11961e152d5eSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1197a045b73aSRui Ueyama return EC; 1198c2bed429SRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 11997d099195SRui Ueyama return std::error_code(); 1200c2bed429SRui Ueyama } 1201c2bed429SRui Ueyama 120215d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 120315d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 120415d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 120515d99359SRui Ueyama } 120615d99359SRui Ueyama 120715d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 120815d99359SRui Ueyama ++Index; 120915d99359SRui Ueyama } 121015d99359SRui Ueyama 121115d99359SRui Ueyama imported_symbol_iterator 121215d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 121315d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 121415d99359SRui Ueyama OwningObject); 121515d99359SRui Ueyama } 121615d99359SRui Ueyama 121715d99359SRui Ueyama imported_symbol_iterator 121815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 121915d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 122015d99359SRui Ueyama OwningObject); 122115d99359SRui Ueyama } 122215d99359SRui Ueyama 1223979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1224979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1225979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1226979fb40bSRui Ueyama } 1227979fb40bSRui Ueyama 122815d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 122915d99359SRui Ueyama uintptr_t IntPtr = 0; 123015d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 123115d99359SRui Ueyama return EC; 123215d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 12337d099195SRui Ueyama return std::error_code(); 123415d99359SRui Ueyama } 123515d99359SRui Ueyama 12361af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 12371af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 12381af08658SRui Ueyama Result = Table; 12397d099195SRui Ueyama return std::error_code(); 12401af08658SRui Ueyama } 12411af08658SRui Ueyama 1242ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1243ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1244ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1245ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1246ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1247ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1248ffa4cebeSRui Ueyama return EC; 1249ffa4cebeSRui Ueyama if (OwningObject->is64()) 12505dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1251ffa4cebeSRui Ueyama else 12525dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 12537d099195SRui Ueyama return std::error_code(); 1254ffa4cebeSRui Ueyama } 1255ffa4cebeSRui Ueyama 1256ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1257ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1258ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1259ad882ba8SRui Ueyama } 1260ad882ba8SRui Ueyama 12615e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 12625e812afaSRafael Espindola ++Index; 1263ad882ba8SRui Ueyama } 1264ad882ba8SRui Ueyama 1265da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1266da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1267db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1268da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1269db4ed0bdSRafael Espindola if (std::error_code EC = 1270db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1271da49d0d4SRui Ueyama return EC; 1272da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 12737d099195SRui Ueyama return std::error_code(); 1274da49d0d4SRui Ueyama } 1275da49d0d4SRui Ueyama 1276e5df6095SRui Ueyama // Returns the starting ordinal number. 1277db4ed0bdSRafael Espindola std::error_code 1278db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1279e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 12807d099195SRui Ueyama return std::error_code(); 1281e5df6095SRui Ueyama } 1282e5df6095SRui Ueyama 1283ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1284db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1285ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 12867d099195SRui Ueyama return std::error_code(); 1287ad882ba8SRui Ueyama } 1288ad882ba8SRui Ueyama 1289ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1290db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1291ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1292db4ed0bdSRafael Espindola if (std::error_code EC = 1293db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1294ad882ba8SRui Ueyama return EC; 129524fc2d64SRui Ueyama const export_address_table_entry *entry = 129624fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1297ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 12987d099195SRui Ueyama return std::error_code(); 1299ad882ba8SRui Ueyama } 1300ad882ba8SRui Ueyama 1301ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1302ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1303db4ed0bdSRafael Espindola std::error_code 1304db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1305ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1306db4ed0bdSRafael Espindola if (std::error_code EC = 1307db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1308ad882ba8SRui Ueyama return EC; 1309ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1310ad882ba8SRui Ueyama 1311ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1312ad882ba8SRui Ueyama int Offset = 0; 1313ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1314ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1315ad882ba8SRui Ueyama if (*I != Index) 1316ad882ba8SRui Ueyama continue; 1317db4ed0bdSRafael Espindola if (std::error_code EC = 1318db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1319ad882ba8SRui Ueyama return EC; 1320ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1321db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1322ad882ba8SRui Ueyama return EC; 1323ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13247d099195SRui Ueyama return std::error_code(); 1325ad882ba8SRui Ueyama } 1326ad882ba8SRui Ueyama Result = ""; 13277d099195SRui Ueyama return std::error_code(); 1328ad882ba8SRui Ueyama } 1329ad882ba8SRui Ueyama 1330861021f9SRui Ueyama bool ImportedSymbolRef:: 1331861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1332861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1333861021f9SRui Ueyama && Index == Other.Index; 1334861021f9SRui Ueyama } 1335861021f9SRui Ueyama 1336861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1337861021f9SRui Ueyama ++Index; 1338861021f9SRui Ueyama } 1339861021f9SRui Ueyama 1340861021f9SRui Ueyama std::error_code 1341861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1342861021f9SRui Ueyama uint32_t RVA; 1343861021f9SRui Ueyama if (Entry32) { 1344861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1345861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 13467d099195SRui Ueyama return std::error_code(); 1347861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1348861021f9SRui Ueyama } else { 1349861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 13507d099195SRui Ueyama return std::error_code(); 1351861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1352861021f9SRui Ueyama } 1353861021f9SRui Ueyama uintptr_t IntPtr = 0; 1354861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1355861021f9SRui Ueyama return EC; 1356861021f9SRui Ueyama // +2 because the first two bytes is hint. 1357861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 13587d099195SRui Ueyama return std::error_code(); 1359861021f9SRui Ueyama } 1360861021f9SRui Ueyama 1361861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1362861021f9SRui Ueyama uint32_t RVA; 1363861021f9SRui Ueyama if (Entry32) { 1364861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1365861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 13667d099195SRui Ueyama return std::error_code(); 1367861021f9SRui Ueyama } 1368861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1369861021f9SRui Ueyama } else { 1370861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1371861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 13727d099195SRui Ueyama return std::error_code(); 1373861021f9SRui Ueyama } 1374861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1375861021f9SRui Ueyama } 1376861021f9SRui Ueyama uintptr_t IntPtr = 0; 1377861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1378861021f9SRui Ueyama return EC; 1379861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 13807d099195SRui Ueyama return std::error_code(); 1381861021f9SRui Ueyama } 1382861021f9SRui Ueyama 1383437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 138448af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1385db4ed0bdSRafael Espindola std::error_code EC; 138648af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1387692410efSRafael Espindola if (EC) 1388692410efSRafael Espindola return EC; 1389437b0d58SRafael Espindola return std::move(Ret); 1390686738e2SRui Ueyama } 139174e85130SRui Ueyama 139274e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 139374e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 139474e85130SRui Ueyama } 139574e85130SRui Ueyama 139674e85130SRui Ueyama void BaseRelocRef::moveNext() { 139774e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 139874e85130SRui Ueyama // size of the header itself. 139974e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1400970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 140174e85130SRui Ueyama if (Size == Header->BlockSize) { 140274e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 140374e85130SRui Ueyama // consists of the header followed by entries. The header contains 140474e85130SRui Ueyama // how many entories will follow. When we reach the end of the 140574e85130SRui Ueyama // current block, proceed to the next block. 140674e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 140774e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 140874e85130SRui Ueyama Index = 0; 140974e85130SRui Ueyama } else { 141074e85130SRui Ueyama ++Index; 141174e85130SRui Ueyama } 141274e85130SRui Ueyama } 141374e85130SRui Ueyama 141474e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 141574e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 141674e85130SRui Ueyama Type = Entry[Index].getType(); 14177d099195SRui Ueyama return std::error_code(); 141874e85130SRui Ueyama } 141974e85130SRui Ueyama 142074e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 142174e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 142274e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 14237d099195SRui Ueyama return std::error_code(); 142474e85130SRui Ueyama } 1425