10b57cec5SDimitry Andric //===- COFFObjectFile.cpp - COFF object file implementation ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares the COFFObjectFile class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 155ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 160b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 170b57cec5SDimitry Andric #include "llvm/Object/Binary.h" 180b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 190b57cec5SDimitry Andric #include "llvm/Object/Error.h" 200b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 21*0fca6ea1SDimitry Andric #include "llvm/Object/WindowsMachineFlag.h" 220b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 230b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 240b57cec5SDimitry Andric #include "llvm/Support/Error.h" 250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 260b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 2781ad6265SDimitry Andric #include "llvm/Support/MemoryBufferRef.h" 280b57cec5SDimitry Andric #include <algorithm> 290b57cec5SDimitry Andric #include <cassert> 30e8d8bef9SDimitry Andric #include <cinttypes> 310b57cec5SDimitry Andric #include <cstddef> 320b57cec5SDimitry Andric #include <cstring> 330b57cec5SDimitry Andric #include <limits> 340b57cec5SDimitry Andric #include <memory> 350b57cec5SDimitry Andric #include <system_error> 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace llvm; 380b57cec5SDimitry Andric using namespace object; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric using support::ulittle16_t; 410b57cec5SDimitry Andric using support::ulittle32_t; 420b57cec5SDimitry Andric using support::ulittle64_t; 430b57cec5SDimitry Andric using support::little16_t; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // Returns false if size is greater than the buffer size. And sets ec. 460b57cec5SDimitry Andric static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 470b57cec5SDimitry Andric if (M.getBufferSize() < Size) { 480b57cec5SDimitry Andric EC = object_error::unexpected_eof; 490b57cec5SDimitry Andric return false; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric return true; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 550b57cec5SDimitry Andric // Returns unexpected_eof if error. 560b57cec5SDimitry Andric template <typename T> 575ffd83dbSDimitry Andric static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, 580b57cec5SDimitry Andric const uint64_t Size = sizeof(T)) { 59e8d8bef9SDimitry Andric uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr); 605ffd83dbSDimitry Andric if (Error E = Binary::checkOffset(M, Addr, Size)) 615ffd83dbSDimitry Andric return E; 620b57cec5SDimitry Andric Obj = reinterpret_cast<const T *>(Addr); 635ffd83dbSDimitry Andric return Error::success(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 670b57cec5SDimitry Andric // prefixed slashes. 680b57cec5SDimitry Andric static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 690b57cec5SDimitry Andric assert(Str.size() <= 6 && "String too long, possible overflow."); 700b57cec5SDimitry Andric if (Str.size() > 6) 710b57cec5SDimitry Andric return true; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric uint64_t Value = 0; 740b57cec5SDimitry Andric while (!Str.empty()) { 750b57cec5SDimitry Andric unsigned CharVal; 760b57cec5SDimitry Andric if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 770b57cec5SDimitry Andric CharVal = Str[0] - 'A'; 780b57cec5SDimitry Andric else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 790b57cec5SDimitry Andric CharVal = Str[0] - 'a' + 26; 800b57cec5SDimitry Andric else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 810b57cec5SDimitry Andric CharVal = Str[0] - '0' + 52; 820b57cec5SDimitry Andric else if (Str[0] == '+') // 62 830b57cec5SDimitry Andric CharVal = 62; 840b57cec5SDimitry Andric else if (Str[0] == '/') // 63 850b57cec5SDimitry Andric CharVal = 63; 860b57cec5SDimitry Andric else 870b57cec5SDimitry Andric return true; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric Value = (Value * 64) + CharVal; 900b57cec5SDimitry Andric Str = Str.substr(1); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric if (Value > std::numeric_limits<uint32_t>::max()) 940b57cec5SDimitry Andric return true; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric Result = static_cast<uint32_t>(Value); 970b57cec5SDimitry Andric return false; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric template <typename coff_symbol_type> 1010b57cec5SDimitry Andric const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 1020b57cec5SDimitry Andric const coff_symbol_type *Addr = 1030b57cec5SDimitry Andric reinterpret_cast<const coff_symbol_type *>(Ref.p); 1040b57cec5SDimitry Andric 105e8d8bef9SDimitry Andric assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr))); 1060b57cec5SDimitry Andric #ifndef NDEBUG 1070b57cec5SDimitry Andric // Verify that the symbol points to a valid entry in the symbol table. 108e8d8bef9SDimitry Andric uintptr_t Offset = 109e8d8bef9SDimitry Andric reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base()); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 1120b57cec5SDimitry Andric "Symbol did not point to the beginning of a symbol"); 1130b57cec5SDimitry Andric #endif 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric return Addr; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 1190b57cec5SDimitry Andric const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric #ifndef NDEBUG 1220b57cec5SDimitry Andric // Verify that the section points to a valid entry in the section table. 1230b57cec5SDimitry Andric if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 1240b57cec5SDimitry Andric report_fatal_error("Section was outside of section table."); 1250b57cec5SDimitry Andric 126e8d8bef9SDimitry Andric uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) - 127e8d8bef9SDimitry Andric reinterpret_cast<uintptr_t>(SectionTable); 1280b57cec5SDimitry Andric assert(Offset % sizeof(coff_section) == 0 && 1290b57cec5SDimitry Andric "Section did not point to the beginning of a section"); 1300b57cec5SDimitry Andric #endif 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric return Addr; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 1360b57cec5SDimitry Andric auto End = reinterpret_cast<uintptr_t>(StringTable); 1370b57cec5SDimitry Andric if (SymbolTable16) { 1380b57cec5SDimitry Andric const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 1390b57cec5SDimitry Andric Symb += 1 + Symb->NumberOfAuxSymbols; 1400b57cec5SDimitry Andric Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 1410b57cec5SDimitry Andric } else if (SymbolTable32) { 1420b57cec5SDimitry Andric const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 1430b57cec5SDimitry Andric Symb += 1 + Symb->NumberOfAuxSymbols; 1440b57cec5SDimitry Andric Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 1450b57cec5SDimitry Andric } else { 1460b57cec5SDimitry Andric llvm_unreachable("no symbol table pointer!"); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 1515ffd83dbSDimitry Andric return getSymbolName(getCOFFSymbol(Ref)); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 1550b57cec5SDimitry Andric return getCOFFSymbol(Ref).getValue(); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const { 1590b57cec5SDimitry Andric // MSVC/link.exe seems to align symbols to the next-power-of-2 1600b57cec5SDimitry Andric // up to 32 bytes. 1610b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref); 1620b57cec5SDimitry Andric return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue())); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 1665ffd83dbSDimitry Andric uint64_t Result = cantFail(getSymbolValue(Ref)); 1670b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref); 1680b57cec5SDimitry Andric int32_t SectionNumber = Symb.getSectionNumber(); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric if (Symb.isAnyUndefined() || Symb.isCommon() || 1710b57cec5SDimitry Andric COFF::isReservedSectionNumber(SectionNumber)) 1720b57cec5SDimitry Andric return Result; 1730b57cec5SDimitry Andric 1745ffd83dbSDimitry Andric Expected<const coff_section *> Section = getSection(SectionNumber); 1755ffd83dbSDimitry Andric if (!Section) 1765ffd83dbSDimitry Andric return Section.takeError(); 1775ffd83dbSDimitry Andric Result += (*Section)->VirtualAddress; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // The section VirtualAddress does not include ImageBase, and we want to 1800b57cec5SDimitry Andric // return virtual addresses. 1810b57cec5SDimitry Andric Result += getImageBase(); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric return Result; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 1870b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref); 1880b57cec5SDimitry Andric int32_t SectionNumber = Symb.getSectionNumber(); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 1910b57cec5SDimitry Andric return SymbolRef::ST_Function; 1920b57cec5SDimitry Andric if (Symb.isAnyUndefined()) 1930b57cec5SDimitry Andric return SymbolRef::ST_Unknown; 1940b57cec5SDimitry Andric if (Symb.isCommon()) 1950b57cec5SDimitry Andric return SymbolRef::ST_Data; 1960b57cec5SDimitry Andric if (Symb.isFileRecord()) 1970b57cec5SDimitry Andric return SymbolRef::ST_File; 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // TODO: perhaps we need a new symbol type ST_Section. 2000b57cec5SDimitry Andric if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 2010b57cec5SDimitry Andric return SymbolRef::ST_Debug; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric if (!COFF::isReservedSectionNumber(SectionNumber)) 2040b57cec5SDimitry Andric return SymbolRef::ST_Data; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric return SymbolRef::ST_Other; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2095ffd83dbSDimitry Andric Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 2100b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref); 2110b57cec5SDimitry Andric uint32_t Result = SymbolRef::SF_None; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric if (Symb.isExternal() || Symb.isWeakExternal()) 2140b57cec5SDimitry Andric Result |= SymbolRef::SF_Global; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) { 2170b57cec5SDimitry Andric Result |= SymbolRef::SF_Weak; 2180b57cec5SDimitry Andric if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS) 2190b57cec5SDimitry Andric Result |= SymbolRef::SF_Undefined; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 2230b57cec5SDimitry Andric Result |= SymbolRef::SF_Absolute; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric if (Symb.isFileRecord()) 2260b57cec5SDimitry Andric Result |= SymbolRef::SF_FormatSpecific; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric if (Symb.isSectionDefinition()) 2290b57cec5SDimitry Andric Result |= SymbolRef::SF_FormatSpecific; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric if (Symb.isCommon()) 2320b57cec5SDimitry Andric Result |= SymbolRef::SF_Common; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric if (Symb.isUndefined()) 2350b57cec5SDimitry Andric Result |= SymbolRef::SF_Undefined; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric return Result; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 2410b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref); 2420b57cec5SDimitry Andric return Symb.getValue(); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric Expected<section_iterator> 2460b57cec5SDimitry Andric COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 2470b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref); 2480b57cec5SDimitry Andric if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 2490b57cec5SDimitry Andric return section_end(); 2505ffd83dbSDimitry Andric Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber()); 2515ffd83dbSDimitry Andric if (!Sec) 2525ffd83dbSDimitry Andric return Sec.takeError(); 2530b57cec5SDimitry Andric DataRefImpl Ret; 2545ffd83dbSDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(*Sec); 2550b57cec5SDimitry Andric return section_iterator(SectionRef(Ret, this)); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 2590b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 2600b57cec5SDimitry Andric return Symb.getSectionNumber(); 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 2640b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 2650b57cec5SDimitry Andric Sec += 1; 2660b57cec5SDimitry Andric Ref.p = reinterpret_cast<uintptr_t>(Sec); 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const { 2700b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 2710b57cec5SDimitry Andric return getSectionName(Sec); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 2750b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 2760b57cec5SDimitry Andric uint64_t Result = Sec->VirtualAddress; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric // The section VirtualAddress does not include ImageBase, and we want to 2790b57cec5SDimitry Andric // return virtual addresses. 2800b57cec5SDimitry Andric Result += getImageBase(); 2810b57cec5SDimitry Andric return Result; 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 2850b57cec5SDimitry Andric return toSec(Sec) - SectionTable; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 2890b57cec5SDimitry Andric return getSectionSize(toSec(Ref)); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>> 2930b57cec5SDimitry Andric COFFObjectFile::getSectionContents(DataRefImpl Ref) const { 2940b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 2950b57cec5SDimitry Andric ArrayRef<uint8_t> Res; 2960b57cec5SDimitry Andric if (Error E = getSectionContents(Sec, Res)) 297*0fca6ea1SDimitry Andric return E; 2980b57cec5SDimitry Andric return Res; 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 3020b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 3030b57cec5SDimitry Andric return Sec->getAlignment(); 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 3070b57cec5SDimitry Andric return false; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 3110b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 3120b57cec5SDimitry Andric return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 3160b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 3170b57cec5SDimitry Andric return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 3210b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 3220b57cec5SDimitry Andric const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3230b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_READ | 3240b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_WRITE; 3250b57cec5SDimitry Andric return (Sec->Characteristics & BssFlags) == BssFlags; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 3285ffd83dbSDimitry Andric // The .debug sections are the only debug sections for COFF 3295ffd83dbSDimitry Andric // (\see MCObjectFileInfo.cpp). 330fe6060f1SDimitry Andric bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const { 331fe6060f1SDimitry Andric Expected<StringRef> SectionNameOrErr = getSectionName(Ref); 332fe6060f1SDimitry Andric if (!SectionNameOrErr) { 333fe6060f1SDimitry Andric // TODO: Report the error message properly. 334fe6060f1SDimitry Andric consumeError(SectionNameOrErr.takeError()); 335fe6060f1SDimitry Andric return false; 336fe6060f1SDimitry Andric } 337fe6060f1SDimitry Andric StringRef SectionName = SectionNameOrErr.get(); 3385f757f3fSDimitry Andric return SectionName.starts_with(".debug"); 3395ffd83dbSDimitry Andric } 3405ffd83dbSDimitry Andric 3410b57cec5SDimitry Andric unsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 3420b57cec5SDimitry Andric uintptr_t Offset = 343e8d8bef9SDimitry Andric Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable); 3440b57cec5SDimitry Andric assert((Offset % sizeof(coff_section)) == 0); 3450b57cec5SDimitry Andric return (Offset / sizeof(coff_section)) + 1; 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 3490b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 3500b57cec5SDimitry Andric // In COFF, a virtual section won't have any in-file 3510b57cec5SDimitry Andric // content, so the file pointer to the content will be zero. 3520b57cec5SDimitry Andric return Sec->PointerToRawData == 0; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric static uint32_t getNumberOfRelocations(const coff_section *Sec, 3560b57cec5SDimitry Andric MemoryBufferRef M, const uint8_t *base) { 3570b57cec5SDimitry Andric // The field for the number of relocations in COFF section table is only 3580b57cec5SDimitry Andric // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 3590b57cec5SDimitry Andric // NumberOfRelocations field, and the actual relocation count is stored in the 3600b57cec5SDimitry Andric // VirtualAddress field in the first relocation entry. 3610b57cec5SDimitry Andric if (Sec->hasExtendedRelocations()) { 3620b57cec5SDimitry Andric const coff_relocation *FirstReloc; 3635ffd83dbSDimitry Andric if (Error E = getObject(FirstReloc, M, 3645ffd83dbSDimitry Andric reinterpret_cast<const coff_relocation *>( 3655ffd83dbSDimitry Andric base + Sec->PointerToRelocations))) { 3665ffd83dbSDimitry Andric consumeError(std::move(E)); 3670b57cec5SDimitry Andric return 0; 3685ffd83dbSDimitry Andric } 3690b57cec5SDimitry Andric // -1 to exclude this first relocation entry. 3700b57cec5SDimitry Andric return FirstReloc->VirtualAddress - 1; 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric return Sec->NumberOfRelocations; 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric static const coff_relocation * 3760b57cec5SDimitry Andric getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 3770b57cec5SDimitry Andric uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 3780b57cec5SDimitry Andric if (!NumRelocs) 3790b57cec5SDimitry Andric return nullptr; 3800b57cec5SDimitry Andric auto begin = reinterpret_cast<const coff_relocation *>( 3810b57cec5SDimitry Andric Base + Sec->PointerToRelocations); 3820b57cec5SDimitry Andric if (Sec->hasExtendedRelocations()) { 3830b57cec5SDimitry Andric // Skip the first relocation entry repurposed to store the number of 3840b57cec5SDimitry Andric // relocations. 3850b57cec5SDimitry Andric begin++; 3860b57cec5SDimitry Andric } 387e8d8bef9SDimitry Andric if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin), 3885ffd83dbSDimitry Andric sizeof(coff_relocation) * NumRelocs)) { 3895ffd83dbSDimitry Andric consumeError(std::move(E)); 3900b57cec5SDimitry Andric return nullptr; 3915ffd83dbSDimitry Andric } 3920b57cec5SDimitry Andric return begin; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 3960b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 3970b57cec5SDimitry Andric const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 3980b57cec5SDimitry Andric if (begin && Sec->VirtualAddress != 0) 3990b57cec5SDimitry Andric report_fatal_error("Sections with relocations should have an address of 0"); 4000b57cec5SDimitry Andric DataRefImpl Ret; 4010b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(begin); 4020b57cec5SDimitry Andric return relocation_iterator(RelocationRef(Ret, this)); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 4060b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref); 4070b57cec5SDimitry Andric const coff_relocation *I = getFirstReloc(Sec, Data, base()); 4080b57cec5SDimitry Andric if (I) 4090b57cec5SDimitry Andric I += getNumberOfRelocations(Sec, Data, base()); 4100b57cec5SDimitry Andric DataRefImpl Ret; 4110b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(I); 4120b57cec5SDimitry Andric return relocation_iterator(RelocationRef(Ret, this)); 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric // Initialize the pointer to the symbol table. 4165ffd83dbSDimitry Andric Error COFFObjectFile::initSymbolTablePtr() { 4170b57cec5SDimitry Andric if (COFFHeader) 4185ffd83dbSDimitry Andric if (Error E = getObject( 4190b57cec5SDimitry Andric SymbolTable16, Data, base() + getPointerToSymbolTable(), 4200b57cec5SDimitry Andric (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4215ffd83dbSDimitry Andric return E; 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric if (COFFBigObjHeader) 4245ffd83dbSDimitry Andric if (Error E = getObject( 4250b57cec5SDimitry Andric SymbolTable32, Data, base() + getPointerToSymbolTable(), 4260b57cec5SDimitry Andric (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 4275ffd83dbSDimitry Andric return E; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric // Find string table. The first four byte of the string table contains the 4300b57cec5SDimitry Andric // total size of the string table, including the size field itself. If the 4310b57cec5SDimitry Andric // string table is empty, the value of the first four byte would be 4. 4320b57cec5SDimitry Andric uint32_t StringTableOffset = getPointerToSymbolTable() + 4330b57cec5SDimitry Andric getNumberOfSymbols() * getSymbolTableEntrySize(); 4340b57cec5SDimitry Andric const uint8_t *StringTableAddr = base() + StringTableOffset; 4350b57cec5SDimitry Andric const ulittle32_t *StringTableSizePtr; 4365ffd83dbSDimitry Andric if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr)) 4375ffd83dbSDimitry Andric return E; 4380b57cec5SDimitry Andric StringTableSize = *StringTableSizePtr; 4395ffd83dbSDimitry Andric if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize)) 4405ffd83dbSDimitry Andric return E; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 4430b57cec5SDimitry Andric // tools like cvtres write a size of 0 for an empty table instead of 4. 4440b57cec5SDimitry Andric if (StringTableSize < 4) 4450b57cec5SDimitry Andric StringTableSize = 4; 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric // Check that the string table is null terminated if has any in it. 4480b57cec5SDimitry Andric if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 44981ad6265SDimitry Andric return createStringError(object_error::parse_failed, 45081ad6265SDimitry Andric "string table missing null terminator"); 4515ffd83dbSDimitry Andric return Error::success(); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric uint64_t COFFObjectFile::getImageBase() const { 4550b57cec5SDimitry Andric if (PE32Header) 4560b57cec5SDimitry Andric return PE32Header->ImageBase; 4570b57cec5SDimitry Andric else if (PE32PlusHeader) 4580b57cec5SDimitry Andric return PE32PlusHeader->ImageBase; 4590b57cec5SDimitry Andric // This actually comes up in practice. 4600b57cec5SDimitry Andric return 0; 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric // Returns the file offset for the given VA. 4645ffd83dbSDimitry Andric Error COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 4650b57cec5SDimitry Andric uint64_t ImageBase = getImageBase(); 4660b57cec5SDimitry Andric uint64_t Rva = Addr - ImageBase; 4670b57cec5SDimitry Andric assert(Rva <= UINT32_MAX); 4680b57cec5SDimitry Andric return getRvaPtr((uint32_t)Rva, Res); 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric // Returns the file offset for the given RVA. 47281ad6265SDimitry Andric Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res, 47381ad6265SDimitry Andric const char *ErrorContext) const { 4740b57cec5SDimitry Andric for (const SectionRef &S : sections()) { 4750b57cec5SDimitry Andric const coff_section *Section = getCOFFSection(S); 4760b57cec5SDimitry Andric uint32_t SectionStart = Section->VirtualAddress; 4770b57cec5SDimitry Andric uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 4780b57cec5SDimitry Andric if (SectionStart <= Addr && Addr < SectionEnd) { 47981ad6265SDimitry Andric // A table/directory entry can be pointing to somewhere in a stripped 48081ad6265SDimitry Andric // section, in an object that went through `objcopy --only-keep-debug`. 48181ad6265SDimitry Andric // In this case we don't want to cause the parsing of the object file to 48281ad6265SDimitry Andric // fail, otherwise it will be impossible to use this object as debug info 48381ad6265SDimitry Andric // in LLDB. Return SectionStrippedError here so that 48481ad6265SDimitry Andric // COFFObjectFile::initialize can ignore the error. 48581ad6265SDimitry Andric // Somewhat common binaries may have RVAs pointing outside of the 48681ad6265SDimitry Andric // provided raw data. Instead of rejecting the binaries, just 48781ad6265SDimitry Andric // treat the section as stripped for these purposes. 48881ad6265SDimitry Andric if (Section->SizeOfRawData < Section->VirtualSize && 48981ad6265SDimitry Andric Addr >= SectionStart + Section->SizeOfRawData) { 49081ad6265SDimitry Andric return make_error<SectionStrippedError>(); 49181ad6265SDimitry Andric } 4920b57cec5SDimitry Andric uint32_t Offset = Addr - SectionStart; 493e8d8bef9SDimitry Andric Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData + 494e8d8bef9SDimitry Andric Offset; 4955ffd83dbSDimitry Andric return Error::success(); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric } 49881ad6265SDimitry Andric if (ErrorContext) 49981ad6265SDimitry Andric return createStringError(object_error::parse_failed, 50081ad6265SDimitry Andric "RVA 0x%" PRIx32 " for %s not found", Addr, 50181ad6265SDimitry Andric ErrorContext); 50281ad6265SDimitry Andric return createStringError(object_error::parse_failed, 50381ad6265SDimitry Andric "RVA 0x%" PRIx32 " not found", Addr); 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5065ffd83dbSDimitry Andric Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 50781ad6265SDimitry Andric ArrayRef<uint8_t> &Contents, 50881ad6265SDimitry Andric const char *ErrorContext) const { 5090b57cec5SDimitry Andric for (const SectionRef &S : sections()) { 5100b57cec5SDimitry Andric const coff_section *Section = getCOFFSection(S); 5110b57cec5SDimitry Andric uint32_t SectionStart = Section->VirtualAddress; 5120b57cec5SDimitry Andric // Check if this RVA is within the section bounds. Be careful about integer 5130b57cec5SDimitry Andric // overflow. 5140b57cec5SDimitry Andric uint32_t OffsetIntoSection = RVA - SectionStart; 5150b57cec5SDimitry Andric if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 5160b57cec5SDimitry Andric Size <= Section->VirtualSize - OffsetIntoSection) { 517e8d8bef9SDimitry Andric uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) + 518e8d8bef9SDimitry Andric Section->PointerToRawData + OffsetIntoSection; 5190b57cec5SDimitry Andric Contents = 5200b57cec5SDimitry Andric ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 5215ffd83dbSDimitry Andric return Error::success(); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric } 52481ad6265SDimitry Andric if (ErrorContext) 52581ad6265SDimitry Andric return createStringError(object_error::parse_failed, 52681ad6265SDimitry Andric "RVA 0x%" PRIx32 " for %s not found", RVA, 52781ad6265SDimitry Andric ErrorContext); 52881ad6265SDimitry Andric return createStringError(object_error::parse_failed, 52981ad6265SDimitry Andric "RVA 0x%" PRIx32 " not found", RVA); 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 5330b57cec5SDimitry Andric // table entry. 5345ffd83dbSDimitry Andric Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 5350b57cec5SDimitry Andric StringRef &Name) const { 5360b57cec5SDimitry Andric uintptr_t IntPtr = 0; 5375ffd83dbSDimitry Andric if (Error E = getRvaPtr(Rva, IntPtr)) 5385ffd83dbSDimitry Andric return E; 5390b57cec5SDimitry Andric const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 5400b57cec5SDimitry Andric Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 5410b57cec5SDimitry Andric Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 5425ffd83dbSDimitry Andric return Error::success(); 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric 5455ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 5460b57cec5SDimitry Andric const codeview::DebugInfo *&PDBInfo, 5470b57cec5SDimitry Andric StringRef &PDBFileName) const { 5480b57cec5SDimitry Andric ArrayRef<uint8_t> InfoBytes; 54981ad6265SDimitry Andric if (Error E = 55081ad6265SDimitry Andric getRvaAndSizeAsBytes(DebugDir->AddressOfRawData, DebugDir->SizeOfData, 55181ad6265SDimitry Andric InfoBytes, "PDB info")) 5525ffd83dbSDimitry Andric return E; 5530b57cec5SDimitry Andric if (InfoBytes.size() < sizeof(*PDBInfo) + 1) 55481ad6265SDimitry Andric return createStringError(object_error::parse_failed, "PDB info too small"); 5550b57cec5SDimitry Andric PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data()); 5560b57cec5SDimitry Andric InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo)); 5570b57cec5SDimitry Andric PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 5580b57cec5SDimitry Andric InfoBytes.size()); 5590b57cec5SDimitry Andric // Truncate the name at the first null byte. Ignore any padding. 5600b57cec5SDimitry Andric PDBFileName = PDBFileName.split('\0').first; 5615ffd83dbSDimitry Andric return Error::success(); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5645ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo, 5650b57cec5SDimitry Andric StringRef &PDBFileName) const { 5660b57cec5SDimitry Andric for (const debug_directory &D : debug_directories()) 5670b57cec5SDimitry Andric if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 5680b57cec5SDimitry Andric return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 5690b57cec5SDimitry Andric // If we get here, there is no PDB info to return. 5700b57cec5SDimitry Andric PDBInfo = nullptr; 5710b57cec5SDimitry Andric PDBFileName = StringRef(); 5725ffd83dbSDimitry Andric return Error::success(); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric // Find the import table. 5765ffd83dbSDimitry Andric Error COFFObjectFile::initImportTablePtr() { 5770b57cec5SDimitry Andric // First, we get the RVA of the import table. If the file lacks a pointer to 5780b57cec5SDimitry Andric // the import table, do nothing. 5795ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE); 5805ffd83dbSDimitry Andric if (!DataEntry) 5815ffd83dbSDimitry Andric return Error::success(); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric // Do nothing if the pointer to import table is NULL. 5840b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 5855ffd83dbSDimitry Andric return Error::success(); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric // Find the section that contains the RVA. This is needed because the RVA is 5900b57cec5SDimitry Andric // the import table's memory address which is different from its file offset. 5910b57cec5SDimitry Andric uintptr_t IntPtr = 0; 59281ad6265SDimitry Andric if (Error E = getRvaPtr(ImportTableRva, IntPtr, "import table")) 5935ffd83dbSDimitry Andric return E; 5945ffd83dbSDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 5955ffd83dbSDimitry Andric return E; 5960b57cec5SDimitry Andric ImportDirectory = reinterpret_cast< 5970b57cec5SDimitry Andric const coff_import_directory_table_entry *>(IntPtr); 5985ffd83dbSDimitry Andric return Error::success(); 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 6025ffd83dbSDimitry Andric Error COFFObjectFile::initDelayImportTablePtr() { 6035ffd83dbSDimitry Andric const data_directory *DataEntry = 6045ffd83dbSDimitry Andric getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR); 6055ffd83dbSDimitry Andric if (!DataEntry) 6065ffd83dbSDimitry Andric return Error::success(); 6070b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 6085ffd83dbSDimitry Andric return Error::success(); 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric uint32_t RVA = DataEntry->RelativeVirtualAddress; 6110b57cec5SDimitry Andric NumberOfDelayImportDirectory = DataEntry->Size / 6120b57cec5SDimitry Andric sizeof(delay_import_directory_table_entry) - 1; 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric uintptr_t IntPtr = 0; 61581ad6265SDimitry Andric if (Error E = getRvaPtr(RVA, IntPtr, "delay import table")) 6165ffd83dbSDimitry Andric return E; 61781ad6265SDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 61881ad6265SDimitry Andric return E; 61981ad6265SDimitry Andric 6200b57cec5SDimitry Andric DelayImportDirectory = reinterpret_cast< 6210b57cec5SDimitry Andric const delay_import_directory_table_entry *>(IntPtr); 6225ffd83dbSDimitry Andric return Error::success(); 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric // Find the export table. 6265ffd83dbSDimitry Andric Error COFFObjectFile::initExportTablePtr() { 6270b57cec5SDimitry Andric // First, we get the RVA of the export table. If the file lacks a pointer to 6280b57cec5SDimitry Andric // the export table, do nothing. 6295ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE); 6305ffd83dbSDimitry Andric if (!DataEntry) 6315ffd83dbSDimitry Andric return Error::success(); 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric // Do nothing if the pointer to export table is NULL. 6340b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 6355ffd83dbSDimitry Andric return Error::success(); 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 6380b57cec5SDimitry Andric uintptr_t IntPtr = 0; 63981ad6265SDimitry Andric if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table")) 6405ffd83dbSDimitry Andric return E; 64181ad6265SDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 64281ad6265SDimitry Andric return E; 64381ad6265SDimitry Andric 6440b57cec5SDimitry Andric ExportDirectory = 6450b57cec5SDimitry Andric reinterpret_cast<const export_directory_table_entry *>(IntPtr); 6465ffd83dbSDimitry Andric return Error::success(); 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 6495ffd83dbSDimitry Andric Error COFFObjectFile::initBaseRelocPtr() { 6505ffd83dbSDimitry Andric const data_directory *DataEntry = 6515ffd83dbSDimitry Andric getDataDirectory(COFF::BASE_RELOCATION_TABLE); 6525ffd83dbSDimitry Andric if (!DataEntry) 6535ffd83dbSDimitry Andric return Error::success(); 6540b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 6555ffd83dbSDimitry Andric return Error::success(); 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric uintptr_t IntPtr = 0; 65881ad6265SDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, 65981ad6265SDimitry Andric "base reloc table")) 6605ffd83dbSDimitry Andric return E; 66181ad6265SDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 66281ad6265SDimitry Andric return E; 66381ad6265SDimitry Andric 6640b57cec5SDimitry Andric BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 6650b57cec5SDimitry Andric IntPtr); 6660b57cec5SDimitry Andric BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 6670b57cec5SDimitry Andric IntPtr + DataEntry->Size); 6680b57cec5SDimitry Andric // FIXME: Verify the section containing BaseRelocHeader has at least 6690b57cec5SDimitry Andric // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 6705ffd83dbSDimitry Andric return Error::success(); 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6735ffd83dbSDimitry Andric Error COFFObjectFile::initDebugDirectoryPtr() { 6740b57cec5SDimitry Andric // Get the RVA of the debug directory. Do nothing if it does not exist. 6755ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY); 6765ffd83dbSDimitry Andric if (!DataEntry) 6775ffd83dbSDimitry Andric return Error::success(); 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric // Do nothing if the RVA is NULL. 6800b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 6815ffd83dbSDimitry Andric return Error::success(); 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric // Check that the size is a multiple of the entry size. 6840b57cec5SDimitry Andric if (DataEntry->Size % sizeof(debug_directory) != 0) 68581ad6265SDimitry Andric return createStringError(object_error::parse_failed, 68681ad6265SDimitry Andric "debug directory has uneven size"); 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric uintptr_t IntPtr = 0; 68981ad6265SDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, 69081ad6265SDimitry Andric "debug directory")) 6915ffd83dbSDimitry Andric return E; 69281ad6265SDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 69381ad6265SDimitry Andric return E; 69481ad6265SDimitry Andric 6950b57cec5SDimitry Andric DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 6960b57cec5SDimitry Andric DebugDirectoryEnd = reinterpret_cast<const debug_directory *>( 6970b57cec5SDimitry Andric IntPtr + DataEntry->Size); 6980b57cec5SDimitry Andric // FIXME: Verify the section containing DebugDirectoryBegin has at least 6990b57cec5SDimitry Andric // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress. 7005ffd83dbSDimitry Andric return Error::success(); 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 703e8d8bef9SDimitry Andric Error COFFObjectFile::initTLSDirectoryPtr() { 704e8d8bef9SDimitry Andric // Get the RVA of the TLS directory. Do nothing if it does not exist. 705e8d8bef9SDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE); 706e8d8bef9SDimitry Andric if (!DataEntry) 707e8d8bef9SDimitry Andric return Error::success(); 708e8d8bef9SDimitry Andric 709e8d8bef9SDimitry Andric // Do nothing if the RVA is NULL. 710e8d8bef9SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 711e8d8bef9SDimitry Andric return Error::success(); 712e8d8bef9SDimitry Andric 713e8d8bef9SDimitry Andric uint64_t DirSize = 714e8d8bef9SDimitry Andric is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32); 715e8d8bef9SDimitry Andric 716e8d8bef9SDimitry Andric // Check that the size is correct. 717e8d8bef9SDimitry Andric if (DataEntry->Size != DirSize) 718e8d8bef9SDimitry Andric return createStringError( 719e8d8bef9SDimitry Andric object_error::parse_failed, 720e8d8bef9SDimitry Andric "TLS Directory size (%u) is not the expected size (%" PRIu64 ").", 721e8d8bef9SDimitry Andric static_cast<uint32_t>(DataEntry->Size), DirSize); 722e8d8bef9SDimitry Andric 723e8d8bef9SDimitry Andric uintptr_t IntPtr = 0; 72481ad6265SDimitry Andric if (Error E = 72581ad6265SDimitry Andric getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory")) 72681ad6265SDimitry Andric return E; 72781ad6265SDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 728e8d8bef9SDimitry Andric return E; 729e8d8bef9SDimitry Andric 730e8d8bef9SDimitry Andric if (is64()) 731e8d8bef9SDimitry Andric TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr); 732e8d8bef9SDimitry Andric else 733e8d8bef9SDimitry Andric TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr); 734e8d8bef9SDimitry Andric 735e8d8bef9SDimitry Andric return Error::success(); 736e8d8bef9SDimitry Andric } 737e8d8bef9SDimitry Andric 7385ffd83dbSDimitry Andric Error COFFObjectFile::initLoadConfigPtr() { 7390b57cec5SDimitry Andric // Get the RVA of the debug directory. Do nothing if it does not exist. 7405ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE); 7415ffd83dbSDimitry Andric if (!DataEntry) 7425ffd83dbSDimitry Andric return Error::success(); 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric // Do nothing if the RVA is NULL. 7450b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0) 7465ffd83dbSDimitry Andric return Error::success(); 7470b57cec5SDimitry Andric uintptr_t IntPtr = 0; 74881ad6265SDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, 74981ad6265SDimitry Andric "load config table")) 75081ad6265SDimitry Andric return E; 75181ad6265SDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size)) 7525ffd83dbSDimitry Andric return E; 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric LoadConfig = (const void *)IntPtr; 75506c3fb27SDimitry Andric 75606c3fb27SDimitry Andric if (is64()) { 75706c3fb27SDimitry Andric auto Config = getLoadConfig64(); 75806c3fb27SDimitry Andric if (Config->Size >= 75906c3fb27SDimitry Andric offsetof(coff_load_configuration64, CHPEMetadataPointer) + 76006c3fb27SDimitry Andric sizeof(Config->CHPEMetadataPointer) && 76106c3fb27SDimitry Andric Config->CHPEMetadataPointer) { 76206c3fb27SDimitry Andric uint64_t ChpeOff = Config->CHPEMetadataPointer; 76306c3fb27SDimitry Andric if (Error E = 76406c3fb27SDimitry Andric getRvaPtr(ChpeOff - getImageBase(), IntPtr, "CHPE metadata")) 76506c3fb27SDimitry Andric return E; 76606c3fb27SDimitry Andric if (Error E = checkOffset(Data, IntPtr, sizeof(CHPEMetadata))) 76706c3fb27SDimitry Andric return E; 76806c3fb27SDimitry Andric 76906c3fb27SDimitry Andric CHPEMetadata = reinterpret_cast<const chpe_metadata *>(IntPtr); 77006c3fb27SDimitry Andric 77106c3fb27SDimitry Andric // Validate CHPE metadata 77206c3fb27SDimitry Andric if (CHPEMetadata->CodeMapCount) { 77306c3fb27SDimitry Andric if (Error E = getRvaPtr(CHPEMetadata->CodeMap, IntPtr, "CHPE code map")) 77406c3fb27SDimitry Andric return E; 77506c3fb27SDimitry Andric if (Error E = checkOffset(Data, IntPtr, 77606c3fb27SDimitry Andric CHPEMetadata->CodeMapCount * 77706c3fb27SDimitry Andric sizeof(chpe_range_entry))) 77806c3fb27SDimitry Andric return E; 77906c3fb27SDimitry Andric } 78006c3fb27SDimitry Andric 78106c3fb27SDimitry Andric if (CHPEMetadata->CodeRangesToEntryPointsCount) { 78206c3fb27SDimitry Andric if (Error E = getRvaPtr(CHPEMetadata->CodeRangesToEntryPoints, IntPtr, 78306c3fb27SDimitry Andric "CHPE entry point ranges")) 78406c3fb27SDimitry Andric return E; 78506c3fb27SDimitry Andric if (Error E = checkOffset(Data, IntPtr, 78606c3fb27SDimitry Andric CHPEMetadata->CodeRangesToEntryPointsCount * 78706c3fb27SDimitry Andric sizeof(chpe_code_range_entry))) 78806c3fb27SDimitry Andric return E; 78906c3fb27SDimitry Andric } 79006c3fb27SDimitry Andric 79106c3fb27SDimitry Andric if (CHPEMetadata->RedirectionMetadataCount) { 79206c3fb27SDimitry Andric if (Error E = getRvaPtr(CHPEMetadata->RedirectionMetadata, IntPtr, 79306c3fb27SDimitry Andric "CHPE redirection metadata")) 79406c3fb27SDimitry Andric return E; 79506c3fb27SDimitry Andric if (Error E = checkOffset(Data, IntPtr, 79606c3fb27SDimitry Andric CHPEMetadata->RedirectionMetadataCount * 79706c3fb27SDimitry Andric sizeof(chpe_redirection_entry))) 79806c3fb27SDimitry Andric return E; 79906c3fb27SDimitry Andric } 80006c3fb27SDimitry Andric } 80106c3fb27SDimitry Andric } 80206c3fb27SDimitry Andric 8035ffd83dbSDimitry Andric return Error::success(); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8065ffd83dbSDimitry Andric Expected<std::unique_ptr<COFFObjectFile>> 8075ffd83dbSDimitry Andric COFFObjectFile::create(MemoryBufferRef Object) { 8085ffd83dbSDimitry Andric std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object))); 8095ffd83dbSDimitry Andric if (Error E = Obj->initialize()) 810*0fca6ea1SDimitry Andric return E; 8115ffd83dbSDimitry Andric return std::move(Obj); 8125ffd83dbSDimitry Andric } 8135ffd83dbSDimitry Andric 8145ffd83dbSDimitry Andric COFFObjectFile::COFFObjectFile(MemoryBufferRef Object) 8150b57cec5SDimitry Andric : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 8160b57cec5SDimitry Andric COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 8170b57cec5SDimitry Andric DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 8180b57cec5SDimitry Andric SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 8195ffd83dbSDimitry Andric ImportDirectory(nullptr), DelayImportDirectory(nullptr), 8205ffd83dbSDimitry Andric NumberOfDelayImportDirectory(0), ExportDirectory(nullptr), 8215ffd83dbSDimitry Andric BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 822e8d8bef9SDimitry Andric DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr), 823e8d8bef9SDimitry Andric TLSDirectory32(nullptr), TLSDirectory64(nullptr) {} 8245ffd83dbSDimitry Andric 82581ad6265SDimitry Andric static Error ignoreStrippedErrors(Error E) { 82681ad6265SDimitry Andric if (E.isA<SectionStrippedError>()) { 82781ad6265SDimitry Andric consumeError(std::move(E)); 82881ad6265SDimitry Andric return Error::success(); 82981ad6265SDimitry Andric } 83081ad6265SDimitry Andric return E; 83181ad6265SDimitry Andric } 83281ad6265SDimitry Andric 8335ffd83dbSDimitry Andric Error COFFObjectFile::initialize() { 8340b57cec5SDimitry Andric // Check that we at least have enough room for a header. 8355ffd83dbSDimitry Andric std::error_code EC; 8360b57cec5SDimitry Andric if (!checkSize(Data, EC, sizeof(coff_file_header))) 8375ffd83dbSDimitry Andric return errorCodeToError(EC); 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric // The current location in the file where we are looking at. 8400b57cec5SDimitry Andric uint64_t CurPtr = 0; 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric // PE header is optional and is present only in executables. If it exists, 8430b57cec5SDimitry Andric // it is placed right after COFF header. 8440b57cec5SDimitry Andric bool HasPEHeader = false; 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric // Check if this is a PE/COFF file. 8470b57cec5SDimitry Andric if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 8480b57cec5SDimitry Andric // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 8490b57cec5SDimitry Andric // PE signature to find 'normal' COFF header. 8500b57cec5SDimitry Andric const auto *DH = reinterpret_cast<const dos_header *>(base()); 8510b57cec5SDimitry Andric if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 8520b57cec5SDimitry Andric CurPtr = DH->AddressOfNewExeHeader; 8530b57cec5SDimitry Andric // Check the PE magic bytes. ("PE\0\0") 8540b57cec5SDimitry Andric if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 85581ad6265SDimitry Andric return createStringError(object_error::parse_failed, 85681ad6265SDimitry Andric "incorrect PE magic"); 8570b57cec5SDimitry Andric } 8580b57cec5SDimitry Andric CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 8590b57cec5SDimitry Andric HasPEHeader = true; 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric 8635ffd83dbSDimitry Andric if (Error E = getObject(COFFHeader, Data, base() + CurPtr)) 8645ffd83dbSDimitry Andric return E; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 8670b57cec5SDimitry Andric // import libraries share a common prefix but bigobj is more restrictive. 8680b57cec5SDimitry Andric if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 8690b57cec5SDimitry Andric COFFHeader->NumberOfSections == uint16_t(0xffff) && 8700b57cec5SDimitry Andric checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 8715ffd83dbSDimitry Andric if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr)) 8725ffd83dbSDimitry Andric return E; 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric // Verify that we are dealing with bigobj. 8750b57cec5SDimitry Andric if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 8760b57cec5SDimitry Andric std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 8770b57cec5SDimitry Andric sizeof(COFF::BigObjMagic)) == 0) { 8780b57cec5SDimitry Andric COFFHeader = nullptr; 8790b57cec5SDimitry Andric CurPtr += sizeof(coff_bigobj_file_header); 8800b57cec5SDimitry Andric } else { 8810b57cec5SDimitry Andric // It's not a bigobj. 8820b57cec5SDimitry Andric COFFBigObjHeader = nullptr; 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric if (COFFHeader) { 8860b57cec5SDimitry Andric // The prior checkSize call may have failed. This isn't a hard error 8870b57cec5SDimitry Andric // because we were just trying to sniff out bigobj. 8880b57cec5SDimitry Andric EC = std::error_code(); 8890b57cec5SDimitry Andric CurPtr += sizeof(coff_file_header); 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric if (COFFHeader->isImportLibrary()) 8925ffd83dbSDimitry Andric return errorCodeToError(EC); 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric if (HasPEHeader) { 8960b57cec5SDimitry Andric const pe32_header *Header; 8975ffd83dbSDimitry Andric if (Error E = getObject(Header, Data, base() + CurPtr)) 8985ffd83dbSDimitry Andric return E; 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric const uint8_t *DataDirAddr; 9010b57cec5SDimitry Andric uint64_t DataDirSize; 9020b57cec5SDimitry Andric if (Header->Magic == COFF::PE32Header::PE32) { 9030b57cec5SDimitry Andric PE32Header = Header; 9040b57cec5SDimitry Andric DataDirAddr = base() + CurPtr + sizeof(pe32_header); 9050b57cec5SDimitry Andric DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 9060b57cec5SDimitry Andric } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 9070b57cec5SDimitry Andric PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 9080b57cec5SDimitry Andric DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 9090b57cec5SDimitry Andric DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 9100b57cec5SDimitry Andric } else { 9110b57cec5SDimitry Andric // It's neither PE32 nor PE32+. 91281ad6265SDimitry Andric return createStringError(object_error::parse_failed, 91381ad6265SDimitry Andric "incorrect PE magic"); 9140b57cec5SDimitry Andric } 9155ffd83dbSDimitry Andric if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)) 9165ffd83dbSDimitry Andric return E; 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric if (COFFHeader) 9200b57cec5SDimitry Andric CurPtr += COFFHeader->SizeOfOptionalHeader; 9210b57cec5SDimitry Andric 9225ffd83dbSDimitry Andric assert(COFFHeader || COFFBigObjHeader); 9235ffd83dbSDimitry Andric 9245ffd83dbSDimitry Andric if (Error E = 9255ffd83dbSDimitry Andric getObject(SectionTable, Data, base() + CurPtr, 9265ffd83dbSDimitry Andric (uint64_t)getNumberOfSections() * sizeof(coff_section))) 9275ffd83dbSDimitry Andric return E; 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric // Initialize the pointer to the symbol table. 9300b57cec5SDimitry Andric if (getPointerToSymbolTable() != 0) { 9315ffd83dbSDimitry Andric if (Error E = initSymbolTablePtr()) { 9325ffd83dbSDimitry Andric // Recover from errors reading the symbol table. 9335ffd83dbSDimitry Andric consumeError(std::move(E)); 9340b57cec5SDimitry Andric SymbolTable16 = nullptr; 9350b57cec5SDimitry Andric SymbolTable32 = nullptr; 9360b57cec5SDimitry Andric StringTable = nullptr; 9370b57cec5SDimitry Andric StringTableSize = 0; 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric } else { 9400b57cec5SDimitry Andric // We had better not have any symbols if we don't have a symbol table. 9410b57cec5SDimitry Andric if (getNumberOfSymbols() != 0) { 94281ad6265SDimitry Andric return createStringError(object_error::parse_failed, 94381ad6265SDimitry Andric "symbol table missing"); 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric 9470b57cec5SDimitry Andric // Initialize the pointer to the beginning of the import table. 94881ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initImportTablePtr())) 9495ffd83dbSDimitry Andric return E; 95081ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initDelayImportTablePtr())) 9515ffd83dbSDimitry Andric return E; 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric // Initialize the pointer to the export table. 95481ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initExportTablePtr())) 9555ffd83dbSDimitry Andric return E; 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric // Initialize the pointer to the base relocation table. 95881ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initBaseRelocPtr())) 9595ffd83dbSDimitry Andric return E; 9600b57cec5SDimitry Andric 961e8d8bef9SDimitry Andric // Initialize the pointer to the debug directory. 96281ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr())) 9635ffd83dbSDimitry Andric return E; 9640b57cec5SDimitry Andric 965e8d8bef9SDimitry Andric // Initialize the pointer to the TLS directory. 96681ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr())) 967e8d8bef9SDimitry Andric return E; 968e8d8bef9SDimitry Andric 96981ad6265SDimitry Andric if (Error E = ignoreStrippedErrors(initLoadConfigPtr())) 9705ffd83dbSDimitry Andric return E; 9710b57cec5SDimitry Andric 9725ffd83dbSDimitry Andric return Error::success(); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_begin() const { 9760b57cec5SDimitry Andric DataRefImpl Ret; 9770b57cec5SDimitry Andric Ret.p = getSymbolTable(); 9780b57cec5SDimitry Andric return basic_symbol_iterator(SymbolRef(Ret, this)); 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_end() const { 9820b57cec5SDimitry Andric // The symbol table ends where the string table begins. 9830b57cec5SDimitry Andric DataRefImpl Ret; 9840b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(StringTable); 9850b57cec5SDimitry Andric return basic_symbol_iterator(SymbolRef(Ret, this)); 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_begin() const { 9890b57cec5SDimitry Andric if (!ImportDirectory) 9900b57cec5SDimitry Andric return import_directory_end(); 9910b57cec5SDimitry Andric if (ImportDirectory->isNull()) 9920b57cec5SDimitry Andric return import_directory_end(); 9930b57cec5SDimitry Andric return import_directory_iterator( 9940b57cec5SDimitry Andric ImportDirectoryEntryRef(ImportDirectory, 0, this)); 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_end() const { 9980b57cec5SDimitry Andric return import_directory_iterator( 9990b57cec5SDimitry Andric ImportDirectoryEntryRef(nullptr, -1, this)); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric delay_import_directory_iterator 10030b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_begin() const { 10040b57cec5SDimitry Andric return delay_import_directory_iterator( 10050b57cec5SDimitry Andric DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric delay_import_directory_iterator 10090b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_end() const { 10100b57cec5SDimitry Andric return delay_import_directory_iterator( 10110b57cec5SDimitry Andric DelayImportDirectoryEntryRef( 10120b57cec5SDimitry Andric DelayImportDirectory, NumberOfDelayImportDirectory, this)); 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_begin() const { 10160b57cec5SDimitry Andric return export_directory_iterator( 10170b57cec5SDimitry Andric ExportDirectoryEntryRef(ExportDirectory, 0, this)); 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_end() const { 10210b57cec5SDimitry Andric if (!ExportDirectory) 10220b57cec5SDimitry Andric return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 10230b57cec5SDimitry Andric ExportDirectoryEntryRef Ref(ExportDirectory, 10240b57cec5SDimitry Andric ExportDirectory->AddressTableEntries, this); 10250b57cec5SDimitry Andric return export_directory_iterator(Ref); 10260b57cec5SDimitry Andric } 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric section_iterator COFFObjectFile::section_begin() const { 10290b57cec5SDimitry Andric DataRefImpl Ret; 10300b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 10310b57cec5SDimitry Andric return section_iterator(SectionRef(Ret, this)); 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric section_iterator COFFObjectFile::section_end() const { 10350b57cec5SDimitry Andric DataRefImpl Ret; 10360b57cec5SDimitry Andric int NumSections = 10370b57cec5SDimitry Andric COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 10380b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 10390b57cec5SDimitry Andric return section_iterator(SectionRef(Ret, this)); 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_begin() const { 10430b57cec5SDimitry Andric return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_end() const { 10470b57cec5SDimitry Andric return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric uint8_t COFFObjectFile::getBytesInAddress() const { 10510b57cec5SDimitry Andric return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric StringRef COFFObjectFile::getFileFormatName() const { 10550b57cec5SDimitry Andric switch(getMachine()) { 10560b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386: 10570b57cec5SDimitry Andric return "COFF-i386"; 10580b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64: 10590b57cec5SDimitry Andric return "COFF-x86-64"; 10600b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT: 10610b57cec5SDimitry Andric return "COFF-ARM"; 10620b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64: 10630b57cec5SDimitry Andric return "COFF-ARM64"; 1064bdd1243dSDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64EC: 1065bdd1243dSDimitry Andric return "COFF-ARM64EC"; 106606c3fb27SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64X: 106706c3fb27SDimitry Andric return "COFF-ARM64X"; 10680b57cec5SDimitry Andric default: 10690b57cec5SDimitry Andric return "COFF-<unknown arch>"; 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric } 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric Triple::ArchType COFFObjectFile::getArch() const { 1074*0fca6ea1SDimitry Andric return getMachineArchType(getMachine()); 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getStartAddress() const { 10780b57cec5SDimitry Andric if (PE32Header) 10790b57cec5SDimitry Andric return PE32Header->AddressOfEntryPoint; 10800b57cec5SDimitry Andric return 0; 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric iterator_range<import_directory_iterator> 10840b57cec5SDimitry Andric COFFObjectFile::import_directories() const { 10850b57cec5SDimitry Andric return make_range(import_directory_begin(), import_directory_end()); 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric iterator_range<delay_import_directory_iterator> 10890b57cec5SDimitry Andric COFFObjectFile::delay_import_directories() const { 10900b57cec5SDimitry Andric return make_range(delay_import_directory_begin(), 10910b57cec5SDimitry Andric delay_import_directory_end()); 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric iterator_range<export_directory_iterator> 10950b57cec5SDimitry Andric COFFObjectFile::export_directories() const { 10960b57cec5SDimitry Andric return make_range(export_directory_begin(), export_directory_end()); 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 11000b57cec5SDimitry Andric return make_range(base_reloc_begin(), base_reloc_end()); 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric 11035ffd83dbSDimitry Andric const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const { 11045ffd83dbSDimitry Andric if (!DataDirectory) 11055ffd83dbSDimitry Andric return nullptr; 11060b57cec5SDimitry Andric assert(PE32Header || PE32PlusHeader); 11070b57cec5SDimitry Andric uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 11080b57cec5SDimitry Andric : PE32PlusHeader->NumberOfRvaAndSize; 11095ffd83dbSDimitry Andric if (Index >= NumEnt) 11105ffd83dbSDimitry Andric return nullptr; 11115ffd83dbSDimitry Andric return &DataDirectory[Index]; 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric 11145ffd83dbSDimitry Andric Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const { 11155ffd83dbSDimitry Andric // Perhaps getting the section of a reserved section index should be an error, 11165ffd83dbSDimitry Andric // but callers rely on this to return null. 11170b57cec5SDimitry Andric if (COFF::isReservedSectionNumber(Index)) 11185ffd83dbSDimitry Andric return (const coff_section *)nullptr; 11190b57cec5SDimitry Andric if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 11200b57cec5SDimitry Andric // We already verified the section table data, so no need to check again. 11215ffd83dbSDimitry Andric return SectionTable + (Index - 1); 11220b57cec5SDimitry Andric } 112381ad6265SDimitry Andric return createStringError(object_error::parse_failed, 112481ad6265SDimitry Andric "section index out of bounds"); 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric 11275ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const { 11280b57cec5SDimitry Andric if (StringTableSize <= 4) 11290b57cec5SDimitry Andric // Tried to get a string from an empty string table. 113081ad6265SDimitry Andric return createStringError(object_error::parse_failed, "string table empty"); 11310b57cec5SDimitry Andric if (Offset >= StringTableSize) 11325ffd83dbSDimitry Andric return errorCodeToError(object_error::unexpected_eof); 11335ffd83dbSDimitry Andric return StringRef(StringTable + Offset); 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11365ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const { 11375ffd83dbSDimitry Andric return getSymbolName(Symbol.getGeneric()); 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 11405ffd83dbSDimitry Andric Expected<StringRef> 11415ffd83dbSDimitry Andric COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const { 11420b57cec5SDimitry Andric // Check for string table entry. First 4 bytes are 0. 11435ffd83dbSDimitry Andric if (Symbol->Name.Offset.Zeroes == 0) 11445ffd83dbSDimitry Andric return getString(Symbol->Name.Offset.Offset); 11450b57cec5SDimitry Andric 11460b57cec5SDimitry Andric // Null terminated, let ::strlen figure out the length. 11475ffd83dbSDimitry Andric if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 11485ffd83dbSDimitry Andric return StringRef(Symbol->Name.ShortName); 11495ffd83dbSDimitry Andric 11500b57cec5SDimitry Andric // Not null terminated, use all 8 bytes. 11515ffd83dbSDimitry Andric return StringRef(Symbol->Name.ShortName, COFF::NameSize); 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric ArrayRef<uint8_t> 11550b57cec5SDimitry Andric COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 11560b57cec5SDimitry Andric const uint8_t *Aux = nullptr; 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric size_t SymbolSize = getSymbolTableEntrySize(); 11590b57cec5SDimitry Andric if (Symbol.getNumberOfAuxSymbols() > 0) { 11600b57cec5SDimitry Andric // AUX data comes immediately after the symbol in COFF 11610b57cec5SDimitry Andric Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 11620b57cec5SDimitry Andric #ifndef NDEBUG 11630b57cec5SDimitry Andric // Verify that the Aux symbol points to a valid entry in the symbol table. 11640b57cec5SDimitry Andric uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 11650b57cec5SDimitry Andric if (Offset < getPointerToSymbolTable() || 11660b57cec5SDimitry Andric Offset >= 11670b57cec5SDimitry Andric getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 11680b57cec5SDimitry Andric report_fatal_error("Aux Symbol data was outside of symbol table."); 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 11710b57cec5SDimitry Andric "Aux Symbol data did not point to the beginning of a symbol"); 11720b57cec5SDimitry Andric #endif 11730b57cec5SDimitry Andric } 1174bdd1243dSDimitry Andric return ArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const { 11780b57cec5SDimitry Andric uintptr_t Offset = 11790b57cec5SDimitry Andric reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable(); 11800b57cec5SDimitry Andric assert(Offset % getSymbolTableEntrySize() == 0 && 11810b57cec5SDimitry Andric "Symbol did not point to the beginning of a symbol"); 11820b57cec5SDimitry Andric size_t Index = Offset / getSymbolTableEntrySize(); 11830b57cec5SDimitry Andric assert(Index < getNumberOfSymbols()); 11840b57cec5SDimitry Andric return Index; 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric Expected<StringRef> 11880b57cec5SDimitry Andric COFFObjectFile::getSectionName(const coff_section *Sec) const { 118981ad6265SDimitry Andric StringRef Name = StringRef(Sec->Name, COFF::NameSize).split('\0').first; 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric // Check for string table entry. First byte is '/'. 11925f757f3fSDimitry Andric if (Name.starts_with("/")) { 11930b57cec5SDimitry Andric uint32_t Offset; 11945f757f3fSDimitry Andric if (Name.starts_with("//")) { 11950b57cec5SDimitry Andric if (decodeBase64StringEntry(Name.substr(2), Offset)) 11960b57cec5SDimitry Andric return createStringError(object_error::parse_failed, 11975ffd83dbSDimitry Andric "invalid section name"); 11980b57cec5SDimitry Andric } else { 11990b57cec5SDimitry Andric if (Name.substr(1).getAsInteger(10, Offset)) 12000b57cec5SDimitry Andric return createStringError(object_error::parse_failed, 12010b57cec5SDimitry Andric "invalid section name"); 12020b57cec5SDimitry Andric } 12035ffd83dbSDimitry Andric return getString(Offset); 12040b57cec5SDimitry Andric } 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric return Name; 12070b57cec5SDimitry Andric } 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 12100b57cec5SDimitry Andric // SizeOfRawData and VirtualSize change what they represent depending on 12110b57cec5SDimitry Andric // whether or not we have an executable image. 12120b57cec5SDimitry Andric // 12130b57cec5SDimitry Andric // For object files, SizeOfRawData contains the size of section's data; 12140b57cec5SDimitry Andric // VirtualSize should be zero but isn't due to buggy COFF writers. 12150b57cec5SDimitry Andric // 12160b57cec5SDimitry Andric // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 12170b57cec5SDimitry Andric // actual section size is in VirtualSize. It is possible for VirtualSize to 12180b57cec5SDimitry Andric // be greater than SizeOfRawData; the contents past that point should be 12190b57cec5SDimitry Andric // considered to be zero. 12200b57cec5SDimitry Andric if (getDOSHeader()) 12210b57cec5SDimitry Andric return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 12220b57cec5SDimitry Andric return Sec->SizeOfRawData; 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric 12250b57cec5SDimitry Andric Error COFFObjectFile::getSectionContents(const coff_section *Sec, 12260b57cec5SDimitry Andric ArrayRef<uint8_t> &Res) const { 12270b57cec5SDimitry Andric // In COFF, a virtual section won't have any in-file 12280b57cec5SDimitry Andric // content, so the file pointer to the content will be zero. 12290b57cec5SDimitry Andric if (Sec->PointerToRawData == 0) 12300b57cec5SDimitry Andric return Error::success(); 12310b57cec5SDimitry Andric // The only thing that we need to verify is that the contents is contained 12320b57cec5SDimitry Andric // within the file bounds. We don't need to make sure it doesn't cover other 12330b57cec5SDimitry Andric // data, as there's nothing that says that is not allowed. 1234e8d8bef9SDimitry Andric uintptr_t ConStart = 1235e8d8bef9SDimitry Andric reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData; 12360b57cec5SDimitry Andric uint32_t SectionSize = getSectionSize(Sec); 12375ffd83dbSDimitry Andric if (Error E = checkOffset(Data, ConStart, SectionSize)) 12385ffd83dbSDimitry Andric return E; 1239bdd1243dSDimitry Andric Res = ArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 12400b57cec5SDimitry Andric return Error::success(); 12410b57cec5SDimitry Andric } 12420b57cec5SDimitry Andric 12430b57cec5SDimitry Andric const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 12440b57cec5SDimitry Andric return reinterpret_cast<const coff_relocation*>(Rel.p); 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 12480b57cec5SDimitry Andric Rel.p = reinterpret_cast<uintptr_t>( 12490b57cec5SDimitry Andric reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric 12520b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 12530b57cec5SDimitry Andric const coff_relocation *R = toRel(Rel); 12540b57cec5SDimitry Andric return R->VirtualAddress; 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric 12570b57cec5SDimitry Andric symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 12580b57cec5SDimitry Andric const coff_relocation *R = toRel(Rel); 12590b57cec5SDimitry Andric DataRefImpl Ref; 12600b57cec5SDimitry Andric if (R->SymbolTableIndex >= getNumberOfSymbols()) 12610b57cec5SDimitry Andric return symbol_end(); 12620b57cec5SDimitry Andric if (SymbolTable16) 12630b57cec5SDimitry Andric Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 12640b57cec5SDimitry Andric else if (SymbolTable32) 12650b57cec5SDimitry Andric Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 12660b57cec5SDimitry Andric else 12670b57cec5SDimitry Andric llvm_unreachable("no symbol table pointer!"); 12680b57cec5SDimitry Andric return symbol_iterator(SymbolRef(Ref, this)); 12690b57cec5SDimitry Andric } 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 12720b57cec5SDimitry Andric const coff_relocation* R = toRel(Rel); 12730b57cec5SDimitry Andric return R->Type; 12740b57cec5SDimitry Andric } 12750b57cec5SDimitry Andric 12760b57cec5SDimitry Andric const coff_section * 12770b57cec5SDimitry Andric COFFObjectFile::getCOFFSection(const SectionRef &Section) const { 12780b57cec5SDimitry Andric return toSec(Section.getRawDataRefImpl()); 12790b57cec5SDimitry Andric } 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 12820b57cec5SDimitry Andric if (SymbolTable16) 12830b57cec5SDimitry Andric return toSymb<coff_symbol16>(Ref); 12840b57cec5SDimitry Andric if (SymbolTable32) 12850b57cec5SDimitry Andric return toSymb<coff_symbol32>(Ref); 12860b57cec5SDimitry Andric llvm_unreachable("no symbol table pointer!"); 12870b57cec5SDimitry Andric } 12880b57cec5SDimitry Andric 12890b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 12900b57cec5SDimitry Andric return getCOFFSymbol(Symbol.getRawDataRefImpl()); 12910b57cec5SDimitry Andric } 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andric const coff_relocation * 12940b57cec5SDimitry Andric COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 12950b57cec5SDimitry Andric return toRel(Reloc.getRawDataRefImpl()); 12960b57cec5SDimitry Andric } 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric ArrayRef<coff_relocation> 12990b57cec5SDimitry Andric COFFObjectFile::getRelocations(const coff_section *Sec) const { 13000b57cec5SDimitry Andric return {getFirstReloc(Sec, Data, base()), 13010b57cec5SDimitry Andric getNumberOfRelocations(Sec, Data, base())}; 13020b57cec5SDimitry Andric } 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 13050b57cec5SDimitry Andric case COFF::reloc_type: \ 13060b57cec5SDimitry Andric return #reloc_type; 13070b57cec5SDimitry Andric 13080b57cec5SDimitry Andric StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const { 1309*0fca6ea1SDimitry Andric switch (getArch()) { 1310*0fca6ea1SDimitry Andric case Triple::x86_64: 13110b57cec5SDimitry Andric switch (Type) { 13120b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 13130b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 13140b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 13150b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 13160b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 13170b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 13180b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 13190b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 13200b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 13210b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 13220b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 13230b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 13240b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 13250b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 13260b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 13270b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 13280b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 13290b57cec5SDimitry Andric default: 13300b57cec5SDimitry Andric return "Unknown"; 13310b57cec5SDimitry Andric } 13320b57cec5SDimitry Andric break; 1333*0fca6ea1SDimitry Andric case Triple::thumb: 13340b57cec5SDimitry Andric switch (Type) { 13350b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 13360b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 13370b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 13380b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 13390b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 13400b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 13410b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 13420b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 13430b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32); 13440b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 13450b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 13460b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 13470b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 13480b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 13490b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 13500b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 13510b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR); 13520b57cec5SDimitry Andric default: 13530b57cec5SDimitry Andric return "Unknown"; 13540b57cec5SDimitry Andric } 13550b57cec5SDimitry Andric break; 1356*0fca6ea1SDimitry Andric case Triple::aarch64: 13570b57cec5SDimitry Andric switch (Type) { 13580b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE); 13590b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32); 13600b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB); 13610b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26); 13620b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21); 13630b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21); 13640b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A); 13650b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L); 13660b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL); 13670b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A); 13680b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A); 13690b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L); 13700b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN); 13710b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION); 13720b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64); 13730b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19); 13740b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14); 13750b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32); 13760b57cec5SDimitry Andric default: 13770b57cec5SDimitry Andric return "Unknown"; 13780b57cec5SDimitry Andric } 13790b57cec5SDimitry Andric break; 1380*0fca6ea1SDimitry Andric case Triple::x86: 13810b57cec5SDimitry Andric switch (Type) { 13820b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 13830b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 13840b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 13850b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 13860b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 13870b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 13880b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 13890b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 13900b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 13910b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 13920b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 13930b57cec5SDimitry Andric default: 13940b57cec5SDimitry Andric return "Unknown"; 13950b57cec5SDimitry Andric } 13960b57cec5SDimitry Andric break; 13970b57cec5SDimitry Andric default: 13980b57cec5SDimitry Andric return "Unknown"; 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric void COFFObjectFile::getRelocationTypeName( 14050b57cec5SDimitry Andric DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 14060b57cec5SDimitry Andric const coff_relocation *Reloc = toRel(Rel); 14070b57cec5SDimitry Andric StringRef Res = getRelocationTypeName(Reloc->Type); 14080b57cec5SDimitry Andric Result.append(Res.begin(), Res.end()); 14090b57cec5SDimitry Andric } 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric bool COFFObjectFile::isRelocatableObject() const { 14120b57cec5SDimitry Andric return !DataDirectory; 14130b57cec5SDimitry Andric } 14140b57cec5SDimitry Andric 14150b57cec5SDimitry Andric StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const { 14160b57cec5SDimitry Andric return StringSwitch<StringRef>(Name) 14170b57cec5SDimitry Andric .Case("eh_fram", "eh_frame") 14180b57cec5SDimitry Andric .Default(Name); 14190b57cec5SDimitry Andric } 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric bool ImportDirectoryEntryRef:: 14220b57cec5SDimitry Andric operator==(const ImportDirectoryEntryRef &Other) const { 14230b57cec5SDimitry Andric return ImportTable == Other.ImportTable && Index == Other.Index; 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric void ImportDirectoryEntryRef::moveNext() { 14270b57cec5SDimitry Andric ++Index; 14280b57cec5SDimitry Andric if (ImportTable[Index].isNull()) { 14290b57cec5SDimitry Andric Index = -1; 14300b57cec5SDimitry Andric ImportTable = nullptr; 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric 14345ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportTableEntry( 14350b57cec5SDimitry Andric const coff_import_directory_table_entry *&Result) const { 14360b57cec5SDimitry Andric return getObject(Result, OwningObject->Data, ImportTable + Index); 14370b57cec5SDimitry Andric } 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric static imported_symbol_iterator 14400b57cec5SDimitry Andric makeImportedSymbolIterator(const COFFObjectFile *Object, 14410b57cec5SDimitry Andric uintptr_t Ptr, int Index) { 14420b57cec5SDimitry Andric if (Object->getBytesInAddress() == 4) { 14430b57cec5SDimitry Andric auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 14440b57cec5SDimitry Andric return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 14470b57cec5SDimitry Andric return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric static imported_symbol_iterator 14510b57cec5SDimitry Andric importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 14520b57cec5SDimitry Andric uintptr_t IntPtr = 0; 14535ffd83dbSDimitry Andric // FIXME: Handle errors. 14545ffd83dbSDimitry Andric cantFail(Object->getRvaPtr(RVA, IntPtr)); 14550b57cec5SDimitry Andric return makeImportedSymbolIterator(Object, IntPtr, 0); 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric static imported_symbol_iterator 14590b57cec5SDimitry Andric importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 14600b57cec5SDimitry Andric uintptr_t IntPtr = 0; 14615ffd83dbSDimitry Andric // FIXME: Handle errors. 14625ffd83dbSDimitry Andric cantFail(Object->getRvaPtr(RVA, IntPtr)); 14630b57cec5SDimitry Andric // Forward the pointer to the last entry which is null. 14640b57cec5SDimitry Andric int Index = 0; 14650b57cec5SDimitry Andric if (Object->getBytesInAddress() == 4) { 14660b57cec5SDimitry Andric auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 14670b57cec5SDimitry Andric while (*Entry++) 14680b57cec5SDimitry Andric ++Index; 14690b57cec5SDimitry Andric } else { 14700b57cec5SDimitry Andric auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 14710b57cec5SDimitry Andric while (*Entry++) 14720b57cec5SDimitry Andric ++Index; 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric return makeImportedSymbolIterator(Object, IntPtr, Index); 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric 14770b57cec5SDimitry Andric imported_symbol_iterator 14780b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_begin() const { 14790b57cec5SDimitry Andric return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA, 14800b57cec5SDimitry Andric OwningObject); 14810b57cec5SDimitry Andric } 14820b57cec5SDimitry Andric 14830b57cec5SDimitry Andric imported_symbol_iterator 14840b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_end() const { 14850b57cec5SDimitry Andric return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA, 14860b57cec5SDimitry Andric OwningObject); 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric iterator_range<imported_symbol_iterator> 14900b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbols() const { 14910b57cec5SDimitry Andric return make_range(imported_symbol_begin(), imported_symbol_end()); 14920b57cec5SDimitry Andric } 14930b57cec5SDimitry Andric 14940b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const { 14950b57cec5SDimitry Andric return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 14960b57cec5SDimitry Andric OwningObject); 14970b57cec5SDimitry Andric } 14980b57cec5SDimitry Andric 14990b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const { 15000b57cec5SDimitry Andric return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 15010b57cec5SDimitry Andric OwningObject); 15020b57cec5SDimitry Andric } 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric iterator_range<imported_symbol_iterator> 15050b57cec5SDimitry Andric ImportDirectoryEntryRef::lookup_table_symbols() const { 15060b57cec5SDimitry Andric return make_range(lookup_table_begin(), lookup_table_end()); 15070b57cec5SDimitry Andric } 15080b57cec5SDimitry Andric 15095ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getName(StringRef &Result) const { 15100b57cec5SDimitry Andric uintptr_t IntPtr = 0; 151181ad6265SDimitry Andric if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr, 151281ad6265SDimitry Andric "import directory name")) 15135ffd83dbSDimitry Andric return E; 15140b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15155ffd83dbSDimitry Andric return Error::success(); 15160b57cec5SDimitry Andric } 15170b57cec5SDimitry Andric 15185ffd83dbSDimitry Andric Error 15190b57cec5SDimitry Andric ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 15200b57cec5SDimitry Andric Result = ImportTable[Index].ImportLookupTableRVA; 15215ffd83dbSDimitry Andric return Error::success(); 15220b57cec5SDimitry Andric } 15230b57cec5SDimitry Andric 15245ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportAddressTableRVA( 15255ffd83dbSDimitry Andric uint32_t &Result) const { 15260b57cec5SDimitry Andric Result = ImportTable[Index].ImportAddressTableRVA; 15275ffd83dbSDimitry Andric return Error::success(); 15280b57cec5SDimitry Andric } 15290b57cec5SDimitry Andric 15300b57cec5SDimitry Andric bool DelayImportDirectoryEntryRef:: 15310b57cec5SDimitry Andric operator==(const DelayImportDirectoryEntryRef &Other) const { 15320b57cec5SDimitry Andric return Table == Other.Table && Index == Other.Index; 15330b57cec5SDimitry Andric } 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric void DelayImportDirectoryEntryRef::moveNext() { 15360b57cec5SDimitry Andric ++Index; 15370b57cec5SDimitry Andric } 15380b57cec5SDimitry Andric 15390b57cec5SDimitry Andric imported_symbol_iterator 15400b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_begin() const { 15410b57cec5SDimitry Andric return importedSymbolBegin(Table[Index].DelayImportNameTable, 15420b57cec5SDimitry Andric OwningObject); 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric imported_symbol_iterator 15460b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_end() const { 15470b57cec5SDimitry Andric return importedSymbolEnd(Table[Index].DelayImportNameTable, 15480b57cec5SDimitry Andric OwningObject); 15490b57cec5SDimitry Andric } 15500b57cec5SDimitry Andric 15510b57cec5SDimitry Andric iterator_range<imported_symbol_iterator> 15520b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbols() const { 15530b57cec5SDimitry Andric return make_range(imported_symbol_begin(), imported_symbol_end()); 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric 15565ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 15570b57cec5SDimitry Andric uintptr_t IntPtr = 0; 155881ad6265SDimitry Andric if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr, 155981ad6265SDimitry Andric "delay import directory name")) 15605ffd83dbSDimitry Andric return E; 15610b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 15625ffd83dbSDimitry Andric return Error::success(); 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric 15655ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getDelayImportTable( 15665ffd83dbSDimitry Andric const delay_import_directory_table_entry *&Result) const { 15670b57cec5SDimitry Andric Result = &Table[Index]; 15685ffd83dbSDimitry Andric return Error::success(); 15690b57cec5SDimitry Andric } 15700b57cec5SDimitry Andric 15715ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex, 15725ffd83dbSDimitry Andric uint64_t &Result) const { 15730b57cec5SDimitry Andric uint32_t RVA = Table[Index].DelayImportAddressTable + 15740b57cec5SDimitry Andric AddrIndex * (OwningObject->is64() ? 8 : 4); 15750b57cec5SDimitry Andric uintptr_t IntPtr = 0; 157681ad6265SDimitry Andric if (Error E = OwningObject->getRvaPtr(RVA, IntPtr, "import address")) 15775ffd83dbSDimitry Andric return E; 15780b57cec5SDimitry Andric if (OwningObject->is64()) 15790b57cec5SDimitry Andric Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 15800b57cec5SDimitry Andric else 15810b57cec5SDimitry Andric Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 15825ffd83dbSDimitry Andric return Error::success(); 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric bool ExportDirectoryEntryRef:: 15860b57cec5SDimitry Andric operator==(const ExportDirectoryEntryRef &Other) const { 15870b57cec5SDimitry Andric return ExportTable == Other.ExportTable && Index == Other.Index; 15880b57cec5SDimitry Andric } 15890b57cec5SDimitry Andric 15900b57cec5SDimitry Andric void ExportDirectoryEntryRef::moveNext() { 15910b57cec5SDimitry Andric ++Index; 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only 15950b57cec5SDimitry Andric // by ordinal, the empty string is set as a result. 15965ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 15970b57cec5SDimitry Andric uintptr_t IntPtr = 0; 159881ad6265SDimitry Andric if (Error E = 159981ad6265SDimitry Andric OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr, "dll name")) 16005ffd83dbSDimitry Andric return E; 16010b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 16025ffd83dbSDimitry Andric return Error::success(); 16030b57cec5SDimitry Andric } 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric // Returns the starting ordinal number. 16065ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 16070b57cec5SDimitry Andric Result = ExportTable->OrdinalBase; 16085ffd83dbSDimitry Andric return Error::success(); 16090b57cec5SDimitry Andric } 16100b57cec5SDimitry Andric 16110b57cec5SDimitry Andric // Returns the export ordinal of the current export symbol. 16125ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 16130b57cec5SDimitry Andric Result = ExportTable->OrdinalBase + Index; 16145ffd83dbSDimitry Andric return Error::success(); 16150b57cec5SDimitry Andric } 16160b57cec5SDimitry Andric 16170b57cec5SDimitry Andric // Returns the address of the current export symbol. 16185ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 16190b57cec5SDimitry Andric uintptr_t IntPtr = 0; 162081ad6265SDimitry Andric if (Error EC = OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, 162181ad6265SDimitry Andric IntPtr, "export address")) 16220b57cec5SDimitry Andric return EC; 16230b57cec5SDimitry Andric const export_address_table_entry *entry = 16240b57cec5SDimitry Andric reinterpret_cast<const export_address_table_entry *>(IntPtr); 16250b57cec5SDimitry Andric Result = entry[Index].ExportRVA; 16265ffd83dbSDimitry Andric return Error::success(); 16270b57cec5SDimitry Andric } 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only 16300b57cec5SDimitry Andric // by ordinal, the empty string is set as a result. 16315ffd83dbSDimitry Andric Error 16320b57cec5SDimitry Andric ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 16330b57cec5SDimitry Andric uintptr_t IntPtr = 0; 163481ad6265SDimitry Andric if (Error EC = OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr, 163581ad6265SDimitry Andric "export ordinal table")) 16360b57cec5SDimitry Andric return EC; 16370b57cec5SDimitry Andric const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric uint32_t NumEntries = ExportTable->NumberOfNamePointers; 16400b57cec5SDimitry Andric int Offset = 0; 16410b57cec5SDimitry Andric for (const ulittle16_t *I = Start, *E = Start + NumEntries; 16420b57cec5SDimitry Andric I < E; ++I, ++Offset) { 16430b57cec5SDimitry Andric if (*I != Index) 16440b57cec5SDimitry Andric continue; 164581ad6265SDimitry Andric if (Error EC = OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr, 164681ad6265SDimitry Andric "export table entry")) 16470b57cec5SDimitry Andric return EC; 16480b57cec5SDimitry Andric const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 164981ad6265SDimitry Andric if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr, 165081ad6265SDimitry Andric "export symbol name")) 16510b57cec5SDimitry Andric return EC; 16520b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 16535ffd83dbSDimitry Andric return Error::success(); 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric Result = ""; 16565ffd83dbSDimitry Andric return Error::success(); 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric 16595ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::isForwarder(bool &Result) const { 16605ffd83dbSDimitry Andric const data_directory *DataEntry = 16615ffd83dbSDimitry Andric OwningObject->getDataDirectory(COFF::EXPORT_TABLE); 16625ffd83dbSDimitry Andric if (!DataEntry) 166381ad6265SDimitry Andric return createStringError(object_error::parse_failed, 166481ad6265SDimitry Andric "export table missing"); 16650b57cec5SDimitry Andric uint32_t RVA; 16660b57cec5SDimitry Andric if (auto EC = getExportRVA(RVA)) 16670b57cec5SDimitry Andric return EC; 16680b57cec5SDimitry Andric uint32_t Begin = DataEntry->RelativeVirtualAddress; 16690b57cec5SDimitry Andric uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 16700b57cec5SDimitry Andric Result = (Begin <= RVA && RVA < End); 16715ffd83dbSDimitry Andric return Error::success(); 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric 16745ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 16750b57cec5SDimitry Andric uint32_t RVA; 16760b57cec5SDimitry Andric if (auto EC = getExportRVA(RVA)) 16770b57cec5SDimitry Andric return EC; 16780b57cec5SDimitry Andric uintptr_t IntPtr = 0; 167981ad6265SDimitry Andric if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr, "export forward target")) 16800b57cec5SDimitry Andric return EC; 16810b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 16825ffd83dbSDimitry Andric return Error::success(); 16830b57cec5SDimitry Andric } 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric bool ImportedSymbolRef:: 16860b57cec5SDimitry Andric operator==(const ImportedSymbolRef &Other) const { 16870b57cec5SDimitry Andric return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 16880b57cec5SDimitry Andric && Index == Other.Index; 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric void ImportedSymbolRef::moveNext() { 16920b57cec5SDimitry Andric ++Index; 16930b57cec5SDimitry Andric } 16940b57cec5SDimitry Andric 16955ffd83dbSDimitry Andric Error ImportedSymbolRef::getSymbolName(StringRef &Result) const { 16960b57cec5SDimitry Andric uint32_t RVA; 16970b57cec5SDimitry Andric if (Entry32) { 16980b57cec5SDimitry Andric // If a symbol is imported only by ordinal, it has no name. 16990b57cec5SDimitry Andric if (Entry32[Index].isOrdinal()) 17005ffd83dbSDimitry Andric return Error::success(); 17010b57cec5SDimitry Andric RVA = Entry32[Index].getHintNameRVA(); 17020b57cec5SDimitry Andric } else { 17030b57cec5SDimitry Andric if (Entry64[Index].isOrdinal()) 17045ffd83dbSDimitry Andric return Error::success(); 17050b57cec5SDimitry Andric RVA = Entry64[Index].getHintNameRVA(); 17060b57cec5SDimitry Andric } 17070b57cec5SDimitry Andric uintptr_t IntPtr = 0; 170881ad6265SDimitry Andric if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol name")) 17090b57cec5SDimitry Andric return EC; 17100b57cec5SDimitry Andric // +2 because the first two bytes is hint. 17110b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 17125ffd83dbSDimitry Andric return Error::success(); 17130b57cec5SDimitry Andric } 17140b57cec5SDimitry Andric 17155ffd83dbSDimitry Andric Error ImportedSymbolRef::isOrdinal(bool &Result) const { 17160b57cec5SDimitry Andric if (Entry32) 17170b57cec5SDimitry Andric Result = Entry32[Index].isOrdinal(); 17180b57cec5SDimitry Andric else 17190b57cec5SDimitry Andric Result = Entry64[Index].isOrdinal(); 17205ffd83dbSDimitry Andric return Error::success(); 17210b57cec5SDimitry Andric } 17220b57cec5SDimitry Andric 17235ffd83dbSDimitry Andric Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 17240b57cec5SDimitry Andric if (Entry32) 17250b57cec5SDimitry Andric Result = Entry32[Index].getHintNameRVA(); 17260b57cec5SDimitry Andric else 17270b57cec5SDimitry Andric Result = Entry64[Index].getHintNameRVA(); 17285ffd83dbSDimitry Andric return Error::success(); 17290b57cec5SDimitry Andric } 17300b57cec5SDimitry Andric 17315ffd83dbSDimitry Andric Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 17320b57cec5SDimitry Andric uint32_t RVA; 17330b57cec5SDimitry Andric if (Entry32) { 17340b57cec5SDimitry Andric if (Entry32[Index].isOrdinal()) { 17350b57cec5SDimitry Andric Result = Entry32[Index].getOrdinal(); 17365ffd83dbSDimitry Andric return Error::success(); 17370b57cec5SDimitry Andric } 17380b57cec5SDimitry Andric RVA = Entry32[Index].getHintNameRVA(); 17390b57cec5SDimitry Andric } else { 17400b57cec5SDimitry Andric if (Entry64[Index].isOrdinal()) { 17410b57cec5SDimitry Andric Result = Entry64[Index].getOrdinal(); 17425ffd83dbSDimitry Andric return Error::success(); 17430b57cec5SDimitry Andric } 17440b57cec5SDimitry Andric RVA = Entry64[Index].getHintNameRVA(); 17450b57cec5SDimitry Andric } 17460b57cec5SDimitry Andric uintptr_t IntPtr = 0; 174781ad6265SDimitry Andric if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr, "import symbol ordinal")) 17480b57cec5SDimitry Andric return EC; 17490b57cec5SDimitry Andric Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 17505ffd83dbSDimitry Andric return Error::success(); 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric Expected<std::unique_ptr<COFFObjectFile>> 17540b57cec5SDimitry Andric ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 17555ffd83dbSDimitry Andric return COFFObjectFile::create(Object); 17560b57cec5SDimitry Andric } 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 17590b57cec5SDimitry Andric return Header == Other.Header && Index == Other.Index; 17600b57cec5SDimitry Andric } 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric void BaseRelocRef::moveNext() { 17630b57cec5SDimitry Andric // Header->BlockSize is the size of the current block, including the 17640b57cec5SDimitry Andric // size of the header itself. 17650b57cec5SDimitry Andric uint32_t Size = sizeof(*Header) + 17660b57cec5SDimitry Andric sizeof(coff_base_reloc_block_entry) * (Index + 1); 17670b57cec5SDimitry Andric if (Size == Header->BlockSize) { 17680b57cec5SDimitry Andric // .reloc contains a list of base relocation blocks. Each block 17690b57cec5SDimitry Andric // consists of the header followed by entries. The header contains 17700b57cec5SDimitry Andric // how many entories will follow. When we reach the end of the 17710b57cec5SDimitry Andric // current block, proceed to the next block. 17720b57cec5SDimitry Andric Header = reinterpret_cast<const coff_base_reloc_block_header *>( 17730b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Header) + Size); 17740b57cec5SDimitry Andric Index = 0; 17750b57cec5SDimitry Andric } else { 17760b57cec5SDimitry Andric ++Index; 17770b57cec5SDimitry Andric } 17780b57cec5SDimitry Andric } 17790b57cec5SDimitry Andric 17805ffd83dbSDimitry Andric Error BaseRelocRef::getType(uint8_t &Type) const { 17810b57cec5SDimitry Andric auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 17820b57cec5SDimitry Andric Type = Entry[Index].getType(); 17835ffd83dbSDimitry Andric return Error::success(); 17840b57cec5SDimitry Andric } 17850b57cec5SDimitry Andric 17865ffd83dbSDimitry Andric Error BaseRelocRef::getRVA(uint32_t &Result) const { 17870b57cec5SDimitry Andric auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 17880b57cec5SDimitry Andric Result = Header->PageRVA + Entry[Index].getOffset(); 17895ffd83dbSDimitry Andric return Error::success(); 17900b57cec5SDimitry Andric } 17910b57cec5SDimitry Andric 17928bcb0991SDimitry Andric #define RETURN_IF_ERROR(Expr) \ 17938bcb0991SDimitry Andric do { \ 17948bcb0991SDimitry Andric Error E = (Expr); \ 17950b57cec5SDimitry Andric if (E) \ 17968bcb0991SDimitry Andric return std::move(E); \ 17978bcb0991SDimitry Andric } while (0) 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric Expected<ArrayRef<UTF16>> 18000b57cec5SDimitry Andric ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) { 18010b57cec5SDimitry Andric BinaryStreamReader Reader = BinaryStreamReader(BBS); 18020b57cec5SDimitry Andric Reader.setOffset(Offset); 18030b57cec5SDimitry Andric uint16_t Length; 18040b57cec5SDimitry Andric RETURN_IF_ERROR(Reader.readInteger(Length)); 18050b57cec5SDimitry Andric ArrayRef<UTF16> RawDirString; 18060b57cec5SDimitry Andric RETURN_IF_ERROR(Reader.readArray(RawDirString, Length)); 18070b57cec5SDimitry Andric return RawDirString; 18080b57cec5SDimitry Andric } 18090b57cec5SDimitry Andric 18100b57cec5SDimitry Andric Expected<ArrayRef<UTF16>> 18110b57cec5SDimitry Andric ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) { 18120b57cec5SDimitry Andric return getDirStringAtOffset(Entry.Identifier.getNameOffset()); 18130b57cec5SDimitry Andric } 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric Expected<const coff_resource_dir_table &> 18160b57cec5SDimitry Andric ResourceSectionRef::getTableAtOffset(uint32_t Offset) { 18170b57cec5SDimitry Andric const coff_resource_dir_table *Table = nullptr; 18180b57cec5SDimitry Andric 18190b57cec5SDimitry Andric BinaryStreamReader Reader(BBS); 18200b57cec5SDimitry Andric Reader.setOffset(Offset); 18210b57cec5SDimitry Andric RETURN_IF_ERROR(Reader.readObject(Table)); 18220b57cec5SDimitry Andric assert(Table != nullptr); 18230b57cec5SDimitry Andric return *Table; 18240b57cec5SDimitry Andric } 18250b57cec5SDimitry Andric 18268bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &> 18278bcb0991SDimitry Andric ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) { 18288bcb0991SDimitry Andric const coff_resource_dir_entry *Entry = nullptr; 18298bcb0991SDimitry Andric 18308bcb0991SDimitry Andric BinaryStreamReader Reader(BBS); 18318bcb0991SDimitry Andric Reader.setOffset(Offset); 18328bcb0991SDimitry Andric RETURN_IF_ERROR(Reader.readObject(Entry)); 18338bcb0991SDimitry Andric assert(Entry != nullptr); 18348bcb0991SDimitry Andric return *Entry; 18358bcb0991SDimitry Andric } 18368bcb0991SDimitry Andric 18378bcb0991SDimitry Andric Expected<const coff_resource_data_entry &> 18388bcb0991SDimitry Andric ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) { 18398bcb0991SDimitry Andric const coff_resource_data_entry *Entry = nullptr; 18408bcb0991SDimitry Andric 18418bcb0991SDimitry Andric BinaryStreamReader Reader(BBS); 18428bcb0991SDimitry Andric Reader.setOffset(Offset); 18438bcb0991SDimitry Andric RETURN_IF_ERROR(Reader.readObject(Entry)); 18448bcb0991SDimitry Andric assert(Entry != nullptr); 18458bcb0991SDimitry Andric return *Entry; 18468bcb0991SDimitry Andric } 18478bcb0991SDimitry Andric 18480b57cec5SDimitry Andric Expected<const coff_resource_dir_table &> 18490b57cec5SDimitry Andric ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) { 18508bcb0991SDimitry Andric assert(Entry.Offset.isSubDir()); 18510b57cec5SDimitry Andric return getTableAtOffset(Entry.Offset.value()); 18520b57cec5SDimitry Andric } 18530b57cec5SDimitry Andric 18548bcb0991SDimitry Andric Expected<const coff_resource_data_entry &> 18558bcb0991SDimitry Andric ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) { 18568bcb0991SDimitry Andric assert(!Entry.Offset.isSubDir()); 18578bcb0991SDimitry Andric return getDataEntryAtOffset(Entry.Offset.value()); 18588bcb0991SDimitry Andric } 18598bcb0991SDimitry Andric 18600b57cec5SDimitry Andric Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() { 18610b57cec5SDimitry Andric return getTableAtOffset(0); 18620b57cec5SDimitry Andric } 18638bcb0991SDimitry Andric 18648bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &> 18658bcb0991SDimitry Andric ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table, 18668bcb0991SDimitry Andric uint32_t Index) { 18678bcb0991SDimitry Andric if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries)) 18688bcb0991SDimitry Andric return createStringError(object_error::parse_failed, "index out of range"); 18698bcb0991SDimitry Andric const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table); 18708bcb0991SDimitry Andric ptrdiff_t TableOffset = TablePtr - BBS.data().data(); 18718bcb0991SDimitry Andric return getTableEntryAtOffset(TableOffset + sizeof(Table) + 18728bcb0991SDimitry Andric Index * sizeof(coff_resource_dir_entry)); 18738bcb0991SDimitry Andric } 18748bcb0991SDimitry Andric 18758bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O) { 18768bcb0991SDimitry Andric for (const SectionRef &S : O->sections()) { 18778bcb0991SDimitry Andric Expected<StringRef> Name = S.getName(); 18788bcb0991SDimitry Andric if (!Name) 18798bcb0991SDimitry Andric return Name.takeError(); 18808bcb0991SDimitry Andric 18818bcb0991SDimitry Andric if (*Name == ".rsrc" || *Name == ".rsrc$01") 18828bcb0991SDimitry Andric return load(O, S); 18838bcb0991SDimitry Andric } 18848bcb0991SDimitry Andric return createStringError(object_error::parse_failed, 18858bcb0991SDimitry Andric "no resource section found"); 18868bcb0991SDimitry Andric } 18878bcb0991SDimitry Andric 18888bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) { 18898bcb0991SDimitry Andric Obj = O; 18908bcb0991SDimitry Andric Section = S; 18918bcb0991SDimitry Andric Expected<StringRef> Contents = Section.getContents(); 18928bcb0991SDimitry Andric if (!Contents) 18938bcb0991SDimitry Andric return Contents.takeError(); 18945f757f3fSDimitry Andric BBS = BinaryByteStream(*Contents, llvm::endianness::little); 18958bcb0991SDimitry Andric const coff_section *COFFSect = Obj->getCOFFSection(Section); 18968bcb0991SDimitry Andric ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect); 18978bcb0991SDimitry Andric Relocs.reserve(OrigRelocs.size()); 18988bcb0991SDimitry Andric for (const coff_relocation &R : OrigRelocs) 18998bcb0991SDimitry Andric Relocs.push_back(&R); 1900e8d8bef9SDimitry Andric llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) { 19018bcb0991SDimitry Andric return A->VirtualAddress < B->VirtualAddress; 19028bcb0991SDimitry Andric }); 19038bcb0991SDimitry Andric return Error::success(); 19048bcb0991SDimitry Andric } 19058bcb0991SDimitry Andric 19068bcb0991SDimitry Andric Expected<StringRef> 19078bcb0991SDimitry Andric ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) { 19088bcb0991SDimitry Andric if (!Obj) 19098bcb0991SDimitry Andric return createStringError(object_error::parse_failed, "no object provided"); 19108bcb0991SDimitry Andric 19118bcb0991SDimitry Andric // Find a potential relocation at the DataRVA field (first member of 19128bcb0991SDimitry Andric // the coff_resource_data_entry struct). 19138bcb0991SDimitry Andric const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry); 19148bcb0991SDimitry Andric ptrdiff_t EntryOffset = EntryPtr - BBS.data().data(); 19158bcb0991SDimitry Andric coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0), 19168bcb0991SDimitry Andric ulittle16_t(0)}; 19178bcb0991SDimitry Andric auto RelocsForOffset = 19188bcb0991SDimitry Andric std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget, 19198bcb0991SDimitry Andric [](const coff_relocation *A, const coff_relocation *B) { 19208bcb0991SDimitry Andric return A->VirtualAddress < B->VirtualAddress; 19218bcb0991SDimitry Andric }); 19228bcb0991SDimitry Andric 19238bcb0991SDimitry Andric if (RelocsForOffset.first != RelocsForOffset.second) { 19248bcb0991SDimitry Andric // We found a relocation with the right offset. Check that it does have 19258bcb0991SDimitry Andric // the expected type. 19268bcb0991SDimitry Andric const coff_relocation &R = **RelocsForOffset.first; 19278bcb0991SDimitry Andric uint16_t RVAReloc; 1928*0fca6ea1SDimitry Andric switch (Obj->getArch()) { 1929*0fca6ea1SDimitry Andric case Triple::x86: 19308bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_I386_DIR32NB; 19318bcb0991SDimitry Andric break; 1932*0fca6ea1SDimitry Andric case Triple::x86_64: 19338bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB; 19348bcb0991SDimitry Andric break; 1935*0fca6ea1SDimitry Andric case Triple::thumb: 19368bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB; 19378bcb0991SDimitry Andric break; 1938*0fca6ea1SDimitry Andric case Triple::aarch64: 19398bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB; 19408bcb0991SDimitry Andric break; 19418bcb0991SDimitry Andric default: 19428bcb0991SDimitry Andric return createStringError(object_error::parse_failed, 19438bcb0991SDimitry Andric "unsupported architecture"); 19448bcb0991SDimitry Andric } 19458bcb0991SDimitry Andric if (R.Type != RVAReloc) 19468bcb0991SDimitry Andric return createStringError(object_error::parse_failed, 19478bcb0991SDimitry Andric "unexpected relocation type"); 19488bcb0991SDimitry Andric // Get the relocation's symbol 19498bcb0991SDimitry Andric Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex); 19508bcb0991SDimitry Andric if (!Sym) 19518bcb0991SDimitry Andric return Sym.takeError(); 19528bcb0991SDimitry Andric // And the symbol's section 19535ffd83dbSDimitry Andric Expected<const coff_section *> Section = 19545ffd83dbSDimitry Andric Obj->getSection(Sym->getSectionNumber()); 19555ffd83dbSDimitry Andric if (!Section) 19565ffd83dbSDimitry Andric return Section.takeError(); 19578bcb0991SDimitry Andric // Add the initial value of DataRVA to the symbol's offset to find the 19588bcb0991SDimitry Andric // data it points at. 19598bcb0991SDimitry Andric uint64_t Offset = Entry.DataRVA + Sym->getValue(); 19608bcb0991SDimitry Andric ArrayRef<uint8_t> Contents; 19615ffd83dbSDimitry Andric if (Error E = Obj->getSectionContents(*Section, Contents)) 1962*0fca6ea1SDimitry Andric return E; 19638bcb0991SDimitry Andric if (Offset + Entry.DataSize > Contents.size()) 19648bcb0991SDimitry Andric return createStringError(object_error::parse_failed, 19658bcb0991SDimitry Andric "data outside of section"); 19668bcb0991SDimitry Andric // Return a reference to the data inside the section. 19678bcb0991SDimitry Andric return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset, 19688bcb0991SDimitry Andric Entry.DataSize); 19698bcb0991SDimitry Andric } else { 19708bcb0991SDimitry Andric // Relocatable objects need a relocation for the DataRVA field. 19718bcb0991SDimitry Andric if (Obj->isRelocatableObject()) 19728bcb0991SDimitry Andric return createStringError(object_error::parse_failed, 19738bcb0991SDimitry Andric "no relocation found for DataRVA"); 19748bcb0991SDimitry Andric 19758bcb0991SDimitry Andric // Locate the section that contains the address that DataRVA points at. 19768bcb0991SDimitry Andric uint64_t VA = Entry.DataRVA + Obj->getImageBase(); 19778bcb0991SDimitry Andric for (const SectionRef &S : Obj->sections()) { 19788bcb0991SDimitry Andric if (VA >= S.getAddress() && 19798bcb0991SDimitry Andric VA + Entry.DataSize <= S.getAddress() + S.getSize()) { 19808bcb0991SDimitry Andric uint64_t Offset = VA - S.getAddress(); 19818bcb0991SDimitry Andric Expected<StringRef> Contents = S.getContents(); 19828bcb0991SDimitry Andric if (!Contents) 19838bcb0991SDimitry Andric return Contents.takeError(); 19848bcb0991SDimitry Andric return Contents->slice(Offset, Offset + Entry.DataSize); 19858bcb0991SDimitry Andric } 19868bcb0991SDimitry Andric } 19878bcb0991SDimitry Andric return createStringError(object_error::parse_failed, 19888bcb0991SDimitry Andric "address not found in image"); 19898bcb0991SDimitry Andric } 19908bcb0991SDimitry Andric } 1991