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 49001528021SSaleem Abdulrasool std::error_code 49101528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 49201528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 4932da433eaSReid Kleckner StringRef &PDBFileName) const { 4942da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 4952da433eaSReid Kleckner if (std::error_code EC = getRvaAndSizeAsBytes( 4962da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 4972da433eaSReid Kleckner return EC; 49801528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 4992da433eaSReid Kleckner return object_error::parse_failed; 50001528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 50101528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5022da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5032da433eaSReid Kleckner InfoBytes.size()); 5042da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5052da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5062da433eaSReid Kleckner return std::error_code(); 5072da433eaSReid Kleckner } 5082da433eaSReid Kleckner 50901528021SSaleem Abdulrasool std::error_code 51001528021SSaleem Abdulrasool COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 511f27f3f84SReid Kleckner StringRef &PDBFileName) const { 512f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 513f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 514f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 515f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 516f27f3f84SReid Kleckner PDBInfo = nullptr; 517f27f3f84SReid Kleckner PDBFileName = StringRef(); 518f27f3f84SReid Kleckner return std::error_code(); 519f27f3f84SReid Kleckner } 520f27f3f84SReid Kleckner 521c2bed429SRui Ueyama // Find the import table. 522db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initImportTablePtr() { 523c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 524c2bed429SRui Ueyama // the import table, do nothing. 525c2bed429SRui Ueyama const data_directory *DataEntry; 526c2bed429SRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5277d099195SRui Ueyama return std::error_code(); 528c2bed429SRui Ueyama 529c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 530c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5317d099195SRui Ueyama return std::error_code(); 532c2bed429SRui Ueyama 533c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 534c2bed429SRui Ueyama 535c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 536c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 537c2bed429SRui Ueyama uintptr_t IntPtr = 0; 538db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 5398ff24d25SRui Ueyama return EC; 540ad7b7e73SDavid Majnemer if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 541ad7b7e73SDavid Majnemer return EC; 542c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5431c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5447d099195SRui Ueyama return std::error_code(); 545ad882ba8SRui Ueyama } 546c2bed429SRui Ueyama 54715d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 54815d99359SRui Ueyama std::error_code COFFObjectFile::initDelayImportTablePtr() { 54915d99359SRui Ueyama const data_directory *DataEntry; 55015d99359SRui Ueyama if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5517d099195SRui Ueyama return std::error_code(); 55215d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5537d099195SRui Ueyama return std::error_code(); 55415d99359SRui Ueyama 55515d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 55615d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 55715d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 55815d99359SRui Ueyama 55915d99359SRui Ueyama uintptr_t IntPtr = 0; 56015d99359SRui Ueyama if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 56115d99359SRui Ueyama return EC; 56215d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 56315d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5647d099195SRui Ueyama return std::error_code(); 56515d99359SRui Ueyama } 56615d99359SRui Ueyama 567ad882ba8SRui Ueyama // Find the export table. 568db4ed0bdSRafael Espindola std::error_code COFFObjectFile::initExportTablePtr() { 569ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 570ad882ba8SRui Ueyama // the export table, do nothing. 571ad882ba8SRui Ueyama const data_directory *DataEntry; 572ad882ba8SRui Ueyama if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5737d099195SRui Ueyama return std::error_code(); 574ad882ba8SRui Ueyama 575ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 576ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5777d099195SRui Ueyama return std::error_code(); 578ad882ba8SRui Ueyama 579ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 580ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 581db4ed0bdSRafael Espindola if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 582ad882ba8SRui Ueyama return EC; 58324fc2d64SRui Ueyama ExportDirectory = 58424fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 5857d099195SRui Ueyama return std::error_code(); 586c2bed429SRui Ueyama } 587c2bed429SRui Ueyama 58874e85130SRui Ueyama std::error_code COFFObjectFile::initBaseRelocPtr() { 58974e85130SRui Ueyama const data_directory *DataEntry; 59074e85130SRui Ueyama if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 5917d099195SRui Ueyama return std::error_code(); 59274e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5937d099195SRui Ueyama return std::error_code(); 59474e85130SRui Ueyama 59574e85130SRui Ueyama uintptr_t IntPtr = 0; 59674e85130SRui Ueyama if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 59774e85130SRui Ueyama return EC; 59874e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 59974e85130SRui Ueyama IntPtr); 60074e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 60174e85130SRui Ueyama IntPtr + DataEntry->Size); 6027d099195SRui Ueyama return std::error_code(); 60374e85130SRui Ueyama } 60474e85130SRui Ueyama 6052da433eaSReid Kleckner std::error_code COFFObjectFile::initDebugDirectoryPtr() { 6062da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6072da433eaSReid Kleckner const data_directory *DataEntry; 6082da433eaSReid Kleckner if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 6092da433eaSReid Kleckner return std::error_code(); 6102da433eaSReid Kleckner 6112da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6122da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6132da433eaSReid Kleckner return std::error_code(); 6142da433eaSReid Kleckner 6152da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6162da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6172da433eaSReid Kleckner return object_error::parse_failed; 6182da433eaSReid Kleckner 6192da433eaSReid Kleckner uintptr_t IntPtr = 0; 6202da433eaSReid Kleckner if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6212da433eaSReid Kleckner return EC; 6222da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6232da433eaSReid Kleckner if (std::error_code EC = getRvaPtr( 6242da433eaSReid Kleckner DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 6252da433eaSReid Kleckner return EC; 6262da433eaSReid Kleckner DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 6272da433eaSReid Kleckner return std::error_code(); 6282da433eaSReid Kleckner } 6292da433eaSReid Kleckner 63048af1c2aSRafael Espindola COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 63148af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 63244f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 63344f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 63444f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 635ad7b7e73SDavid Majnemer ImportDirectory(nullptr), 63615d99359SRui Ueyama DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 6372da433eaSReid Kleckner ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 6382da433eaSReid Kleckner DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 6391d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 64048af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 641c3f9b5a5SRafael Espindola return; 642ee066fc4SEric Christopher 64382ebd8e3SRui Ueyama // The current location in the file where we are looking at. 64482ebd8e3SRui Ueyama uint64_t CurPtr = 0; 64582ebd8e3SRui Ueyama 64682ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 64782ebd8e3SRui Ueyama // it is placed right after COFF header. 6488ff24d25SRui Ueyama bool HasPEHeader = false; 649ee066fc4SEric Christopher 6501d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 65150267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 652ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 653ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 65450267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 65550267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 65650267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 65782ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 65850267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 6598ff24d25SRui Ueyama EC = object_error::parse_failed; 6601d6167fdSMichael J. Spencer return; 6611d6167fdSMichael J. Spencer } 66244f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 6638ff24d25SRui Ueyama HasPEHeader = true; 664ee066fc4SEric Christopher } 66550267222SDavid Majnemer } 666ee066fc4SEric Christopher 66748af1c2aSRafael Espindola if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 6681d6167fdSMichael J. Spencer return; 66944f51e51SDavid Majnemer 67044f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 67144f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 67244f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 67344f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 67444f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 67544f51e51SDavid Majnemer if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 67644f51e51SDavid Majnemer return; 67744f51e51SDavid Majnemer 67844f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 67944f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 68044f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 68144f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 68244f51e51SDavid Majnemer COFFHeader = nullptr; 68344f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 68444f51e51SDavid Majnemer } else { 68544f51e51SDavid Majnemer // It's not a bigobj. 68644f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 68744f51e51SDavid Majnemer } 68844f51e51SDavid Majnemer } 68944f51e51SDavid Majnemer if (COFFHeader) { 69044f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 69144f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 6927d099195SRui Ueyama EC = std::error_code(); 69382ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 69482ebd8e3SRui Ueyama 69544f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 69644f51e51SDavid Majnemer return; 69744f51e51SDavid Majnemer } 69844f51e51SDavid Majnemer 6998ff24d25SRui Ueyama if (HasPEHeader) { 70010ed9ddcSRui Ueyama const pe32_header *Header; 70148af1c2aSRafael Espindola if ((EC = getObject(Header, Data, base() + CurPtr))) 70282ebd8e3SRui Ueyama return; 70310ed9ddcSRui Ueyama 70410ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 70510ed9ddcSRui Ueyama uint64_t DataDirSize; 70650267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 70710ed9ddcSRui Ueyama PE32Header = Header; 70810ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 70910ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 71050267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 71110ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 71210ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 71310ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 71410ed9ddcSRui Ueyama } else { 71510ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 71610ed9ddcSRui Ueyama EC = object_error::parse_failed; 717ed64342bSRui Ueyama return; 718ed64342bSRui Ueyama } 71948af1c2aSRafael Espindola if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 72010ed9ddcSRui Ueyama return; 721f53c8cb4SRui Ueyama } 722776c6828SRui Ueyama 723*8950a538SRui Ueyama if (COFFHeader) 724*8950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 725*8950a538SRui Ueyama 72648af1c2aSRafael Espindola if ((EC = getObject(SectionTable, Data, base() + CurPtr, 727236b0ca7SDavid Majnemer (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 7281d6167fdSMichael J. Spencer return; 7291d6167fdSMichael J. Spencer 730c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 731236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 7328ff24d25SRui Ueyama if ((EC = initSymbolTablePtr())) 7331d6167fdSMichael J. Spencer return; 734236b0ca7SDavid Majnemer } else { 735236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 736236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 737236b0ca7SDavid Majnemer EC = object_error::parse_failed; 738236b0ca7SDavid Majnemer return; 739236b0ca7SDavid Majnemer } 740236b0ca7SDavid Majnemer } 7418e90adafSMichael J. Spencer 742c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 7438ff24d25SRui Ueyama if ((EC = initImportTablePtr())) 744ed64342bSRui Ueyama return; 74515d99359SRui Ueyama if ((EC = initDelayImportTablePtr())) 74615d99359SRui Ueyama return; 7471d6167fdSMichael J. Spencer 748ad882ba8SRui Ueyama // Initialize the pointer to the export table. 7498ff24d25SRui Ueyama if ((EC = initExportTablePtr())) 750ad882ba8SRui Ueyama return; 751ad882ba8SRui Ueyama 75274e85130SRui Ueyama // Initialize the pointer to the base relocation table. 75374e85130SRui Ueyama if ((EC = initBaseRelocPtr())) 75474e85130SRui Ueyama return; 75574e85130SRui Ueyama 7562da433eaSReid Kleckner // Initialize the pointer to the export table. 7572da433eaSReid Kleckner if ((EC = initDebugDirectoryPtr())) 7582da433eaSReid Kleckner return; 7592da433eaSReid Kleckner 7607d099195SRui Ueyama EC = std::error_code(); 7618e90adafSMichael J. Spencer } 7628e90adafSMichael J. Spencer 763f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 7648ff24d25SRui Ueyama DataRefImpl Ret; 76544f51e51SDavid Majnemer Ret.p = getSymbolTable(); 766f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7678e90adafSMichael J. Spencer } 7688e90adafSMichael J. Spencer 769f12b8282SRafael Espindola basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 7708e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 7718ff24d25SRui Ueyama DataRefImpl Ret; 7728ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 773f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 7748e90adafSMichael J. Spencer } 7758e90adafSMichael J. Spencer 776bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 777ad7b7e73SDavid Majnemer if (!ImportDirectory) 778ad7b7e73SDavid Majnemer return import_directory_end(); 7791c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 780ad7b7e73SDavid Majnemer return import_directory_end(); 781a045b73aSRui Ueyama return import_directory_iterator( 782a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 783c2bed429SRui Ueyama } 784c2bed429SRui Ueyama 785bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 786a045b73aSRui Ueyama return import_directory_iterator( 787ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 788c2bed429SRui Ueyama } 789c429b80dSDavid Meyer 79015d99359SRui Ueyama delay_import_directory_iterator 79115d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 79215d99359SRui Ueyama return delay_import_directory_iterator( 79315d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 79415d99359SRui Ueyama } 79515d99359SRui Ueyama 79615d99359SRui Ueyama delay_import_directory_iterator 79715d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 79815d99359SRui Ueyama return delay_import_directory_iterator( 79915d99359SRui Ueyama DelayImportDirectoryEntryRef( 80015d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 80115d99359SRui Ueyama } 80215d99359SRui Ueyama 803ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 804ad882ba8SRui Ueyama return export_directory_iterator( 805ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 806ad882ba8SRui Ueyama } 807ad882ba8SRui Ueyama 808ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 8092617dcceSCraig Topper if (!ExportDirectory) 8102617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 8118ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 812ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 8138ff24d25SRui Ueyama return export_directory_iterator(Ref); 814ad882ba8SRui Ueyama } 815ad882ba8SRui Ueyama 816b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 8178ff24d25SRui Ueyama DataRefImpl Ret; 8188ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 8198ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8208e90adafSMichael J. Spencer } 8218e90adafSMichael J. Spencer 822b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 8238ff24d25SRui Ueyama DataRefImpl Ret; 82444f51e51SDavid Majnemer int NumSections = 82544f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 8268ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 8278ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 8288e90adafSMichael J. Spencer } 8298e90adafSMichael J. Spencer 83074e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 83174e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 83274e85130SRui Ueyama } 83374e85130SRui Ueyama 83474e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 83574e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 83674e85130SRui Ueyama } 83774e85130SRui Ueyama 8388e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 8390324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 8408e90adafSMichael J. Spencer } 8418e90adafSMichael J. Spencer 8428e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 84344f51e51SDavid Majnemer switch(getMachine()) { 8448e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8458e90adafSMichael J. Spencer return "COFF-i386"; 8468e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8478e90adafSMichael J. Spencer return "COFF-x86-64"; 8489b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8499b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 8501eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8511eff5c9cSMartell Malone return "COFF-ARM64"; 8528e90adafSMichael J. Spencer default: 8538e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 8548e90adafSMichael J. Spencer } 8558e90adafSMichael J. Spencer } 8568e90adafSMichael J. Spencer 8578e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 85844f51e51SDavid Majnemer switch (getMachine()) { 8598e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 8608e90adafSMichael J. Spencer return Triple::x86; 8618e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 8628e90adafSMichael J. Spencer return Triple::x86_64; 8639b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 8649b7c0af2SSaleem Abdulrasool return Triple::thumb; 8651eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 8661eff5c9cSMartell Malone return Triple::aarch64; 8678e90adafSMichael J. Spencer default: 8688e90adafSMichael J. Spencer return Triple::UnknownArch; 8698e90adafSMichael J. Spencer } 8708e90adafSMichael J. Spencer } 8718e90adafSMichael J. Spencer 872979fb40bSRui Ueyama iterator_range<import_directory_iterator> 873979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 874979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 875979fb40bSRui Ueyama } 876979fb40bSRui Ueyama 877979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 878979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 879979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 880979fb40bSRui Ueyama delay_import_directory_end()); 881979fb40bSRui Ueyama } 882979fb40bSRui Ueyama 883979fb40bSRui Ueyama iterator_range<export_directory_iterator> 884979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 885979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 886979fb40bSRui Ueyama } 887979fb40bSRui Ueyama 88874e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 88974e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 89074e85130SRui Ueyama } 89174e85130SRui Ueyama 892db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 89382ebd8e3SRui Ueyama Res = PE32Header; 8947d099195SRui Ueyama return std::error_code(); 89589a7a5eaSMichael J. Spencer } 89689a7a5eaSMichael J. Spencer 897db4ed0bdSRafael Espindola std::error_code 89810ed9ddcSRui Ueyama COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 89910ed9ddcSRui Ueyama Res = PE32PlusHeader; 9007d099195SRui Ueyama return std::error_code(); 90110ed9ddcSRui Ueyama } 90210ed9ddcSRui Ueyama 903db4ed0bdSRafael Espindola std::error_code 904db4ed0bdSRafael Espindola COFFObjectFile::getDataDirectory(uint32_t Index, 905ed64342bSRui Ueyama const data_directory *&Res) const { 906ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 907f69b0585SDavid Majnemer if (!DataDirectory) { 908f69b0585SDavid Majnemer Res = nullptr; 90910ed9ddcSRui Ueyama return object_error::parse_failed; 910f69b0585SDavid Majnemer } 91110ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 91210ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 91310ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 914f69b0585SDavid Majnemer if (Index >= NumEnt) { 915f69b0585SDavid Majnemer Res = nullptr; 916ed64342bSRui Ueyama return object_error::parse_failed; 917f69b0585SDavid Majnemer } 9188ff24d25SRui Ueyama Res = &DataDirectory[Index]; 9197d099195SRui Ueyama return std::error_code(); 920ed64342bSRui Ueyama } 921ed64342bSRui Ueyama 922db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSection(int32_t Index, 9231d6167fdSMichael J. Spencer const coff_section *&Result) const { 9242617dcceSCraig Topper Result = nullptr; 925236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 9267d099195SRui Ueyama return std::error_code(); 927236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 9281d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 9298ff24d25SRui Ueyama Result = SectionTable + (Index - 1); 9307d099195SRui Ueyama return std::error_code(); 9318e90adafSMichael J. Spencer } 932236b0ca7SDavid Majnemer return object_error::parse_failed; 933236b0ca7SDavid Majnemer } 9348e90adafSMichael J. Spencer 935db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getString(uint32_t Offset, 9361d6167fdSMichael J. Spencer StringRef &Result) const { 9371d6167fdSMichael J. Spencer if (StringTableSize <= 4) 9381d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 9391d6167fdSMichael J. Spencer return object_error::parse_failed; 9408ff24d25SRui Ueyama if (Offset >= StringTableSize) 9411d6167fdSMichael J. Spencer return object_error::unexpected_eof; 9428ff24d25SRui Ueyama Result = StringRef(StringTable + Offset); 9437d099195SRui Ueyama return std::error_code(); 9448e90adafSMichael J. Spencer } 945022ecdf2SBenjamin Kramer 94644f51e51SDavid Majnemer std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 94789a7a5eaSMichael J. Spencer StringRef &Res) const { 948e40d30f3SRui Ueyama return getSymbolName(Symbol.getGeneric(), Res); 949e40d30f3SRui Ueyama } 950e40d30f3SRui Ueyama 951e40d30f3SRui Ueyama std::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 952e40d30f3SRui Ueyama StringRef &Res) const { 95389a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 954e40d30f3SRui Ueyama if (Symbol->Name.Offset.Zeroes == 0) { 955e40d30f3SRui Ueyama if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 9568ff24d25SRui Ueyama return EC; 9577d099195SRui Ueyama return std::error_code(); 95889a7a5eaSMichael J. Spencer } 95989a7a5eaSMichael J. Spencer 960e40d30f3SRui Ueyama if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 96189a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 962e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName); 96389a7a5eaSMichael J. Spencer else 96489a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 965e40d30f3SRui Ueyama Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 9667d099195SRui Ueyama return std::error_code(); 96789a7a5eaSMichael J. Spencer } 96889a7a5eaSMichael J. Spencer 96944f51e51SDavid Majnemer ArrayRef<uint8_t> 97044f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 9712617dcceSCraig Topper const uint8_t *Aux = nullptr; 97271757ef3SMarshall Clow 97344f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 97444f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 97571757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 97644f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 97771757ef3SMarshall Clow # ifndef NDEBUG 9788ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 9798ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 98044f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 98144f51e51SDavid Majnemer Offset >= 98244f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 98371757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 98471757ef3SMarshall Clow 98544f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 98644f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 98771757ef3SMarshall Clow # endif 988bfb85e67SMarshall Clow } 98944f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 99071757ef3SMarshall Clow } 99171757ef3SMarshall Clow 992db4ed0bdSRafael Espindola std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 99353c2d547SMichael J. Spencer StringRef &Res) const { 99453c2d547SMichael J. Spencer StringRef Name; 99544f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 99653c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 99753c2d547SMichael J. Spencer Name = Sec->Name; 99853c2d547SMichael J. Spencer else 99953c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 100044f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 100153c2d547SMichael J. Spencer 100253c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10032314b3deSDavid Majnemer if (Name.startswith("/")) { 100453c2d547SMichael J. Spencer uint32_t Offset; 10052314b3deSDavid Majnemer if (Name.startswith("//")) { 10069d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 10079d2c15efSNico Rieck return object_error::parse_failed; 10089d2c15efSNico Rieck } else { 100953c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 101053c2d547SMichael J. Spencer return object_error::parse_failed; 10119d2c15efSNico Rieck } 1012db4ed0bdSRafael Espindola if (std::error_code EC = getString(Offset, Name)) 10138ff24d25SRui Ueyama return EC; 101453c2d547SMichael J. Spencer } 101553c2d547SMichael J. Spencer 101653c2d547SMichael J. Spencer Res = Name; 10177d099195SRui Ueyama return std::error_code(); 101853c2d547SMichael J. Spencer } 101953c2d547SMichael J. Spencer 1020a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1021a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1022a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1023a9ee5c06SDavid Majnemer // 1024a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1025d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1026a9ee5c06SDavid Majnemer // 1027a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1028a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1029a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1030a9ee5c06SDavid Majnemer // considered to be zero. 1031d5297ee7SRui Ueyama if (getDOSHeader()) 1032d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1033d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1034a9ee5c06SDavid Majnemer } 1035a9ee5c06SDavid Majnemer 1036db4ed0bdSRafael Espindola std::error_code 1037db4ed0bdSRafael Espindola COFFObjectFile::getSectionContents(const coff_section *Sec, 10389da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1039e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1040e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1041e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1042e2129662SDavid Majnemer return object_error::parse_failed; 10439da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 10449da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10459da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 10469da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 1047a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1048e830c60dSDavid Majnemer if (checkOffset(Data, ConStart, SectionSize)) 10499da9e693SMichael J. Spencer return object_error::parse_failed; 1050a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10517d099195SRui Ueyama return std::error_code(); 10529da9e693SMichael J. Spencer } 10539da9e693SMichael J. Spencer 1054022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1055e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1056022ecdf2SBenjamin Kramer } 10578ff24d25SRui Ueyama 10585e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1059e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1060e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1061022ecdf2SBenjamin Kramer } 10628ff24d25SRui Ueyama 106396d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 106458323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 106596d071cdSRafael Espindola return R->VirtualAddress; 1066cbe72fc9SDanil Malyshev } 10678ff24d25SRui Ueyama 1068806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1069022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 10708ff24d25SRui Ueyama DataRefImpl Ref; 1071236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1072236b0ca7SDavid Majnemer return symbol_end(); 107344f51e51SDavid Majnemer if (SymbolTable16) 107444f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 107544f51e51SDavid Majnemer else if (SymbolTable32) 107644f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 107744f51e51SDavid Majnemer else 1078c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 10798ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1080022ecdf2SBenjamin Kramer } 10818ff24d25SRui Ueyama 108299c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1083022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 108499c041b7SRafael Espindola return R->Type; 1085022ecdf2SBenjamin Kramer } 1086e5fd0047SMichael J. Spencer 108727dc8394SAlexey Samsonov const coff_section * 108827dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 108927dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 109071757ef3SMarshall Clow } 109171757ef3SMarshall Clow 109244f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 109344f51e51SDavid Majnemer if (SymbolTable16) 109444f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 109544f51e51SDavid Majnemer if (SymbolTable32) 109644f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 109744f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 109844f51e51SDavid Majnemer } 109944f51e51SDavid Majnemer 110044f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 110144f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 110271757ef3SMarshall Clow } 110371757ef3SMarshall Clow 1104f12b8282SRafael Espindola const coff_relocation * 110527dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 110627dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1107d3e2a76cSMarshall Clow } 1108d3e2a76cSMarshall Clow 11096a75acb1SRui Ueyama iterator_range<const coff_relocation *> 11106a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 11116a75acb1SRui Ueyama const coff_relocation *I = getFirstReloc(Sec, Data, base()); 11126a75acb1SRui Ueyama const coff_relocation *E = I; 11136a75acb1SRui Ueyama if (I) 11146a75acb1SRui Ueyama E += getNumberOfRelocations(Sec, Data, base()); 11156a75acb1SRui Ueyama return make_range(I, E); 11166a75acb1SRui Ueyama } 11176a75acb1SRui Ueyama 111827dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 111927dc8394SAlexey Samsonov case COFF::reloc_type: \ 112027dc8394SAlexey Samsonov Res = #reloc_type; \ 112127dc8394SAlexey Samsonov break; 1122e5fd0047SMichael J. Spencer 112341bb4325SRafael Espindola void COFFObjectFile::getRelocationTypeName( 112441bb4325SRafael Espindola DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 11258ff24d25SRui Ueyama const coff_relocation *Reloc = toRel(Rel); 11268ff24d25SRui Ueyama StringRef Res; 112744f51e51SDavid Majnemer switch (getMachine()) { 1128e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 11298ff24d25SRui Ueyama switch (Reloc->Type) { 1130e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1131e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1132e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1133e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1134e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1135e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1136e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1137e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1138e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1139e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1140e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1141e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1142e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1143e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1144e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1145e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1146e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1147e5fd0047SMichael J. Spencer default: 11488ff24d25SRui Ueyama Res = "Unknown"; 1149e5fd0047SMichael J. Spencer } 1150e5fd0047SMichael J. Spencer break; 11515c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 11525c503bf4SSaleem Abdulrasool switch (Reloc->Type) { 11535c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 11545c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 11555c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 11565c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 11575c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 11585c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 11595c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 11605c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 11615c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 11625c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 11635c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 11645c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 11655c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 11665c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 11675c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 11685c503bf4SSaleem Abdulrasool default: 11695c503bf4SSaleem Abdulrasool Res = "Unknown"; 11705c503bf4SSaleem Abdulrasool } 11715c503bf4SSaleem Abdulrasool break; 1172e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 11738ff24d25SRui Ueyama switch (Reloc->Type) { 1174e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1175e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1176e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1177e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1178e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1179e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1180e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1181e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1182e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1183e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1184e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1185e5fd0047SMichael J. Spencer default: 11868ff24d25SRui Ueyama Res = "Unknown"; 1187e5fd0047SMichael J. Spencer } 1188e5fd0047SMichael J. Spencer break; 1189e5fd0047SMichael J. Spencer default: 11908ff24d25SRui Ueyama Res = "Unknown"; 1191e5fd0047SMichael J. Spencer } 11928ff24d25SRui Ueyama Result.append(Res.begin(), Res.end()); 1193e5fd0047SMichael J. Spencer } 1194e5fd0047SMichael J. Spencer 1195e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1196e5fd0047SMichael J. Spencer 1197c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1198c66d761bSRafael Espindola return !DataDirectory; 1199c66d761bSRafael Espindola } 1200c66d761bSRafael Espindola 1201c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1202c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1203a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1204c2bed429SRui Ueyama } 1205c2bed429SRui Ueyama 12065e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 12075e812afaSRafael Espindola ++Index; 12081c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1209ad7b7e73SDavid Majnemer Index = -1; 1210ad7b7e73SDavid Majnemer ImportTable = nullptr; 1211ad7b7e73SDavid Majnemer } 1212c2bed429SRui Ueyama } 1213c2bed429SRui Ueyama 1214db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getImportTableEntry( 12151c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1216ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1217c2bed429SRui Ueyama } 1218c2bed429SRui Ueyama 1219861021f9SRui Ueyama static imported_symbol_iterator 122015d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1221861021f9SRui Ueyama uintptr_t Ptr, int Index) { 122215d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1223861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 122415d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1225861021f9SRui Ueyama } 1226861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 122715d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1228861021f9SRui Ueyama } 1229861021f9SRui Ueyama 123015d99359SRui Ueyama static imported_symbol_iterator 123115d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1232861021f9SRui Ueyama uintptr_t IntPtr = 0; 123315d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 123415d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1235861021f9SRui Ueyama } 1236861021f9SRui Ueyama 123715d99359SRui Ueyama static imported_symbol_iterator 123815d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1239861021f9SRui Ueyama uintptr_t IntPtr = 0; 124015d99359SRui Ueyama Object->getRvaPtr(RVA, IntPtr); 1241861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1242861021f9SRui Ueyama int Index = 0; 124315d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1244861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1245861021f9SRui Ueyama while (*Entry++) 1246861021f9SRui Ueyama ++Index; 1247861021f9SRui Ueyama } else { 1248861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1249861021f9SRui Ueyama while (*Entry++) 1250861021f9SRui Ueyama ++Index; 1251861021f9SRui Ueyama } 125215d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 125315d99359SRui Ueyama } 125415d99359SRui Ueyama 125515d99359SRui Ueyama imported_symbol_iterator 125615d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 125760049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 125815d99359SRui Ueyama OwningObject); 125915d99359SRui Ueyama } 126015d99359SRui Ueyama 126115d99359SRui Ueyama imported_symbol_iterator 126215d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 126360049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 126415d99359SRui Ueyama OwningObject); 1265861021f9SRui Ueyama } 1266861021f9SRui Ueyama 1267979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1268979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1269979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1270979fb40bSRui Ueyama } 1271979fb40bSRui Ueyama 127260049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 127360049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 127460049526SDavid Majnemer OwningObject); 127560049526SDavid Majnemer } 127660049526SDavid Majnemer 127760049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 127860049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 127960049526SDavid Majnemer OwningObject); 128060049526SDavid Majnemer } 128160049526SDavid Majnemer 128260049526SDavid Majnemer iterator_range<imported_symbol_iterator> 128360049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 128460049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 128560049526SDavid Majnemer } 128660049526SDavid Majnemer 1287db4ed0bdSRafael Espindola std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1288c2bed429SRui Ueyama uintptr_t IntPtr = 0; 1289db4ed0bdSRafael Espindola if (std::error_code EC = 12901e152d5eSRui Ueyama OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 1291a045b73aSRui Ueyama return EC; 1292a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 12937d099195SRui Ueyama return std::error_code(); 1294c2bed429SRui Ueyama } 1295c2bed429SRui Ueyama 12961e152d5eSRui Ueyama std::error_code 12971e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 12981e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 12997d099195SRui Ueyama return std::error_code(); 13001e152d5eSRui Ueyama } 13011e152d5eSRui Ueyama 13021e152d5eSRui Ueyama std::error_code 13031e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 13041e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 13057d099195SRui Ueyama return std::error_code(); 13061e152d5eSRui Ueyama } 13071e152d5eSRui Ueyama 130815d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 130915d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 131015d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 131115d99359SRui Ueyama } 131215d99359SRui Ueyama 131315d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 131415d99359SRui Ueyama ++Index; 131515d99359SRui Ueyama } 131615d99359SRui Ueyama 131715d99359SRui Ueyama imported_symbol_iterator 131815d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 131915d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 132015d99359SRui Ueyama OwningObject); 132115d99359SRui Ueyama } 132215d99359SRui Ueyama 132315d99359SRui Ueyama imported_symbol_iterator 132415d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 132515d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 132615d99359SRui Ueyama OwningObject); 132715d99359SRui Ueyama } 132815d99359SRui Ueyama 1329979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1330979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1331979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1332979fb40bSRui Ueyama } 1333979fb40bSRui Ueyama 133415d99359SRui Ueyama std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 133515d99359SRui Ueyama uintptr_t IntPtr = 0; 133615d99359SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 133715d99359SRui Ueyama return EC; 133815d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13397d099195SRui Ueyama return std::error_code(); 134015d99359SRui Ueyama } 134115d99359SRui Ueyama 13421af08658SRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 13431af08658SRui Ueyama getDelayImportTable(const delay_import_directory_table_entry *&Result) const { 13441af08658SRui Ueyama Result = Table; 13457d099195SRui Ueyama return std::error_code(); 13461af08658SRui Ueyama } 13471af08658SRui Ueyama 1348ffa4cebeSRui Ueyama std::error_code DelayImportDirectoryEntryRef:: 1349ffa4cebeSRui Ueyama getImportAddress(int AddrIndex, uint64_t &Result) const { 1350ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1351ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1352ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 1353ffa4cebeSRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1354ffa4cebeSRui Ueyama return EC; 1355ffa4cebeSRui Ueyama if (OwningObject->is64()) 13565dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1357ffa4cebeSRui Ueyama else 13585dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 13597d099195SRui Ueyama return std::error_code(); 1360ffa4cebeSRui Ueyama } 1361ffa4cebeSRui Ueyama 1362ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1363ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1364ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1365ad882ba8SRui Ueyama } 1366ad882ba8SRui Ueyama 13675e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 13685e812afaSRafael Espindola ++Index; 1369ad882ba8SRui Ueyama } 1370ad882ba8SRui Ueyama 1371da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1372da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 1373db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1374da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 1375db4ed0bdSRafael Espindola if (std::error_code EC = 1376db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 1377da49d0d4SRui Ueyama return EC; 1378da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13797d099195SRui Ueyama return std::error_code(); 1380da49d0d4SRui Ueyama } 1381da49d0d4SRui Ueyama 1382e5df6095SRui Ueyama // Returns the starting ordinal number. 1383db4ed0bdSRafael Espindola std::error_code 1384db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1385e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 13867d099195SRui Ueyama return std::error_code(); 1387e5df6095SRui Ueyama } 1388e5df6095SRui Ueyama 1389ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 1390db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1391ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 13927d099195SRui Ueyama return std::error_code(); 1393ad882ba8SRui Ueyama } 1394ad882ba8SRui Ueyama 1395ad882ba8SRui Ueyama // Returns the address of the current export symbol. 1396db4ed0bdSRafael Espindola std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1397ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1398db4ed0bdSRafael Espindola if (std::error_code EC = 1399db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1400ad882ba8SRui Ueyama return EC; 140124fc2d64SRui Ueyama const export_address_table_entry *entry = 140224fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1403ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 14047d099195SRui Ueyama return std::error_code(); 1405ad882ba8SRui Ueyama } 1406ad882ba8SRui Ueyama 1407ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1408ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 1409db4ed0bdSRafael Espindola std::error_code 1410db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1411ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 1412db4ed0bdSRafael Espindola if (std::error_code EC = 1413db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1414ad882ba8SRui Ueyama return EC; 1415ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1416ad882ba8SRui Ueyama 1417ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1418ad882ba8SRui Ueyama int Offset = 0; 1419ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1420ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1421ad882ba8SRui Ueyama if (*I != Index) 1422ad882ba8SRui Ueyama continue; 1423db4ed0bdSRafael Espindola if (std::error_code EC = 1424db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1425ad882ba8SRui Ueyama return EC; 1426ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1427db4ed0bdSRafael Espindola if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1428ad882ba8SRui Ueyama return EC; 1429ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14307d099195SRui Ueyama return std::error_code(); 1431ad882ba8SRui Ueyama } 1432ad882ba8SRui Ueyama Result = ""; 14337d099195SRui Ueyama return std::error_code(); 1434ad882ba8SRui Ueyama } 1435ad882ba8SRui Ueyama 14366161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 14376161b38dSRui Ueyama const data_directory *DataEntry; 14386161b38dSRui Ueyama if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 14396161b38dSRui Ueyama return EC; 14406161b38dSRui Ueyama uint32_t RVA; 14416161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14426161b38dSRui Ueyama return EC; 14436161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 14446161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 14456161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 14466161b38dSRui Ueyama return std::error_code(); 14476161b38dSRui Ueyama } 14486161b38dSRui Ueyama 14496161b38dSRui Ueyama std::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 14506161b38dSRui Ueyama uint32_t RVA; 14516161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 14526161b38dSRui Ueyama return EC; 14536161b38dSRui Ueyama uintptr_t IntPtr = 0; 14546161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 14556161b38dSRui Ueyama return EC; 14566161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14576161b38dSRui Ueyama return std::error_code(); 14586161b38dSRui Ueyama } 14596161b38dSRui Ueyama 1460861021f9SRui Ueyama bool ImportedSymbolRef:: 1461861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1462861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1463861021f9SRui Ueyama && Index == Other.Index; 1464861021f9SRui Ueyama } 1465861021f9SRui Ueyama 1466861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1467861021f9SRui Ueyama ++Index; 1468861021f9SRui Ueyama } 1469861021f9SRui Ueyama 1470861021f9SRui Ueyama std::error_code 1471861021f9SRui Ueyama ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1472861021f9SRui Ueyama uint32_t RVA; 1473861021f9SRui Ueyama if (Entry32) { 1474861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1475861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 14767d099195SRui Ueyama return std::error_code(); 1477861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1478861021f9SRui Ueyama } else { 1479861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 14807d099195SRui Ueyama return std::error_code(); 1481861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1482861021f9SRui Ueyama } 1483861021f9SRui Ueyama uintptr_t IntPtr = 0; 1484861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1485861021f9SRui Ueyama return EC; 1486861021f9SRui Ueyama // +2 because the first two bytes is hint. 1487861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 14887d099195SRui Ueyama return std::error_code(); 1489861021f9SRui Ueyama } 1490861021f9SRui Ueyama 1491ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1492ad7b7e73SDavid Majnemer if (Entry32) 1493ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1494ad7b7e73SDavid Majnemer else 1495ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 1496ad7b7e73SDavid Majnemer return std::error_code(); 1497ad7b7e73SDavid Majnemer } 1498ad7b7e73SDavid Majnemer 1499ad7b7e73SDavid Majnemer std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1500ad7b7e73SDavid Majnemer if (Entry32) 1501ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1502ad7b7e73SDavid Majnemer else 1503ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 1504ad7b7e73SDavid Majnemer return std::error_code(); 1505ad7b7e73SDavid Majnemer } 1506ad7b7e73SDavid Majnemer 1507861021f9SRui Ueyama std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1508861021f9SRui Ueyama uint32_t RVA; 1509861021f9SRui Ueyama if (Entry32) { 1510861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1511861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 15127d099195SRui Ueyama return std::error_code(); 1513861021f9SRui Ueyama } 1514861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1515861021f9SRui Ueyama } else { 1516861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1517861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 15187d099195SRui Ueyama return std::error_code(); 1519861021f9SRui Ueyama } 1520861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1521861021f9SRui Ueyama } 1522861021f9SRui Ueyama uintptr_t IntPtr = 0; 1523861021f9SRui Ueyama if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1524861021f9SRui Ueyama return EC; 1525861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15267d099195SRui Ueyama return std::error_code(); 1527861021f9SRui Ueyama } 1528861021f9SRui Ueyama 1529437b0d58SRafael Espindola ErrorOr<std::unique_ptr<COFFObjectFile>> 153048af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1531db4ed0bdSRafael Espindola std::error_code EC; 153248af1c2aSRafael Espindola std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 1533692410efSRafael Espindola if (EC) 1534692410efSRafael Espindola return EC; 1535437b0d58SRafael Espindola return std::move(Ret); 1536686738e2SRui Ueyama } 153774e85130SRui Ueyama 153874e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 153974e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 154074e85130SRui Ueyama } 154174e85130SRui Ueyama 154274e85130SRui Ueyama void BaseRelocRef::moveNext() { 154374e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 154474e85130SRui Ueyama // size of the header itself. 154574e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1546970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 154774e85130SRui Ueyama if (Size == Header->BlockSize) { 154874e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 154974e85130SRui Ueyama // consists of the header followed by entries. The header contains 155074e85130SRui Ueyama // how many entories will follow. When we reach the end of the 155174e85130SRui Ueyama // current block, proceed to the next block. 155274e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 155374e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 155474e85130SRui Ueyama Index = 0; 155574e85130SRui Ueyama } else { 155674e85130SRui Ueyama ++Index; 155774e85130SRui Ueyama } 155874e85130SRui Ueyama } 155974e85130SRui Ueyama 156074e85130SRui Ueyama std::error_code BaseRelocRef::getType(uint8_t &Type) const { 156174e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 156274e85130SRui Ueyama Type = Entry[Index].getType(); 15637d099195SRui Ueyama return std::error_code(); 156474e85130SRui Ueyama } 156574e85130SRui Ueyama 156674e85130SRui Ueyama std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 156774e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 156874e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 15697d099195SRui Ueyama return std::error_code(); 157074e85130SRui Ueyama } 1571