1d341c932SEugene Zelenko //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 28e90adafSMichael J. Spencer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68e90adafSMichael J. Spencer // 78e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 88e90adafSMichael J. Spencer // 98e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 108e90adafSMichael J. Spencer // 118e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 128e90adafSMichael J. Spencer 139da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 14d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h" 150ea52537SSimon Pilgrim #include "llvm/ADT/StringSwitch.h" 168e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 176a75acb1SRui Ueyama #include "llvm/ADT/iterator_range.h" 18264b5d9eSZachary Turner #include "llvm/BinaryFormat/COFF.h" 19d341c932SEugene Zelenko #include "llvm/Object/Binary.h" 20d341c932SEugene Zelenko #include "llvm/Object/COFF.h" 21d341c932SEugene Zelenko #include "llvm/Object/Error.h" 22d341c932SEugene Zelenko #include "llvm/Object/ObjectFile.h" 23efef15a0SEric Beckmann #include "llvm/Support/BinaryStreamReader.h" 24d341c932SEugene Zelenko #include "llvm/Support/Endian.h" 25d341c932SEugene Zelenko #include "llvm/Support/Error.h" 26d341c932SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 27d341c932SEugene Zelenko #include "llvm/Support/MathExtras.h" 28d341c932SEugene Zelenko #include "llvm/Support/MemoryBuffer.h" 29d341c932SEugene Zelenko #include <algorithm> 30d341c932SEugene Zelenko #include <cassert> 312980ce98SHubert Tong #include <cinttypes> 32d341c932SEugene Zelenko #include <cstddef> 33d341c932SEugene Zelenko #include <cstring> 349d2c15efSNico Rieck #include <limits> 35d341c932SEugene Zelenko #include <memory> 36d341c932SEugene Zelenko #include <system_error> 378e90adafSMichael J. Spencer 388e90adafSMichael J. Spencer using namespace llvm; 398e90adafSMichael J. Spencer using namespace object; 408e90adafSMichael J. Spencer 418e90adafSMichael J. Spencer using support::ulittle16_t; 428e90adafSMichael J. Spencer using support::ulittle32_t; 43861021f9SRui Ueyama using support::ulittle64_t; 448e90adafSMichael J. Spencer using support::little16_t; 458e90adafSMichael J. Spencer 461d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 4748af1c2aSRafael Espindola static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 48c3f9b5a5SRafael Espindola if (M.getBufferSize() < Size) { 498ff24d25SRui Ueyama EC = object_error::unexpected_eof; 501d6167fdSMichael J. Spencer return false; 511d6167fdSMichael J. Spencer } 521d6167fdSMichael J. Spencer return true; 538e90adafSMichael J. Spencer } 548e90adafSMichael J. Spencer 55ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 56ed64342bSRui Ueyama // Returns unexpected_eof if error. 57ed64342bSRui Ueyama template <typename T> 581c03389cSReid Kleckner static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, 59236b0ca7SDavid Majnemer const uint64_t Size = sizeof(T)) { 6022cf54a7SArthur O'Dwyer uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr); 61e03a135bSReid Kleckner if (Error E = Binary::checkOffset(M, Addr, Size)) 621c03389cSReid Kleckner return E; 63ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 641c03389cSReid Kleckner return Error::success(); 651d6167fdSMichael J. Spencer } 661d6167fdSMichael J. Spencer 679d2c15efSNico Rieck // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 689d2c15efSNico Rieck // prefixed slashes. 699d2c15efSNico Rieck static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 709d2c15efSNico Rieck assert(Str.size() <= 6 && "String too long, possible overflow."); 719d2c15efSNico Rieck if (Str.size() > 6) 729d2c15efSNico Rieck return true; 739d2c15efSNico Rieck 749d2c15efSNico Rieck uint64_t Value = 0; 759d2c15efSNico Rieck while (!Str.empty()) { 769d2c15efSNico Rieck unsigned CharVal; 779d2c15efSNico Rieck if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 789d2c15efSNico Rieck CharVal = Str[0] - 'A'; 799d2c15efSNico Rieck else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 809d2c15efSNico Rieck CharVal = Str[0] - 'a' + 26; 819d2c15efSNico Rieck else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 829d2c15efSNico Rieck CharVal = Str[0] - '0' + 52; 839d2c15efSNico Rieck else if (Str[0] == '+') // 62 845500b07cSRui Ueyama CharVal = 62; 859d2c15efSNico Rieck else if (Str[0] == '/') // 63 865500b07cSRui Ueyama CharVal = 63; 879d2c15efSNico Rieck else 889d2c15efSNico Rieck return true; 899d2c15efSNico Rieck 909d2c15efSNico Rieck Value = (Value * 64) + CharVal; 919d2c15efSNico Rieck Str = Str.substr(1); 929d2c15efSNico Rieck } 939d2c15efSNico Rieck 949d2c15efSNico Rieck if (Value > std::numeric_limits<uint32_t>::max()) 959d2c15efSNico Rieck return true; 969d2c15efSNico Rieck 979d2c15efSNico Rieck Result = static_cast<uint32_t>(Value); 989d2c15efSNico Rieck return false; 999d2c15efSNico Rieck } 1009d2c15efSNico Rieck 10144f51e51SDavid Majnemer template <typename coff_symbol_type> 10244f51e51SDavid Majnemer const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10344f51e51SDavid Majnemer const coff_symbol_type *Addr = 10444f51e51SDavid Majnemer reinterpret_cast<const coff_symbol_type *>(Ref.p); 1051d6167fdSMichael J. Spencer 10622cf54a7SArthur O'Dwyer assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr))); 1071d6167fdSMichael J. Spencer #ifndef NDEBUG 1081d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 10922cf54a7SArthur O'Dwyer uintptr_t Offset = 11022cf54a7SArthur O'Dwyer reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base()); 1111d6167fdSMichael J. Spencer 11244f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11344f51e51SDavid Majnemer "Symbol did not point to the beginning of a symbol"); 1141d6167fdSMichael J. Spencer #endif 1151d6167fdSMichael J. Spencer 1168ff24d25SRui Ueyama return Addr; 1171d6167fdSMichael J. Spencer } 1181d6167fdSMichael J. Spencer 1198ff24d25SRui Ueyama const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1208ff24d25SRui Ueyama const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1211d6167fdSMichael J. Spencer 1221d6167fdSMichael J. Spencer #ifndef NDEBUG 1231d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 12444f51e51SDavid Majnemer if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1251d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 1261d6167fdSMichael J. Spencer 12722cf54a7SArthur O'Dwyer uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) - 12822cf54a7SArthur O'Dwyer reinterpret_cast<uintptr_t>(SectionTable); 1298ff24d25SRui Ueyama assert(Offset % sizeof(coff_section) == 0 && 1301d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 1311d6167fdSMichael J. Spencer #endif 1321d6167fdSMichael J. Spencer 1338ff24d25SRui Ueyama return Addr; 1341d6167fdSMichael J. Spencer } 1351d6167fdSMichael J. Spencer 1365e812afaSRafael Espindola void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 137236b0ca7SDavid Majnemer auto End = reinterpret_cast<uintptr_t>(StringTable); 13844f51e51SDavid Majnemer if (SymbolTable16) { 13944f51e51SDavid Majnemer const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1408ff24d25SRui Ueyama Symb += 1 + Symb->NumberOfAuxSymbols; 141236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14244f51e51SDavid Majnemer } else if (SymbolTable32) { 14344f51e51SDavid Majnemer const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14444f51e51SDavid Majnemer Symb += 1 + Symb->NumberOfAuxSymbols; 145236b0ca7SDavid Majnemer Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14644f51e51SDavid Majnemer } else { 14744f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 14844f51e51SDavid Majnemer } 1491d6167fdSMichael J. Spencer } 1501d6167fdSMichael J. Spencer 15181e8b7d9SKevin Enderby Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 15277ecf90cSReid Kleckner return getSymbolName(getCOFFSymbol(Ref)); 1538e90adafSMichael J. Spencer } 1548e90adafSMichael J. Spencer 155be8b0ea8SRafael Espindola uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 156be8b0ea8SRafael Espindola return getCOFFSymbol(Ref).getValue(); 157991af666SRafael Espindola } 158991af666SRafael Espindola 1596b2bba14SDavide Italiano uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 1606b2bba14SDavide Italiano // MSVC/link.exe seems to align symbols to the next-power-of-2 1616b2bba14SDavide Italiano // up to 32 bytes. 1626b2bba14SDavide Italiano COFFSymbolRef Symb = getCOFFSymbol(Ref); 16303a85680SDavide Italiano return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 1646b2bba14SDavide Italiano } 1656b2bba14SDavide Italiano 166931cb65dSKevin Enderby Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 167ff6a0b6aSXing GUO uint64_t Result = cantFail(getSymbolValue(Ref)); 16844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 169c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 170991af666SRafael Espindola 171991af666SRafael Espindola if (Symb.isAnyUndefined() || Symb.isCommon() || 172991af666SRafael Espindola COFF::isReservedSectionNumber(SectionNumber)) 173ed067c45SRafael Espindola return Result; 17454c9f3daSRafael Espindola 17577ecf90cSReid Kleckner Expected<const coff_section *> Section = getSection(SectionNumber); 17677ecf90cSReid Kleckner if (!Section) 17777ecf90cSReid Kleckner return Section.takeError(); 17877ecf90cSReid Kleckner Result += (*Section)->VirtualAddress; 17947ea9eceSReid Kleckner 18047ea9eceSReid Kleckner // The section VirtualAddress does not include ImageBase, and we want to 18147ea9eceSReid Kleckner // return virtual addresses. 18221427adaSReid Kleckner Result += getImageBase(); 18347ea9eceSReid Kleckner 184ed067c45SRafael Espindola return Result; 185c7d7c6fbSDavid Majnemer } 186c7d7c6fbSDavid Majnemer 1877bd8d994SKevin Enderby Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 18844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 189c7d7c6fbSDavid Majnemer int32_t SectionNumber = Symb.getSectionNumber(); 19044f51e51SDavid Majnemer 191e834f420SPeter Collingbourne if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 192e834f420SPeter Collingbourne return SymbolRef::ST_Function; 1932fa80cc5SRafael Espindola if (Symb.isAnyUndefined()) 1942fa80cc5SRafael Espindola return SymbolRef::ST_Unknown; 1952fa80cc5SRafael Espindola if (Symb.isCommon()) 1962fa80cc5SRafael Espindola return SymbolRef::ST_Data; 1972fa80cc5SRafael Espindola if (Symb.isFileRecord()) 1982fa80cc5SRafael Espindola return SymbolRef::ST_File; 1992fa80cc5SRafael Espindola 2001a666e0fSDavid Majnemer // TODO: perhaps we need a new symbol type ST_Section. 2012fa80cc5SRafael Espindola if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 2022fa80cc5SRafael Espindola return SymbolRef::ST_Debug; 2032fa80cc5SRafael Espindola 2042fa80cc5SRafael Espindola if (!COFF::isReservedSectionNumber(SectionNumber)) 2052fa80cc5SRafael Espindola return SymbolRef::ST_Data; 2062fa80cc5SRafael Espindola 2072fa80cc5SRafael Espindola return SymbolRef::ST_Other; 20875d1cf33SBenjamin Kramer } 20975d1cf33SBenjamin Kramer 210ac00376aSvgxbj Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 21144f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 21220122a43SRafael Espindola uint32_t Result = SymbolRef::SF_None; 21375d1cf33SBenjamin Kramer 214c7d7c6fbSDavid Majnemer if (Symb.isExternal() || Symb.isWeakExternal()) 2159dc0eb42SLang Hames Result |= SymbolRef::SF_Global; 2161df4b84dSDavid Meyer 217a6ffc9c8SMartin Storsjo if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) { 2181df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 219a6ffc9c8SMartin Storsjo if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS) 220a6ffc9c8SMartin Storsjo Result |= SymbolRef::SF_Undefined; 2211079ef8dSMartell Malone } 2221df4b84dSDavid Meyer 22344f51e51SDavid Majnemer if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2241df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 2251df4b84dSDavid Meyer 226c7d7c6fbSDavid Majnemer if (Symb.isFileRecord()) 227c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 228c7d7c6fbSDavid Majnemer 229c7d7c6fbSDavid Majnemer if (Symb.isSectionDefinition()) 230c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_FormatSpecific; 231c7d7c6fbSDavid Majnemer 232c7d7c6fbSDavid Majnemer if (Symb.isCommon()) 233c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Common; 234c7d7c6fbSDavid Majnemer 235a6ffc9c8SMartin Storsjo if (Symb.isUndefined()) 236c7d7c6fbSDavid Majnemer Result |= SymbolRef::SF_Undefined; 237c7d7c6fbSDavid Majnemer 23820122a43SRafael Espindola return Result; 23901759754SMichael J. Spencer } 24001759754SMichael J. Spencer 241d7a32ea4SRafael Espindola uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 242c7d7c6fbSDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2435eb02e45SRafael Espindola return Symb.getValue(); 2448e90adafSMichael J. Spencer } 2458e90adafSMichael J. Spencer 2467bd8d994SKevin Enderby Expected<section_iterator> 2478bab889bSRafael Espindola COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 24844f51e51SDavid Majnemer COFFSymbolRef Symb = getCOFFSymbol(Ref); 2498bab889bSRafael Espindola if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2508bab889bSRafael Espindola return section_end(); 25177ecf90cSReid Kleckner Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber()); 25277ecf90cSReid Kleckner if (!Sec) 25377ecf90cSReid Kleckner return Sec.takeError(); 2548bab889bSRafael Espindola DataRefImpl Ret; 25577ecf90cSReid Kleckner Ret.p = reinterpret_cast<uintptr_t>(*Sec); 2568bab889bSRafael Espindola return section_iterator(SectionRef(Ret, this)); 25732173153SMichael J. Spencer } 25832173153SMichael J. Spencer 2596bf32210SRafael Espindola unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2606bf32210SRafael Espindola COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2616bf32210SRafael Espindola return Symb.getSectionNumber(); 2626bf32210SRafael Espindola } 2636bf32210SRafael Espindola 2645e812afaSRafael Espindola void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2658ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2668ff24d25SRui Ueyama Sec += 1; 2678ff24d25SRui Ueyama Ref.p = reinterpret_cast<uintptr_t>(Sec); 2688e90adafSMichael J. Spencer } 2698e90adafSMichael J. Spencer 2708be28cdcSFangrui Song Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const { 2718ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2728be28cdcSFangrui Song return getSectionName(Sec); 2738e90adafSMichael J. Spencer } 2748e90adafSMichael J. Spencer 27580291274SRafael Espindola uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2768ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2777c6a071bSDavid Majnemer uint64_t Result = Sec->VirtualAddress; 2787c6a071bSDavid Majnemer 2797c6a071bSDavid Majnemer // The section VirtualAddress does not include ImageBase, and we want to 2807c6a071bSDavid Majnemer // return virtual addresses. 28121427adaSReid Kleckner Result += getImageBase(); 2827c6a071bSDavid Majnemer return Result; 2838e90adafSMichael J. Spencer } 2848e90adafSMichael J. Spencer 285a25d329bSGeorge Rimar uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 286a25d329bSGeorge Rimar return toSec(Sec) - SectionTable; 287a25d329bSGeorge Rimar } 288a25d329bSGeorge Rimar 28980291274SRafael Espindola uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 290a9ee5c06SDavid Majnemer return getSectionSize(toSec(Ref)); 2918e90adafSMichael J. Spencer } 2928e90adafSMichael J. Spencer 293e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>> 294e1cb2c0fSFangrui Song COFFObjectFile::getSectionContents(DataRefImpl Ref) const { 2958ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 2969da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 297e1cb2c0fSFangrui Song if (Error E = getSectionContents(Sec, Res)) 298c55cf4afSBill Wendling return std::move(E); 299e1cb2c0fSFangrui Song return Res; 3008e90adafSMichael J. Spencer } 3018e90adafSMichael J. Spencer 30280291274SRafael Espindola uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3038ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 304511391feSDavid Majnemer return Sec->getAlignment(); 3057989460aSMichael J. Spencer } 3067989460aSMichael J. Spencer 307401e4e57SGeorge Rimar bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 308401e4e57SGeorge Rimar return false; 309401e4e57SGeorge Rimar } 310401e4e57SGeorge Rimar 31180291274SRafael Espindola bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3128ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31380291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3148e90adafSMichael J. Spencer } 3158e90adafSMichael J. Spencer 31680291274SRafael Espindola bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3178ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 31880291274SRafael Espindola return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 319800619f2SMichael J. Spencer } 320800619f2SMichael J. Spencer 32180291274SRafael Espindola bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3228ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3231a666e0fSDavid Majnemer const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3241a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_READ | 3251a666e0fSDavid Majnemer COFF::IMAGE_SCN_MEM_WRITE; 3261a666e0fSDavid Majnemer return (Sec->Characteristics & BssFlags) == BssFlags; 327800619f2SMichael J. Spencer } 328800619f2SMichael J. Spencer 32929d253c4SDjordje Todorovic // The .debug sections are the only debug sections for COFF 33029d253c4SDjordje Todorovic // (\see MCObjectFileInfo.cpp). 331*bf809cd1SEsme-Yi bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const { 332*bf809cd1SEsme-Yi Expected<StringRef> SectionNameOrErr = getSectionName(Ref); 333*bf809cd1SEsme-Yi if (!SectionNameOrErr) { 334*bf809cd1SEsme-Yi // TODO: Report the error message properly. 335*bf809cd1SEsme-Yi consumeError(SectionNameOrErr.takeError()); 336*bf809cd1SEsme-Yi return false; 337*bf809cd1SEsme-Yi } 338*bf809cd1SEsme-Yi StringRef SectionName = SectionNameOrErr.get(); 33929d253c4SDjordje Todorovic return SectionName.startswith(".debug"); 34029d253c4SDjordje Todorovic } 34129d253c4SDjordje Todorovic 3426bf32210SRafael Espindola unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3436bf32210SRafael Espindola uintptr_t Offset = 34422cf54a7SArthur O'Dwyer Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable); 3456bf32210SRafael Espindola assert((Offset % sizeof(coff_section)) == 0); 3466bf32210SRafael Espindola return (Offset / sizeof(coff_section)) + 1; 3476bf32210SRafael Espindola } 3486bf32210SRafael Espindola 34980291274SRafael Espindola bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3508ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 3511a666e0fSDavid Majnemer // In COFF, a virtual section won't have any in-file 3521a666e0fSDavid Majnemer // content, so the file pointer to the content will be zero. 3531a666e0fSDavid Majnemer return Sec->PointerToRawData == 0; 3542138ef6dSPreston Gurd } 3552138ef6dSPreston Gurd 356e830c60dSDavid Majnemer static uint32_t getNumberOfRelocations(const coff_section *Sec, 357e830c60dSDavid Majnemer MemoryBufferRef M, const uint8_t *base) { 358e830c60dSDavid Majnemer // The field for the number of relocations in COFF section table is only 359e830c60dSDavid Majnemer // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 360e830c60dSDavid Majnemer // NumberOfRelocations field, and the actual relocation count is stored in the 361e830c60dSDavid Majnemer // VirtualAddress field in the first relocation entry. 362e830c60dSDavid Majnemer if (Sec->hasExtendedRelocations()) { 363e830c60dSDavid Majnemer const coff_relocation *FirstReloc; 3641c03389cSReid Kleckner if (Error E = getObject(FirstReloc, M, 3651c03389cSReid Kleckner reinterpret_cast<const coff_relocation *>( 3661c03389cSReid Kleckner base + Sec->PointerToRelocations))) { 3671c03389cSReid Kleckner consumeError(std::move(E)); 368e830c60dSDavid Majnemer return 0; 3691c03389cSReid Kleckner } 37098fe58a3SRui Ueyama // -1 to exclude this first relocation entry. 37198fe58a3SRui Ueyama return FirstReloc->VirtualAddress - 1; 372e830c60dSDavid Majnemer } 373e830c60dSDavid Majnemer return Sec->NumberOfRelocations; 374e830c60dSDavid Majnemer } 375e830c60dSDavid Majnemer 37694751be7SDavid Majnemer static const coff_relocation * 37794751be7SDavid Majnemer getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 37894751be7SDavid Majnemer uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 37994751be7SDavid Majnemer if (!NumRelocs) 38094751be7SDavid Majnemer return nullptr; 381827c8a2bSRui Ueyama auto begin = reinterpret_cast<const coff_relocation *>( 38294751be7SDavid Majnemer Base + Sec->PointerToRelocations); 383827c8a2bSRui Ueyama if (Sec->hasExtendedRelocations()) { 384827c8a2bSRui Ueyama // Skip the first relocation entry repurposed to store the number of 385827c8a2bSRui Ueyama // relocations. 386827c8a2bSRui Ueyama begin++; 387827c8a2bSRui Ueyama } 38822cf54a7SArthur O'Dwyer if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin), 389e03a135bSReid Kleckner sizeof(coff_relocation) * NumRelocs)) { 390e03a135bSReid Kleckner consumeError(std::move(E)); 39194751be7SDavid Majnemer return nullptr; 392e03a135bSReid Kleckner } 39394751be7SDavid Majnemer return begin; 394827c8a2bSRui Ueyama } 39594751be7SDavid Majnemer 39694751be7SDavid Majnemer relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 39794751be7SDavid Majnemer const coff_section *Sec = toSec(Ref); 39894751be7SDavid Majnemer const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 39976d650e8SRafael Espindola if (begin && Sec->VirtualAddress != 0) 40076d650e8SRafael Espindola report_fatal_error("Sections with relocations should have an address of 0"); 40194751be7SDavid Majnemer DataRefImpl Ret; 40294751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(begin); 4038ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 404e5fd0047SMichael J. Spencer } 405e5fd0047SMichael J. Spencer 4068ff24d25SRui Ueyama relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 4078ff24d25SRui Ueyama const coff_section *Sec = toSec(Ref); 40894751be7SDavid Majnemer const coff_relocation *I = getFirstReloc(Sec, Data, base()); 40994751be7SDavid Majnemer if (I) 41094751be7SDavid Majnemer I += getNumberOfRelocations(Sec, Data, base()); 4118ff24d25SRui Ueyama DataRefImpl Ret; 41294751be7SDavid Majnemer Ret.p = reinterpret_cast<uintptr_t>(I); 4138ff24d25SRui Ueyama return relocation_iterator(RelocationRef(Ret, this)); 414e5fd0047SMichael J. Spencer } 415e5fd0047SMichael J. Spencer 416c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 4171c03389cSReid Kleckner Error COFFObjectFile::initSymbolTablePtr() { 41844f51e51SDavid Majnemer if (COFFHeader) 4191c03389cSReid Kleckner if (Error E = getObject( 420236b0ca7SDavid Majnemer SymbolTable16, Data, base() + getPointerToSymbolTable(), 421236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4221c03389cSReid Kleckner return E; 42344f51e51SDavid Majnemer 42444f51e51SDavid Majnemer if (COFFBigObjHeader) 4251c03389cSReid Kleckner if (Error E = getObject( 426236b0ca7SDavid Majnemer SymbolTable32, Data, base() + getPointerToSymbolTable(), 427236b0ca7SDavid Majnemer (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4281c03389cSReid Kleckner return E; 429c2bed429SRui Ueyama 430c2bed429SRui Ueyama // Find string table. The first four byte of the string table contains the 431c2bed429SRui Ueyama // total size of the string table, including the size field itself. If the 432c2bed429SRui Ueyama // string table is empty, the value of the first four byte would be 4. 433f69b0585SDavid Majnemer uint32_t StringTableOffset = getPointerToSymbolTable() + 43444f51e51SDavid Majnemer getNumberOfSymbols() * getSymbolTableEntrySize(); 435f69b0585SDavid Majnemer const uint8_t *StringTableAddr = base() + StringTableOffset; 436c2bed429SRui Ueyama const ulittle32_t *StringTableSizePtr; 4371c03389cSReid Kleckner if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr)) 4381c03389cSReid Kleckner return E; 439c2bed429SRui Ueyama StringTableSize = *StringTableSizePtr; 4401c03389cSReid Kleckner if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4411c03389cSReid Kleckner return E; 442c2bed429SRui Ueyama 443773a5795SNico Rieck // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 444773a5795SNico Rieck // tools like cvtres write a size of 0 for an empty table instead of 4. 445773a5795SNico Rieck if (StringTableSize < 4) 446773a5795SNico Rieck StringTableSize = 4; 447773a5795SNico Rieck 448c2bed429SRui Ueyama // Check that the string table is null terminated if has any in it. 449773a5795SNico Rieck if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 4501c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 4511c03389cSReid Kleckner return Error::success(); 452c2bed429SRui Ueyama } 453c2bed429SRui Ueyama 45421427adaSReid Kleckner uint64_t COFFObjectFile::getImageBase() const { 455e94fef7bSReid Kleckner if (PE32Header) 45621427adaSReid Kleckner return PE32Header->ImageBase; 457e94fef7bSReid Kleckner else if (PE32PlusHeader) 45821427adaSReid Kleckner return PE32PlusHeader->ImageBase; 45921427adaSReid Kleckner // This actually comes up in practice. 46021427adaSReid Kleckner return 0; 461e94fef7bSReid Kleckner } 462e94fef7bSReid Kleckner 463215a586cSRui Ueyama // Returns the file offset for the given VA. 4641c03389cSReid Kleckner Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 46521427adaSReid Kleckner uint64_t ImageBase = getImageBase(); 466b7a40081SRui Ueyama uint64_t Rva = Addr - ImageBase; 467b7a40081SRui Ueyama assert(Rva <= UINT32_MAX); 468b7a40081SRui Ueyama return getRvaPtr((uint32_t)Rva, Res); 469215a586cSRui Ueyama } 470215a586cSRui Ueyama 471c2bed429SRui Ueyama // Returns the file offset for the given RVA. 4721c03389cSReid Kleckner Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 47327dc8394SAlexey Samsonov for (const SectionRef &S : sections()) { 47427dc8394SAlexey Samsonov const coff_section *Section = getCOFFSection(S); 475c2bed429SRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 476c2bed429SRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 477215a586cSRui Ueyama if (SectionStart <= Addr && Addr < SectionEnd) { 478215a586cSRui Ueyama uint32_t Offset = Addr - SectionStart; 47922cf54a7SArthur O'Dwyer Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData + 48022cf54a7SArthur O'Dwyer Offset; 4811c03389cSReid Kleckner return Error::success(); 482c2bed429SRui Ueyama } 483c2bed429SRui Ueyama } 4841c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 485c2bed429SRui Ueyama } 486c2bed429SRui Ueyama 4871c03389cSReid Kleckner Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 4882da433eaSReid Kleckner ArrayRef<uint8_t> &Contents) const { 4892da433eaSReid Kleckner for (const SectionRef &S : sections()) { 4902da433eaSReid Kleckner const coff_section *Section = getCOFFSection(S); 4912da433eaSReid Kleckner uint32_t SectionStart = Section->VirtualAddress; 4922da433eaSReid Kleckner // Check if this RVA is within the section bounds. Be careful about integer 4932da433eaSReid Kleckner // overflow. 4942da433eaSReid Kleckner uint32_t OffsetIntoSection = RVA - SectionStart; 4952da433eaSReid Kleckner if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 4962da433eaSReid Kleckner Size <= Section->VirtualSize - OffsetIntoSection) { 49722cf54a7SArthur O'Dwyer uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) + 49822cf54a7SArthur O'Dwyer Section->PointerToRawData + OffsetIntoSection; 4992da433eaSReid Kleckner Contents = 5002da433eaSReid Kleckner ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 5011c03389cSReid Kleckner return Error::success(); 5022da433eaSReid Kleckner } 5032da433eaSReid Kleckner } 5041c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 5052da433eaSReid Kleckner } 5062da433eaSReid Kleckner 507c2bed429SRui Ueyama // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 508c2bed429SRui Ueyama // table entry. 5091c03389cSReid Kleckner Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 510db4ed0bdSRafael Espindola StringRef &Name) const { 511c2bed429SRui Ueyama uintptr_t IntPtr = 0; 5121c03389cSReid Kleckner if (Error E = getRvaPtr(Rva, IntPtr)) 5131c03389cSReid Kleckner return E; 514c2bed429SRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 515c2bed429SRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 516c2bed429SRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5171c03389cSReid Kleckner return Error::success(); 518c2bed429SRui Ueyama } 519c2bed429SRui Ueyama 5201c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 52101528021SSaleem Abdulrasool const codeview::DebugInfo *&PDBInfo, 5222da433eaSReid Kleckner StringRef &PDBFileName) const { 5232da433eaSReid Kleckner ArrayRef<uint8_t> InfoBytes; 5241c03389cSReid Kleckner if (Error E = getRvaAndSizeAsBytes( 5252da433eaSReid Kleckner DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 5261c03389cSReid Kleckner return E; 52701528021SSaleem Abdulrasool if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 5281c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 52901528021SSaleem Abdulrasool PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 53001528021SSaleem Abdulrasool InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5312da433eaSReid Kleckner PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5322da433eaSReid Kleckner InfoBytes.size()); 5332da433eaSReid Kleckner // Truncate the name at the first null byte. Ignore any padding. 5342da433eaSReid Kleckner PDBFileName = PDBFileName.split('\0').first; 5351c03389cSReid Kleckner return Error::success(); 5362da433eaSReid Kleckner } 5372da433eaSReid Kleckner 5381c03389cSReid Kleckner Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 539f27f3f84SReid Kleckner StringRef &PDBFileName) const { 540f27f3f84SReid Kleckner for (const debug_directory &D : debug_directories()) 541f27f3f84SReid Kleckner if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 542f27f3f84SReid Kleckner return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 543f27f3f84SReid Kleckner // If we get here, there is no PDB info to return. 544f27f3f84SReid Kleckner PDBInfo = nullptr; 545f27f3f84SReid Kleckner PDBFileName = StringRef(); 5461c03389cSReid Kleckner return Error::success(); 547f27f3f84SReid Kleckner } 548f27f3f84SReid Kleckner 549c2bed429SRui Ueyama // Find the import table. 5501c03389cSReid Kleckner Error COFFObjectFile::initImportTablePtr() { 551c2bed429SRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 552c2bed429SRui Ueyama // the import table, do nothing. 5531c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE); 5541c03389cSReid Kleckner if (!DataEntry) 5551c03389cSReid Kleckner return Error::success(); 556c2bed429SRui Ueyama 557c2bed429SRui Ueyama // Do nothing if the pointer to import table is NULL. 558c2bed429SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5591c03389cSReid Kleckner return Error::success(); 560c2bed429SRui Ueyama 561c2bed429SRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 562c2bed429SRui Ueyama 563c2bed429SRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 564c2bed429SRui Ueyama // the import table's memory address which is different from its file offset. 565c2bed429SRui Ueyama uintptr_t IntPtr = 0; 5661c03389cSReid Kleckner if (Error E = getRvaPtr(ImportTableRva, IntPtr)) 5671c03389cSReid Kleckner return E; 568e03a135bSReid Kleckner if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 5691c03389cSReid Kleckner return E; 570c2bed429SRui Ueyama ImportDirectory = reinterpret_cast< 5711c0aa04eSDavid Majnemer const coff_import_directory_table_entry *>(IntPtr); 5721c03389cSReid Kleckner return Error::success(); 573ad882ba8SRui Ueyama } 574c2bed429SRui Ueyama 57515d99359SRui Ueyama // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 5761c03389cSReid Kleckner Error COFFObjectFile::initDelayImportTablePtr() { 5771c03389cSReid Kleckner const data_directory *DataEntry = 5781c03389cSReid Kleckner getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR); 5791c03389cSReid Kleckner if (!DataEntry) 5801c03389cSReid Kleckner return Error::success(); 58115d99359SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5821c03389cSReid Kleckner return Error::success(); 58315d99359SRui Ueyama 58415d99359SRui Ueyama uint32_t RVA = DataEntry->RelativeVirtualAddress; 58515d99359SRui Ueyama NumberOfDelayImportDirectory = DataEntry->Size / 58615d99359SRui Ueyama sizeof(delay_import_directory_table_entry) - 1; 58715d99359SRui Ueyama 58815d99359SRui Ueyama uintptr_t IntPtr = 0; 5891c03389cSReid Kleckner if (Error E = getRvaPtr(RVA, IntPtr)) 5901c03389cSReid Kleckner return E; 59115d99359SRui Ueyama DelayImportDirectory = reinterpret_cast< 59215d99359SRui Ueyama const delay_import_directory_table_entry *>(IntPtr); 5931c03389cSReid Kleckner return Error::success(); 59415d99359SRui Ueyama } 59515d99359SRui Ueyama 596ad882ba8SRui Ueyama // Find the export table. 5971c03389cSReid Kleckner Error COFFObjectFile::initExportTablePtr() { 598ad882ba8SRui Ueyama // First, we get the RVA of the export table. If the file lacks a pointer to 599ad882ba8SRui Ueyama // the export table, do nothing. 6001c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE); 6011c03389cSReid Kleckner if (!DataEntry) 6021c03389cSReid Kleckner return Error::success(); 603ad882ba8SRui Ueyama 604ad882ba8SRui Ueyama // Do nothing if the pointer to export table is NULL. 605ad882ba8SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6061c03389cSReid Kleckner return Error::success(); 607ad882ba8SRui Ueyama 608ad882ba8SRui Ueyama uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 609ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 6101c03389cSReid Kleckner if (Error E = getRvaPtr(ExportTableRva, IntPtr)) 6111c03389cSReid Kleckner return E; 61224fc2d64SRui Ueyama ExportDirectory = 61324fc2d64SRui Ueyama reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6141c03389cSReid Kleckner return Error::success(); 615c2bed429SRui Ueyama } 616c2bed429SRui Ueyama 6171c03389cSReid Kleckner Error COFFObjectFile::initBaseRelocPtr() { 6181c03389cSReid Kleckner const data_directory *DataEntry = 6191c03389cSReid Kleckner getDataDirectory(COFF::BASE_RELOCATION_TABLE); 6201c03389cSReid Kleckner if (!DataEntry) 6211c03389cSReid Kleckner return Error::success(); 62274e85130SRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 6231c03389cSReid Kleckner return Error::success(); 62474e85130SRui Ueyama 62574e85130SRui Ueyama uintptr_t IntPtr = 0; 6261c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6271c03389cSReid Kleckner return E; 62874e85130SRui Ueyama BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 62974e85130SRui Ueyama IntPtr); 63074e85130SRui Ueyama BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 63174e85130SRui Ueyama IntPtr + DataEntry->Size); 632893c6469SNico Weber // FIXME: Verify the section containing BaseRelocHeader has at least 633893c6469SNico Weber // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6341c03389cSReid Kleckner return Error::success(); 63574e85130SRui Ueyama } 63674e85130SRui Ueyama 6371c03389cSReid Kleckner Error COFFObjectFile::initDebugDirectoryPtr() { 6382da433eaSReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6391c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY); 6401c03389cSReid Kleckner if (!DataEntry) 6411c03389cSReid Kleckner return Error::success(); 6422da433eaSReid Kleckner 6432da433eaSReid Kleckner // Do nothing if the RVA is NULL. 6442da433eaSReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 6451c03389cSReid Kleckner return Error::success(); 6462da433eaSReid Kleckner 6472da433eaSReid Kleckner // Check that the size is a multiple of the entry size. 6482da433eaSReid Kleckner if (DataEntry->Size % sizeof(debug_directory) != 0) 6491c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 6502da433eaSReid Kleckner 6512da433eaSReid Kleckner uintptr_t IntPtr = 0; 6521c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 6531c03389cSReid Kleckner return E; 6542da433eaSReid Kleckner DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 655893c6469SNico Weber DebugDirectoryEnd = reinterpret_cast<const debug_directory *>( 656893c6469SNico Weber IntPtr + DataEntry->Size); 657893c6469SNico Weber // FIXME: Verify the section containing DebugDirectoryBegin has at least 658893c6469SNico Weber // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6591c03389cSReid Kleckner return Error::success(); 6602da433eaSReid Kleckner } 6612da433eaSReid Kleckner 662568035acSLuqman Aden Error COFFObjectFile::initTLSDirectoryPtr() { 663568035acSLuqman Aden // Get the RVA of the TLS directory. Do nothing if it does not exist. 664568035acSLuqman Aden const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE); 665568035acSLuqman Aden if (!DataEntry) 666568035acSLuqman Aden return Error::success(); 667568035acSLuqman Aden 668568035acSLuqman Aden // Do nothing if the RVA is NULL. 669568035acSLuqman Aden if (DataEntry->RelativeVirtualAddress == 0) 670568035acSLuqman Aden return Error::success(); 671568035acSLuqman Aden 672568035acSLuqman Aden uint64_t DirSize = 673568035acSLuqman Aden is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32); 674568035acSLuqman Aden 675568035acSLuqman Aden // Check that the size is correct. 676568035acSLuqman Aden if (DataEntry->Size != DirSize) 677568035acSLuqman Aden return createStringError( 678568035acSLuqman Aden object_error::parse_failed, 6792980ce98SHubert Tong "TLS Directory size (%u) is not the expected size (%" PRIu64 ").", 680568035acSLuqman Aden static_cast<uint32_t>(DataEntry->Size), DirSize); 681568035acSLuqman Aden 682568035acSLuqman Aden uintptr_t IntPtr = 0; 683568035acSLuqman Aden if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 684568035acSLuqman Aden return E; 685568035acSLuqman Aden 686568035acSLuqman Aden if (is64()) 687568035acSLuqman Aden TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr); 688568035acSLuqman Aden else 689568035acSLuqman Aden TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr); 690568035acSLuqman Aden 691568035acSLuqman Aden return Error::success(); 692568035acSLuqman Aden } 693568035acSLuqman Aden 6941c03389cSReid Kleckner Error COFFObjectFile::initLoadConfigPtr() { 695b7d716c0SReid Kleckner // Get the RVA of the debug directory. Do nothing if it does not exist. 6961c03389cSReid Kleckner const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE); 6971c03389cSReid Kleckner if (!DataEntry) 6981c03389cSReid Kleckner return Error::success(); 699b7d716c0SReid Kleckner 700b7d716c0SReid Kleckner // Do nothing if the RVA is NULL. 701b7d716c0SReid Kleckner if (DataEntry->RelativeVirtualAddress == 0) 7021c03389cSReid Kleckner return Error::success(); 703b7d716c0SReid Kleckner uintptr_t IntPtr = 0; 7041c03389cSReid Kleckner if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 7051c03389cSReid Kleckner return E; 706b7d716c0SReid Kleckner 707b7d716c0SReid Kleckner LoadConfig = (const void *)IntPtr; 7081c03389cSReid Kleckner return Error::success(); 709b7d716c0SReid Kleckner } 710b7d716c0SReid Kleckner 71139772063SReid Kleckner Expected<std::unique_ptr<COFFObjectFile>> 71239772063SReid Kleckner COFFObjectFile::create(MemoryBufferRef Object) { 71339772063SReid Kleckner std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object))); 71439772063SReid Kleckner if (Error E = Obj->initialize()) 71539772063SReid Kleckner return std::move(E); 71639772063SReid Kleckner return std::move(Obj); 71739772063SReid Kleckner } 71839772063SReid Kleckner 71939772063SReid Kleckner COFFObjectFile::COFFObjectFile(MemoryBufferRef Object) 72048af1c2aSRafael Espindola : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 72144f51e51SDavid Majnemer COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 72244f51e51SDavid Majnemer DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 72344f51e51SDavid Majnemer SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 72439772063SReid Kleckner ImportDirectory(nullptr), DelayImportDirectory(nullptr), 72539772063SReid Kleckner NumberOfDelayImportDirectory(0), ExportDirectory(nullptr), 72639772063SReid Kleckner BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 727568035acSLuqman Aden DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr), 728568035acSLuqman Aden TLSDirectory32(nullptr), TLSDirectory64(nullptr) {} 72939772063SReid Kleckner 730101fbc01SNico Weber Error COFFObjectFile::initialize() { 7311d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 73239772063SReid Kleckner std::error_code EC; 73348af1c2aSRafael Espindola if (!checkSize(Data, EC, sizeof(coff_file_header))) 73439772063SReid Kleckner return errorCodeToError(EC); 735ee066fc4SEric Christopher 73682ebd8e3SRui Ueyama // The current location in the file where we are looking at. 73782ebd8e3SRui Ueyama uint64_t CurPtr = 0; 73882ebd8e3SRui Ueyama 73982ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 74082ebd8e3SRui Ueyama // it is placed right after COFF header. 7418ff24d25SRui Ueyama bool HasPEHeader = false; 742ee066fc4SEric Christopher 7431d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 74450267222SDavid Majnemer if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 745ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 746ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 74750267222SDavid Majnemer const auto *DH = reinterpret_cast<const dos_header *>(base()); 74850267222SDavid Majnemer if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 74950267222SDavid Majnemer CurPtr = DH->AddressOfNewExeHeader; 75082ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 75150267222SDavid Majnemer if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 75239772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 7531d6167fdSMichael J. Spencer } 75444f51e51SDavid Majnemer CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 7558ff24d25SRui Ueyama HasPEHeader = true; 756ee066fc4SEric Christopher } 75750267222SDavid Majnemer } 758ee066fc4SEric Christopher 7591c03389cSReid Kleckner if (Error E = getObject(COFFHeader, Data, base() + CurPtr)) 7601c03389cSReid Kleckner return E; 76144f51e51SDavid Majnemer 76244f51e51SDavid Majnemer // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 76344f51e51SDavid Majnemer // import libraries share a common prefix but bigobj is more restrictive. 76444f51e51SDavid Majnemer if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 76544f51e51SDavid Majnemer COFFHeader->NumberOfSections == uint16_t(0xffff) && 76644f51e51SDavid Majnemer checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 7671c03389cSReid Kleckner if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr)) 7681c03389cSReid Kleckner return E; 76944f51e51SDavid Majnemer 77044f51e51SDavid Majnemer // Verify that we are dealing with bigobj. 77144f51e51SDavid Majnemer if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 77244f51e51SDavid Majnemer std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 77344f51e51SDavid Majnemer sizeof(COFF::BigObjMagic)) == 0) { 77444f51e51SDavid Majnemer COFFHeader = nullptr; 77544f51e51SDavid Majnemer CurPtr += sizeof(coff_bigobj_file_header); 77644f51e51SDavid Majnemer } else { 77744f51e51SDavid Majnemer // It's not a bigobj. 77844f51e51SDavid Majnemer COFFBigObjHeader = nullptr; 77944f51e51SDavid Majnemer } 78044f51e51SDavid Majnemer } 78144f51e51SDavid Majnemer if (COFFHeader) { 78244f51e51SDavid Majnemer // The prior checkSize call may have failed. This isn't a hard error 78344f51e51SDavid Majnemer // because we were just trying to sniff out bigobj. 7847d099195SRui Ueyama EC = std::error_code(); 78582ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 78682ebd8e3SRui Ueyama 78744f51e51SDavid Majnemer if (COFFHeader->isImportLibrary()) 78839772063SReid Kleckner return errorCodeToError(EC); 78944f51e51SDavid Majnemer } 79044f51e51SDavid Majnemer 7918ff24d25SRui Ueyama if (HasPEHeader) { 79210ed9ddcSRui Ueyama const pe32_header *Header; 7931c03389cSReid Kleckner if (Error E = getObject(Header, Data, base() + CurPtr)) 7941c03389cSReid Kleckner return E; 79510ed9ddcSRui Ueyama 79610ed9ddcSRui Ueyama const uint8_t *DataDirAddr; 79710ed9ddcSRui Ueyama uint64_t DataDirSize; 79850267222SDavid Majnemer if (Header->Magic == COFF::PE32Header::PE32) { 79910ed9ddcSRui Ueyama PE32Header = Header; 80010ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32_header); 80110ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 80250267222SDavid Majnemer } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 80310ed9ddcSRui Ueyama PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 80410ed9ddcSRui Ueyama DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 80510ed9ddcSRui Ueyama DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 80610ed9ddcSRui Ueyama } else { 80710ed9ddcSRui Ueyama // It's neither PE32 nor PE32+. 80839772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 809ed64342bSRui Ueyama } 8101c03389cSReid Kleckner if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)) 8111c03389cSReid Kleckner return E; 812f53c8cb4SRui Ueyama } 813776c6828SRui Ueyama 8148950a538SRui Ueyama if (COFFHeader) 8158950a538SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 8168950a538SRui Ueyama 8171c03389cSReid Kleckner assert(COFFHeader || COFFBigObjHeader); 8181c03389cSReid Kleckner 8191c03389cSReid Kleckner if (Error E = 8201c03389cSReid Kleckner getObject(SectionTable, Data, base() + CurPtr, 8211c03389cSReid Kleckner (uint64_t)getNumberOfSections() * sizeof(coff_section))) 8221c03389cSReid Kleckner return E; 8231d6167fdSMichael J. Spencer 824c2bed429SRui Ueyama // Initialize the pointer to the symbol table. 825236b0ca7SDavid Majnemer if (getPointerToSymbolTable() != 0) { 8261c03389cSReid Kleckner if (Error E = initSymbolTablePtr()) { 8271c03389cSReid Kleckner // Recover from errors reading the symbol table. 8281c03389cSReid Kleckner consumeError(std::move(E)); 829ac8cfab5SDavid Majnemer SymbolTable16 = nullptr; 830ac8cfab5SDavid Majnemer SymbolTable32 = nullptr; 831ac8cfab5SDavid Majnemer StringTable = nullptr; 832ac8cfab5SDavid Majnemer StringTableSize = 0; 833ac8cfab5SDavid Majnemer } 834236b0ca7SDavid Majnemer } else { 835236b0ca7SDavid Majnemer // We had better not have any symbols if we don't have a symbol table. 836236b0ca7SDavid Majnemer if (getNumberOfSymbols() != 0) { 83739772063SReid Kleckner return errorCodeToError(object_error::parse_failed); 838236b0ca7SDavid Majnemer } 839236b0ca7SDavid Majnemer } 8408e90adafSMichael J. Spencer 841c2bed429SRui Ueyama // Initialize the pointer to the beginning of the import table. 8421c03389cSReid Kleckner if (Error E = initImportTablePtr()) 8431c03389cSReid Kleckner return E; 8441c03389cSReid Kleckner if (Error E = initDelayImportTablePtr()) 8451c03389cSReid Kleckner return E; 8461d6167fdSMichael J. Spencer 847ad882ba8SRui Ueyama // Initialize the pointer to the export table. 8481c03389cSReid Kleckner if (Error E = initExportTablePtr()) 8491c03389cSReid Kleckner return E; 850ad882ba8SRui Ueyama 85174e85130SRui Ueyama // Initialize the pointer to the base relocation table. 8521c03389cSReid Kleckner if (Error E = initBaseRelocPtr()) 8531c03389cSReid Kleckner return E; 85474e85130SRui Ueyama 855568035acSLuqman Aden // Initialize the pointer to the debug directory. 8561c03389cSReid Kleckner if (Error E = initDebugDirectoryPtr()) 8571c03389cSReid Kleckner return E; 8582da433eaSReid Kleckner 859568035acSLuqman Aden // Initialize the pointer to the TLS directory. 860568035acSLuqman Aden if (Error E = initTLSDirectoryPtr()) 861568035acSLuqman Aden return E; 862568035acSLuqman Aden 8631c03389cSReid Kleckner if (Error E = initLoadConfigPtr()) 8641c03389cSReid Kleckner return E; 865b7d716c0SReid Kleckner 86639772063SReid Kleckner return Error::success(); 8678e90adafSMichael J. Spencer } 8688e90adafSMichael J. Spencer 869435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_begin() const { 8708ff24d25SRui Ueyama DataRefImpl Ret; 87144f51e51SDavid Majnemer Ret.p = getSymbolTable(); 872f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8738e90adafSMichael J. Spencer } 8748e90adafSMichael J. Spencer 875435890a4SPeter Collingbourne basic_symbol_iterator COFFObjectFile::symbol_end() const { 8768e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 8778ff24d25SRui Ueyama DataRefImpl Ret; 8788ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(StringTable); 879f12b8282SRafael Espindola return basic_symbol_iterator(SymbolRef(Ret, this)); 8808e90adafSMichael J. Spencer } 8818e90adafSMichael J. Spencer 882bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_begin() const { 883ad7b7e73SDavid Majnemer if (!ImportDirectory) 884ad7b7e73SDavid Majnemer return import_directory_end(); 8851c0aa04eSDavid Majnemer if (ImportDirectory->isNull()) 886ad7b7e73SDavid Majnemer return import_directory_end(); 887a045b73aSRui Ueyama return import_directory_iterator( 888a045b73aSRui Ueyama ImportDirectoryEntryRef(ImportDirectory, 0, this)); 889c2bed429SRui Ueyama } 890c2bed429SRui Ueyama 891bc654b18SRui Ueyama import_directory_iterator COFFObjectFile::import_directory_end() const { 892a045b73aSRui Ueyama return import_directory_iterator( 893ad7b7e73SDavid Majnemer ImportDirectoryEntryRef(nullptr, -1, this)); 894c2bed429SRui Ueyama } 895c429b80dSDavid Meyer 89615d99359SRui Ueyama delay_import_directory_iterator 89715d99359SRui Ueyama COFFObjectFile::delay_import_directory_begin() const { 89815d99359SRui Ueyama return delay_import_directory_iterator( 89915d99359SRui Ueyama DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 90015d99359SRui Ueyama } 90115d99359SRui Ueyama 90215d99359SRui Ueyama delay_import_directory_iterator 90315d99359SRui Ueyama COFFObjectFile::delay_import_directory_end() const { 90415d99359SRui Ueyama return delay_import_directory_iterator( 90515d99359SRui Ueyama DelayImportDirectoryEntryRef( 90615d99359SRui Ueyama DelayImportDirectory, NumberOfDelayImportDirectory, this)); 90715d99359SRui Ueyama } 90815d99359SRui Ueyama 909ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_begin() const { 910ad882ba8SRui Ueyama return export_directory_iterator( 911ad882ba8SRui Ueyama ExportDirectoryEntryRef(ExportDirectory, 0, this)); 912ad882ba8SRui Ueyama } 913ad882ba8SRui Ueyama 914ad882ba8SRui Ueyama export_directory_iterator COFFObjectFile::export_directory_end() const { 9152617dcceSCraig Topper if (!ExportDirectory) 9162617dcceSCraig Topper return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 9178ff24d25SRui Ueyama ExportDirectoryEntryRef Ref(ExportDirectory, 918ad882ba8SRui Ueyama ExportDirectory->AddressTableEntries, this); 9198ff24d25SRui Ueyama return export_directory_iterator(Ref); 920ad882ba8SRui Ueyama } 921ad882ba8SRui Ueyama 922b5155a57SRafael Espindola section_iterator COFFObjectFile::section_begin() const { 9238ff24d25SRui Ueyama DataRefImpl Ret; 9248ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 9258ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 9268e90adafSMichael J. Spencer } 9278e90adafSMichael J. Spencer 928b5155a57SRafael Espindola section_iterator COFFObjectFile::section_end() const { 9298ff24d25SRui Ueyama DataRefImpl Ret; 93044f51e51SDavid Majnemer int NumSections = 93144f51e51SDavid Majnemer COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 9328ff24d25SRui Ueyama Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 9338ff24d25SRui Ueyama return section_iterator(SectionRef(Ret, this)); 9348e90adafSMichael J. Spencer } 9358e90adafSMichael J. Spencer 93674e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 93774e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 93874e85130SRui Ueyama } 93974e85130SRui Ueyama 94074e85130SRui Ueyama base_reloc_iterator COFFObjectFile::base_reloc_end() const { 94174e85130SRui Ueyama return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 94274e85130SRui Ueyama } 94374e85130SRui Ueyama 9448e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 94543c85453SMartin Storsjo return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 9468e90adafSMichael J. Spencer } 9478e90adafSMichael J. Spencer 9488e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 94944f51e51SDavid Majnemer switch(getMachine()) { 9508e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9518e90adafSMichael J. Spencer return "COFF-i386"; 9528e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9538e90adafSMichael J. Spencer return "COFF-x86-64"; 9549b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9559b7c0af2SSaleem Abdulrasool return "COFF-ARM"; 9561eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9571eff5c9cSMartell Malone return "COFF-ARM64"; 9588e90adafSMichael J. Spencer default: 9598e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 9608e90adafSMichael J. Spencer } 9618e90adafSMichael J. Spencer } 9628e90adafSMichael J. Spencer 963260fe3ecSZachary Turner Triple::ArchType COFFObjectFile::getArch() const { 96444f51e51SDavid Majnemer switch (getMachine()) { 9658e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 9668e90adafSMichael J. Spencer return Triple::x86; 9678e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 9688e90adafSMichael J. Spencer return Triple::x86_64; 9699b7c0af2SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 9709b7c0af2SSaleem Abdulrasool return Triple::thumb; 9711eff5c9cSMartell Malone case COFF::IMAGE_FILE_MACHINE_ARM64: 9721eff5c9cSMartell Malone return Triple::aarch64; 9738e90adafSMichael J. Spencer default: 9748e90adafSMichael J. Spencer return Triple::UnknownArch; 9758e90adafSMichael J. Spencer } 9768e90adafSMichael J. Spencer } 9778e90adafSMichael J. Spencer 978d2af4d6fSPaul Semel Expected<uint64_t> COFFObjectFile::getStartAddress() const { 979d2af4d6fSPaul Semel if (PE32Header) 980d2af4d6fSPaul Semel return PE32Header->AddressOfEntryPoint; 981d2af4d6fSPaul Semel return 0; 982d2af4d6fSPaul Semel } 983d2af4d6fSPaul Semel 984979fb40bSRui Ueyama iterator_range<import_directory_iterator> 985979fb40bSRui Ueyama COFFObjectFile::import_directories() const { 986979fb40bSRui Ueyama return make_range(import_directory_begin(), import_directory_end()); 987979fb40bSRui Ueyama } 988979fb40bSRui Ueyama 989979fb40bSRui Ueyama iterator_range<delay_import_directory_iterator> 990979fb40bSRui Ueyama COFFObjectFile::delay_import_directories() const { 991979fb40bSRui Ueyama return make_range(delay_import_directory_begin(), 992979fb40bSRui Ueyama delay_import_directory_end()); 993979fb40bSRui Ueyama } 994979fb40bSRui Ueyama 995979fb40bSRui Ueyama iterator_range<export_directory_iterator> 996979fb40bSRui Ueyama COFFObjectFile::export_directories() const { 997979fb40bSRui Ueyama return make_range(export_directory_begin(), export_directory_end()); 998979fb40bSRui Ueyama } 999979fb40bSRui Ueyama 100074e85130SRui Ueyama iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 100174e85130SRui Ueyama return make_range(base_reloc_begin(), base_reloc_end()); 100274e85130SRui Ueyama } 100374e85130SRui Ueyama 10041c03389cSReid Kleckner const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const { 10051c03389cSReid Kleckner if (!DataDirectory) 10061c03389cSReid Kleckner return nullptr; 100710ed9ddcSRui Ueyama assert(PE32Header || PE32PlusHeader); 100810ed9ddcSRui Ueyama uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 100910ed9ddcSRui Ueyama : PE32PlusHeader->NumberOfRvaAndSize; 10101c03389cSReid Kleckner if (Index >= NumEnt) 10111c03389cSReid Kleckner return nullptr; 10121c03389cSReid Kleckner return &DataDirectory[Index]; 1013ed64342bSRui Ueyama } 1014ed64342bSRui Ueyama 101577ecf90cSReid Kleckner Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const { 101677ecf90cSReid Kleckner // Perhaps getting the section of a reserved section index should be an error, 101777ecf90cSReid Kleckner // but callers rely on this to return null. 1018236b0ca7SDavid Majnemer if (COFF::isReservedSectionNumber(Index)) 101977ecf90cSReid Kleckner return (const coff_section *)nullptr; 1020236b0ca7SDavid Majnemer if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 10211d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 102277ecf90cSReid Kleckner return SectionTable + (Index - 1); 10238e90adafSMichael J. Spencer } 102477ecf90cSReid Kleckner return errorCodeToError(object_error::parse_failed); 1025236b0ca7SDavid Majnemer } 10268e90adafSMichael J. Spencer 102777ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const { 10281d6167fdSMichael J. Spencer if (StringTableSize <= 4) 10291d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 103077ecf90cSReid Kleckner return errorCodeToError(object_error::parse_failed); 10318ff24d25SRui Ueyama if (Offset >= StringTableSize) 103277ecf90cSReid Kleckner return errorCodeToError(object_error::unexpected_eof); 103377ecf90cSReid Kleckner return StringRef(StringTable + Offset); 10348e90adafSMichael J. Spencer } 1035022ecdf2SBenjamin Kramer 103677ecf90cSReid Kleckner Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const { 103777ecf90cSReid Kleckner return getSymbolName(Symbol.getGeneric()); 1038e40d30f3SRui Ueyama } 1039e40d30f3SRui Ueyama 104077ecf90cSReid Kleckner Expected<StringRef> 104177ecf90cSReid Kleckner COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const { 104289a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 104377ecf90cSReid Kleckner if (Symbol->Name.Offset.Zeroes == 0) 104477ecf90cSReid Kleckner return getString(Symbol->Name.Offset.Offset); 104589a7a5eaSMichael J. Spencer 104689a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 104777ecf90cSReid Kleckner if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 104877ecf90cSReid Kleckner return StringRef(Symbol->Name.ShortName); 104977ecf90cSReid Kleckner 105089a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 105177ecf90cSReid Kleckner return StringRef(Symbol->Name.ShortName, COFF::NameSize); 105289a7a5eaSMichael J. Spencer } 105389a7a5eaSMichael J. Spencer 105444f51e51SDavid Majnemer ArrayRef<uint8_t> 105544f51e51SDavid Majnemer COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 10562617dcceSCraig Topper const uint8_t *Aux = nullptr; 105771757ef3SMarshall Clow 105844f51e51SDavid Majnemer size_t SymbolSize = getSymbolTableEntrySize(); 105944f51e51SDavid Majnemer if (Symbol.getNumberOfAuxSymbols() > 0) { 106071757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 106144f51e51SDavid Majnemer Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 106271757ef3SMarshall Clow #ifndef NDEBUG 10638ff24d25SRui Ueyama // Verify that the Aux symbol points to a valid entry in the symbol table. 10648ff24d25SRui Ueyama uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 106544f51e51SDavid Majnemer if (Offset < getPointerToSymbolTable() || 106644f51e51SDavid Majnemer Offset >= 106744f51e51SDavid Majnemer getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 106871757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 106971757ef3SMarshall Clow 107044f51e51SDavid Majnemer assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 107144f51e51SDavid Majnemer "Aux Symbol data did not point to the beginning of a symbol"); 107271757ef3SMarshall Clow #endif 1073bfb85e67SMarshall Clow } 107444f51e51SDavid Majnemer return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 107571757ef3SMarshall Clow } 107671757ef3SMarshall Clow 107774e7d260SMartin Storsjo uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { 107874e7d260SMartin Storsjo uintptr_t Offset = 107974e7d260SMartin Storsjo reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable(); 108074e7d260SMartin Storsjo assert(Offset % getSymbolTableEntrySize() == 0 && 108174e7d260SMartin Storsjo "Symbol did not point to the beginning of a symbol"); 108274e7d260SMartin Storsjo size_t Index = Offset / getSymbolTableEntrySize(); 108374e7d260SMartin Storsjo assert(Index < getNumberOfSymbols()); 108474e7d260SMartin Storsjo return Index; 108574e7d260SMartin Storsjo } 108674e7d260SMartin Storsjo 10878be28cdcSFangrui Song Expected<StringRef> 10888be28cdcSFangrui Song COFFObjectFile::getSectionName(const coff_section *Sec) const { 108953c2d547SMichael J. Spencer StringRef Name; 109044f51e51SDavid Majnemer if (Sec->Name[COFF::NameSize - 1] == 0) 109153c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 109253c2d547SMichael J. Spencer Name = Sec->Name; 109353c2d547SMichael J. Spencer else 109453c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 109544f51e51SDavid Majnemer Name = StringRef(Sec->Name, COFF::NameSize); 109653c2d547SMichael J. Spencer 109753c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 10982314b3deSDavid Majnemer if (Name.startswith("/")) { 109953c2d547SMichael J. Spencer uint32_t Offset; 11002314b3deSDavid Majnemer if (Name.startswith("//")) { 11019d2c15efSNico Rieck if (decodeBase64StringEntry(Name.substr(2), Offset)) 11028be28cdcSFangrui Song return createStringError(object_error::parse_failed, 1103400b6c08Sserge-sans-paille "invalid section name"); 11049d2c15efSNico Rieck } else { 110553c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 11068be28cdcSFangrui Song return createStringError(object_error::parse_failed, 11078be28cdcSFangrui Song "invalid section name"); 11089d2c15efSNico Rieck } 110977ecf90cSReid Kleckner return getString(Offset); 111053c2d547SMichael J. Spencer } 111153c2d547SMichael J. Spencer 11128be28cdcSFangrui Song return Name; 111353c2d547SMichael J. Spencer } 111453c2d547SMichael J. Spencer 1115a9ee5c06SDavid Majnemer uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 1116a9ee5c06SDavid Majnemer // SizeOfRawData and VirtualSize change what they represent depending on 1117a9ee5c06SDavid Majnemer // whether or not we have an executable image. 1118a9ee5c06SDavid Majnemer // 1119a9ee5c06SDavid Majnemer // For object files, SizeOfRawData contains the size of section's data; 1120d5297ee7SRui Ueyama // VirtualSize should be zero but isn't due to buggy COFF writers. 1121a9ee5c06SDavid Majnemer // 1122a9ee5c06SDavid Majnemer // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 1123a9ee5c06SDavid Majnemer // actual section size is in VirtualSize. It is possible for VirtualSize to 1124a9ee5c06SDavid Majnemer // be greater than SizeOfRawData; the contents past that point should be 1125a9ee5c06SDavid Majnemer // considered to be zero. 1126d5297ee7SRui Ueyama if (getDOSHeader()) 1127d5297ee7SRui Ueyama return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1128d5297ee7SRui Ueyama return Sec->SizeOfRawData; 1129a9ee5c06SDavid Majnemer } 1130a9ee5c06SDavid Majnemer 1131e1cb2c0fSFangrui Song Error COFFObjectFile::getSectionContents(const coff_section *Sec, 11329da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 1133e2129662SDavid Majnemer // In COFF, a virtual section won't have any in-file 1134e2129662SDavid Majnemer // content, so the file pointer to the content will be zero. 1135e2129662SDavid Majnemer if (Sec->PointerToRawData == 0) 1136e1cb2c0fSFangrui Song return Error::success(); 11379da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 11389da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 11399da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 114022cf54a7SArthur O'Dwyer uintptr_t ConStart = 114122cf54a7SArthur O'Dwyer reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData; 1142a9ee5c06SDavid Majnemer uint32_t SectionSize = getSectionSize(Sec); 1143e03a135bSReid Kleckner if (Error E = checkOffset(Data, ConStart, SectionSize)) 1144e03a135bSReid Kleckner return E; 1145a9ee5c06SDavid Majnemer Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 1146e1cb2c0fSFangrui Song return Error::success(); 11479da9e693SMichael J. Spencer } 11489da9e693SMichael J. Spencer 1149022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 1150e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 1151022ecdf2SBenjamin Kramer } 11528ff24d25SRui Ueyama 11535e812afaSRafael Espindola void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1154e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 1155e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 1156022ecdf2SBenjamin Kramer } 11578ff24d25SRui Ueyama 115896d071cdSRafael Espindola uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 115958323a97SDavid Majnemer const coff_relocation *R = toRel(Rel); 116096d071cdSRafael Espindola return R->VirtualAddress; 1161cbe72fc9SDanil Malyshev } 11628ff24d25SRui Ueyama 1163806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1164022ecdf2SBenjamin Kramer const coff_relocation *R = toRel(Rel); 11658ff24d25SRui Ueyama DataRefImpl Ref; 1166236b0ca7SDavid Majnemer if (R->SymbolTableIndex >= getNumberOfSymbols()) 1167236b0ca7SDavid Majnemer return symbol_end(); 116844f51e51SDavid Majnemer if (SymbolTable16) 116944f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 117044f51e51SDavid Majnemer else if (SymbolTable32) 117144f51e51SDavid Majnemer Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 117244f51e51SDavid Majnemer else 1173c7353b58SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 11748ff24d25SRui Ueyama return symbol_iterator(SymbolRef(Ref, this)); 1175022ecdf2SBenjamin Kramer } 11768ff24d25SRui Ueyama 117799c041b7SRafael Espindola uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 1178022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 117999c041b7SRafael Espindola return R->Type; 1180022ecdf2SBenjamin Kramer } 1181e5fd0047SMichael J. Spencer 118227dc8394SAlexey Samsonov const coff_section * 118327dc8394SAlexey Samsonov COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 118427dc8394SAlexey Samsonov return toSec(Section.getRawDataRefImpl()); 118571757ef3SMarshall Clow } 118671757ef3SMarshall Clow 118744f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 118844f51e51SDavid Majnemer if (SymbolTable16) 118944f51e51SDavid Majnemer return toSymb<coff_symbol16>(Ref); 119044f51e51SDavid Majnemer if (SymbolTable32) 119144f51e51SDavid Majnemer return toSymb<coff_symbol32>(Ref); 119244f51e51SDavid Majnemer llvm_unreachable("no symbol table pointer!"); 119344f51e51SDavid Majnemer } 119444f51e51SDavid Majnemer 119544f51e51SDavid Majnemer COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 119644f51e51SDavid Majnemer return getCOFFSymbol(Symbol.getRawDataRefImpl()); 119771757ef3SMarshall Clow } 119871757ef3SMarshall Clow 1199f12b8282SRafael Espindola const coff_relocation * 120027dc8394SAlexey Samsonov COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 120127dc8394SAlexey Samsonov return toRel(Reloc.getRawDataRefImpl()); 1202d3e2a76cSMarshall Clow } 1203d3e2a76cSMarshall Clow 12042f6d0061SPeter Collingbourne ArrayRef<coff_relocation> 12056a75acb1SRui Ueyama COFFObjectFile::getRelocations(const coff_section *Sec) const { 12062f6d0061SPeter Collingbourne return {getFirstReloc(Sec, Data, base()), 12072f6d0061SPeter Collingbourne getNumberOfRelocations(Sec, Data, base())}; 12086a75acb1SRui Ueyama } 12096a75acb1SRui Ueyama 121027dc8394SAlexey Samsonov #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 121127dc8394SAlexey Samsonov case COFF::reloc_type: \ 1212114ebf4aSMartin Storsjo return #reloc_type; 1213e5fd0047SMichael J. Spencer 1214114ebf4aSMartin Storsjo StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { 121544f51e51SDavid Majnemer switch (getMachine()) { 1216e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 1217114ebf4aSMartin Storsjo switch (Type) { 1218e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 1219e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 1220e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 1221e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 1222e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 1223e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 1224e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 1225e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 1226e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 1227e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 1228e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 1229e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 1230e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 1231e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 1232e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 1233e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 1234e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 1235e5fd0047SMichael J. Spencer default: 1236114ebf4aSMartin Storsjo return "Unknown"; 1237e5fd0047SMichael J. Spencer } 1238e5fd0047SMichael J. Spencer break; 12395c503bf4SSaleem Abdulrasool case COFF::IMAGE_FILE_MACHINE_ARMNT: 1240114ebf4aSMartin Storsjo switch (Type) { 12415c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 12425c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 12435c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 12445c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 12455c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 12465c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 12475c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 12485c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 1249e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32); 12505c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 12515c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 12525c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 12535c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 12545c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 12555c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 12565c503bf4SSaleem Abdulrasool LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 1257e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR); 12585c503bf4SSaleem Abdulrasool default: 1259114ebf4aSMartin Storsjo return "Unknown"; 12605c503bf4SSaleem Abdulrasool } 12615c503bf4SSaleem Abdulrasool break; 12620c72172eSMandeep Singh Grang case COFF::IMAGE_FILE_MACHINE_ARM64: 1263114ebf4aSMartin Storsjo switch (Type) { 12640c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 12650c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 12660c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 12670c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 12680c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 12690c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 12700c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 12710c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 12720c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 12730c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 12740c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 12750c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 12760c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 12770c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 12780c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 12790c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 12800c72172eSMandeep Singh Grang LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 1281e5eb6fb9SMartin Storsjo LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32); 12820c72172eSMandeep Singh Grang default: 1283114ebf4aSMartin Storsjo return "Unknown"; 12840c72172eSMandeep Singh Grang } 12850c72172eSMandeep Singh Grang break; 1286e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 1287114ebf4aSMartin Storsjo switch (Type) { 1288e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 1289e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 1290e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 1291e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 1292e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 1293e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 1294e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 1295e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 1296e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 1297e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 1298e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 1299e5fd0047SMichael J. Spencer default: 1300114ebf4aSMartin Storsjo return "Unknown"; 1301e5fd0047SMichael J. Spencer } 1302e5fd0047SMichael J. Spencer break; 1303e5fd0047SMichael J. Spencer default: 1304114ebf4aSMartin Storsjo return "Unknown"; 1305e5fd0047SMichael J. Spencer } 1306e5fd0047SMichael J. Spencer } 1307e5fd0047SMichael J. Spencer 1308e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 1309e5fd0047SMichael J. Spencer 1310114ebf4aSMartin Storsjo void COFFObjectFile::getRelocationTypeName( 1311114ebf4aSMartin Storsjo DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1312114ebf4aSMartin Storsjo const coff_relocation *Reloc = toRel(Rel); 1313114ebf4aSMartin Storsjo StringRef Res = getRelocationTypeName(Reloc->Type); 1314114ebf4aSMartin Storsjo Result.append(Res.begin(), Res.end()); 1315114ebf4aSMartin Storsjo } 1316114ebf4aSMartin Storsjo 1317c66d761bSRafael Espindola bool COFFObjectFile::isRelocatableObject() const { 1318c66d761bSRafael Espindola return !DataDirectory; 1319c66d761bSRafael Espindola } 1320c66d761bSRafael Espindola 1321e3093808SMartin Storsjo StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const { 1322e3093808SMartin Storsjo return StringSwitch<StringRef>(Name) 1323e3093808SMartin Storsjo .Case("eh_fram", "eh_frame") 1324e3093808SMartin Storsjo .Default(Name); 1325e3093808SMartin Storsjo } 1326e3093808SMartin Storsjo 1327c2bed429SRui Ueyama bool ImportDirectoryEntryRef:: 1328c2bed429SRui Ueyama operator==(const ImportDirectoryEntryRef &Other) const { 1329a045b73aSRui Ueyama return ImportTable == Other.ImportTable && Index == Other.Index; 1330c2bed429SRui Ueyama } 1331c2bed429SRui Ueyama 13325e812afaSRafael Espindola void ImportDirectoryEntryRef::moveNext() { 13335e812afaSRafael Espindola ++Index; 13341c0aa04eSDavid Majnemer if (ImportTable[Index].isNull()) { 1335ad7b7e73SDavid Majnemer Index = -1; 1336ad7b7e73SDavid Majnemer ImportTable = nullptr; 1337ad7b7e73SDavid Majnemer } 1338c2bed429SRui Ueyama } 1339c2bed429SRui Ueyama 13401c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportTableEntry( 13411c0aa04eSDavid Majnemer const coff_import_directory_table_entry *&Result) const { 1342ad7b7e73SDavid Majnemer return getObject(Result, OwningObject->Data, ImportTable + Index); 1343c2bed429SRui Ueyama } 1344c2bed429SRui Ueyama 1345861021f9SRui Ueyama static imported_symbol_iterator 134615d99359SRui Ueyama makeImportedSymbolIterator(const COFFObjectFile *Object, 1347861021f9SRui Ueyama uintptr_t Ptr, int Index) { 134815d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1349861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 135015d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1351861021f9SRui Ueyama } 1352861021f9SRui Ueyama auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 135315d99359SRui Ueyama return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 1354861021f9SRui Ueyama } 1355861021f9SRui Ueyama 135615d99359SRui Ueyama static imported_symbol_iterator 135715d99359SRui Ueyama importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 1358861021f9SRui Ueyama uintptr_t IntPtr = 0; 13591c03389cSReid Kleckner // FIXME: Handle errors. 13601c03389cSReid Kleckner cantFail(Object->getRvaPtr(RVA, IntPtr)); 136115d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, 0); 1362861021f9SRui Ueyama } 1363861021f9SRui Ueyama 136415d99359SRui Ueyama static imported_symbol_iterator 136515d99359SRui Ueyama importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 1366861021f9SRui Ueyama uintptr_t IntPtr = 0; 13671c03389cSReid Kleckner // FIXME: Handle errors. 13681c03389cSReid Kleckner cantFail(Object->getRvaPtr(RVA, IntPtr)); 1369861021f9SRui Ueyama // Forward the pointer to the last entry which is null. 1370861021f9SRui Ueyama int Index = 0; 137115d99359SRui Ueyama if (Object->getBytesInAddress() == 4) { 1372861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 1373861021f9SRui Ueyama while (*Entry++) 1374861021f9SRui Ueyama ++Index; 1375861021f9SRui Ueyama } else { 1376861021f9SRui Ueyama auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 1377861021f9SRui Ueyama while (*Entry++) 1378861021f9SRui Ueyama ++Index; 1379861021f9SRui Ueyama } 138015d99359SRui Ueyama return makeImportedSymbolIterator(Object, IntPtr, Index); 138115d99359SRui Ueyama } 138215d99359SRui Ueyama 138315d99359SRui Ueyama imported_symbol_iterator 138415d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_begin() const { 138560049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 138615d99359SRui Ueyama OwningObject); 138715d99359SRui Ueyama } 138815d99359SRui Ueyama 138915d99359SRui Ueyama imported_symbol_iterator 139015d99359SRui Ueyama ImportDirectoryEntryRef::imported_symbol_end() const { 139160049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 139215d99359SRui Ueyama OwningObject); 1393861021f9SRui Ueyama } 1394861021f9SRui Ueyama 1395979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1396979fb40bSRui Ueyama ImportDirectoryEntryRef::imported_symbols() const { 1397979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1398979fb40bSRui Ueyama } 1399979fb40bSRui Ueyama 140060049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 140160049526SDavid Majnemer return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 140260049526SDavid Majnemer OwningObject); 140360049526SDavid Majnemer } 140460049526SDavid Majnemer 140560049526SDavid Majnemer imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 140660049526SDavid Majnemer return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 140760049526SDavid Majnemer OwningObject); 140860049526SDavid Majnemer } 140960049526SDavid Majnemer 141060049526SDavid Majnemer iterator_range<imported_symbol_iterator> 141160049526SDavid Majnemer ImportDirectoryEntryRef::lookup_table_symbols() const { 141260049526SDavid Majnemer return make_range(lookup_table_begin(), lookup_table_end()); 141360049526SDavid Majnemer } 141460049526SDavid Majnemer 14151c03389cSReid Kleckner Error ImportDirectoryEntryRef::getName(StringRef &Result) const { 1416c2bed429SRui Ueyama uintptr_t IntPtr = 0; 14171c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 14181c03389cSReid Kleckner return E; 1419a045b73aSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14201c03389cSReid Kleckner return Error::success(); 1421c2bed429SRui Ueyama } 1422c2bed429SRui Ueyama 14231c03389cSReid Kleckner Error 14241e152d5eSRui Ueyama ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 14251e152d5eSRui Ueyama Result = ImportTable[Index].ImportLookupTableRVA; 14261c03389cSReid Kleckner return Error::success(); 14271e152d5eSRui Ueyama } 14281e152d5eSRui Ueyama 14291c03389cSReid Kleckner Error ImportDirectoryEntryRef::getImportAddressTableRVA( 14301c03389cSReid Kleckner uint32_t &Result) const { 14311e152d5eSRui Ueyama Result = ImportTable[Index].ImportAddressTableRVA; 14321c03389cSReid Kleckner return Error::success(); 14331e152d5eSRui Ueyama } 14341e152d5eSRui Ueyama 143515d99359SRui Ueyama bool DelayImportDirectoryEntryRef:: 143615d99359SRui Ueyama operator==(const DelayImportDirectoryEntryRef &Other) const { 143715d99359SRui Ueyama return Table == Other.Table && Index == Other.Index; 143815d99359SRui Ueyama } 143915d99359SRui Ueyama 144015d99359SRui Ueyama void DelayImportDirectoryEntryRef::moveNext() { 144115d99359SRui Ueyama ++Index; 144215d99359SRui Ueyama } 144315d99359SRui Ueyama 144415d99359SRui Ueyama imported_symbol_iterator 144515d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_begin() const { 144615d99359SRui Ueyama return importedSymbolBegin(Table[Index].DelayImportNameTable, 144715d99359SRui Ueyama OwningObject); 144815d99359SRui Ueyama } 144915d99359SRui Ueyama 145015d99359SRui Ueyama imported_symbol_iterator 145115d99359SRui Ueyama DelayImportDirectoryEntryRef::imported_symbol_end() const { 145215d99359SRui Ueyama return importedSymbolEnd(Table[Index].DelayImportNameTable, 145315d99359SRui Ueyama OwningObject); 145415d99359SRui Ueyama } 145515d99359SRui Ueyama 1456979fb40bSRui Ueyama iterator_range<imported_symbol_iterator> 1457979fb40bSRui Ueyama DelayImportDirectoryEntryRef::imported_symbols() const { 1458979fb40bSRui Ueyama return make_range(imported_symbol_begin(), imported_symbol_end()); 1459979fb40bSRui Ueyama } 1460979fb40bSRui Ueyama 14611c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 146215d99359SRui Ueyama uintptr_t IntPtr = 0; 14631c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 14641c03389cSReid Kleckner return E; 146515d99359SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14661c03389cSReid Kleckner return Error::success(); 146715d99359SRui Ueyama } 146815d99359SRui Ueyama 14691c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getDelayImportTable( 14701c03389cSReid Kleckner const delay_import_directory_table_entry *&Result) const { 14719f598ac7SJoseph Tremoulet Result = &Table[Index]; 14721c03389cSReid Kleckner return Error::success(); 14731af08658SRui Ueyama } 14741af08658SRui Ueyama 14751c03389cSReid Kleckner Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex, 14761c03389cSReid Kleckner uint64_t &Result) const { 1477ffa4cebeSRui Ueyama uint32_t RVA = Table[Index].DelayImportAddressTable + 1478ffa4cebeSRui Ueyama AddrIndex * (OwningObject->is64() ? 8 : 4); 1479ffa4cebeSRui Ueyama uintptr_t IntPtr = 0; 14801c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(RVA, IntPtr)) 14811c03389cSReid Kleckner return E; 1482ffa4cebeSRui Ueyama if (OwningObject->is64()) 14835dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 1484ffa4cebeSRui Ueyama else 14855dcf11d1SRui Ueyama Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 14861c03389cSReid Kleckner return Error::success(); 1487ffa4cebeSRui Ueyama } 1488ffa4cebeSRui Ueyama 1489ad882ba8SRui Ueyama bool ExportDirectoryEntryRef:: 1490ad882ba8SRui Ueyama operator==(const ExportDirectoryEntryRef &Other) const { 1491ad882ba8SRui Ueyama return ExportTable == Other.ExportTable && Index == Other.Index; 1492ad882ba8SRui Ueyama } 1493ad882ba8SRui Ueyama 14945e812afaSRafael Espindola void ExportDirectoryEntryRef::moveNext() { 14955e812afaSRafael Espindola ++Index; 1496ad882ba8SRui Ueyama } 1497ad882ba8SRui Ueyama 1498da49d0d4SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1499da49d0d4SRui Ueyama // by ordinal, the empty string is set as a result. 15001c03389cSReid Kleckner Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 1501da49d0d4SRui Ueyama uintptr_t IntPtr = 0; 15021c03389cSReid Kleckner if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 15031c03389cSReid Kleckner return E; 1504da49d0d4SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15051c03389cSReid Kleckner return Error::success(); 1506da49d0d4SRui Ueyama } 1507da49d0d4SRui Ueyama 1508e5df6095SRui Ueyama // Returns the starting ordinal number. 15091c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 1510e5df6095SRui Ueyama Result = ExportTable->OrdinalBase; 15111c03389cSReid Kleckner return Error::success(); 1512e5df6095SRui Ueyama } 1513e5df6095SRui Ueyama 1514ad882ba8SRui Ueyama // Returns the export ordinal of the current export symbol. 15151c03389cSReid Kleckner Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 1516ad882ba8SRui Ueyama Result = ExportTable->OrdinalBase + Index; 15171c03389cSReid Kleckner return Error::success(); 1518ad882ba8SRui Ueyama } 1519ad882ba8SRui Ueyama 1520ad882ba8SRui Ueyama // Returns the address of the current export symbol. 15211c03389cSReid Kleckner Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 1522ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 15231c03389cSReid Kleckner if (Error EC = 1524db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 1525ad882ba8SRui Ueyama return EC; 152624fc2d64SRui Ueyama const export_address_table_entry *entry = 152724fc2d64SRui Ueyama reinterpret_cast<const export_address_table_entry *>(IntPtr); 1528ad882ba8SRui Ueyama Result = entry[Index].ExportRVA; 15291c03389cSReid Kleckner return Error::success(); 1530ad882ba8SRui Ueyama } 1531ad882ba8SRui Ueyama 1532ad882ba8SRui Ueyama // Returns the name of the current export symbol. If the symbol is exported only 1533ad882ba8SRui Ueyama // by ordinal, the empty string is set as a result. 15341c03389cSReid Kleckner Error 1535db4ed0bdSRafael Espindola ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 1536ad882ba8SRui Ueyama uintptr_t IntPtr = 0; 15371c03389cSReid Kleckner if (Error EC = 1538db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 1539ad882ba8SRui Ueyama return EC; 1540ad882ba8SRui Ueyama const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 1541ad882ba8SRui Ueyama 1542ad882ba8SRui Ueyama uint32_t NumEntries = ExportTable->NumberOfNamePointers; 1543ad882ba8SRui Ueyama int Offset = 0; 1544ad882ba8SRui Ueyama for (const ulittle16_t *I = Start, *E = Start + NumEntries; 1545ad882ba8SRui Ueyama I < E; ++I, ++Offset) { 1546ad882ba8SRui Ueyama if (*I != Index) 1547ad882ba8SRui Ueyama continue; 15481c03389cSReid Kleckner if (Error EC = 1549db4ed0bdSRafael Espindola OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 1550ad882ba8SRui Ueyama return EC; 1551ad882ba8SRui Ueyama const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 15521c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 1553ad882ba8SRui Ueyama return EC; 1554ad882ba8SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15551c03389cSReid Kleckner return Error::success(); 1556ad882ba8SRui Ueyama } 1557ad882ba8SRui Ueyama Result = ""; 15581c03389cSReid Kleckner return Error::success(); 1559ad882ba8SRui Ueyama } 1560ad882ba8SRui Ueyama 15611c03389cSReid Kleckner Error ExportDirectoryEntryRef::isForwarder(bool &Result) const { 15621c03389cSReid Kleckner const data_directory *DataEntry = 15631c03389cSReid Kleckner OwningObject->getDataDirectory(COFF::EXPORT_TABLE); 15641c03389cSReid Kleckner if (!DataEntry) 15651c03389cSReid Kleckner return errorCodeToError(object_error::parse_failed); 15666161b38dSRui Ueyama uint32_t RVA; 15676161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15686161b38dSRui Ueyama return EC; 15696161b38dSRui Ueyama uint32_t Begin = DataEntry->RelativeVirtualAddress; 15706161b38dSRui Ueyama uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 15716161b38dSRui Ueyama Result = (Begin <= RVA && RVA < End); 15721c03389cSReid Kleckner return Error::success(); 15736161b38dSRui Ueyama } 15746161b38dSRui Ueyama 15751c03389cSReid Kleckner Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 15766161b38dSRui Ueyama uint32_t RVA; 15776161b38dSRui Ueyama if (auto EC = getExportRVA(RVA)) 15786161b38dSRui Ueyama return EC; 15796161b38dSRui Ueyama uintptr_t IntPtr = 0; 15806161b38dSRui Ueyama if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 15816161b38dSRui Ueyama return EC; 15826161b38dSRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15831c03389cSReid Kleckner return Error::success(); 15846161b38dSRui Ueyama } 15856161b38dSRui Ueyama 1586861021f9SRui Ueyama bool ImportedSymbolRef:: 1587861021f9SRui Ueyama operator==(const ImportedSymbolRef &Other) const { 1588861021f9SRui Ueyama return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 1589861021f9SRui Ueyama && Index == Other.Index; 1590861021f9SRui Ueyama } 1591861021f9SRui Ueyama 1592861021f9SRui Ueyama void ImportedSymbolRef::moveNext() { 1593861021f9SRui Ueyama ++Index; 1594861021f9SRui Ueyama } 1595861021f9SRui Ueyama 15961c03389cSReid Kleckner Error ImportedSymbolRef::getSymbolName(StringRef &Result) const { 1597861021f9SRui Ueyama uint32_t RVA; 1598861021f9SRui Ueyama if (Entry32) { 1599861021f9SRui Ueyama // If a symbol is imported only by ordinal, it has no name. 1600861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) 16011c03389cSReid Kleckner return Error::success(); 1602861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1603861021f9SRui Ueyama } else { 1604861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) 16051c03389cSReid Kleckner return Error::success(); 1606861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1607861021f9SRui Ueyama } 1608861021f9SRui Ueyama uintptr_t IntPtr = 0; 16091c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1610861021f9SRui Ueyama return EC; 1611861021f9SRui Ueyama // +2 because the first two bytes is hint. 1612861021f9SRui Ueyama Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 16131c03389cSReid Kleckner return Error::success(); 1614861021f9SRui Ueyama } 1615861021f9SRui Ueyama 16161c03389cSReid Kleckner Error ImportedSymbolRef::isOrdinal(bool &Result) const { 1617ad7b7e73SDavid Majnemer if (Entry32) 1618ad7b7e73SDavid Majnemer Result = Entry32[Index].isOrdinal(); 1619ad7b7e73SDavid Majnemer else 1620ad7b7e73SDavid Majnemer Result = Entry64[Index].isOrdinal(); 16211c03389cSReid Kleckner return Error::success(); 1622ad7b7e73SDavid Majnemer } 1623ad7b7e73SDavid Majnemer 16241c03389cSReid Kleckner Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1625ad7b7e73SDavid Majnemer if (Entry32) 1626ad7b7e73SDavid Majnemer Result = Entry32[Index].getHintNameRVA(); 1627ad7b7e73SDavid Majnemer else 1628ad7b7e73SDavid Majnemer Result = Entry64[Index].getHintNameRVA(); 16291c03389cSReid Kleckner return Error::success(); 1630ad7b7e73SDavid Majnemer } 1631ad7b7e73SDavid Majnemer 16321c03389cSReid Kleckner Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 1633861021f9SRui Ueyama uint32_t RVA; 1634861021f9SRui Ueyama if (Entry32) { 1635861021f9SRui Ueyama if (Entry32[Index].isOrdinal()) { 1636861021f9SRui Ueyama Result = Entry32[Index].getOrdinal(); 16371c03389cSReid Kleckner return Error::success(); 1638861021f9SRui Ueyama } 1639861021f9SRui Ueyama RVA = Entry32[Index].getHintNameRVA(); 1640861021f9SRui Ueyama } else { 1641861021f9SRui Ueyama if (Entry64[Index].isOrdinal()) { 1642861021f9SRui Ueyama Result = Entry64[Index].getOrdinal(); 16431c03389cSReid Kleckner return Error::success(); 1644861021f9SRui Ueyama } 1645861021f9SRui Ueyama RVA = Entry64[Index].getHintNameRVA(); 1646861021f9SRui Ueyama } 1647861021f9SRui Ueyama uintptr_t IntPtr = 0; 16481c03389cSReid Kleckner if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1649861021f9SRui Ueyama return EC; 1650861021f9SRui Ueyama Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 16511c03389cSReid Kleckner return Error::success(); 1652861021f9SRui Ueyama } 1653861021f9SRui Ueyama 165412db383eSRafael Espindola Expected<std::unique_ptr<COFFObjectFile>> 165548af1c2aSRafael Espindola ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 165639772063SReid Kleckner return COFFObjectFile::create(Object); 1657686738e2SRui Ueyama } 165874e85130SRui Ueyama 165974e85130SRui Ueyama bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 166074e85130SRui Ueyama return Header == Other.Header && Index == Other.Index; 166174e85130SRui Ueyama } 166274e85130SRui Ueyama 166374e85130SRui Ueyama void BaseRelocRef::moveNext() { 166474e85130SRui Ueyama // Header->BlockSize is the size of the current block, including the 166574e85130SRui Ueyama // size of the header itself. 166674e85130SRui Ueyama uint32_t Size = sizeof(*Header) + 1667970dda29SRui Ueyama sizeof(coff_base_reloc_block_entry) * (Index + 1); 166874e85130SRui Ueyama if (Size == Header->BlockSize) { 166974e85130SRui Ueyama // .reloc contains a list of base relocation blocks. Each block 167074e85130SRui Ueyama // consists of the header followed by entries. The header contains 167174e85130SRui Ueyama // how many entories will follow. When we reach the end of the 167274e85130SRui Ueyama // current block, proceed to the next block. 167374e85130SRui Ueyama Header = reinterpret_cast<const coff_base_reloc_block_header *>( 167474e85130SRui Ueyama reinterpret_cast<const uint8_t *>(Header) + Size); 167574e85130SRui Ueyama Index = 0; 167674e85130SRui Ueyama } else { 167774e85130SRui Ueyama ++Index; 167874e85130SRui Ueyama } 167974e85130SRui Ueyama } 168074e85130SRui Ueyama 16811c03389cSReid Kleckner Error BaseRelocRef::getType(uint8_t &Type) const { 168274e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 168374e85130SRui Ueyama Type = Entry[Index].getType(); 16841c03389cSReid Kleckner return Error::success(); 168574e85130SRui Ueyama } 168674e85130SRui Ueyama 16871c03389cSReid Kleckner Error BaseRelocRef::getRVA(uint32_t &Result) const { 168874e85130SRui Ueyama auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 168974e85130SRui Ueyama Result = Header->PageRVA + Entry[Index].getOffset(); 16901c03389cSReid Kleckner return Error::success(); 169174e85130SRui Ueyama } 1692efef15a0SEric Beckmann 1693357a40ecSMartin Storsjo #define RETURN_IF_ERROR(Expr) \ 1694357a40ecSMartin Storsjo do { \ 1695357a40ecSMartin Storsjo Error E = (Expr); \ 169687867988SRafael Espindola if (E) \ 1697c55cf4afSBill Wendling return std::move(E); \ 1698357a40ecSMartin Storsjo } while (0) 1699efef15a0SEric Beckmann 170087867988SRafael Espindola Expected<ArrayRef<UTF16>> 170187867988SRafael Espindola ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 1702efef15a0SEric Beckmann BinaryStreamReader Reader = BinaryStreamReader(BBS); 1703efef15a0SEric Beckmann Reader.setOffset(Offset); 1704efef15a0SEric Beckmann uint16_t Length; 1705efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readInteger(Length)); 1706efef15a0SEric Beckmann ArrayRef<UTF16> RawDirString; 1707efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 1708cd704cb6SEric Beckmann return RawDirString; 1709efef15a0SEric Beckmann } 1710efef15a0SEric Beckmann 1711f3404674SRafael Espindola Expected<ArrayRef<UTF16>> 1712efef15a0SEric Beckmann ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 1713f3404674SRafael Espindola return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 1714efef15a0SEric Beckmann } 1715efef15a0SEric Beckmann 171687867988SRafael Espindola Expected<const coff_resource_dir_table &> 1717efef15a0SEric Beckmann ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 1718efef15a0SEric Beckmann const coff_resource_dir_table *Table = nullptr; 1719efef15a0SEric Beckmann 1720efef15a0SEric Beckmann BinaryStreamReader Reader(BBS); 1721efef15a0SEric Beckmann Reader.setOffset(Offset); 1722efef15a0SEric Beckmann RETURN_IF_ERROR(Reader.readObject(Table)); 1723efef15a0SEric Beckmann assert(Table != nullptr); 1724efef15a0SEric Beckmann return *Table; 1725efef15a0SEric Beckmann } 1726efef15a0SEric Beckmann 1727edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &> 1728edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) { 1729edb6ab9bSMartin Storsjo const coff_resource_dir_entry *Entry = nullptr; 1730edb6ab9bSMartin Storsjo 1731edb6ab9bSMartin Storsjo BinaryStreamReader Reader(BBS); 1732edb6ab9bSMartin Storsjo Reader.setOffset(Offset); 1733edb6ab9bSMartin Storsjo RETURN_IF_ERROR(Reader.readObject(Entry)); 1734edb6ab9bSMartin Storsjo assert(Entry != nullptr); 1735edb6ab9bSMartin Storsjo return *Entry; 1736edb6ab9bSMartin Storsjo } 1737edb6ab9bSMartin Storsjo 17387ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &> 17397ba81d95SMartin Storsjo ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) { 17407ba81d95SMartin Storsjo const coff_resource_data_entry *Entry = nullptr; 17417ba81d95SMartin Storsjo 17427ba81d95SMartin Storsjo BinaryStreamReader Reader(BBS); 17437ba81d95SMartin Storsjo Reader.setOffset(Offset); 17447ba81d95SMartin Storsjo RETURN_IF_ERROR(Reader.readObject(Entry)); 17457ba81d95SMartin Storsjo assert(Entry != nullptr); 17467ba81d95SMartin Storsjo return *Entry; 17477ba81d95SMartin Storsjo } 17487ba81d95SMartin Storsjo 1749f3404674SRafael Espindola Expected<const coff_resource_dir_table &> 1750efef15a0SEric Beckmann ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 17517ba81d95SMartin Storsjo assert(Entry.Offset.isSubDir()); 1752f3404674SRafael Espindola return getTableAtOffset(Entry.Offset.value()); 1753efef15a0SEric Beckmann } 1754efef15a0SEric Beckmann 17557ba81d95SMartin Storsjo Expected<const coff_resource_data_entry &> 17567ba81d95SMartin Storsjo ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) { 17577ba81d95SMartin Storsjo assert(!Entry.Offset.isSubDir()); 17587ba81d95SMartin Storsjo return getDataEntryAtOffset(Entry.Offset.value()); 17597ba81d95SMartin Storsjo } 17607ba81d95SMartin Storsjo 1761f3404674SRafael Espindola Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 1762f3404674SRafael Espindola return getTableAtOffset(0); 1763efef15a0SEric Beckmann } 1764edb6ab9bSMartin Storsjo 1765edb6ab9bSMartin Storsjo Expected<const coff_resource_dir_entry &> 1766edb6ab9bSMartin Storsjo ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table, 1767edb6ab9bSMartin Storsjo uint32_t Index) { 1768edb6ab9bSMartin Storsjo if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) 1769edb6ab9bSMartin Storsjo return createStringError(object_error::parse_failed, "index out of range"); 1770edb6ab9bSMartin Storsjo const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table); 1771edb6ab9bSMartin Storsjo ptrdiff_t TableOffset = TablePtr - BBS.data().data(); 1772edb6ab9bSMartin Storsjo return getTableEntryAtOffset(TableOffset + sizeof(Table) + 1773edb6ab9bSMartin Storsjo Index * sizeof(coff_resource_dir_entry)); 1774edb6ab9bSMartin Storsjo } 177594382217SMartin Storsjo 177694382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O) { 177794382217SMartin Storsjo for (const SectionRef &S : O->sections()) { 177894382217SMartin Storsjo Expected<StringRef> Name = S.getName(); 177994382217SMartin Storsjo if (!Name) 178094382217SMartin Storsjo return Name.takeError(); 178194382217SMartin Storsjo 178294382217SMartin Storsjo if (*Name == ".rsrc" || *Name == ".rsrc$01") 178394382217SMartin Storsjo return load(O, S); 178494382217SMartin Storsjo } 178594382217SMartin Storsjo return createStringError(object_error::parse_failed, 178694382217SMartin Storsjo "no resource section found"); 178794382217SMartin Storsjo } 178894382217SMartin Storsjo 178994382217SMartin Storsjo Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) { 179094382217SMartin Storsjo Obj = O; 179194382217SMartin Storsjo Section = S; 179294382217SMartin Storsjo Expected<StringRef> Contents = Section.getContents(); 179394382217SMartin Storsjo if (!Contents) 179494382217SMartin Storsjo return Contents.takeError(); 179594382217SMartin Storsjo BBS = BinaryByteStream(*Contents, support::little); 179694382217SMartin Storsjo const coff_section *COFFSect = Obj->getCOFFSection(Section); 179794382217SMartin Storsjo ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect); 179894382217SMartin Storsjo Relocs.reserve(OrigRelocs.size()); 179994382217SMartin Storsjo for (const coff_relocation &R : OrigRelocs) 180094382217SMartin Storsjo Relocs.push_back(&R); 1801352fcfc6SKazu Hirata llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) { 180294382217SMartin Storsjo return A->VirtualAddress < B->VirtualAddress; 180394382217SMartin Storsjo }); 180494382217SMartin Storsjo return Error::success(); 180594382217SMartin Storsjo } 180694382217SMartin Storsjo 180794382217SMartin Storsjo Expected<StringRef> 180894382217SMartin Storsjo ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { 180994382217SMartin Storsjo if (!Obj) 181094382217SMartin Storsjo return createStringError(object_error::parse_failed, "no object provided"); 181194382217SMartin Storsjo 181294382217SMartin Storsjo // Find a potential relocation at the DataRVA field (first member of 181394382217SMartin Storsjo // the coff_resource_data_entry struct). 181494382217SMartin Storsjo const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry); 181594382217SMartin Storsjo ptrdiff_t EntryOffset = EntryPtr - BBS.data().data(); 181694382217SMartin Storsjo coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0), 181794382217SMartin Storsjo ulittle16_t(0)}; 181894382217SMartin Storsjo auto RelocsForOffset = 181994382217SMartin Storsjo std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget, 182094382217SMartin Storsjo [](const coff_relocation *A, const coff_relocation *B) { 182194382217SMartin Storsjo return A->VirtualAddress < B->VirtualAddress; 182294382217SMartin Storsjo }); 182394382217SMartin Storsjo 182494382217SMartin Storsjo if (RelocsForOffset.first != RelocsForOffset.second) { 182594382217SMartin Storsjo // We found a relocation with the right offset. Check that it does have 182694382217SMartin Storsjo // the expected type. 182794382217SMartin Storsjo const coff_relocation &R = **RelocsForOffset.first; 182894382217SMartin Storsjo uint16_t RVAReloc; 182994382217SMartin Storsjo switch (Obj->getMachine()) { 183094382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_I386: 183194382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_I386_DIR32NB; 183294382217SMartin Storsjo break; 183394382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_AMD64: 183494382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB; 183594382217SMartin Storsjo break; 183694382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_ARMNT: 183794382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB; 183894382217SMartin Storsjo break; 183994382217SMartin Storsjo case COFF::IMAGE_FILE_MACHINE_ARM64: 184094382217SMartin Storsjo RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB; 184194382217SMartin Storsjo break; 184294382217SMartin Storsjo default: 184394382217SMartin Storsjo return createStringError(object_error::parse_failed, 184494382217SMartin Storsjo "unsupported architecture"); 184594382217SMartin Storsjo } 184694382217SMartin Storsjo if (R.Type != RVAReloc) 184794382217SMartin Storsjo return createStringError(object_error::parse_failed, 184894382217SMartin Storsjo "unexpected relocation type"); 184994382217SMartin Storsjo // Get the relocation's symbol 185094382217SMartin Storsjo Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex); 185194382217SMartin Storsjo if (!Sym) 185294382217SMartin Storsjo return Sym.takeError(); 185394382217SMartin Storsjo // And the symbol's section 185477ecf90cSReid Kleckner Expected<const coff_section *> Section = 185577ecf90cSReid Kleckner Obj->getSection(Sym->getSectionNumber()); 185677ecf90cSReid Kleckner if (!Section) 185777ecf90cSReid Kleckner return Section.takeError(); 185894382217SMartin Storsjo // Add the initial value of DataRVA to the symbol's offset to find the 185994382217SMartin Storsjo // data it points at. 186094382217SMartin Storsjo uint64_t Offset = Entry.DataRVA + Sym->getValue(); 186194382217SMartin Storsjo ArrayRef<uint8_t> Contents; 186277ecf90cSReid Kleckner if (Error E = Obj->getSectionContents(*Section, Contents)) 1863c55cf4afSBill Wendling return std::move(E); 186494382217SMartin Storsjo if (Offset + Entry.DataSize > Contents.size()) 186594382217SMartin Storsjo return createStringError(object_error::parse_failed, 186694382217SMartin Storsjo "data outside of section"); 186794382217SMartin Storsjo // Return a reference to the data inside the section. 186894382217SMartin Storsjo return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset, 186994382217SMartin Storsjo Entry.DataSize); 187094382217SMartin Storsjo } else { 187194382217SMartin Storsjo // Relocatable objects need a relocation for the DataRVA field. 187294382217SMartin Storsjo if (Obj->isRelocatableObject()) 187394382217SMartin Storsjo return createStringError(object_error::parse_failed, 187494382217SMartin Storsjo "no relocation found for DataRVA"); 187594382217SMartin Storsjo 187694382217SMartin Storsjo // Locate the section that contains the address that DataRVA points at. 187794382217SMartin Storsjo uint64_t VA = Entry.DataRVA + Obj->getImageBase(); 187894382217SMartin Storsjo for (const SectionRef &S : Obj->sections()) { 187994382217SMartin Storsjo if (VA >= S.getAddress() && 188094382217SMartin Storsjo VA + Entry.DataSize <= S.getAddress() + S.getSize()) { 188194382217SMartin Storsjo uint64_t Offset = VA - S.getAddress(); 188294382217SMartin Storsjo Expected<StringRef> Contents = S.getContents(); 188394382217SMartin Storsjo if (!Contents) 188494382217SMartin Storsjo return Contents.takeError(); 188594382217SMartin Storsjo return Contents->slice(Offset, Offset + Entry.DataSize); 188694382217SMartin Storsjo } 188794382217SMartin Storsjo } 188894382217SMartin Storsjo return createStringError(object_error::parse_failed, 188994382217SMartin Storsjo "address not found in image"); 189094382217SMartin Storsjo } 189194382217SMartin Storsjo } 1892