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" 168e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 178e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 186a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.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 } 497d099195SRui Ueyama return std::error_code(); 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); 627d099195SRui Ueyama return std::error_code(); 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 14781e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 14844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 1495d0c2ffaSRafael Espindola StringRef Result; 1505d0c2ffaSRafael Espindola std::error_code EC = getSymbolName(Symb, Result); 1515d0c2ffaSRafael Espindola if (EC) 15281e8b7d9SKevin Enderby return errorCodeToError(EC); 1535d0c2ffaSRafael Espindola return Result; 1548e90adafSMichael J. Spencer } 1558e90adafSMichael J. Spencer 156be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 157be8b0ea8SRafael Espindola return getCOFFSymbol(Ref).getValue(); 158991af666SRafael Espindola } 159991af666SRafael Espindola 160931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 161ed067c45SRafael Espindola uint64_t Result = getSymbolValue(Ref); 16244f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 163c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 164991af666SRafael Espindola 165991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 166991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 167ed067c45SRafael Espindola return Result; 16854c9f3daSRafael Espindola 1692617dcceSCraig Topper const coff_section *Section = nullptr; 170c7d7c6fbSDavid Majnemer if (std::error_code EC = getSection(SectionNumber, Section)) 171931cb65dSKevin Enderby return errorCodeToError(EC); 172991af666SRafael Espindola Result += Section->VirtualAddress; 17347ea9eceSReid Kleckner 17447ea9eceSReid Kleckner // The section VirtualAddress does not include ImageBase, and we want to 17547ea9eceSReid Kleckner // return virtual addresses. 17621427adaSReid Kleckner Result += getImageBase(); 17747ea9eceSReid Kleckner 178ed067c45SRafael Espindola return Result; 179c7d7c6fbSDavid Majnemer } 180c7d7c6fbSDavid Majnemer 1817bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 18244f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 183c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 18444f51e51SDavid Majnemer 185e834f420SPeter Collingbourne if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 186e834f420SPeter Collingbourne return SymbolRef::ST_Function; 1872fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 1882fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 1892fa80cc5SRafael Espindola if (Symb.isCommon()) 1902fa80cc5SRafael Espindola return SymbolRef::ST_Data; 1912fa80cc5SRafael Espindola if (Symb.isFileRecord()) 1922fa80cc5SRafael Espindola return SymbolRef::ST_File; 1932fa80cc5SRafael Espindola 1941a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 1952fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 1962fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 1972fa80cc5SRafael Espindola 1982fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 1992fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2002fa80cc5SRafael Espindola 2012fa80cc5SRafael Espindola return SymbolRef::ST_Other; 20275d1cf33SBenjamin Kramer } 20375d1cf33SBenjamin Kramer 20420122a43SRafael Espindola uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 20544f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 20620122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 20775d1cf33SBenjamin Kramer 208c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2099dc0eb42SLang Hames Result |= SymbolRef::SF_Global; 2101df4b84dSDavid Meyer 211c7d7c6fbSDavid Majnemer if (Symb.isWeakExternal()) 2121df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 2131df4b84dSDavid Meyer 21444f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2151df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2161df4b84dSDavid Meyer 217c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 218c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 219c7d7c6fbSDavid Majnemer 220c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 221c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 222c7d7c6fbSDavid Majnemer 223c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 224c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 225c7d7c6fbSDavid Majnemer 226c7d7c6fbSDavid Majnemer if (Symb.isAnyUndefined()) 227c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 228c7d7c6fbSDavid Majnemer 22920122a43SRafael Espindola return Result; 23001759754SMichael J. Spencer } 23101759754SMichael J. Spencer 232d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 233c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2345eb02e45SRafael Espindola return Symb.getValue(); 2358e90adafSMichael J. Spencer } 2368e90adafSMichael J. Spencer 2377bd8d994SKevin Enderby Expected<section_iterator> 2388bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 23944f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2408bab889bSRafael Espindola if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2418bab889bSRafael Espindola return section_end(); 2422617dcceSCraig Topper const coff_section *Sec = nullptr; 24344f51e51SDavid Majnemer if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 2447bd8d994SKevin Enderby return errorCodeToError(EC); 2458bab889bSRafael Espindola DataRefImpl Ret; 2468bab889bSRafael Espindola Ret.p = reinterpret_cast<uintptr_t>(Sec); 2478bab889bSRafael Espindola return section_iterator(SectionRef(Ret, this)); 24832173153SMichael J. Spencer } 24932173153SMichael J. Spencer 2506bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2516bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2526bf32210SRafael Espindola return Symb.getSectionNumber(); 2536bf32210SRafael Espindola } 2546bf32210SRafael Espindola 2555e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2568ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2578ff24d25SRui Ueyama Sec += 1; 2588ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2598e90adafSMichael J. Spencer } 2608e90adafSMichael J. Spencer 261db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 2621d6167fdSMichael J. Spencer StringRef &Result) const { 2638ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2648ff24d25SRui Ueyama return getSectionName(Sec, Result); 2658e90adafSMichael J. Spencer } 2668e90adafSMichael J. Spencer 26780291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2688ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2697c6a071bSDavid Majnemer uint64_t Result = Sec->VirtualAddress; 2707c6a071bSDavid Majnemer 2717c6a071bSDavid Majnemer // The section VirtualAddress does not include ImageBase, and we want to 2727c6a071bSDavid Majnemer // return virtual addresses. 27321427adaSReid Kleckner Result += getImageBase(); 2747c6a071bSDavid Majnemer return Result; 2758e90adafSMichael J. Spencer } 2768e90adafSMichael J. Spencer 27780291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 278a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2798e90adafSMichael J. Spencer } 2808e90adafSMichael J. Spencer 281db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 2821d6167fdSMichael J. Spencer StringRef &Result) const { 2838ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2849da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 285db4ed0bdSRafael Espindola std::error_code EC = getSectionContents(Sec, Res); 2869da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2879da9e693SMichael J. Spencer return EC; 2888e90adafSMichael J. Spencer } 2898e90adafSMichael J. Spencer 29080291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 2918ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 292511391feSDavid Majnemer return Sec->getAlignment(); 2937989460aSMichael J. Spencer } 2947989460aSMichael J. Spencer 295401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 296401e4e57SGeorge Rimar return false; 297401e4e57SGeorge Rimar } 298401e4e57SGeorge Rimar 29980291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3008ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 30180291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3028e90adafSMichael J. Spencer } 3038e90adafSMichael J. Spencer 30480291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3058ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 30680291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 307800619f2SMichael J. Spencer } 308800619f2SMichael J. Spencer 30980291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3108ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3111a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3121a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3131a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3141a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 315800619f2SMichael J. Spencer } 316800619f2SMichael J. Spencer 3176bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3186bf32210SRafael Espindola uintptr_t Offset = 3196bf32210SRafael Espindola uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 3206bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3216bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3226bf32210SRafael Espindola } 3236bf32210SRafael Espindola 32480291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3258ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3261a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3271a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3281a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3292138ef6dSPreston Gurd } 3302138ef6dSPreston Gurd 331e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 332e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 333e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 334e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 335e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 336e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 337e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 338e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 339e830c60dSDavid Majnemer if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 340e830c60dSDavid Majnemer base + Sec->PointerToRelocations))) 341e830c60dSDavid Majnemer return 0; 34298fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 34398fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 344e830c60dSDavid Majnemer } 345e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 346e830c60dSDavid Majnemer } 347e830c60dSDavid Majnemer 34894751be7SDavid Majnemer static const coff_relocation * 34994751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 35094751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 35194751be7SDavid Majnemer if (!NumRelocs) 35294751be7SDavid Majnemer return nullptr; 353827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 35494751be7SDavid Majnemer Base + Sec->PointerToRelocations); 355827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 356827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 357827c8a2bSRui Ueyama // relocations. 358827c8a2bSRui Ueyama begin++; 359827c8a2bSRui Ueyama } 36094751be7SDavid Majnemer if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 36194751be7SDavid Majnemer return nullptr; 36294751be7SDavid Majnemer return begin; 363827c8a2bSRui Ueyama } 36494751be7SDavid Majnemer 36594751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 36694751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 36794751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 36876d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 36976d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 37094751be7SDavid Majnemer DataRefImpl Ret; 37194751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 3728ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 373e5fd0047SMichael J. Spencer } 374e5fd0047SMichael J. Spencer 3758ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 3768ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 37794751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 37894751be7SDavid Majnemer if (I) 37994751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 3808ff24d25SRui Ueyama DataRefImpl Ret; 38194751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 3828ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 383e5fd0047SMichael J. Spencer } 384e5fd0047SMichael J. Spencer 385c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 386db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initSymbolTablePtr() { 38744f51e51SDavid Majnemer if (COFFHeader) 388236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 389236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 390236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 39144f51e51SDavid Majnemer return EC; 39244f51e51SDavid Majnemer 39344f51e51SDavid Majnemer if (COFFBigObjHeader) 394236b0ca7SDavid Majnemer if (std::error_code EC = getObject( 395236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 396236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 3978ff24d25SRui Ueyama return EC; 398c2bed429SRui Ueyama 399c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 400c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 401c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 402f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 40344f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 404f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 405c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 40648af1c2aSRafael Espindola if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 4078ff24d25SRui Ueyama return EC; 408c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 409db4ed0bdSRafael Espindola if (std::error_code EC = 41048af1c2aSRafael Espindola getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4118ff24d25SRui Ueyama return EC; 412c2bed429SRui Ueyama 413773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 414773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 415773a5795SNico Rieck if (StringTableSize < 4) 416773a5795SNico Rieck StringTableSize = 4; 417773a5795SNico Rieck 418c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 419773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 420c2bed429SRui Ueyama return object_error::parse_failed; 4217d099195SRui Ueyama return std::error_code(); 422c2bed429SRui Ueyama } 423c2bed429SRui Ueyama 42421427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 425e94fef7bSReid Kleckner if (PE32Header) 42621427adaSReid Kleckner return PE32Header->ImageBase; 427e94fef7bSReid Kleckner else if (PE32PlusHeader) 42821427adaSReid Kleckner return PE32PlusHeader->ImageBase; 42921427adaSReid Kleckner // This actually comes up in practice. 43021427adaSReid Kleckner return 0; 431e94fef7bSReid Kleckner } 432e94fef7bSReid Kleckner 433215a586cSRui Ueyama // Returns the file offset for the given VA. 434db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 43521427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 436b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 437b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 438b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 439215a586cSRui Ueyama } 440215a586cSRui Ueyama 441c2bed429SRui Ueyama // Returns the file offset for the given RVA. 442db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 44327dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 44427dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 445c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 446c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 447215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 448215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 449c2bed429SRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4507d099195SRui Ueyama return std::error_code(); 451c2bed429SRui Ueyama } 452c2bed429SRui Ueyama } 453c2bed429SRui Ueyama return object_error::parse_failed; 454c2bed429SRui Ueyama } 455c2bed429SRui Ueyama 4562da433eaSReid Kleckner std::error_code 4572da433eaSReid Kleckner COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4582da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4592da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4602da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4612da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4622da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4632da433eaSReid Kleckner // overflow. 4642da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4652da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4662da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 4672da433eaSReid Kleckner uintptr_t Begin = 4682da433eaSReid Kleckner uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 4692da433eaSReid Kleckner Contents = 4702da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 4712da433eaSReid Kleckner return std::error_code(); 4722da433eaSReid Kleckner } 4732da433eaSReid Kleckner } 4742da433eaSReid Kleckner return object_error::parse_failed; 4752da433eaSReid Kleckner } 4762da433eaSReid Kleckner 477c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 478c2bed429SRui Ueyama // table entry. 479db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 480db4ed0bdSRafael Espindola StringRef &Name) const { 481c2bed429SRui Ueyama uintptr_t IntPtr = 0; 482db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 4838ff24d25SRui Ueyama return EC; 484c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 485c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 486c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 4877d099195SRui Ueyama return std::error_code(); 488c2bed429SRui Ueyama } 489c2bed429SRui Ueyama 4902da433eaSReid Kleckner std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 4912da433eaSReid Kleckner const debug_pdb_info *&PDBInfo, 4922da433eaSReid Kleckner StringRef &PDBFileName) const { 4932da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 4942da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 4952da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 4962da433eaSReid Kleckner return EC; 4972da433eaSReid Kleckner if (InfoBytes.size() < sizeof(debug_pdb_info) + 1) 4982da433eaSReid Kleckner return object_error::parse_failed; 4992da433eaSReid Kleckner PDBInfo = reinterpret_cast<const debug_pdb_info *>(InfoBytes.data()); 5002da433eaSReid Kleckner InfoBytes = InfoBytes.drop_front(sizeof(debug_pdb_info)); 5012da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5022da433eaSReid Kleckner InfoBytes.size()); 5032da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5042da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5052da433eaSReid Kleckner return std::error_code(); 5062da433eaSReid Kleckner } 5072da433eaSReid Kleckner 508f27f3f84SReid Kleckner std::error_code COFFObjectFile::getDebugPDBInfo(const debug_pdb_info *&PDBInfo, 509f27f3f84SReid Kleckner StringRef &PDBFileName) const { 510f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 511f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 512f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 513f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 514f27f3f84SReid Kleckner PDBInfo = nullptr; 515f27f3f84SReid Kleckner PDBFileName = StringRef(); 516f27f3f84SReid Kleckner return std::error_code(); 517f27f3f84SReid Kleckner } 518f27f3f84SReid Kleckner 519c2bed429SRui Ueyama // Find the import table. 520db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 521c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 522c2bed429SRui Ueyama // the import table, do nothing. 523c2bed429SRui Ueyama const data_directory *DataEntry; 524c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5257d099195SRui Ueyama return std::error_code(); 526c2bed429SRui Ueyama 527c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 528c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5297d099195SRui Ueyama return std::error_code(); 530c2bed429SRui Ueyama 531c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 532c2bed429SRui Ueyama 533c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 534c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 535c2bed429SRui Ueyama uintptr_t IntPtr = 0; 536db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5378ff24d25SRui Ueyama return EC; 538*ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 539*ad7b7e73SDavid Majnemer return EC; 540c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 541c2bed429SRui Ueyama const import_directory_table_entry *>(IntPtr); 5427d099195SRui Ueyama return std::error_code(); 543ad882ba8SRui Ueyama } 544c2bed429SRui Ueyama 54515d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 54615d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 54715d99359SRui Ueyama const data_directory *DataEntry; 54815d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5497d099195SRui Ueyama return std::error_code(); 55015d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5517d099195SRui Ueyama return std::error_code(); 55215d99359SRui Ueyama 55315d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 55415d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 55515d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 55615d99359SRui Ueyama 55715d99359SRui Ueyama uintptr_t IntPtr = 0; 55815d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 55915d99359SRui Ueyama return EC; 56015d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 56115d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5627d099195SRui Ueyama return std::error_code(); 56315d99359SRui Ueyama } 56415d99359SRui Ueyama 565ad882ba8SRui Ueyama // Find the export table. 566db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 567ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 568ad882ba8SRui Ueyama // the export table, do nothing. 569ad882ba8SRui Ueyama const data_directory *DataEntry; 570ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5717d099195SRui Ueyama return std::error_code(); 572ad882ba8SRui Ueyama 573ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 574ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5757d099195SRui Ueyama return std::error_code(); 576ad882ba8SRui Ueyama 577ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 578ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 579db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 580ad882ba8SRui Ueyama return EC; 58124fc2d64SRui Ueyama ExportDirectory = 58224fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 5837d099195SRui Ueyama return std::error_code(); 584c2bed429SRui Ueyama } 585c2bed429SRui Ueyama 58674e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 58774e85130SRui Ueyama const data_directory *DataEntry; 58874e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 5897d099195SRui Ueyama return std::error_code(); 59074e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5917d099195SRui Ueyama return std::error_code(); 59274e85130SRui Ueyama 59374e85130SRui Ueyama uintptr_t IntPtr = 0; 59474e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 59574e85130SRui Ueyama return EC; 59674e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 59774e85130SRui Ueyama IntPtr); 59874e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 59974e85130SRui Ueyama IntPtr + DataEntry->Size); 6007d099195SRui Ueyama return std::error_code(); 60174e85130SRui Ueyama } 60274e85130SRui Ueyama 6032da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6042da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6052da433eaSReid Kleckner const data_directory *DataEntry; 6062da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6072da433eaSReid Kleckner return std::error_code(); 6082da433eaSReid Kleckner 6092da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6102da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6112da433eaSReid Kleckner return std::error_code(); 6122da433eaSReid Kleckner 6132da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6142da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6152da433eaSReid Kleckner return object_error::parse_failed; 6162da433eaSReid Kleckner 6172da433eaSReid Kleckner uintptr_t IntPtr = 0; 6182da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6192da433eaSReid Kleckner return EC; 6202da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6212da433eaSReid Kleckner if (std::error_code EC = getRvaPtr( 6222da433eaSReid Kleckner DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 6232da433eaSReid Kleckner return EC; 6242da433eaSReid Kleckner DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 6252da433eaSReid Kleckner return std::error_code(); 6262da433eaSReid Kleckner } 6272da433eaSReid Kleckner 62848af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 62948af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 63044f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 63144f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 63244f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 633*ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 63415d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6352da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6362da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6371d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 63848af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 639c3f9b5a5SRafael Espindola return; 640ee066fc4SEric Christopher 64182ebd8e3SRui Ueyama // The current location in the file where we are looking at. 64282ebd8e3SRui Ueyama uint64_t CurPtr = 0; 64382ebd8e3SRui Ueyama 64482ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 64582ebd8e3SRui Ueyama // it is placed right after COFF header. 6468ff24d25SRui Ueyama bool HasPEHeader = false; 647ee066fc4SEric Christopher 6481d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 64950267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 650ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 651ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 65250267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 65350267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 65450267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 65582ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 65650267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6578ff24d25SRui Ueyama EC = object_error::parse_failed; 6581d6167fdSMichael J. Spencer return; 6591d6167fdSMichael J. Spencer } 66044f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6618ff24d25SRui Ueyama HasPEHeader = true; 662ee066fc4SEric Christopher } 66350267222SDavid Majnemer } 664ee066fc4SEric Christopher 66548af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 6661d6167fdSMichael J. Spencer return; 66744f51e51SDavid Majnemer 66844f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 66944f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 67044f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 67144f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 67244f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 67344f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 67444f51e51SDavid Majnemer return; 67544f51e51SDavid Majnemer 67644f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 67744f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 67844f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 67944f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 68044f51e51SDavid Majnemer COFFHeader = nullptr; 68144f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 68244f51e51SDavid Majnemer } else { 68344f51e51SDavid Majnemer // It's not a bigobj. 68444f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 68544f51e51SDavid Majnemer } 68644f51e51SDavid Majnemer } 68744f51e51SDavid Majnemer if (COFFHeader) { 68844f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 68944f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 6907d099195SRui Ueyama EC = std::error_code(); 69182ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 69282ebd8e3SRui Ueyama 69344f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 69444f51e51SDavid Majnemer return; 69544f51e51SDavid Majnemer } 69644f51e51SDavid Majnemer 6978ff24d25SRui Ueyama if (HasPEHeader) { 69810ed9ddcSRui Ueyama const pe32_header *Header; 69948af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 70082ebd8e3SRui Ueyama return; 70110ed9ddcSRui Ueyama 70210ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 70310ed9ddcSRui Ueyama uint64_t DataDirSize; 70450267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 70510ed9ddcSRui Ueyama PE32Header = Header; 70610ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 70710ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 70850267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 70910ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 71010ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 71110ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 71210ed9ddcSRui Ueyama } else { 71310ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 71410ed9ddcSRui Ueyama EC = object_error::parse_failed; 715ed64342bSRui Ueyama return; 716ed64342bSRui Ueyama } 71748af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 71810ed9ddcSRui Ueyama return; 71982ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 72082ebd8e3SRui Ueyama } 7211d6167fdSMichael J. Spencer 72248af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 723236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7241d6167fdSMichael J. Spencer return; 7251d6167fdSMichael J. Spencer 726c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 727236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 7288ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 7291d6167fdSMichael J. Spencer return; 730236b0ca7SDavid Majnemer } else { 731236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 732236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 733236b0ca7SDavid Majnemer EC = object_error::parse_failed; 734236b0ca7SDavid Majnemer return; 735236b0ca7SDavid Majnemer } 736236b0ca7SDavid Majnemer } 7378e90adafSMichael J. Spencer 738c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7398ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 740ed64342bSRui Ueyama return; 74115d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 74215d99359SRui Ueyama return; 7431d6167fdSMichael J. Spencer 744ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7458ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 746ad882ba8SRui Ueyama return; 747ad882ba8SRui Ueyama 74874e85130SRui Ueyama // Initialize the pointer to the base relocation table. 74974e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 75074e85130SRui Ueyama return; 75174e85130SRui Ueyama 7522da433eaSReid Kleckner // Initialize the pointer to the export table. 7532da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 7542da433eaSReid Kleckner return; 7552da433eaSReid Kleckner 7567d099195SRui Ueyama EC = std::error_code(); 7578e90adafSMichael J. Spencer } 7588e90adafSMichael J. Spencer 759f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 7608ff24d25SRui Ueyama DataRefImpl Ret; 76144f51e51SDavid Majnemer Ret.p = getSymbolTable(); 762f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7638e90adafSMichael J. Spencer } 7648e90adafSMichael J. Spencer 765f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 7668e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 7678ff24d25SRui Ueyama DataRefImpl Ret; 7688ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 769f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7708e90adafSMichael J. Spencer } 7718e90adafSMichael J. Spencer 772bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 773*ad7b7e73SDavid Majnemer if (!ImportDirectory) 774*ad7b7e73SDavid Majnemer return import_directory_end(); 775*ad7b7e73SDavid Majnemer if (ImportDirectory[0].ImportLookupTableRVA == 0) 776*ad7b7e73SDavid Majnemer return import_directory_end(); 777a045b73aSRui Ueyama return import_directory_iterator( 778a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 779c2bed429SRui Ueyama } 780c2bed429SRui Ueyama 781bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 782a045b73aSRui Ueyama return import_directory_iterator( 783*ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 784c2bed429SRui Ueyama } 785c429b80dSDavid Meyer 78615d99359SRui Ueyama delay_import_directory_iterator 78715d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 78815d99359SRui Ueyama return delay_import_directory_iterator( 78915d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 79015d99359SRui Ueyama } 79115d99359SRui Ueyama 79215d99359SRui Ueyama delay_import_directory_iterator 79315d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 79415d99359SRui Ueyama return delay_import_directory_iterator( 79515d99359SRui Ueyama DelayImportDirectoryEntryRef( 79615d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 79715d99359SRui Ueyama } 79815d99359SRui Ueyama 799ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 800ad882ba8SRui Ueyama return export_directory_iterator( 801ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 802ad882ba8SRui Ueyama } 803ad882ba8SRui Ueyama 804ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8052617dcceSCraig Topper if (!ExportDirectory) 8062617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8078ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 808ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8098ff24d25SRui Ueyama return export_directory_iterator(Ref); 810ad882ba8SRui Ueyama } 811ad882ba8SRui Ueyama 812b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8138ff24d25SRui Ueyama DataRefImpl Ret; 8148ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8158ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8168e90adafSMichael J. Spencer } 8178e90adafSMichael J. Spencer 818b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8198ff24d25SRui Ueyama DataRefImpl Ret; 82044f51e51SDavid Majnemer int NumSections = 82144f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8228ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8238ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8248e90adafSMichael J. Spencer } 8258e90adafSMichael J. Spencer 82674e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 82774e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 82874e85130SRui Ueyama } 82974e85130SRui Ueyama 83074e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 83174e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 83274e85130SRui Ueyama } 83374e85130SRui Ueyama 8348e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 8350324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 8368e90adafSMichael J. Spencer } 8378e90adafSMichael J. Spencer 8388e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 83944f51e51SDavid Majnemer switch(getMachine()) { 8408e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8418e90adafSMichael J. Spencer return "COFF-i386"; 8428e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8438e90adafSMichael J. Spencer return "COFF-x86-64"; 8449b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8459b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8461eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8471eff5c9cSMartell Malone return "COFF-ARM64"; 8488e90adafSMichael J. Spencer default: 8498e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8508e90adafSMichael J. Spencer } 8518e90adafSMichael J. Spencer } 8528e90adafSMichael J. Spencer 8538e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 85444f51e51SDavid Majnemer switch (getMachine()) { 8558e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8568e90adafSMichael J. Spencer return Triple::x86; 8578e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8588e90adafSMichael J. Spencer return Triple::x86_64; 8599b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8609b7c0af2SSaleem Abdulrasool return Triple::thumb; 8611eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8621eff5c9cSMartell Malone return Triple::aarch64; 8638e90adafSMichael J. Spencer default: 8648e90adafSMichael J. Spencer return Triple::UnknownArch; 8658e90adafSMichael J. Spencer } 8668e90adafSMichael J. Spencer } 8678e90adafSMichael J. Spencer 868979fb40bSRui Ueyama iterator_range<import_directory_iterator> 869979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 870979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 871979fb40bSRui Ueyama } 872979fb40bSRui Ueyama 873979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 874979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 875979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 876979fb40bSRui Ueyama delay_import_directory_end()); 877979fb40bSRui Ueyama } 878979fb40bSRui Ueyama 879979fb40bSRui Ueyama iterator_range<export_directory_iterator> 880979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 881979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 882979fb40bSRui Ueyama } 883979fb40bSRui Ueyama 88474e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 88574e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 88674e85130SRui Ueyama } 88774e85130SRui Ueyama 888db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 88982ebd8e3SRui Ueyama Res = PE32Header; 8907d099195SRui Ueyama return std::error_code(); 89189a7a5eaSMichael J. Spencer } 89289a7a5eaSMichael J. Spencer 893db4ed0bdSRafael Espindola std::error_code 89410ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 89510ed9ddcSRui Ueyama Res = PE32PlusHeader; 8967d099195SRui Ueyama return std::error_code(); 89710ed9ddcSRui Ueyama } 89810ed9ddcSRui Ueyama 899db4ed0bdSRafael Espindola std::error_code 900db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 901ed64342bSRui Ueyama const data_directory *&Res) const { 902ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 903f69b0585SDavid Majnemer if (!DataDirectory) { 904f69b0585SDavid Majnemer Res = nullptr; 90510ed9ddcSRui Ueyama return object_error::parse_failed; 906f69b0585SDavid Majnemer } 90710ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 90810ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 90910ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 910f69b0585SDavid Majnemer if (Index >= NumEnt) { 911f69b0585SDavid Majnemer Res = nullptr; 912ed64342bSRui Ueyama return object_error::parse_failed; 913f69b0585SDavid Majnemer } 9148ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9157d099195SRui Ueyama return std::error_code(); 916ed64342bSRui Ueyama } 917ed64342bSRui Ueyama 918db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9191d6167fdSMichael J. Spencer const coff_section *&Result) const { 9202617dcceSCraig Topper Result = nullptr; 921236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9227d099195SRui Ueyama return std::error_code(); 923236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9241d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9258ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9267d099195SRui Ueyama return std::error_code(); 9278e90adafSMichael J. Spencer } 928236b0ca7SDavid Majnemer return object_error::parse_failed; 929236b0ca7SDavid Majnemer } 9308e90adafSMichael J. Spencer 931db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9321d6167fdSMichael J. Spencer StringRef &Result) const { 9331d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9341d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9351d6167fdSMichael J. Spencer return object_error::parse_failed; 9368ff24d25SRui Ueyama if (Offset >= StringTableSize) 9371d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9388ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9397d099195SRui Ueyama return std::error_code(); 9408e90adafSMichael J. Spencer } 941022ecdf2SBenjamin Kramer 94244f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 94389a7a5eaSMichael J. Spencer StringRef &Res) const { 944e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 945e40d30f3SRui Ueyama } 946e40d30f3SRui Ueyama 947e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 948e40d30f3SRui Ueyama StringRef &Res) const { 94989a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 950e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 951e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 9528ff24d25SRui Ueyama return EC; 9537d099195SRui Ueyama return std::error_code(); 95489a7a5eaSMichael J. Spencer } 95589a7a5eaSMichael J. Spencer 956e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 95789a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 958e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 95989a7a5eaSMichael J. Spencer else 96089a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 961e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 9627d099195SRui Ueyama return std::error_code(); 96389a7a5eaSMichael J. Spencer } 96489a7a5eaSMichael J. Spencer 96544f51e51SDavid Majnemer ArrayRef<uint8_t> 96644f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 9672617dcceSCraig Topper const uint8_t *Aux = nullptr; 96871757ef3SMarshall Clow 96944f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 97044f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 97171757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 97244f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 97371757ef3SMarshall Clow # ifndef NDEBUG 9748ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 9758ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 97644f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 97744f51e51SDavid Majnemer Offset >= 97844f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 97971757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 98071757ef3SMarshall Clow 98144f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 98244f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 98371757ef3SMarshall Clow # endif 984bfb85e67SMarshall Clow } 98544f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 98671757ef3SMarshall Clow } 98771757ef3SMarshall Clow 988db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 98953c2d547SMichael J. Spencer StringRef &Res) const { 99053c2d547SMichael J. Spencer StringRef Name; 99144f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 99253c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 99353c2d547SMichael J. Spencer Name = Sec->Name; 99453c2d547SMichael J. Spencer else 99553c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 99644f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 99753c2d547SMichael J. Spencer 99853c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 9992314b3deSDavid Majnemer if (Name.startswith("/")) { 100053c2d547SMichael J. Spencer uint32_t Offset; 10012314b3deSDavid Majnemer if (Name.startswith("//")) { 10029d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10039d2c15efSNico Rieck return object_error::parse_failed; 10049d2c15efSNico Rieck } else { 100553c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 100653c2d547SMichael J. Spencer return object_error::parse_failed; 10079d2c15efSNico Rieck } 1008db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 10098ff24d25SRui Ueyama return EC; 101053c2d547SMichael J. Spencer } 101153c2d547SMichael J. Spencer 101253c2d547SMichael J. Spencer Res = Name; 10137d099195SRui Ueyama return std::error_code(); 101453c2d547SMichael J. Spencer } 101553c2d547SMichael J. Spencer 1016a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1017a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1018a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1019a9ee5c06SDavid Majnemer // 1020a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1021d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1022a9ee5c06SDavid Majnemer // 1023a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1024a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1025a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1026a9ee5c06SDavid Majnemer // considered to be zero. 1027d5297ee7SRui Ueyama if (getDOSHeader()) 1028d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1029d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1030a9ee5c06SDavid Majnemer } 1031a9ee5c06SDavid Majnemer 1032db4ed0bdSRafael Espindola std::error_code 1033db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10349da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1035e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1036e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1037e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1038e2129662SDavid Majnemer return object_error::parse_failed; 10399da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10409da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10419da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10429da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1043a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1044e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10459da9e693SMichael J. Spencer return object_error::parse_failed; 1046a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10477d099195SRui Ueyama return std::error_code(); 10489da9e693SMichael J. Spencer } 10499da9e693SMichael J. Spencer 1050022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1051e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1052022ecdf2SBenjamin Kramer } 10538ff24d25SRui Ueyama 10545e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1055e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1056e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1057022ecdf2SBenjamin Kramer } 10588ff24d25SRui Ueyama 105996d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 106058323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 106196d071cdSRafael Espindola return R->VirtualAddress; 1062cbe72fc9SDanil Malyshev } 10638ff24d25SRui Ueyama 1064806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1065022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 10668ff24d25SRui Ueyama DataRefImpl Ref; 1067236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1068236b0ca7SDavid Majnemer return symbol_end(); 106944f51e51SDavid Majnemer if (SymbolTable16) 107044f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 107144f51e51SDavid Majnemer else if (SymbolTable32) 107244f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 107344f51e51SDavid Majnemer else 1074c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 10758ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1076022ecdf2SBenjamin Kramer } 10778ff24d25SRui Ueyama 107899c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1079022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 108099c041b7SRafael Espindola return R->Type; 1081022ecdf2SBenjamin Kramer } 1082e5fd0047SMichael J. Spencer 108327dc8394SAlexey Samsonov const coff_section * 108427dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 108527dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 108671757ef3SMarshall Clow } 108771757ef3SMarshall Clow 108844f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 108944f51e51SDavid Majnemer if (SymbolTable16) 109044f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 109144f51e51SDavid Majnemer if (SymbolTable32) 109244f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 109344f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 109444f51e51SDavid Majnemer } 109544f51e51SDavid Majnemer 109644f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 109744f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 109871757ef3SMarshall Clow } 109971757ef3SMarshall Clow 1100f12b8282SRafael Espindola const coff_relocation * 110127dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 110227dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1103d3e2a76cSMarshall Clow } 1104d3e2a76cSMarshall Clow 11056a75acb1SRui Ueyama iterator_range<const coff_relocation *> 11066a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11076a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 11086a75acb1SRui Ueyama const coff_relocation *E = I; 11096a75acb1SRui Ueyama if (I) 11106a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 11116a75acb1SRui Ueyama return make_range(I, E); 11126a75acb1SRui Ueyama } 11136a75acb1SRui Ueyama 111427dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 111527dc8394SAlexey Samsonov case COFF::reloc_type: \ 111627dc8394SAlexey Samsonov Res = #reloc_type; \ 111727dc8394SAlexey Samsonov break; 1118e5fd0047SMichael J. Spencer 111941bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 112041bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 11218ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11228ff24d25SRui Ueyama StringRef Res; 112344f51e51SDavid Majnemer switch (getMachine()) { 1124e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11258ff24d25SRui Ueyama switch (Reloc->Type) { 1126e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1127e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1128e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1129e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1130e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1131e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1132e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1133e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1134e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1135e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1136e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1137e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1138e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1139e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1140e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1141e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1142e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1143e5fd0047SMichael J. Spencer default: 11448ff24d25SRui Ueyama Res = "Unknown"; 1145e5fd0047SMichael J. Spencer } 1146e5fd0047SMichael J. Spencer break; 11475c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11485c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 11495c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11505c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11515c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11525c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11535c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11545c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 11555c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 11565c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 11575c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 11585c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 11595c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 11605c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 11615c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 11625c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 11635c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 11645c503bf4SSaleem Abdulrasool default: 11655c503bf4SSaleem Abdulrasool Res = "Unknown"; 11665c503bf4SSaleem Abdulrasool } 11675c503bf4SSaleem Abdulrasool break; 1168e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 11698ff24d25SRui Ueyama switch (Reloc->Type) { 1170e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1171e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1172e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1173e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1174e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1175e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1176e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1177e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1178e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1179e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1180e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1181e5fd0047SMichael J. Spencer default: 11828ff24d25SRui Ueyama Res = "Unknown"; 1183e5fd0047SMichael J. Spencer } 1184e5fd0047SMichael J. Spencer break; 1185e5fd0047SMichael J. Spencer default: 11868ff24d25SRui Ueyama Res = "Unknown"; 1187e5fd0047SMichael J. Spencer } 11888ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1189e5fd0047SMichael J. Spencer } 1190e5fd0047SMichael J. Spencer 1191e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1192e5fd0047SMichael J. Spencer 1193c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1194c66d761bSRafael Espindola return !DataDirectory; 1195c66d761bSRafael Espindola } 1196c66d761bSRafael Espindola 1197c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1198c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1199a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1200c2bed429SRui Ueyama } 1201c2bed429SRui Ueyama 12025e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12035e812afaSRafael Espindola ++Index; 1204*ad7b7e73SDavid Majnemer if (ImportTable[Index].ImportLookupTableRVA == 0) { 1205*ad7b7e73SDavid Majnemer Index = -1; 1206*ad7b7e73SDavid Majnemer ImportTable = nullptr; 1207*ad7b7e73SDavid Majnemer } 1208c2bed429SRui Ueyama } 1209c2bed429SRui Ueyama 1210db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 1211db4ed0bdSRafael Espindola const import_directory_table_entry *&Result) const { 1212*ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1213c2bed429SRui Ueyama } 1214c2bed429SRui Ueyama 1215861021f9SRui Ueyama static imported_symbol_iterator 121615d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1217861021f9SRui Ueyama uintptr_t Ptr, int Index) { 121815d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1219861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 122015d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1221861021f9SRui Ueyama } 1222861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 122315d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1224861021f9SRui Ueyama } 1225861021f9SRui Ueyama 122615d99359SRui Ueyama static imported_symbol_iterator 122715d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1228861021f9SRui Ueyama uintptr_t IntPtr = 0; 122915d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 123015d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1231861021f9SRui Ueyama } 1232861021f9SRui Ueyama 123315d99359SRui Ueyama static imported_symbol_iterator 123415d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1235861021f9SRui Ueyama uintptr_t IntPtr = 0; 123615d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1237861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1238861021f9SRui Ueyama int Index = 0; 123915d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1240861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1241861021f9SRui Ueyama while (*Entry++) 1242861021f9SRui Ueyama ++Index; 1243861021f9SRui Ueyama } else { 1244861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1245861021f9SRui Ueyama while (*Entry++) 1246861021f9SRui Ueyama ++Index; 1247861021f9SRui Ueyama } 124815d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 124915d99359SRui Ueyama } 125015d99359SRui Ueyama 125115d99359SRui Ueyama imported_symbol_iterator 125215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 125315d99359SRui Ueyama return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 125415d99359SRui Ueyama OwningObject); 125515d99359SRui Ueyama } 125615d99359SRui Ueyama 125715d99359SRui Ueyama imported_symbol_iterator 125815d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 125915d99359SRui Ueyama return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 126015d99359SRui Ueyama OwningObject); 1261861021f9SRui Ueyama } 1262861021f9SRui Ueyama 1263979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1264979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1265979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1266979fb40bSRui Ueyama } 1267979fb40bSRui Ueyama 1268db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1269c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1270db4ed0bdSRafael Espindola if (std::error_code EC = 12711e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1272a045b73aSRui Ueyama return EC; 1273a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 12747d099195SRui Ueyama return std::error_code(); 1275c2bed429SRui Ueyama } 1276c2bed429SRui Ueyama 12771e152d5eSRui Ueyama std::error_code 12781e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 12791e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 12807d099195SRui Ueyama return std::error_code(); 12811e152d5eSRui Ueyama } 12821e152d5eSRui Ueyama 12831e152d5eSRui Ueyama std::error_code 12841e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 12851e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 12867d099195SRui Ueyama return std::error_code(); 12871e152d5eSRui Ueyama } 12881e152d5eSRui Ueyama 128915d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 129015d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 129115d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 129215d99359SRui Ueyama } 129315d99359SRui Ueyama 129415d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 129515d99359SRui Ueyama ++Index; 129615d99359SRui Ueyama } 129715d99359SRui Ueyama 129815d99359SRui Ueyama imported_symbol_iterator 129915d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 130015d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 130115d99359SRui Ueyama OwningObject); 130215d99359SRui Ueyama } 130315d99359SRui Ueyama 130415d99359SRui Ueyama imported_symbol_iterator 130515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 130615d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 130715d99359SRui Ueyama OwningObject); 130815d99359SRui Ueyama } 130915d99359SRui Ueyama 1310979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1311979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1312979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1313979fb40bSRui Ueyama } 1314979fb40bSRui Ueyama 131515d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 131615d99359SRui Ueyama uintptr_t IntPtr = 0; 131715d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 131815d99359SRui Ueyama return EC; 131915d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13207d099195SRui Ueyama return std::error_code(); 132115d99359SRui Ueyama } 132215d99359SRui Ueyama 13231af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 13241af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 13251af08658SRui Ueyama Result = Table; 13267d099195SRui Ueyama return std::error_code(); 13271af08658SRui Ueyama } 13281af08658SRui Ueyama 1329ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1330ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1331ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1332ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1333ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1334ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1335ffa4cebeSRui Ueyama return EC; 1336ffa4cebeSRui Ueyama if (OwningObject->is64()) 13375dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1338ffa4cebeSRui Ueyama else 13395dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 13407d099195SRui Ueyama return std::error_code(); 1341ffa4cebeSRui Ueyama } 1342ffa4cebeSRui Ueyama 1343ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1344ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1345ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1346ad882ba8SRui Ueyama } 1347ad882ba8SRui Ueyama 13485e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 13495e812afaSRafael Espindola ++Index; 1350ad882ba8SRui Ueyama } 1351ad882ba8SRui Ueyama 1352da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1353da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1354db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1355da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1356db4ed0bdSRafael Espindola if (std::error_code EC = 1357db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1358da49d0d4SRui Ueyama return EC; 1359da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13607d099195SRui Ueyama return std::error_code(); 1361da49d0d4SRui Ueyama } 1362da49d0d4SRui Ueyama 1363e5df6095SRui Ueyama // Returns the starting ordinal number. 1364db4ed0bdSRafael Espindola std::error_code 1365db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1366e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 13677d099195SRui Ueyama return std::error_code(); 1368e5df6095SRui Ueyama } 1369e5df6095SRui Ueyama 1370ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1371db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1372ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 13737d099195SRui Ueyama return std::error_code(); 1374ad882ba8SRui Ueyama } 1375ad882ba8SRui Ueyama 1376ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1377db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1378ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1379db4ed0bdSRafael Espindola if (std::error_code EC = 1380db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1381ad882ba8SRui Ueyama return EC; 138224fc2d64SRui Ueyama const export_address_table_entry *entry = 138324fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1384ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 13857d099195SRui Ueyama return std::error_code(); 1386ad882ba8SRui Ueyama } 1387ad882ba8SRui Ueyama 1388ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1389ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1390db4ed0bdSRafael Espindola std::error_code 1391db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1392ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1393db4ed0bdSRafael Espindola if (std::error_code EC = 1394db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1395ad882ba8SRui Ueyama return EC; 1396ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1397ad882ba8SRui Ueyama 1398ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1399ad882ba8SRui Ueyama int Offset = 0; 1400ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1401ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1402ad882ba8SRui Ueyama if (*I != Index) 1403ad882ba8SRui Ueyama continue; 1404db4ed0bdSRafael Espindola if (std::error_code EC = 1405db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1406ad882ba8SRui Ueyama return EC; 1407ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1408db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1409ad882ba8SRui Ueyama return EC; 1410ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14117d099195SRui Ueyama return std::error_code(); 1412ad882ba8SRui Ueyama } 1413ad882ba8SRui Ueyama Result = ""; 14147d099195SRui Ueyama return std::error_code(); 1415ad882ba8SRui Ueyama } 1416ad882ba8SRui Ueyama 14176161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 14186161b38dSRui Ueyama const data_directory *DataEntry; 14196161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 14206161b38dSRui Ueyama return EC; 14216161b38dSRui Ueyama uint32_t RVA; 14226161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14236161b38dSRui Ueyama return EC; 14246161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 14256161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 14266161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 14276161b38dSRui Ueyama return std::error_code(); 14286161b38dSRui Ueyama } 14296161b38dSRui Ueyama 14306161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 14316161b38dSRui Ueyama uint32_t RVA; 14326161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14336161b38dSRui Ueyama return EC; 14346161b38dSRui Ueyama uintptr_t IntPtr = 0; 14356161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 14366161b38dSRui Ueyama return EC; 14376161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14386161b38dSRui Ueyama return std::error_code(); 14396161b38dSRui Ueyama } 14406161b38dSRui Ueyama 1441861021f9SRui Ueyama bool ImportedSymbolRef:: 1442861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1443861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1444861021f9SRui Ueyama && Index == Other.Index; 1445861021f9SRui Ueyama } 1446861021f9SRui Ueyama 1447861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1448861021f9SRui Ueyama ++Index; 1449861021f9SRui Ueyama } 1450861021f9SRui Ueyama 1451861021f9SRui Ueyama std::error_code 1452861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1453861021f9SRui Ueyama uint32_t RVA; 1454861021f9SRui Ueyama if (Entry32) { 1455861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1456861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 14577d099195SRui Ueyama return std::error_code(); 1458861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1459861021f9SRui Ueyama } else { 1460861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 14617d099195SRui Ueyama return std::error_code(); 1462861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1463861021f9SRui Ueyama } 1464861021f9SRui Ueyama uintptr_t IntPtr = 0; 1465861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1466861021f9SRui Ueyama return EC; 1467861021f9SRui Ueyama // +2 because the first two bytes is hint. 1468861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 14697d099195SRui Ueyama return std::error_code(); 1470861021f9SRui Ueyama } 1471861021f9SRui Ueyama 1472*ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1473*ad7b7e73SDavid Majnemer if (Entry32) 1474*ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1475*ad7b7e73SDavid Majnemer else 1476*ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1477*ad7b7e73SDavid Majnemer return std::error_code(); 1478*ad7b7e73SDavid Majnemer } 1479*ad7b7e73SDavid Majnemer 1480*ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1481*ad7b7e73SDavid Majnemer if (Entry32) 1482*ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1483*ad7b7e73SDavid Majnemer else 1484*ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1485*ad7b7e73SDavid Majnemer return std::error_code(); 1486*ad7b7e73SDavid Majnemer } 1487*ad7b7e73SDavid Majnemer 1488861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1489861021f9SRui Ueyama uint32_t RVA; 1490861021f9SRui Ueyama if (Entry32) { 1491861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1492861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 14937d099195SRui Ueyama return std::error_code(); 1494861021f9SRui Ueyama } 1495861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1496861021f9SRui Ueyama } else { 1497861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1498861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 14997d099195SRui Ueyama return std::error_code(); 1500861021f9SRui Ueyama } 1501861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1502861021f9SRui Ueyama } 1503861021f9SRui Ueyama uintptr_t IntPtr = 0; 1504861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1505861021f9SRui Ueyama return EC; 1506861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15077d099195SRui Ueyama return std::error_code(); 1508861021f9SRui Ueyama } 1509861021f9SRui Ueyama 1510437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 151148af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1512db4ed0bdSRafael Espindola std::error_code EC; 151348af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1514692410efSRafael Espindola if (EC) 1515692410efSRafael Espindola return EC; 1516437b0d58SRafael Espindola return std::move(Ret); 1517686738e2SRui Ueyama } 151874e85130SRui Ueyama 151974e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 152074e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 152174e85130SRui Ueyama } 152274e85130SRui Ueyama 152374e85130SRui Ueyama void BaseRelocRef::moveNext() { 152474e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 152574e85130SRui Ueyama // size of the header itself. 152674e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1527970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 152874e85130SRui Ueyama if (Size == Header->BlockSize) { 152974e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 153074e85130SRui Ueyama // consists of the header followed by entries. The header contains 153174e85130SRui Ueyama // how many entories will follow. When we reach the end of the 153274e85130SRui Ueyama // current block, proceed to the next block. 153374e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 153474e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 153574e85130SRui Ueyama Index = 0; 153674e85130SRui Ueyama } else { 153774e85130SRui Ueyama ++Index; 153874e85130SRui Ueyama } 153974e85130SRui Ueyama } 154074e85130SRui Ueyama 154174e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 154274e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 154374e85130SRui Ueyama Type = Entry[Index].getType(); 15447d099195SRui Ueyama return std::error_code(); 154574e85130SRui Ueyama } 154674e85130SRui Ueyama 154774e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 154874e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 154974e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 15507d099195SRui Ueyama return std::error_code(); 155174e85130SRui Ueyama } 1552