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/Triple.h"
170b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
180b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
190b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
200b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
210b57cec5SDimitry Andric #include "llvm/Object/Error.h"
220b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
230b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
240b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
250b57cec5SDimitry Andric #include "llvm/Support/Error.h"
260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
270b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
280b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
290b57cec5SDimitry Andric #include <algorithm>
300b57cec5SDimitry Andric #include <cassert>
31af732203SDimitry Andric #include <cinttypes>
320b57cec5SDimitry Andric #include <cstddef>
330b57cec5SDimitry Andric #include <cstring>
340b57cec5SDimitry Andric #include <limits>
350b57cec5SDimitry Andric #include <memory>
360b57cec5SDimitry Andric #include <system_error>
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric using namespace object;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric using support::ulittle16_t;
420b57cec5SDimitry Andric using support::ulittle32_t;
430b57cec5SDimitry Andric using support::ulittle64_t;
440b57cec5SDimitry Andric using support::little16_t;
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric // Returns false if size is greater than the buffer size. And sets ec.
checkSize(MemoryBufferRef M,std::error_code & EC,uint64_t Size)470b57cec5SDimitry Andric static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
480b57cec5SDimitry Andric if (M.getBufferSize() < Size) {
490b57cec5SDimitry Andric EC = object_error::unexpected_eof;
500b57cec5SDimitry Andric return false;
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric return true;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
560b57cec5SDimitry Andric // Returns unexpected_eof if error.
570b57cec5SDimitry Andric template <typename T>
getObject(const T * & Obj,MemoryBufferRef M,const void * Ptr,const uint64_t Size=sizeof (T))585ffd83dbSDimitry Andric static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr,
590b57cec5SDimitry Andric const uint64_t Size = sizeof(T)) {
60af732203SDimitry Andric uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr);
615ffd83dbSDimitry Andric if (Error E = Binary::checkOffset(M, Addr, Size))
625ffd83dbSDimitry Andric return E;
630b57cec5SDimitry Andric Obj = reinterpret_cast<const T *>(Addr);
645ffd83dbSDimitry Andric return Error::success();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
680b57cec5SDimitry Andric // prefixed slashes.
decodeBase64StringEntry(StringRef Str,uint32_t & Result)690b57cec5SDimitry Andric static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
700b57cec5SDimitry Andric assert(Str.size() <= 6 && "String too long, possible overflow.");
710b57cec5SDimitry Andric if (Str.size() > 6)
720b57cec5SDimitry Andric return true;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric uint64_t Value = 0;
750b57cec5SDimitry Andric while (!Str.empty()) {
760b57cec5SDimitry Andric unsigned CharVal;
770b57cec5SDimitry Andric if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
780b57cec5SDimitry Andric CharVal = Str[0] - 'A';
790b57cec5SDimitry Andric else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
800b57cec5SDimitry Andric CharVal = Str[0] - 'a' + 26;
810b57cec5SDimitry Andric else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
820b57cec5SDimitry Andric CharVal = Str[0] - '0' + 52;
830b57cec5SDimitry Andric else if (Str[0] == '+') // 62
840b57cec5SDimitry Andric CharVal = 62;
850b57cec5SDimitry Andric else if (Str[0] == '/') // 63
860b57cec5SDimitry Andric CharVal = 63;
870b57cec5SDimitry Andric else
880b57cec5SDimitry Andric return true;
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric Value = (Value * 64) + CharVal;
910b57cec5SDimitry Andric Str = Str.substr(1);
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric if (Value > std::numeric_limits<uint32_t>::max())
950b57cec5SDimitry Andric return true;
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric Result = static_cast<uint32_t>(Value);
980b57cec5SDimitry Andric return false;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric template <typename coff_symbol_type>
toSymb(DataRefImpl Ref) const1020b57cec5SDimitry Andric const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const {
1030b57cec5SDimitry Andric const coff_symbol_type *Addr =
1040b57cec5SDimitry Andric reinterpret_cast<const coff_symbol_type *>(Ref.p);
1050b57cec5SDimitry Andric
106af732203SDimitry Andric assert(!checkOffset(Data, reinterpret_cast<uintptr_t>(Addr), sizeof(*Addr)));
1070b57cec5SDimitry Andric #ifndef NDEBUG
1080b57cec5SDimitry Andric // Verify that the symbol points to a valid entry in the symbol table.
109af732203SDimitry Andric uintptr_t Offset =
110af732203SDimitry Andric reinterpret_cast<uintptr_t>(Addr) - reinterpret_cast<uintptr_t>(base());
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 &&
1130b57cec5SDimitry Andric "Symbol did not point to the beginning of a symbol");
1140b57cec5SDimitry Andric #endif
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric return Addr;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric
toSec(DataRefImpl Ref) const1190b57cec5SDimitry Andric const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
1200b57cec5SDimitry Andric const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric #ifndef NDEBUG
1230b57cec5SDimitry Andric // Verify that the section points to a valid entry in the section table.
1240b57cec5SDimitry Andric if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections()))
1250b57cec5SDimitry Andric report_fatal_error("Section was outside of section table.");
1260b57cec5SDimitry Andric
127af732203SDimitry Andric uintptr_t Offset = reinterpret_cast<uintptr_t>(Addr) -
128af732203SDimitry Andric reinterpret_cast<uintptr_t>(SectionTable);
1290b57cec5SDimitry Andric assert(Offset % sizeof(coff_section) == 0 &&
1300b57cec5SDimitry Andric "Section did not point to the beginning of a section");
1310b57cec5SDimitry Andric #endif
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric return Addr;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
moveSymbolNext(DataRefImpl & Ref) const1360b57cec5SDimitry Andric void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
1370b57cec5SDimitry Andric auto End = reinterpret_cast<uintptr_t>(StringTable);
1380b57cec5SDimitry Andric if (SymbolTable16) {
1390b57cec5SDimitry Andric const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref);
1400b57cec5SDimitry Andric Symb += 1 + Symb->NumberOfAuxSymbols;
1410b57cec5SDimitry Andric Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
1420b57cec5SDimitry Andric } else if (SymbolTable32) {
1430b57cec5SDimitry Andric const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref);
1440b57cec5SDimitry Andric Symb += 1 + Symb->NumberOfAuxSymbols;
1450b57cec5SDimitry Andric Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End);
1460b57cec5SDimitry Andric } else {
1470b57cec5SDimitry Andric llvm_unreachable("no symbol table pointer!");
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
getSymbolName(DataRefImpl Ref) const1510b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const {
1525ffd83dbSDimitry Andric return getSymbolName(getCOFFSymbol(Ref));
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
getSymbolValueImpl(DataRefImpl Ref) const1550b57cec5SDimitry Andric uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const {
1560b57cec5SDimitry Andric return getCOFFSymbol(Ref).getValue();
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
getSymbolAlignment(DataRefImpl Ref) const1590b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolAlignment(DataRefImpl Ref) const {
1600b57cec5SDimitry Andric // MSVC/link.exe seems to align symbols to the next-power-of-2
1610b57cec5SDimitry Andric // up to 32 bytes.
1620b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref);
1630b57cec5SDimitry Andric return std::min(uint64_t(32), PowerOf2Ceil(Symb.getValue()));
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
getSymbolAddress(DataRefImpl Ref) const1660b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const {
1675ffd83dbSDimitry Andric uint64_t Result = cantFail(getSymbolValue(Ref));
1680b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref);
1690b57cec5SDimitry Andric int32_t SectionNumber = Symb.getSectionNumber();
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric if (Symb.isAnyUndefined() || Symb.isCommon() ||
1720b57cec5SDimitry Andric COFF::isReservedSectionNumber(SectionNumber))
1730b57cec5SDimitry Andric return Result;
1740b57cec5SDimitry Andric
1755ffd83dbSDimitry Andric Expected<const coff_section *> Section = getSection(SectionNumber);
1765ffd83dbSDimitry Andric if (!Section)
1775ffd83dbSDimitry Andric return Section.takeError();
1785ffd83dbSDimitry Andric Result += (*Section)->VirtualAddress;
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric // The section VirtualAddress does not include ImageBase, and we want to
1810b57cec5SDimitry Andric // return virtual addresses.
1820b57cec5SDimitry Andric Result += getImageBase();
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric return Result;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
getSymbolType(DataRefImpl Ref) const1870b57cec5SDimitry Andric Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const {
1880b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref);
1890b57cec5SDimitry Andric int32_t SectionNumber = Symb.getSectionNumber();
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
1920b57cec5SDimitry Andric return SymbolRef::ST_Function;
1930b57cec5SDimitry Andric if (Symb.isAnyUndefined())
1940b57cec5SDimitry Andric return SymbolRef::ST_Unknown;
1950b57cec5SDimitry Andric if (Symb.isCommon())
1960b57cec5SDimitry Andric return SymbolRef::ST_Data;
1970b57cec5SDimitry Andric if (Symb.isFileRecord())
1980b57cec5SDimitry Andric return SymbolRef::ST_File;
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric // TODO: perhaps we need a new symbol type ST_Section.
2010b57cec5SDimitry Andric if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition())
2020b57cec5SDimitry Andric return SymbolRef::ST_Debug;
2030b57cec5SDimitry Andric
2040b57cec5SDimitry Andric if (!COFF::isReservedSectionNumber(SectionNumber))
2050b57cec5SDimitry Andric return SymbolRef::ST_Data;
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric return SymbolRef::ST_Other;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric
getSymbolFlags(DataRefImpl Ref) const2105ffd83dbSDimitry Andric Expected<uint32_t> COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
2110b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref);
2120b57cec5SDimitry Andric uint32_t Result = SymbolRef::SF_None;
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric if (Symb.isExternal() || Symb.isWeakExternal())
2150b57cec5SDimitry Andric Result |= SymbolRef::SF_Global;
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric if (const coff_aux_weak_external *AWE = Symb.getWeakExternal()) {
2180b57cec5SDimitry Andric Result |= SymbolRef::SF_Weak;
2190b57cec5SDimitry Andric if (AWE->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
2200b57cec5SDimitry Andric Result |= SymbolRef::SF_Undefined;
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
2240b57cec5SDimitry Andric Result |= SymbolRef::SF_Absolute;
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric if (Symb.isFileRecord())
2270b57cec5SDimitry Andric Result |= SymbolRef::SF_FormatSpecific;
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric if (Symb.isSectionDefinition())
2300b57cec5SDimitry Andric Result |= SymbolRef::SF_FormatSpecific;
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric if (Symb.isCommon())
2330b57cec5SDimitry Andric Result |= SymbolRef::SF_Common;
2340b57cec5SDimitry Andric
2350b57cec5SDimitry Andric if (Symb.isUndefined())
2360b57cec5SDimitry Andric Result |= SymbolRef::SF_Undefined;
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric return Result;
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric
getCommonSymbolSizeImpl(DataRefImpl Ref) const2410b57cec5SDimitry Andric uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const {
2420b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref);
2430b57cec5SDimitry Andric return Symb.getValue();
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Ref) const2470b57cec5SDimitry Andric COFFObjectFile::getSymbolSection(DataRefImpl Ref) const {
2480b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Ref);
2490b57cec5SDimitry Andric if (COFF::isReservedSectionNumber(Symb.getSectionNumber()))
2500b57cec5SDimitry Andric return section_end();
2515ffd83dbSDimitry Andric Expected<const coff_section *> Sec = getSection(Symb.getSectionNumber());
2525ffd83dbSDimitry Andric if (!Sec)
2535ffd83dbSDimitry Andric return Sec.takeError();
2540b57cec5SDimitry Andric DataRefImpl Ret;
2555ffd83dbSDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(*Sec);
2560b57cec5SDimitry Andric return section_iterator(SectionRef(Ret, this));
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric
getSymbolSectionID(SymbolRef Sym) const2590b57cec5SDimitry Andric unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const {
2600b57cec5SDimitry Andric COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl());
2610b57cec5SDimitry Andric return Symb.getSectionNumber();
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric
moveSectionNext(DataRefImpl & Ref) const2640b57cec5SDimitry Andric void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
2650b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
2660b57cec5SDimitry Andric Sec += 1;
2670b57cec5SDimitry Andric Ref.p = reinterpret_cast<uintptr_t>(Sec);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric
getSectionName(DataRefImpl Ref) const2700b57cec5SDimitry Andric Expected<StringRef> COFFObjectFile::getSectionName(DataRefImpl Ref) const {
2710b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
2720b57cec5SDimitry Andric return getSectionName(Sec);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
getSectionAddress(DataRefImpl Ref) const2750b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const {
2760b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
2770b57cec5SDimitry Andric uint64_t Result = Sec->VirtualAddress;
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andric // The section VirtualAddress does not include ImageBase, and we want to
2800b57cec5SDimitry Andric // return virtual addresses.
2810b57cec5SDimitry Andric Result += getImageBase();
2820b57cec5SDimitry Andric return Result;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric
getSectionIndex(DataRefImpl Sec) const2850b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
2860b57cec5SDimitry Andric return toSec(Sec) - SectionTable;
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric
getSectionSize(DataRefImpl Ref) const2890b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const {
2900b57cec5SDimitry Andric return getSectionSize(toSec(Ref));
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
2930b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Ref) const2940b57cec5SDimitry Andric COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
2950b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
2960b57cec5SDimitry Andric ArrayRef<uint8_t> Res;
2970b57cec5SDimitry Andric if (Error E = getSectionContents(Sec, Res))
2980b57cec5SDimitry Andric return std::move(E);
2990b57cec5SDimitry Andric return Res;
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric
getSectionAlignment(DataRefImpl Ref) const3020b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
3030b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
3040b57cec5SDimitry Andric return Sec->getAlignment();
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
isSectionCompressed(DataRefImpl Sec) const3070b57cec5SDimitry Andric bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
3080b57cec5SDimitry Andric return false;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric
isSectionText(DataRefImpl Ref) const3110b57cec5SDimitry Andric bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
3120b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
3130b57cec5SDimitry Andric return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric
isSectionData(DataRefImpl Ref) const3160b57cec5SDimitry Andric bool COFFObjectFile::isSectionData(DataRefImpl Ref) const {
3170b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
3180b57cec5SDimitry Andric return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric
isSectionBSS(DataRefImpl Ref) const3210b57cec5SDimitry Andric bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const {
3220b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
3230b57cec5SDimitry Andric const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
3240b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_READ |
3250b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_WRITE;
3260b57cec5SDimitry Andric return (Sec->Characteristics & BssFlags) == BssFlags;
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric
3295ffd83dbSDimitry Andric // The .debug sections are the only debug sections for COFF
3305ffd83dbSDimitry Andric // (\see MCObjectFileInfo.cpp).
isDebugSection(DataRefImpl Ref) const331*5f7ddb14SDimitry Andric bool COFFObjectFile::isDebugSection(DataRefImpl Ref) const {
332*5f7ddb14SDimitry Andric Expected<StringRef> SectionNameOrErr = getSectionName(Ref);
333*5f7ddb14SDimitry Andric if (!SectionNameOrErr) {
334*5f7ddb14SDimitry Andric // TODO: Report the error message properly.
335*5f7ddb14SDimitry Andric consumeError(SectionNameOrErr.takeError());
336*5f7ddb14SDimitry Andric return false;
337*5f7ddb14SDimitry Andric }
338*5f7ddb14SDimitry Andric StringRef SectionName = SectionNameOrErr.get();
3395ffd83dbSDimitry Andric return SectionName.startswith(".debug");
3405ffd83dbSDimitry Andric }
3415ffd83dbSDimitry Andric
getSectionID(SectionRef Sec) const3420b57cec5SDimitry Andric unsigned COFFObjectFile::getSectionID(SectionRef Sec) const {
3430b57cec5SDimitry Andric uintptr_t Offset =
344af732203SDimitry Andric Sec.getRawDataRefImpl().p - reinterpret_cast<uintptr_t>(SectionTable);
3450b57cec5SDimitry Andric assert((Offset % sizeof(coff_section)) == 0);
3460b57cec5SDimitry Andric return (Offset / sizeof(coff_section)) + 1;
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric
isSectionVirtual(DataRefImpl Ref) const3490b57cec5SDimitry Andric bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const {
3500b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
3510b57cec5SDimitry Andric // In COFF, a virtual section won't have any in-file
3520b57cec5SDimitry Andric // content, so the file pointer to the content will be zero.
3530b57cec5SDimitry Andric return Sec->PointerToRawData == 0;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
getNumberOfRelocations(const coff_section * Sec,MemoryBufferRef M,const uint8_t * base)3560b57cec5SDimitry Andric static uint32_t getNumberOfRelocations(const coff_section *Sec,
3570b57cec5SDimitry Andric MemoryBufferRef M, const uint8_t *base) {
3580b57cec5SDimitry Andric // The field for the number of relocations in COFF section table is only
3590b57cec5SDimitry Andric // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
3600b57cec5SDimitry Andric // NumberOfRelocations field, and the actual relocation count is stored in the
3610b57cec5SDimitry Andric // VirtualAddress field in the first relocation entry.
3620b57cec5SDimitry Andric if (Sec->hasExtendedRelocations()) {
3630b57cec5SDimitry Andric const coff_relocation *FirstReloc;
3645ffd83dbSDimitry Andric if (Error E = getObject(FirstReloc, M,
3655ffd83dbSDimitry Andric reinterpret_cast<const coff_relocation *>(
3665ffd83dbSDimitry Andric base + Sec->PointerToRelocations))) {
3675ffd83dbSDimitry Andric consumeError(std::move(E));
3680b57cec5SDimitry Andric return 0;
3695ffd83dbSDimitry Andric }
3700b57cec5SDimitry Andric // -1 to exclude this first relocation entry.
3710b57cec5SDimitry Andric return FirstReloc->VirtualAddress - 1;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric return Sec->NumberOfRelocations;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric static const coff_relocation *
getFirstReloc(const coff_section * Sec,MemoryBufferRef M,const uint8_t * Base)3770b57cec5SDimitry Andric getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
3780b57cec5SDimitry Andric uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base);
3790b57cec5SDimitry Andric if (!NumRelocs)
3800b57cec5SDimitry Andric return nullptr;
3810b57cec5SDimitry Andric auto begin = reinterpret_cast<const coff_relocation *>(
3820b57cec5SDimitry Andric Base + Sec->PointerToRelocations);
3830b57cec5SDimitry Andric if (Sec->hasExtendedRelocations()) {
3840b57cec5SDimitry Andric // Skip the first relocation entry repurposed to store the number of
3850b57cec5SDimitry Andric // relocations.
3860b57cec5SDimitry Andric begin++;
3870b57cec5SDimitry Andric }
388af732203SDimitry Andric if (auto E = Binary::checkOffset(M, reinterpret_cast<uintptr_t>(begin),
3895ffd83dbSDimitry Andric sizeof(coff_relocation) * NumRelocs)) {
3905ffd83dbSDimitry Andric consumeError(std::move(E));
3910b57cec5SDimitry Andric return nullptr;
3925ffd83dbSDimitry Andric }
3930b57cec5SDimitry Andric return begin;
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric
section_rel_begin(DataRefImpl Ref) const3960b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
3970b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
3980b57cec5SDimitry Andric const coff_relocation *begin = getFirstReloc(Sec, Data, base());
3990b57cec5SDimitry Andric if (begin && Sec->VirtualAddress != 0)
4000b57cec5SDimitry Andric report_fatal_error("Sections with relocations should have an address of 0");
4010b57cec5SDimitry Andric DataRefImpl Ret;
4020b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(begin);
4030b57cec5SDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric
section_rel_end(DataRefImpl Ref) const4060b57cec5SDimitry Andric relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
4070b57cec5SDimitry Andric const coff_section *Sec = toSec(Ref);
4080b57cec5SDimitry Andric const coff_relocation *I = getFirstReloc(Sec, Data, base());
4090b57cec5SDimitry Andric if (I)
4100b57cec5SDimitry Andric I += getNumberOfRelocations(Sec, Data, base());
4110b57cec5SDimitry Andric DataRefImpl Ret;
4120b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(I);
4130b57cec5SDimitry Andric return relocation_iterator(RelocationRef(Ret, this));
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric // Initialize the pointer to the symbol table.
initSymbolTablePtr()4175ffd83dbSDimitry Andric Error COFFObjectFile::initSymbolTablePtr() {
4180b57cec5SDimitry Andric if (COFFHeader)
4195ffd83dbSDimitry Andric if (Error E = getObject(
4200b57cec5SDimitry Andric SymbolTable16, Data, base() + getPointerToSymbolTable(),
4210b57cec5SDimitry Andric (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4225ffd83dbSDimitry Andric return E;
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric if (COFFBigObjHeader)
4255ffd83dbSDimitry Andric if (Error E = getObject(
4260b57cec5SDimitry Andric SymbolTable32, Data, base() + getPointerToSymbolTable(),
4270b57cec5SDimitry Andric (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize()))
4285ffd83dbSDimitry Andric return E;
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric // Find string table. The first four byte of the string table contains the
4310b57cec5SDimitry Andric // total size of the string table, including the size field itself. If the
4320b57cec5SDimitry Andric // string table is empty, the value of the first four byte would be 4.
4330b57cec5SDimitry Andric uint32_t StringTableOffset = getPointerToSymbolTable() +
4340b57cec5SDimitry Andric getNumberOfSymbols() * getSymbolTableEntrySize();
4350b57cec5SDimitry Andric const uint8_t *StringTableAddr = base() + StringTableOffset;
4360b57cec5SDimitry Andric const ulittle32_t *StringTableSizePtr;
4375ffd83dbSDimitry Andric if (Error E = getObject(StringTableSizePtr, Data, StringTableAddr))
4385ffd83dbSDimitry Andric return E;
4390b57cec5SDimitry Andric StringTableSize = *StringTableSizePtr;
4405ffd83dbSDimitry Andric if (Error E = getObject(StringTable, Data, StringTableAddr, StringTableSize))
4415ffd83dbSDimitry Andric return E;
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
4440b57cec5SDimitry Andric // tools like cvtres write a size of 0 for an empty table instead of 4.
4450b57cec5SDimitry Andric if (StringTableSize < 4)
4460b57cec5SDimitry Andric StringTableSize = 4;
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric // Check that the string table is null terminated if has any in it.
4490b57cec5SDimitry Andric if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
4505ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
4515ffd83dbSDimitry Andric return Error::success();
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric
getImageBase() const4540b57cec5SDimitry 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.
getVaPtr(uint64_t Addr,uintptr_t & Res) const4645ffd83dbSDimitry 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.
getRvaPtr(uint32_t Addr,uintptr_t & Res) const4725ffd83dbSDimitry Andric Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
4730b57cec5SDimitry Andric for (const SectionRef &S : sections()) {
4740b57cec5SDimitry Andric const coff_section *Section = getCOFFSection(S);
4750b57cec5SDimitry Andric uint32_t SectionStart = Section->VirtualAddress;
4760b57cec5SDimitry Andric uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
4770b57cec5SDimitry Andric if (SectionStart <= Addr && Addr < SectionEnd) {
4780b57cec5SDimitry Andric uint32_t Offset = Addr - SectionStart;
479af732203SDimitry Andric Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
480af732203SDimitry Andric Offset;
4815ffd83dbSDimitry Andric return Error::success();
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric }
4845ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
getRvaAndSizeAsBytes(uint32_t RVA,uint32_t Size,ArrayRef<uint8_t> & Contents) const4875ffd83dbSDimitry Andric Error COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
4880b57cec5SDimitry Andric ArrayRef<uint8_t> &Contents) const {
4890b57cec5SDimitry Andric for (const SectionRef &S : sections()) {
4900b57cec5SDimitry Andric const coff_section *Section = getCOFFSection(S);
4910b57cec5SDimitry Andric uint32_t SectionStart = Section->VirtualAddress;
4920b57cec5SDimitry Andric // Check if this RVA is within the section bounds. Be careful about integer
4930b57cec5SDimitry Andric // overflow.
4940b57cec5SDimitry Andric uint32_t OffsetIntoSection = RVA - SectionStart;
4950b57cec5SDimitry Andric if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize &&
4960b57cec5SDimitry Andric Size <= Section->VirtualSize - OffsetIntoSection) {
497af732203SDimitry Andric uintptr_t Begin = reinterpret_cast<uintptr_t>(base()) +
498af732203SDimitry Andric Section->PointerToRawData + OffsetIntoSection;
4990b57cec5SDimitry Andric Contents =
5000b57cec5SDimitry Andric ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size);
5015ffd83dbSDimitry Andric return Error::success();
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric }
5045ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric
5070b57cec5SDimitry Andric // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
5080b57cec5SDimitry Andric // table entry.
getHintName(uint32_t Rva,uint16_t & Hint,StringRef & Name) const5095ffd83dbSDimitry Andric Error COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
5100b57cec5SDimitry Andric StringRef &Name) const {
5110b57cec5SDimitry Andric uintptr_t IntPtr = 0;
5125ffd83dbSDimitry Andric if (Error E = getRvaPtr(Rva, IntPtr))
5135ffd83dbSDimitry Andric return E;
5140b57cec5SDimitry Andric const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
5150b57cec5SDimitry Andric Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
5160b57cec5SDimitry Andric Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
5175ffd83dbSDimitry Andric return Error::success();
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric
getDebugPDBInfo(const debug_directory * DebugDir,const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const5205ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
5210b57cec5SDimitry Andric const codeview::DebugInfo *&PDBInfo,
5220b57cec5SDimitry Andric StringRef &PDBFileName) const {
5230b57cec5SDimitry Andric ArrayRef<uint8_t> InfoBytes;
5245ffd83dbSDimitry Andric if (Error E = getRvaAndSizeAsBytes(
5250b57cec5SDimitry Andric DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
5265ffd83dbSDimitry Andric return E;
5270b57cec5SDimitry Andric if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
5285ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
5290b57cec5SDimitry Andric PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
5300b57cec5SDimitry Andric InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
5310b57cec5SDimitry Andric PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
5320b57cec5SDimitry Andric InfoBytes.size());
5330b57cec5SDimitry Andric // Truncate the name at the first null byte. Ignore any padding.
5340b57cec5SDimitry Andric PDBFileName = PDBFileName.split('\0').first;
5355ffd83dbSDimitry Andric return Error::success();
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric
getDebugPDBInfo(const codeview::DebugInfo * & PDBInfo,StringRef & PDBFileName) const5385ffd83dbSDimitry Andric Error COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
5390b57cec5SDimitry Andric StringRef &PDBFileName) const {
5400b57cec5SDimitry Andric for (const debug_directory &D : debug_directories())
5410b57cec5SDimitry Andric if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
5420b57cec5SDimitry Andric return getDebugPDBInfo(&D, PDBInfo, PDBFileName);
5430b57cec5SDimitry Andric // If we get here, there is no PDB info to return.
5440b57cec5SDimitry Andric PDBInfo = nullptr;
5450b57cec5SDimitry Andric PDBFileName = StringRef();
5465ffd83dbSDimitry Andric return Error::success();
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric // Find the import table.
initImportTablePtr()5505ffd83dbSDimitry Andric Error COFFObjectFile::initImportTablePtr() {
5510b57cec5SDimitry Andric // First, we get the RVA of the import table. If the file lacks a pointer to
5520b57cec5SDimitry Andric // the import table, do nothing.
5535ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::IMPORT_TABLE);
5545ffd83dbSDimitry Andric if (!DataEntry)
5555ffd83dbSDimitry Andric return Error::success();
5560b57cec5SDimitry Andric
5570b57cec5SDimitry Andric // Do nothing if the pointer to import table is NULL.
5580b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
5595ffd83dbSDimitry Andric return Error::success();
5600b57cec5SDimitry Andric
5610b57cec5SDimitry Andric uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric // Find the section that contains the RVA. This is needed because the RVA is
5640b57cec5SDimitry Andric // the import table's memory address which is different from its file offset.
5650b57cec5SDimitry Andric uintptr_t IntPtr = 0;
5665ffd83dbSDimitry Andric if (Error E = getRvaPtr(ImportTableRva, IntPtr))
5675ffd83dbSDimitry Andric return E;
5685ffd83dbSDimitry Andric if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
5695ffd83dbSDimitry Andric return E;
5700b57cec5SDimitry Andric ImportDirectory = reinterpret_cast<
5710b57cec5SDimitry Andric const coff_import_directory_table_entry *>(IntPtr);
5725ffd83dbSDimitry Andric return Error::success();
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric
5750b57cec5SDimitry Andric // Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
initDelayImportTablePtr()5765ffd83dbSDimitry Andric Error COFFObjectFile::initDelayImportTablePtr() {
5775ffd83dbSDimitry Andric const data_directory *DataEntry =
5785ffd83dbSDimitry Andric getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR);
5795ffd83dbSDimitry Andric if (!DataEntry)
5805ffd83dbSDimitry Andric return Error::success();
5810b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
5825ffd83dbSDimitry Andric return Error::success();
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric uint32_t RVA = DataEntry->RelativeVirtualAddress;
5850b57cec5SDimitry Andric NumberOfDelayImportDirectory = DataEntry->Size /
5860b57cec5SDimitry Andric sizeof(delay_import_directory_table_entry) - 1;
5870b57cec5SDimitry Andric
5880b57cec5SDimitry Andric uintptr_t IntPtr = 0;
5895ffd83dbSDimitry Andric if (Error E = getRvaPtr(RVA, IntPtr))
5905ffd83dbSDimitry Andric return E;
5910b57cec5SDimitry Andric DelayImportDirectory = reinterpret_cast<
5920b57cec5SDimitry Andric const delay_import_directory_table_entry *>(IntPtr);
5935ffd83dbSDimitry Andric return Error::success();
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric // Find the export table.
initExportTablePtr()5975ffd83dbSDimitry Andric Error COFFObjectFile::initExportTablePtr() {
5980b57cec5SDimitry Andric // First, we get the RVA of the export table. If the file lacks a pointer to
5990b57cec5SDimitry Andric // the export table, do nothing.
6005ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::EXPORT_TABLE);
6015ffd83dbSDimitry Andric if (!DataEntry)
6025ffd83dbSDimitry Andric return Error::success();
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andric // Do nothing if the pointer to export table is NULL.
6050b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
6065ffd83dbSDimitry Andric return Error::success();
6070b57cec5SDimitry Andric
6080b57cec5SDimitry Andric uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
6090b57cec5SDimitry Andric uintptr_t IntPtr = 0;
6105ffd83dbSDimitry Andric if (Error E = getRvaPtr(ExportTableRva, IntPtr))
6115ffd83dbSDimitry Andric return E;
6120b57cec5SDimitry Andric ExportDirectory =
6130b57cec5SDimitry Andric reinterpret_cast<const export_directory_table_entry *>(IntPtr);
6145ffd83dbSDimitry Andric return Error::success();
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric
initBaseRelocPtr()6175ffd83dbSDimitry Andric Error COFFObjectFile::initBaseRelocPtr() {
6185ffd83dbSDimitry Andric const data_directory *DataEntry =
6195ffd83dbSDimitry Andric getDataDirectory(COFF::BASE_RELOCATION_TABLE);
6205ffd83dbSDimitry Andric if (!DataEntry)
6215ffd83dbSDimitry Andric return Error::success();
6220b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
6235ffd83dbSDimitry Andric return Error::success();
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andric uintptr_t IntPtr = 0;
6265ffd83dbSDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6275ffd83dbSDimitry Andric return E;
6280b57cec5SDimitry Andric BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
6290b57cec5SDimitry Andric IntPtr);
6300b57cec5SDimitry Andric BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
6310b57cec5SDimitry Andric IntPtr + DataEntry->Size);
6320b57cec5SDimitry Andric // FIXME: Verify the section containing BaseRelocHeader has at least
6330b57cec5SDimitry Andric // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6345ffd83dbSDimitry Andric return Error::success();
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric
initDebugDirectoryPtr()6375ffd83dbSDimitry Andric Error COFFObjectFile::initDebugDirectoryPtr() {
6380b57cec5SDimitry Andric // Get the RVA of the debug directory. Do nothing if it does not exist.
6395ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::DEBUG_DIRECTORY);
6405ffd83dbSDimitry Andric if (!DataEntry)
6415ffd83dbSDimitry Andric return Error::success();
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andric // Do nothing if the RVA is NULL.
6440b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
6455ffd83dbSDimitry Andric return Error::success();
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric // Check that the size is a multiple of the entry size.
6480b57cec5SDimitry Andric if (DataEntry->Size % sizeof(debug_directory) != 0)
6495ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric uintptr_t IntPtr = 0;
6525ffd83dbSDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
6535ffd83dbSDimitry Andric return E;
6540b57cec5SDimitry Andric DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
6550b57cec5SDimitry Andric DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
6560b57cec5SDimitry Andric IntPtr + DataEntry->Size);
6570b57cec5SDimitry Andric // FIXME: Verify the section containing DebugDirectoryBegin has at least
6580b57cec5SDimitry Andric // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
6595ffd83dbSDimitry Andric return Error::success();
6600b57cec5SDimitry Andric }
6610b57cec5SDimitry Andric
initTLSDirectoryPtr()662af732203SDimitry Andric Error COFFObjectFile::initTLSDirectoryPtr() {
663af732203SDimitry Andric // Get the RVA of the TLS directory. Do nothing if it does not exist.
664af732203SDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
665af732203SDimitry Andric if (!DataEntry)
666af732203SDimitry Andric return Error::success();
667af732203SDimitry Andric
668af732203SDimitry Andric // Do nothing if the RVA is NULL.
669af732203SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
670af732203SDimitry Andric return Error::success();
671af732203SDimitry Andric
672af732203SDimitry Andric uint64_t DirSize =
673af732203SDimitry Andric is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
674af732203SDimitry Andric
675af732203SDimitry Andric // Check that the size is correct.
676af732203SDimitry Andric if (DataEntry->Size != DirSize)
677af732203SDimitry Andric return createStringError(
678af732203SDimitry Andric object_error::parse_failed,
679af732203SDimitry Andric "TLS Directory size (%u) is not the expected size (%" PRIu64 ").",
680af732203SDimitry Andric static_cast<uint32_t>(DataEntry->Size), DirSize);
681af732203SDimitry Andric
682af732203SDimitry Andric uintptr_t IntPtr = 0;
683af732203SDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
684af732203SDimitry Andric return E;
685af732203SDimitry Andric
686af732203SDimitry Andric if (is64())
687af732203SDimitry Andric TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
688af732203SDimitry Andric else
689af732203SDimitry Andric TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
690af732203SDimitry Andric
691af732203SDimitry Andric return Error::success();
692af732203SDimitry Andric }
693af732203SDimitry Andric
initLoadConfigPtr()6945ffd83dbSDimitry Andric Error COFFObjectFile::initLoadConfigPtr() {
6950b57cec5SDimitry Andric // Get the RVA of the debug directory. Do nothing if it does not exist.
6965ffd83dbSDimitry Andric const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
6975ffd83dbSDimitry Andric if (!DataEntry)
6985ffd83dbSDimitry Andric return Error::success();
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric // Do nothing if the RVA is NULL.
7010b57cec5SDimitry Andric if (DataEntry->RelativeVirtualAddress == 0)
7025ffd83dbSDimitry Andric return Error::success();
7030b57cec5SDimitry Andric uintptr_t IntPtr = 0;
7045ffd83dbSDimitry Andric if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
7055ffd83dbSDimitry Andric return E;
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric LoadConfig = (const void *)IntPtr;
7085ffd83dbSDimitry Andric return Error::success();
7090b57cec5SDimitry Andric }
7100b57cec5SDimitry Andric
7115ffd83dbSDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
create(MemoryBufferRef Object)7125ffd83dbSDimitry Andric COFFObjectFile::create(MemoryBufferRef Object) {
7135ffd83dbSDimitry Andric std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
7145ffd83dbSDimitry Andric if (Error E = Obj->initialize())
7155ffd83dbSDimitry Andric return std::move(E);
7165ffd83dbSDimitry Andric return std::move(Obj);
7175ffd83dbSDimitry Andric }
7185ffd83dbSDimitry Andric
COFFObjectFile(MemoryBufferRef Object)7195ffd83dbSDimitry Andric COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
7200b57cec5SDimitry Andric : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
7210b57cec5SDimitry Andric COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
7220b57cec5SDimitry Andric DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
7230b57cec5SDimitry Andric SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
7245ffd83dbSDimitry Andric ImportDirectory(nullptr), DelayImportDirectory(nullptr),
7255ffd83dbSDimitry Andric NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
7265ffd83dbSDimitry Andric BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
727af732203SDimitry Andric DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
728af732203SDimitry Andric TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
7295ffd83dbSDimitry Andric
initialize()7305ffd83dbSDimitry Andric Error COFFObjectFile::initialize() {
7310b57cec5SDimitry Andric // Check that we at least have enough room for a header.
7325ffd83dbSDimitry Andric std::error_code EC;
7330b57cec5SDimitry Andric if (!checkSize(Data, EC, sizeof(coff_file_header)))
7345ffd83dbSDimitry Andric return errorCodeToError(EC);
7350b57cec5SDimitry Andric
7360b57cec5SDimitry Andric // The current location in the file where we are looking at.
7370b57cec5SDimitry Andric uint64_t CurPtr = 0;
7380b57cec5SDimitry Andric
7390b57cec5SDimitry Andric // PE header is optional and is present only in executables. If it exists,
7400b57cec5SDimitry Andric // it is placed right after COFF header.
7410b57cec5SDimitry Andric bool HasPEHeader = false;
7420b57cec5SDimitry Andric
7430b57cec5SDimitry Andric // Check if this is a PE/COFF file.
7440b57cec5SDimitry Andric if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) {
7450b57cec5SDimitry Andric // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
7460b57cec5SDimitry Andric // PE signature to find 'normal' COFF header.
7470b57cec5SDimitry Andric const auto *DH = reinterpret_cast<const dos_header *>(base());
7480b57cec5SDimitry Andric if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
7490b57cec5SDimitry Andric CurPtr = DH->AddressOfNewExeHeader;
7500b57cec5SDimitry Andric // Check the PE magic bytes. ("PE\0\0")
7510b57cec5SDimitry Andric if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) {
7525ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes.
7550b57cec5SDimitry Andric HasPEHeader = true;
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric
7595ffd83dbSDimitry Andric if (Error E = getObject(COFFHeader, Data, base() + CurPtr))
7605ffd83dbSDimitry Andric return E;
7610b57cec5SDimitry Andric
7620b57cec5SDimitry Andric // It might be a bigobj file, let's check. Note that COFF bigobj and COFF
7630b57cec5SDimitry Andric // import libraries share a common prefix but bigobj is more restrictive.
7640b57cec5SDimitry Andric if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
7650b57cec5SDimitry Andric COFFHeader->NumberOfSections == uint16_t(0xffff) &&
7660b57cec5SDimitry Andric checkSize(Data, EC, sizeof(coff_bigobj_file_header))) {
7675ffd83dbSDimitry Andric if (Error E = getObject(COFFBigObjHeader, Data, base() + CurPtr))
7685ffd83dbSDimitry Andric return E;
7690b57cec5SDimitry Andric
7700b57cec5SDimitry Andric // Verify that we are dealing with bigobj.
7710b57cec5SDimitry Andric if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
7720b57cec5SDimitry Andric std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
7730b57cec5SDimitry Andric sizeof(COFF::BigObjMagic)) == 0) {
7740b57cec5SDimitry Andric COFFHeader = nullptr;
7750b57cec5SDimitry Andric CurPtr += sizeof(coff_bigobj_file_header);
7760b57cec5SDimitry Andric } else {
7770b57cec5SDimitry Andric // It's not a bigobj.
7780b57cec5SDimitry Andric COFFBigObjHeader = nullptr;
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric if (COFFHeader) {
7820b57cec5SDimitry Andric // The prior checkSize call may have failed. This isn't a hard error
7830b57cec5SDimitry Andric // because we were just trying to sniff out bigobj.
7840b57cec5SDimitry Andric EC = std::error_code();
7850b57cec5SDimitry Andric CurPtr += sizeof(coff_file_header);
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric if (COFFHeader->isImportLibrary())
7885ffd83dbSDimitry Andric return errorCodeToError(EC);
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric
7910b57cec5SDimitry Andric if (HasPEHeader) {
7920b57cec5SDimitry Andric const pe32_header *Header;
7935ffd83dbSDimitry Andric if (Error E = getObject(Header, Data, base() + CurPtr))
7945ffd83dbSDimitry Andric return E;
7950b57cec5SDimitry Andric
7960b57cec5SDimitry Andric const uint8_t *DataDirAddr;
7970b57cec5SDimitry Andric uint64_t DataDirSize;
7980b57cec5SDimitry Andric if (Header->Magic == COFF::PE32Header::PE32) {
7990b57cec5SDimitry Andric PE32Header = Header;
8000b57cec5SDimitry Andric DataDirAddr = base() + CurPtr + sizeof(pe32_header);
8010b57cec5SDimitry Andric DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
8020b57cec5SDimitry Andric } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) {
8030b57cec5SDimitry Andric PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
8040b57cec5SDimitry Andric DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
8050b57cec5SDimitry Andric DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
8060b57cec5SDimitry Andric } else {
8070b57cec5SDimitry Andric // It's neither PE32 nor PE32+.
8085ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
8090b57cec5SDimitry Andric }
8105ffd83dbSDimitry Andric if (Error E = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))
8115ffd83dbSDimitry Andric return E;
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric
8140b57cec5SDimitry Andric if (COFFHeader)
8150b57cec5SDimitry Andric CurPtr += COFFHeader->SizeOfOptionalHeader;
8160b57cec5SDimitry Andric
8175ffd83dbSDimitry Andric assert(COFFHeader || COFFBigObjHeader);
8185ffd83dbSDimitry Andric
8195ffd83dbSDimitry Andric if (Error E =
8205ffd83dbSDimitry Andric getObject(SectionTable, Data, base() + CurPtr,
8215ffd83dbSDimitry Andric (uint64_t)getNumberOfSections() * sizeof(coff_section)))
8225ffd83dbSDimitry Andric return E;
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric // Initialize the pointer to the symbol table.
8250b57cec5SDimitry Andric if (getPointerToSymbolTable() != 0) {
8265ffd83dbSDimitry Andric if (Error E = initSymbolTablePtr()) {
8275ffd83dbSDimitry Andric // Recover from errors reading the symbol table.
8285ffd83dbSDimitry Andric consumeError(std::move(E));
8290b57cec5SDimitry Andric SymbolTable16 = nullptr;
8300b57cec5SDimitry Andric SymbolTable32 = nullptr;
8310b57cec5SDimitry Andric StringTable = nullptr;
8320b57cec5SDimitry Andric StringTableSize = 0;
8330b57cec5SDimitry Andric }
8340b57cec5SDimitry Andric } else {
8350b57cec5SDimitry Andric // We had better not have any symbols if we don't have a symbol table.
8360b57cec5SDimitry Andric if (getNumberOfSymbols() != 0) {
8375ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric
8410b57cec5SDimitry Andric // Initialize the pointer to the beginning of the import table.
8425ffd83dbSDimitry Andric if (Error E = initImportTablePtr())
8435ffd83dbSDimitry Andric return E;
8445ffd83dbSDimitry Andric if (Error E = initDelayImportTablePtr())
8455ffd83dbSDimitry Andric return E;
8460b57cec5SDimitry Andric
8470b57cec5SDimitry Andric // Initialize the pointer to the export table.
8485ffd83dbSDimitry Andric if (Error E = initExportTablePtr())
8495ffd83dbSDimitry Andric return E;
8500b57cec5SDimitry Andric
8510b57cec5SDimitry Andric // Initialize the pointer to the base relocation table.
8525ffd83dbSDimitry Andric if (Error E = initBaseRelocPtr())
8535ffd83dbSDimitry Andric return E;
8540b57cec5SDimitry Andric
855af732203SDimitry Andric // Initialize the pointer to the debug directory.
8565ffd83dbSDimitry Andric if (Error E = initDebugDirectoryPtr())
8575ffd83dbSDimitry Andric return E;
8580b57cec5SDimitry Andric
859af732203SDimitry Andric // Initialize the pointer to the TLS directory.
860af732203SDimitry Andric if (Error E = initTLSDirectoryPtr())
861af732203SDimitry Andric return E;
862af732203SDimitry Andric
8635ffd83dbSDimitry Andric if (Error E = initLoadConfigPtr())
8645ffd83dbSDimitry Andric return E;
8650b57cec5SDimitry Andric
8665ffd83dbSDimitry Andric return Error::success();
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric
symbol_begin() const8690b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_begin() const {
8700b57cec5SDimitry Andric DataRefImpl Ret;
8710b57cec5SDimitry Andric Ret.p = getSymbolTable();
8720b57cec5SDimitry Andric return basic_symbol_iterator(SymbolRef(Ret, this));
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric
symbol_end() const8750b57cec5SDimitry Andric basic_symbol_iterator COFFObjectFile::symbol_end() const {
8760b57cec5SDimitry Andric // The symbol table ends where the string table begins.
8770b57cec5SDimitry Andric DataRefImpl Ret;
8780b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(StringTable);
8790b57cec5SDimitry Andric return basic_symbol_iterator(SymbolRef(Ret, this));
8800b57cec5SDimitry Andric }
8810b57cec5SDimitry Andric
import_directory_begin() const8820b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_begin() const {
8830b57cec5SDimitry Andric if (!ImportDirectory)
8840b57cec5SDimitry Andric return import_directory_end();
8850b57cec5SDimitry Andric if (ImportDirectory->isNull())
8860b57cec5SDimitry Andric return import_directory_end();
8870b57cec5SDimitry Andric return import_directory_iterator(
8880b57cec5SDimitry Andric ImportDirectoryEntryRef(ImportDirectory, 0, this));
8890b57cec5SDimitry Andric }
8900b57cec5SDimitry Andric
import_directory_end() const8910b57cec5SDimitry Andric import_directory_iterator COFFObjectFile::import_directory_end() const {
8920b57cec5SDimitry Andric return import_directory_iterator(
8930b57cec5SDimitry Andric ImportDirectoryEntryRef(nullptr, -1, this));
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric
8960b57cec5SDimitry Andric delay_import_directory_iterator
delay_import_directory_begin() const8970b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_begin() const {
8980b57cec5SDimitry Andric return delay_import_directory_iterator(
8990b57cec5SDimitry Andric DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
9000b57cec5SDimitry Andric }
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric delay_import_directory_iterator
delay_import_directory_end() const9030b57cec5SDimitry Andric COFFObjectFile::delay_import_directory_end() const {
9040b57cec5SDimitry Andric return delay_import_directory_iterator(
9050b57cec5SDimitry Andric DelayImportDirectoryEntryRef(
9060b57cec5SDimitry Andric DelayImportDirectory, NumberOfDelayImportDirectory, this));
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
export_directory_begin() const9090b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_begin() const {
9100b57cec5SDimitry Andric return export_directory_iterator(
9110b57cec5SDimitry Andric ExportDirectoryEntryRef(ExportDirectory, 0, this));
9120b57cec5SDimitry Andric }
9130b57cec5SDimitry Andric
export_directory_end() const9140b57cec5SDimitry Andric export_directory_iterator COFFObjectFile::export_directory_end() const {
9150b57cec5SDimitry Andric if (!ExportDirectory)
9160b57cec5SDimitry Andric return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
9170b57cec5SDimitry Andric ExportDirectoryEntryRef Ref(ExportDirectory,
9180b57cec5SDimitry Andric ExportDirectory->AddressTableEntries, this);
9190b57cec5SDimitry Andric return export_directory_iterator(Ref);
9200b57cec5SDimitry Andric }
9210b57cec5SDimitry Andric
section_begin() const9220b57cec5SDimitry Andric section_iterator COFFObjectFile::section_begin() const {
9230b57cec5SDimitry Andric DataRefImpl Ret;
9240b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
9250b57cec5SDimitry Andric return section_iterator(SectionRef(Ret, this));
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric
section_end() const9280b57cec5SDimitry Andric section_iterator COFFObjectFile::section_end() const {
9290b57cec5SDimitry Andric DataRefImpl Ret;
9300b57cec5SDimitry Andric int NumSections =
9310b57cec5SDimitry Andric COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections();
9320b57cec5SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
9330b57cec5SDimitry Andric return section_iterator(SectionRef(Ret, this));
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric
base_reloc_begin() const9360b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
9370b57cec5SDimitry Andric return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
9380b57cec5SDimitry Andric }
9390b57cec5SDimitry Andric
base_reloc_end() const9400b57cec5SDimitry Andric base_reloc_iterator COFFObjectFile::base_reloc_end() const {
9410b57cec5SDimitry Andric return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric
getBytesInAddress() const9440b57cec5SDimitry Andric uint8_t COFFObjectFile::getBytesInAddress() const {
9450b57cec5SDimitry Andric return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric
getFileFormatName() const9480b57cec5SDimitry Andric StringRef COFFObjectFile::getFileFormatName() const {
9490b57cec5SDimitry Andric switch(getMachine()) {
9500b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386:
9510b57cec5SDimitry Andric return "COFF-i386";
9520b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64:
9530b57cec5SDimitry Andric return "COFF-x86-64";
9540b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT:
9550b57cec5SDimitry Andric return "COFF-ARM";
9560b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64:
9570b57cec5SDimitry Andric return "COFF-ARM64";
9580b57cec5SDimitry Andric default:
9590b57cec5SDimitry Andric return "COFF-<unknown arch>";
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric
getArch() const9630b57cec5SDimitry Andric Triple::ArchType COFFObjectFile::getArch() const {
9640b57cec5SDimitry Andric switch (getMachine()) {
9650b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386:
9660b57cec5SDimitry Andric return Triple::x86;
9670b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64:
9680b57cec5SDimitry Andric return Triple::x86_64;
9690b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT:
9700b57cec5SDimitry Andric return Triple::thumb;
9710b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64:
9720b57cec5SDimitry Andric return Triple::aarch64;
9730b57cec5SDimitry Andric default:
9740b57cec5SDimitry Andric return Triple::UnknownArch;
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric
getStartAddress() const9780b57cec5SDimitry Andric Expected<uint64_t> COFFObjectFile::getStartAddress() const {
9790b57cec5SDimitry Andric if (PE32Header)
9800b57cec5SDimitry Andric return PE32Header->AddressOfEntryPoint;
9810b57cec5SDimitry Andric return 0;
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric
9840b57cec5SDimitry Andric iterator_range<import_directory_iterator>
import_directories() const9850b57cec5SDimitry Andric COFFObjectFile::import_directories() const {
9860b57cec5SDimitry Andric return make_range(import_directory_begin(), import_directory_end());
9870b57cec5SDimitry Andric }
9880b57cec5SDimitry Andric
9890b57cec5SDimitry Andric iterator_range<delay_import_directory_iterator>
delay_import_directories() const9900b57cec5SDimitry Andric COFFObjectFile::delay_import_directories() const {
9910b57cec5SDimitry Andric return make_range(delay_import_directory_begin(),
9920b57cec5SDimitry Andric delay_import_directory_end());
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric
9950b57cec5SDimitry Andric iterator_range<export_directory_iterator>
export_directories() const9960b57cec5SDimitry Andric COFFObjectFile::export_directories() const {
9970b57cec5SDimitry Andric return make_range(export_directory_begin(), export_directory_end());
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric
base_relocs() const10000b57cec5SDimitry Andric iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
10010b57cec5SDimitry Andric return make_range(base_reloc_begin(), base_reloc_end());
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric
getDataDirectory(uint32_t Index) const10045ffd83dbSDimitry Andric const data_directory *COFFObjectFile::getDataDirectory(uint32_t Index) const {
10055ffd83dbSDimitry Andric if (!DataDirectory)
10065ffd83dbSDimitry Andric return nullptr;
10070b57cec5SDimitry Andric assert(PE32Header || PE32PlusHeader);
10080b57cec5SDimitry Andric uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
10090b57cec5SDimitry Andric : PE32PlusHeader->NumberOfRvaAndSize;
10105ffd83dbSDimitry Andric if (Index >= NumEnt)
10115ffd83dbSDimitry Andric return nullptr;
10125ffd83dbSDimitry Andric return &DataDirectory[Index];
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric
getSection(int32_t Index) const10155ffd83dbSDimitry Andric Expected<const coff_section *> COFFObjectFile::getSection(int32_t Index) const {
10165ffd83dbSDimitry Andric // Perhaps getting the section of a reserved section index should be an error,
10175ffd83dbSDimitry Andric // but callers rely on this to return null.
10180b57cec5SDimitry Andric if (COFF::isReservedSectionNumber(Index))
10195ffd83dbSDimitry Andric return (const coff_section *)nullptr;
10200b57cec5SDimitry Andric if (static_cast<uint32_t>(Index) <= getNumberOfSections()) {
10210b57cec5SDimitry Andric // We already verified the section table data, so no need to check again.
10225ffd83dbSDimitry Andric return SectionTable + (Index - 1);
10230b57cec5SDimitry Andric }
10245ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric
getString(uint32_t Offset) const10275ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getString(uint32_t Offset) const {
10280b57cec5SDimitry Andric if (StringTableSize <= 4)
10290b57cec5SDimitry Andric // Tried to get a string from an empty string table.
10305ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
10310b57cec5SDimitry Andric if (Offset >= StringTableSize)
10325ffd83dbSDimitry Andric return errorCodeToError(object_error::unexpected_eof);
10335ffd83dbSDimitry Andric return StringRef(StringTable + Offset);
10340b57cec5SDimitry Andric }
10350b57cec5SDimitry Andric
getSymbolName(COFFSymbolRef Symbol) const10365ffd83dbSDimitry Andric Expected<StringRef> COFFObjectFile::getSymbolName(COFFSymbolRef Symbol) const {
10375ffd83dbSDimitry Andric return getSymbolName(Symbol.getGeneric());
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric
10405ffd83dbSDimitry Andric Expected<StringRef>
getSymbolName(const coff_symbol_generic * Symbol) const10415ffd83dbSDimitry Andric COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol) const {
10420b57cec5SDimitry Andric // Check for string table entry. First 4 bytes are 0.
10435ffd83dbSDimitry Andric if (Symbol->Name.Offset.Zeroes == 0)
10445ffd83dbSDimitry Andric return getString(Symbol->Name.Offset.Offset);
10450b57cec5SDimitry Andric
10460b57cec5SDimitry Andric // Null terminated, let ::strlen figure out the length.
10475ffd83dbSDimitry Andric if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0)
10485ffd83dbSDimitry Andric return StringRef(Symbol->Name.ShortName);
10495ffd83dbSDimitry Andric
10500b57cec5SDimitry Andric // Not null terminated, use all 8 bytes.
10515ffd83dbSDimitry Andric return StringRef(Symbol->Name.ShortName, COFF::NameSize);
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric
10540b57cec5SDimitry Andric ArrayRef<uint8_t>
getSymbolAuxData(COFFSymbolRef Symbol) const10550b57cec5SDimitry Andric COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
10560b57cec5SDimitry Andric const uint8_t *Aux = nullptr;
10570b57cec5SDimitry Andric
10580b57cec5SDimitry Andric size_t SymbolSize = getSymbolTableEntrySize();
10590b57cec5SDimitry Andric if (Symbol.getNumberOfAuxSymbols() > 0) {
10600b57cec5SDimitry Andric // AUX data comes immediately after the symbol in COFF
10610b57cec5SDimitry Andric Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize;
10620b57cec5SDimitry Andric #ifndef NDEBUG
10630b57cec5SDimitry Andric // Verify that the Aux symbol points to a valid entry in the symbol table.
10640b57cec5SDimitry Andric uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
10650b57cec5SDimitry Andric if (Offset < getPointerToSymbolTable() ||
10660b57cec5SDimitry Andric Offset >=
10670b57cec5SDimitry Andric getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize))
10680b57cec5SDimitry Andric report_fatal_error("Aux Symbol data was outside of symbol table.");
10690b57cec5SDimitry Andric
10700b57cec5SDimitry Andric assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 &&
10710b57cec5SDimitry Andric "Aux Symbol data did not point to the beginning of a symbol");
10720b57cec5SDimitry Andric #endif
10730b57cec5SDimitry Andric }
10740b57cec5SDimitry Andric return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric
getSymbolIndex(COFFSymbolRef Symbol) const10770b57cec5SDimitry Andric uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
10780b57cec5SDimitry Andric uintptr_t Offset =
10790b57cec5SDimitry Andric reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
10800b57cec5SDimitry Andric assert(Offset % getSymbolTableEntrySize() == 0 &&
10810b57cec5SDimitry Andric "Symbol did not point to the beginning of a symbol");
10820b57cec5SDimitry Andric size_t Index = Offset / getSymbolTableEntrySize();
10830b57cec5SDimitry Andric assert(Index < getNumberOfSymbols());
10840b57cec5SDimitry Andric return Index;
10850b57cec5SDimitry Andric }
10860b57cec5SDimitry Andric
10870b57cec5SDimitry Andric Expected<StringRef>
getSectionName(const coff_section * Sec) const10880b57cec5SDimitry Andric COFFObjectFile::getSectionName(const coff_section *Sec) const {
10890b57cec5SDimitry Andric StringRef Name;
10900b57cec5SDimitry Andric if (Sec->Name[COFF::NameSize - 1] == 0)
10910b57cec5SDimitry Andric // Null terminated, let ::strlen figure out the length.
10920b57cec5SDimitry Andric Name = Sec->Name;
10930b57cec5SDimitry Andric else
10940b57cec5SDimitry Andric // Not null terminated, use all 8 bytes.
10950b57cec5SDimitry Andric Name = StringRef(Sec->Name, COFF::NameSize);
10960b57cec5SDimitry Andric
10970b57cec5SDimitry Andric // Check for string table entry. First byte is '/'.
10980b57cec5SDimitry Andric if (Name.startswith("/")) {
10990b57cec5SDimitry Andric uint32_t Offset;
11000b57cec5SDimitry Andric if (Name.startswith("//")) {
11010b57cec5SDimitry Andric if (decodeBase64StringEntry(Name.substr(2), Offset))
11020b57cec5SDimitry Andric return createStringError(object_error::parse_failed,
11035ffd83dbSDimitry Andric "invalid section name");
11040b57cec5SDimitry Andric } else {
11050b57cec5SDimitry Andric if (Name.substr(1).getAsInteger(10, Offset))
11060b57cec5SDimitry Andric return createStringError(object_error::parse_failed,
11070b57cec5SDimitry Andric "invalid section name");
11080b57cec5SDimitry Andric }
11095ffd83dbSDimitry Andric return getString(Offset);
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric
11120b57cec5SDimitry Andric return Name;
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric
getSectionSize(const coff_section * Sec) const11150b57cec5SDimitry Andric uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const {
11160b57cec5SDimitry Andric // SizeOfRawData and VirtualSize change what they represent depending on
11170b57cec5SDimitry Andric // whether or not we have an executable image.
11180b57cec5SDimitry Andric //
11190b57cec5SDimitry Andric // For object files, SizeOfRawData contains the size of section's data;
11200b57cec5SDimitry Andric // VirtualSize should be zero but isn't due to buggy COFF writers.
11210b57cec5SDimitry Andric //
11220b57cec5SDimitry Andric // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the
11230b57cec5SDimitry Andric // actual section size is in VirtualSize. It is possible for VirtualSize to
11240b57cec5SDimitry Andric // be greater than SizeOfRawData; the contents past that point should be
11250b57cec5SDimitry Andric // considered to be zero.
11260b57cec5SDimitry Andric if (getDOSHeader())
11270b57cec5SDimitry Andric return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
11280b57cec5SDimitry Andric return Sec->SizeOfRawData;
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric
getSectionContents(const coff_section * Sec,ArrayRef<uint8_t> & Res) const11310b57cec5SDimitry Andric Error COFFObjectFile::getSectionContents(const coff_section *Sec,
11320b57cec5SDimitry Andric ArrayRef<uint8_t> &Res) const {
11330b57cec5SDimitry Andric // In COFF, a virtual section won't have any in-file
11340b57cec5SDimitry Andric // content, so the file pointer to the content will be zero.
11350b57cec5SDimitry Andric if (Sec->PointerToRawData == 0)
11360b57cec5SDimitry Andric return Error::success();
11370b57cec5SDimitry Andric // The only thing that we need to verify is that the contents is contained
11380b57cec5SDimitry Andric // within the file bounds. We don't need to make sure it doesn't cover other
11390b57cec5SDimitry Andric // data, as there's nothing that says that is not allowed.
1140af732203SDimitry Andric uintptr_t ConStart =
1141af732203SDimitry Andric reinterpret_cast<uintptr_t>(base()) + Sec->PointerToRawData;
11420b57cec5SDimitry Andric uint32_t SectionSize = getSectionSize(Sec);
11435ffd83dbSDimitry Andric if (Error E = checkOffset(Data, ConStart, SectionSize))
11445ffd83dbSDimitry Andric return E;
11450b57cec5SDimitry Andric Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize);
11460b57cec5SDimitry Andric return Error::success();
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric
toRel(DataRefImpl Rel) const11490b57cec5SDimitry Andric const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
11500b57cec5SDimitry Andric return reinterpret_cast<const coff_relocation*>(Rel.p);
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric
moveRelocationNext(DataRefImpl & Rel) const11530b57cec5SDimitry Andric void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
11540b57cec5SDimitry Andric Rel.p = reinterpret_cast<uintptr_t>(
11550b57cec5SDimitry Andric reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric
getRelocationOffset(DataRefImpl Rel) const11580b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
11590b57cec5SDimitry Andric const coff_relocation *R = toRel(Rel);
11600b57cec5SDimitry Andric return R->VirtualAddress;
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric
getRelocationSymbol(DataRefImpl Rel) const11630b57cec5SDimitry Andric symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
11640b57cec5SDimitry Andric const coff_relocation *R = toRel(Rel);
11650b57cec5SDimitry Andric DataRefImpl Ref;
11660b57cec5SDimitry Andric if (R->SymbolTableIndex >= getNumberOfSymbols())
11670b57cec5SDimitry Andric return symbol_end();
11680b57cec5SDimitry Andric if (SymbolTable16)
11690b57cec5SDimitry Andric Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex);
11700b57cec5SDimitry Andric else if (SymbolTable32)
11710b57cec5SDimitry Andric Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex);
11720b57cec5SDimitry Andric else
11730b57cec5SDimitry Andric llvm_unreachable("no symbol table pointer!");
11740b57cec5SDimitry Andric return symbol_iterator(SymbolRef(Ref, this));
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric
getRelocationType(DataRefImpl Rel) const11770b57cec5SDimitry Andric uint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const {
11780b57cec5SDimitry Andric const coff_relocation* R = toRel(Rel);
11790b57cec5SDimitry Andric return R->Type;
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric const coff_section *
getCOFFSection(const SectionRef & Section) const11830b57cec5SDimitry Andric COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
11840b57cec5SDimitry Andric return toSec(Section.getRawDataRefImpl());
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric
getCOFFSymbol(const DataRefImpl & Ref) const11870b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const {
11880b57cec5SDimitry Andric if (SymbolTable16)
11890b57cec5SDimitry Andric return toSymb<coff_symbol16>(Ref);
11900b57cec5SDimitry Andric if (SymbolTable32)
11910b57cec5SDimitry Andric return toSymb<coff_symbol32>(Ref);
11920b57cec5SDimitry Andric llvm_unreachable("no symbol table pointer!");
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric
getCOFFSymbol(const SymbolRef & Symbol) const11950b57cec5SDimitry Andric COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
11960b57cec5SDimitry Andric return getCOFFSymbol(Symbol.getRawDataRefImpl());
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric
11990b57cec5SDimitry Andric const coff_relocation *
getCOFFRelocation(const RelocationRef & Reloc) const12000b57cec5SDimitry Andric COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
12010b57cec5SDimitry Andric return toRel(Reloc.getRawDataRefImpl());
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric
12040b57cec5SDimitry Andric ArrayRef<coff_relocation>
getRelocations(const coff_section * Sec) const12050b57cec5SDimitry Andric COFFObjectFile::getRelocations(const coff_section *Sec) const {
12060b57cec5SDimitry Andric return {getFirstReloc(Sec, Data, base()),
12070b57cec5SDimitry Andric getNumberOfRelocations(Sec, Data, base())};
12080b57cec5SDimitry Andric }
12090b57cec5SDimitry Andric
12100b57cec5SDimitry Andric #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
12110b57cec5SDimitry Andric case COFF::reloc_type: \
12120b57cec5SDimitry Andric return #reloc_type;
12130b57cec5SDimitry Andric
getRelocationTypeName(uint16_t Type) const12140b57cec5SDimitry Andric StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
12150b57cec5SDimitry Andric switch (getMachine()) {
12160b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64:
12170b57cec5SDimitry Andric switch (Type) {
12180b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
12190b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
12200b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
12210b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
12220b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
12230b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
12240b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
12250b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
12260b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
12270b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
12280b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
12290b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
12300b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
12310b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
12320b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
12330b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
12340b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
12350b57cec5SDimitry Andric default:
12360b57cec5SDimitry Andric return "Unknown";
12370b57cec5SDimitry Andric }
12380b57cec5SDimitry Andric break;
12390b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT:
12400b57cec5SDimitry Andric switch (Type) {
12410b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
12420b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
12430b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
12440b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
12450b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
12460b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
12470b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
12480b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
12490b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_REL32);
12500b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
12510b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
12520b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
12530b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
12540b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
12550b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
12560b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
12570b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_PAIR);
12580b57cec5SDimitry Andric default:
12590b57cec5SDimitry Andric return "Unknown";
12600b57cec5SDimitry Andric }
12610b57cec5SDimitry Andric break;
12620b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64:
12630b57cec5SDimitry Andric switch (Type) {
12640b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
12650b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
12660b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
12670b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH26);
12680b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEBASE_REL21);
12690b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL21);
12700b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12A);
12710b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_PAGEOFFSET_12L);
12720b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL);
12730b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12A);
12740b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_HIGH12A);
12750b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECREL_LOW12L);
12760b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_TOKEN);
12770b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_SECTION);
12780b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR64);
12790b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
12800b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
12810b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_REL32);
12820b57cec5SDimitry Andric default:
12830b57cec5SDimitry Andric return "Unknown";
12840b57cec5SDimitry Andric }
12850b57cec5SDimitry Andric break;
12860b57cec5SDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386:
12870b57cec5SDimitry Andric switch (Type) {
12880b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
12890b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
12900b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
12910b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
12920b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
12930b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
12940b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
12950b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
12960b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
12970b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
12980b57cec5SDimitry Andric LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
12990b57cec5SDimitry Andric default:
13000b57cec5SDimitry Andric return "Unknown";
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric break;
13030b57cec5SDimitry Andric default:
13040b57cec5SDimitry Andric return "Unknown";
13050b57cec5SDimitry Andric }
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric
13080b57cec5SDimitry Andric #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
13090b57cec5SDimitry Andric
getRelocationTypeName(DataRefImpl Rel,SmallVectorImpl<char> & Result) const13100b57cec5SDimitry Andric void COFFObjectFile::getRelocationTypeName(
13110b57cec5SDimitry Andric DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
13120b57cec5SDimitry Andric const coff_relocation *Reloc = toRel(Rel);
13130b57cec5SDimitry Andric StringRef Res = getRelocationTypeName(Reloc->Type);
13140b57cec5SDimitry Andric Result.append(Res.begin(), Res.end());
13150b57cec5SDimitry Andric }
13160b57cec5SDimitry Andric
isRelocatableObject() const13170b57cec5SDimitry Andric bool COFFObjectFile::isRelocatableObject() const {
13180b57cec5SDimitry Andric return !DataDirectory;
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric
mapDebugSectionName(StringRef Name) const13210b57cec5SDimitry Andric StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
13220b57cec5SDimitry Andric return StringSwitch<StringRef>(Name)
13230b57cec5SDimitry Andric .Case("eh_fram", "eh_frame")
13240b57cec5SDimitry Andric .Default(Name);
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric
13270b57cec5SDimitry Andric bool ImportDirectoryEntryRef::
operator ==(const ImportDirectoryEntryRef & Other) const13280b57cec5SDimitry Andric operator==(const ImportDirectoryEntryRef &Other) const {
13290b57cec5SDimitry Andric return ImportTable == Other.ImportTable && Index == Other.Index;
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric
moveNext()13320b57cec5SDimitry Andric void ImportDirectoryEntryRef::moveNext() {
13330b57cec5SDimitry Andric ++Index;
13340b57cec5SDimitry Andric if (ImportTable[Index].isNull()) {
13350b57cec5SDimitry Andric Index = -1;
13360b57cec5SDimitry Andric ImportTable = nullptr;
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric }
13390b57cec5SDimitry Andric
getImportTableEntry(const coff_import_directory_table_entry * & Result) const13405ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportTableEntry(
13410b57cec5SDimitry Andric const coff_import_directory_table_entry *&Result) const {
13420b57cec5SDimitry Andric return getObject(Result, OwningObject->Data, ImportTable + Index);
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric
13450b57cec5SDimitry Andric static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile * Object,uintptr_t Ptr,int Index)13460b57cec5SDimitry Andric makeImportedSymbolIterator(const COFFObjectFile *Object,
13470b57cec5SDimitry Andric uintptr_t Ptr, int Index) {
13480b57cec5SDimitry Andric if (Object->getBytesInAddress() == 4) {
13490b57cec5SDimitry Andric auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
13500b57cec5SDimitry Andric return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
13510b57cec5SDimitry Andric }
13520b57cec5SDimitry Andric auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
13530b57cec5SDimitry Andric return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric static imported_symbol_iterator
importedSymbolBegin(uint32_t RVA,const COFFObjectFile * Object)13570b57cec5SDimitry Andric importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
13580b57cec5SDimitry Andric uintptr_t IntPtr = 0;
13595ffd83dbSDimitry Andric // FIXME: Handle errors.
13605ffd83dbSDimitry Andric cantFail(Object->getRvaPtr(RVA, IntPtr));
13610b57cec5SDimitry Andric return makeImportedSymbolIterator(Object, IntPtr, 0);
13620b57cec5SDimitry Andric }
13630b57cec5SDimitry Andric
13640b57cec5SDimitry Andric static imported_symbol_iterator
importedSymbolEnd(uint32_t RVA,const COFFObjectFile * Object)13650b57cec5SDimitry Andric importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
13660b57cec5SDimitry Andric uintptr_t IntPtr = 0;
13675ffd83dbSDimitry Andric // FIXME: Handle errors.
13685ffd83dbSDimitry Andric cantFail(Object->getRvaPtr(RVA, IntPtr));
13690b57cec5SDimitry Andric // Forward the pointer to the last entry which is null.
13700b57cec5SDimitry Andric int Index = 0;
13710b57cec5SDimitry Andric if (Object->getBytesInAddress() == 4) {
13720b57cec5SDimitry Andric auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
13730b57cec5SDimitry Andric while (*Entry++)
13740b57cec5SDimitry Andric ++Index;
13750b57cec5SDimitry Andric } else {
13760b57cec5SDimitry Andric auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
13770b57cec5SDimitry Andric while (*Entry++)
13780b57cec5SDimitry Andric ++Index;
13790b57cec5SDimitry Andric }
13800b57cec5SDimitry Andric return makeImportedSymbolIterator(Object, IntPtr, Index);
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric
13830b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const13840b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_begin() const {
13850b57cec5SDimitry Andric return importedSymbolBegin(ImportTable[Index].ImportAddressTableRVA,
13860b57cec5SDimitry Andric OwningObject);
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric
13890b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_end() const13900b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbol_end() const {
13910b57cec5SDimitry Andric return importedSymbolEnd(ImportTable[Index].ImportAddressTableRVA,
13920b57cec5SDimitry Andric OwningObject);
13930b57cec5SDimitry Andric }
13940b57cec5SDimitry Andric
13950b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const13960b57cec5SDimitry Andric ImportDirectoryEntryRef::imported_symbols() const {
13970b57cec5SDimitry Andric return make_range(imported_symbol_begin(), imported_symbol_end());
13980b57cec5SDimitry Andric }
13990b57cec5SDimitry Andric
lookup_table_begin() const14000b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_begin() const {
14010b57cec5SDimitry Andric return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
14020b57cec5SDimitry Andric OwningObject);
14030b57cec5SDimitry Andric }
14040b57cec5SDimitry Andric
lookup_table_end() const14050b57cec5SDimitry Andric imported_symbol_iterator ImportDirectoryEntryRef::lookup_table_end() const {
14060b57cec5SDimitry Andric return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
14070b57cec5SDimitry Andric OwningObject);
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric
14100b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
lookup_table_symbols() const14110b57cec5SDimitry Andric ImportDirectoryEntryRef::lookup_table_symbols() const {
14120b57cec5SDimitry Andric return make_range(lookup_table_begin(), lookup_table_end());
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric
getName(StringRef & Result) const14155ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getName(StringRef &Result) const {
14160b57cec5SDimitry Andric uintptr_t IntPtr = 0;
14175ffd83dbSDimitry Andric if (Error E = OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr))
14185ffd83dbSDimitry Andric return E;
14190b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14205ffd83dbSDimitry Andric return Error::success();
14210b57cec5SDimitry Andric }
14220b57cec5SDimitry Andric
14235ffd83dbSDimitry Andric Error
getImportLookupTableRVA(uint32_t & Result) const14240b57cec5SDimitry Andric ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const {
14250b57cec5SDimitry Andric Result = ImportTable[Index].ImportLookupTableRVA;
14265ffd83dbSDimitry Andric return Error::success();
14270b57cec5SDimitry Andric }
14280b57cec5SDimitry Andric
getImportAddressTableRVA(uint32_t & Result) const14295ffd83dbSDimitry Andric Error ImportDirectoryEntryRef::getImportAddressTableRVA(
14305ffd83dbSDimitry Andric uint32_t &Result) const {
14310b57cec5SDimitry Andric Result = ImportTable[Index].ImportAddressTableRVA;
14325ffd83dbSDimitry Andric return Error::success();
14330b57cec5SDimitry Andric }
14340b57cec5SDimitry Andric
14350b57cec5SDimitry Andric bool DelayImportDirectoryEntryRef::
operator ==(const DelayImportDirectoryEntryRef & Other) const14360b57cec5SDimitry Andric operator==(const DelayImportDirectoryEntryRef &Other) const {
14370b57cec5SDimitry Andric return Table == Other.Table && Index == Other.Index;
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric
moveNext()14400b57cec5SDimitry Andric void DelayImportDirectoryEntryRef::moveNext() {
14410b57cec5SDimitry Andric ++Index;
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric
14440b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_begin() const14450b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_begin() const {
14460b57cec5SDimitry Andric return importedSymbolBegin(Table[Index].DelayImportNameTable,
14470b57cec5SDimitry Andric OwningObject);
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric
14500b57cec5SDimitry Andric imported_symbol_iterator
imported_symbol_end() const14510b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbol_end() const {
14520b57cec5SDimitry Andric return importedSymbolEnd(Table[Index].DelayImportNameTable,
14530b57cec5SDimitry Andric OwningObject);
14540b57cec5SDimitry Andric }
14550b57cec5SDimitry Andric
14560b57cec5SDimitry Andric iterator_range<imported_symbol_iterator>
imported_symbols() const14570b57cec5SDimitry Andric DelayImportDirectoryEntryRef::imported_symbols() const {
14580b57cec5SDimitry Andric return make_range(imported_symbol_begin(), imported_symbol_end());
14590b57cec5SDimitry Andric }
14600b57cec5SDimitry Andric
getName(StringRef & Result) const14615ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
14620b57cec5SDimitry Andric uintptr_t IntPtr = 0;
14635ffd83dbSDimitry Andric if (Error E = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
14645ffd83dbSDimitry Andric return E;
14650b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr));
14665ffd83dbSDimitry Andric return Error::success();
14670b57cec5SDimitry Andric }
14680b57cec5SDimitry Andric
getDelayImportTable(const delay_import_directory_table_entry * & Result) const14695ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getDelayImportTable(
14705ffd83dbSDimitry Andric const delay_import_directory_table_entry *&Result) const {
14710b57cec5SDimitry Andric Result = &Table[Index];
14725ffd83dbSDimitry Andric return Error::success();
14730b57cec5SDimitry Andric }
14740b57cec5SDimitry Andric
getImportAddress(int AddrIndex,uint64_t & Result) const14755ffd83dbSDimitry Andric Error DelayImportDirectoryEntryRef::getImportAddress(int AddrIndex,
14765ffd83dbSDimitry Andric uint64_t &Result) const {
14770b57cec5SDimitry Andric uint32_t RVA = Table[Index].DelayImportAddressTable +
14780b57cec5SDimitry Andric AddrIndex * (OwningObject->is64() ? 8 : 4);
14790b57cec5SDimitry Andric uintptr_t IntPtr = 0;
14805ffd83dbSDimitry Andric if (Error E = OwningObject->getRvaPtr(RVA, IntPtr))
14815ffd83dbSDimitry Andric return E;
14820b57cec5SDimitry Andric if (OwningObject->is64())
14830b57cec5SDimitry Andric Result = *reinterpret_cast<const ulittle64_t *>(IntPtr);
14840b57cec5SDimitry Andric else
14850b57cec5SDimitry Andric Result = *reinterpret_cast<const ulittle32_t *>(IntPtr);
14865ffd83dbSDimitry Andric return Error::success();
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric
14890b57cec5SDimitry Andric bool ExportDirectoryEntryRef::
operator ==(const ExportDirectoryEntryRef & Other) const14900b57cec5SDimitry Andric operator==(const ExportDirectoryEntryRef &Other) const {
14910b57cec5SDimitry Andric return ExportTable == Other.ExportTable && Index == Other.Index;
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric
moveNext()14940b57cec5SDimitry Andric void ExportDirectoryEntryRef::moveNext() {
14950b57cec5SDimitry Andric ++Index;
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric
14980b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
14990b57cec5SDimitry Andric // by ordinal, the empty string is set as a result.
getDllName(StringRef & Result) const15005ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
15010b57cec5SDimitry Andric uintptr_t IntPtr = 0;
15025ffd83dbSDimitry Andric if (Error E = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
15035ffd83dbSDimitry Andric return E;
15040b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15055ffd83dbSDimitry Andric return Error::success();
15060b57cec5SDimitry Andric }
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric // Returns the starting ordinal number.
getOrdinalBase(uint32_t & Result) const15095ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
15100b57cec5SDimitry Andric Result = ExportTable->OrdinalBase;
15115ffd83dbSDimitry Andric return Error::success();
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric
15140b57cec5SDimitry Andric // Returns the export ordinal of the current export symbol.
getOrdinal(uint32_t & Result) const15155ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
15160b57cec5SDimitry Andric Result = ExportTable->OrdinalBase + Index;
15175ffd83dbSDimitry Andric return Error::success();
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric
15200b57cec5SDimitry Andric // Returns the address of the current export symbol.
getExportRVA(uint32_t & Result) const15215ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
15220b57cec5SDimitry Andric uintptr_t IntPtr = 0;
15235ffd83dbSDimitry Andric if (Error EC =
15240b57cec5SDimitry Andric OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
15250b57cec5SDimitry Andric return EC;
15260b57cec5SDimitry Andric const export_address_table_entry *entry =
15270b57cec5SDimitry Andric reinterpret_cast<const export_address_table_entry *>(IntPtr);
15280b57cec5SDimitry Andric Result = entry[Index].ExportRVA;
15295ffd83dbSDimitry Andric return Error::success();
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric
15320b57cec5SDimitry Andric // Returns the name of the current export symbol. If the symbol is exported only
15330b57cec5SDimitry Andric // by ordinal, the empty string is set as a result.
15345ffd83dbSDimitry Andric Error
getSymbolName(StringRef & Result) const15350b57cec5SDimitry Andric ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
15360b57cec5SDimitry Andric uintptr_t IntPtr = 0;
15375ffd83dbSDimitry Andric if (Error EC =
15380b57cec5SDimitry Andric OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
15390b57cec5SDimitry Andric return EC;
15400b57cec5SDimitry Andric const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
15410b57cec5SDimitry Andric
15420b57cec5SDimitry Andric uint32_t NumEntries = ExportTable->NumberOfNamePointers;
15430b57cec5SDimitry Andric int Offset = 0;
15440b57cec5SDimitry Andric for (const ulittle16_t *I = Start, *E = Start + NumEntries;
15450b57cec5SDimitry Andric I < E; ++I, ++Offset) {
15460b57cec5SDimitry Andric if (*I != Index)
15470b57cec5SDimitry Andric continue;
15485ffd83dbSDimitry Andric if (Error EC =
15490b57cec5SDimitry Andric OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
15500b57cec5SDimitry Andric return EC;
15510b57cec5SDimitry Andric const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
15525ffd83dbSDimitry Andric if (Error EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
15530b57cec5SDimitry Andric return EC;
15540b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15555ffd83dbSDimitry Andric return Error::success();
15560b57cec5SDimitry Andric }
15570b57cec5SDimitry Andric Result = "";
15585ffd83dbSDimitry Andric return Error::success();
15590b57cec5SDimitry Andric }
15600b57cec5SDimitry Andric
isForwarder(bool & Result) const15615ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::isForwarder(bool &Result) const {
15625ffd83dbSDimitry Andric const data_directory *DataEntry =
15635ffd83dbSDimitry Andric OwningObject->getDataDirectory(COFF::EXPORT_TABLE);
15645ffd83dbSDimitry Andric if (!DataEntry)
15655ffd83dbSDimitry Andric return errorCodeToError(object_error::parse_failed);
15660b57cec5SDimitry Andric uint32_t RVA;
15670b57cec5SDimitry Andric if (auto EC = getExportRVA(RVA))
15680b57cec5SDimitry Andric return EC;
15690b57cec5SDimitry Andric uint32_t Begin = DataEntry->RelativeVirtualAddress;
15700b57cec5SDimitry Andric uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size;
15710b57cec5SDimitry Andric Result = (Begin <= RVA && RVA < End);
15725ffd83dbSDimitry Andric return Error::success();
15730b57cec5SDimitry Andric }
15740b57cec5SDimitry Andric
getForwardTo(StringRef & Result) const15755ffd83dbSDimitry Andric Error ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const {
15760b57cec5SDimitry Andric uint32_t RVA;
15770b57cec5SDimitry Andric if (auto EC = getExportRVA(RVA))
15780b57cec5SDimitry Andric return EC;
15790b57cec5SDimitry Andric uintptr_t IntPtr = 0;
15800b57cec5SDimitry Andric if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr))
15810b57cec5SDimitry Andric return EC;
15820b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr));
15835ffd83dbSDimitry Andric return Error::success();
15840b57cec5SDimitry Andric }
15850b57cec5SDimitry Andric
15860b57cec5SDimitry Andric bool ImportedSymbolRef::
operator ==(const ImportedSymbolRef & Other) const15870b57cec5SDimitry Andric operator==(const ImportedSymbolRef &Other) const {
15880b57cec5SDimitry Andric return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
15890b57cec5SDimitry Andric && Index == Other.Index;
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric
moveNext()15920b57cec5SDimitry Andric void ImportedSymbolRef::moveNext() {
15930b57cec5SDimitry Andric ++Index;
15940b57cec5SDimitry Andric }
15950b57cec5SDimitry Andric
getSymbolName(StringRef & Result) const15965ffd83dbSDimitry Andric Error ImportedSymbolRef::getSymbolName(StringRef &Result) const {
15970b57cec5SDimitry Andric uint32_t RVA;
15980b57cec5SDimitry Andric if (Entry32) {
15990b57cec5SDimitry Andric // If a symbol is imported only by ordinal, it has no name.
16000b57cec5SDimitry Andric if (Entry32[Index].isOrdinal())
16015ffd83dbSDimitry Andric return Error::success();
16020b57cec5SDimitry Andric RVA = Entry32[Index].getHintNameRVA();
16030b57cec5SDimitry Andric } else {
16040b57cec5SDimitry Andric if (Entry64[Index].isOrdinal())
16055ffd83dbSDimitry Andric return Error::success();
16060b57cec5SDimitry Andric RVA = Entry64[Index].getHintNameRVA();
16070b57cec5SDimitry Andric }
16080b57cec5SDimitry Andric uintptr_t IntPtr = 0;
16095ffd83dbSDimitry Andric if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
16100b57cec5SDimitry Andric return EC;
16110b57cec5SDimitry Andric // +2 because the first two bytes is hint.
16120b57cec5SDimitry Andric Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
16135ffd83dbSDimitry Andric return Error::success();
16140b57cec5SDimitry Andric }
16150b57cec5SDimitry Andric
isOrdinal(bool & Result) const16165ffd83dbSDimitry Andric Error ImportedSymbolRef::isOrdinal(bool &Result) const {
16170b57cec5SDimitry Andric if (Entry32)
16180b57cec5SDimitry Andric Result = Entry32[Index].isOrdinal();
16190b57cec5SDimitry Andric else
16200b57cec5SDimitry Andric Result = Entry64[Index].isOrdinal();
16215ffd83dbSDimitry Andric return Error::success();
16220b57cec5SDimitry Andric }
16230b57cec5SDimitry Andric
getHintNameRVA(uint32_t & Result) const16245ffd83dbSDimitry Andric Error ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
16250b57cec5SDimitry Andric if (Entry32)
16260b57cec5SDimitry Andric Result = Entry32[Index].getHintNameRVA();
16270b57cec5SDimitry Andric else
16280b57cec5SDimitry Andric Result = Entry64[Index].getHintNameRVA();
16295ffd83dbSDimitry Andric return Error::success();
16300b57cec5SDimitry Andric }
16310b57cec5SDimitry Andric
getOrdinal(uint16_t & Result) const16325ffd83dbSDimitry Andric Error ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
16330b57cec5SDimitry Andric uint32_t RVA;
16340b57cec5SDimitry Andric if (Entry32) {
16350b57cec5SDimitry Andric if (Entry32[Index].isOrdinal()) {
16360b57cec5SDimitry Andric Result = Entry32[Index].getOrdinal();
16375ffd83dbSDimitry Andric return Error::success();
16380b57cec5SDimitry Andric }
16390b57cec5SDimitry Andric RVA = Entry32[Index].getHintNameRVA();
16400b57cec5SDimitry Andric } else {
16410b57cec5SDimitry Andric if (Entry64[Index].isOrdinal()) {
16420b57cec5SDimitry Andric Result = Entry64[Index].getOrdinal();
16435ffd83dbSDimitry Andric return Error::success();
16440b57cec5SDimitry Andric }
16450b57cec5SDimitry Andric RVA = Entry64[Index].getHintNameRVA();
16460b57cec5SDimitry Andric }
16470b57cec5SDimitry Andric uintptr_t IntPtr = 0;
16485ffd83dbSDimitry Andric if (Error EC = OwningObject->getRvaPtr(RVA, IntPtr))
16490b57cec5SDimitry Andric return EC;
16500b57cec5SDimitry Andric Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
16515ffd83dbSDimitry Andric return Error::success();
16520b57cec5SDimitry Andric }
16530b57cec5SDimitry Andric
16540b57cec5SDimitry Andric Expected<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object)16550b57cec5SDimitry Andric ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
16565ffd83dbSDimitry Andric return COFFObjectFile::create(Object);
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric
operator ==(const BaseRelocRef & Other) const16590b57cec5SDimitry Andric bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
16600b57cec5SDimitry Andric return Header == Other.Header && Index == Other.Index;
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric
moveNext()16630b57cec5SDimitry Andric void BaseRelocRef::moveNext() {
16640b57cec5SDimitry Andric // Header->BlockSize is the size of the current block, including the
16650b57cec5SDimitry Andric // size of the header itself.
16660b57cec5SDimitry Andric uint32_t Size = sizeof(*Header) +
16670b57cec5SDimitry Andric sizeof(coff_base_reloc_block_entry) * (Index + 1);
16680b57cec5SDimitry Andric if (Size == Header->BlockSize) {
16690b57cec5SDimitry Andric // .reloc contains a list of base relocation blocks. Each block
16700b57cec5SDimitry Andric // consists of the header followed by entries. The header contains
16710b57cec5SDimitry Andric // how many entories will follow. When we reach the end of the
16720b57cec5SDimitry Andric // current block, proceed to the next block.
16730b57cec5SDimitry Andric Header = reinterpret_cast<const coff_base_reloc_block_header *>(
16740b57cec5SDimitry Andric reinterpret_cast<const uint8_t *>(Header) + Size);
16750b57cec5SDimitry Andric Index = 0;
16760b57cec5SDimitry Andric } else {
16770b57cec5SDimitry Andric ++Index;
16780b57cec5SDimitry Andric }
16790b57cec5SDimitry Andric }
16800b57cec5SDimitry Andric
getType(uint8_t & Type) const16815ffd83dbSDimitry Andric Error BaseRelocRef::getType(uint8_t &Type) const {
16820b57cec5SDimitry Andric auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
16830b57cec5SDimitry Andric Type = Entry[Index].getType();
16845ffd83dbSDimitry Andric return Error::success();
16850b57cec5SDimitry Andric }
16860b57cec5SDimitry Andric
getRVA(uint32_t & Result) const16875ffd83dbSDimitry Andric Error BaseRelocRef::getRVA(uint32_t &Result) const {
16880b57cec5SDimitry Andric auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
16890b57cec5SDimitry Andric Result = Header->PageRVA + Entry[Index].getOffset();
16905ffd83dbSDimitry Andric return Error::success();
16910b57cec5SDimitry Andric }
16920b57cec5SDimitry Andric
16938bcb0991SDimitry Andric #define RETURN_IF_ERROR(Expr) \
16948bcb0991SDimitry Andric do { \
16958bcb0991SDimitry Andric Error E = (Expr); \
16960b57cec5SDimitry Andric if (E) \
16978bcb0991SDimitry Andric return std::move(E); \
16988bcb0991SDimitry Andric } while (0)
16990b57cec5SDimitry Andric
17000b57cec5SDimitry Andric Expected<ArrayRef<UTF16>>
getDirStringAtOffset(uint32_t Offset)17010b57cec5SDimitry Andric ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
17020b57cec5SDimitry Andric BinaryStreamReader Reader = BinaryStreamReader(BBS);
17030b57cec5SDimitry Andric Reader.setOffset(Offset);
17040b57cec5SDimitry Andric uint16_t Length;
17050b57cec5SDimitry Andric RETURN_IF_ERROR(Reader.readInteger(Length));
17060b57cec5SDimitry Andric ArrayRef<UTF16> RawDirString;
17070b57cec5SDimitry Andric RETURN_IF_ERROR(Reader.readArray(RawDirString, Length));
17080b57cec5SDimitry Andric return RawDirString;
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric
17110b57cec5SDimitry Andric Expected<ArrayRef<UTF16>>
getEntryNameString(const coff_resource_dir_entry & Entry)17120b57cec5SDimitry Andric ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
17130b57cec5SDimitry Andric return getDirStringAtOffset(Entry.Identifier.getNameOffset());
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric
17160b57cec5SDimitry Andric Expected<const coff_resource_dir_table &>
getTableAtOffset(uint32_t Offset)17170b57cec5SDimitry Andric ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
17180b57cec5SDimitry Andric const coff_resource_dir_table *Table = nullptr;
17190b57cec5SDimitry Andric
17200b57cec5SDimitry Andric BinaryStreamReader Reader(BBS);
17210b57cec5SDimitry Andric Reader.setOffset(Offset);
17220b57cec5SDimitry Andric RETURN_IF_ERROR(Reader.readObject(Table));
17230b57cec5SDimitry Andric assert(Table != nullptr);
17240b57cec5SDimitry Andric return *Table;
17250b57cec5SDimitry Andric }
17260b57cec5SDimitry Andric
17278bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &>
getTableEntryAtOffset(uint32_t Offset)17288bcb0991SDimitry Andric ResourceSectionRef::getTableEntryAtOffset(uint32_t Offset) {
17298bcb0991SDimitry Andric const coff_resource_dir_entry *Entry = nullptr;
17308bcb0991SDimitry Andric
17318bcb0991SDimitry Andric BinaryStreamReader Reader(BBS);
17328bcb0991SDimitry Andric Reader.setOffset(Offset);
17338bcb0991SDimitry Andric RETURN_IF_ERROR(Reader.readObject(Entry));
17348bcb0991SDimitry Andric assert(Entry != nullptr);
17358bcb0991SDimitry Andric return *Entry;
17368bcb0991SDimitry Andric }
17378bcb0991SDimitry Andric
17388bcb0991SDimitry Andric Expected<const coff_resource_data_entry &>
getDataEntryAtOffset(uint32_t Offset)17398bcb0991SDimitry Andric ResourceSectionRef::getDataEntryAtOffset(uint32_t Offset) {
17408bcb0991SDimitry Andric const coff_resource_data_entry *Entry = nullptr;
17418bcb0991SDimitry Andric
17428bcb0991SDimitry Andric BinaryStreamReader Reader(BBS);
17438bcb0991SDimitry Andric Reader.setOffset(Offset);
17448bcb0991SDimitry Andric RETURN_IF_ERROR(Reader.readObject(Entry));
17458bcb0991SDimitry Andric assert(Entry != nullptr);
17468bcb0991SDimitry Andric return *Entry;
17478bcb0991SDimitry Andric }
17488bcb0991SDimitry Andric
17490b57cec5SDimitry Andric Expected<const coff_resource_dir_table &>
getEntrySubDir(const coff_resource_dir_entry & Entry)17500b57cec5SDimitry Andric ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
17518bcb0991SDimitry Andric assert(Entry.Offset.isSubDir());
17520b57cec5SDimitry Andric return getTableAtOffset(Entry.Offset.value());
17530b57cec5SDimitry Andric }
17540b57cec5SDimitry Andric
17558bcb0991SDimitry Andric Expected<const coff_resource_data_entry &>
getEntryData(const coff_resource_dir_entry & Entry)17568bcb0991SDimitry Andric ResourceSectionRef::getEntryData(const coff_resource_dir_entry &Entry) {
17578bcb0991SDimitry Andric assert(!Entry.Offset.isSubDir());
17588bcb0991SDimitry Andric return getDataEntryAtOffset(Entry.Offset.value());
17598bcb0991SDimitry Andric }
17608bcb0991SDimitry Andric
getBaseTable()17610b57cec5SDimitry Andric Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
17620b57cec5SDimitry Andric return getTableAtOffset(0);
17630b57cec5SDimitry Andric }
17648bcb0991SDimitry Andric
17658bcb0991SDimitry Andric Expected<const coff_resource_dir_entry &>
getTableEntry(const coff_resource_dir_table & Table,uint32_t Index)17668bcb0991SDimitry Andric ResourceSectionRef::getTableEntry(const coff_resource_dir_table &Table,
17678bcb0991SDimitry Andric uint32_t Index) {
17688bcb0991SDimitry Andric if (Index >= (uint32_t)(Table.NumberOfNameEntries + Table.NumberOfIDEntries))
17698bcb0991SDimitry Andric return createStringError(object_error::parse_failed, "index out of range");
17708bcb0991SDimitry Andric const uint8_t *TablePtr = reinterpret_cast<const uint8_t *>(&Table);
17718bcb0991SDimitry Andric ptrdiff_t TableOffset = TablePtr - BBS.data().data();
17728bcb0991SDimitry Andric return getTableEntryAtOffset(TableOffset + sizeof(Table) +
17738bcb0991SDimitry Andric Index * sizeof(coff_resource_dir_entry));
17748bcb0991SDimitry Andric }
17758bcb0991SDimitry Andric
load(const COFFObjectFile * O)17768bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O) {
17778bcb0991SDimitry Andric for (const SectionRef &S : O->sections()) {
17788bcb0991SDimitry Andric Expected<StringRef> Name = S.getName();
17798bcb0991SDimitry Andric if (!Name)
17808bcb0991SDimitry Andric return Name.takeError();
17818bcb0991SDimitry Andric
17828bcb0991SDimitry Andric if (*Name == ".rsrc" || *Name == ".rsrc$01")
17838bcb0991SDimitry Andric return load(O, S);
17848bcb0991SDimitry Andric }
17858bcb0991SDimitry Andric return createStringError(object_error::parse_failed,
17868bcb0991SDimitry Andric "no resource section found");
17878bcb0991SDimitry Andric }
17888bcb0991SDimitry Andric
load(const COFFObjectFile * O,const SectionRef & S)17898bcb0991SDimitry Andric Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
17908bcb0991SDimitry Andric Obj = O;
17918bcb0991SDimitry Andric Section = S;
17928bcb0991SDimitry Andric Expected<StringRef> Contents = Section.getContents();
17938bcb0991SDimitry Andric if (!Contents)
17948bcb0991SDimitry Andric return Contents.takeError();
17958bcb0991SDimitry Andric BBS = BinaryByteStream(*Contents, support::little);
17968bcb0991SDimitry Andric const coff_section *COFFSect = Obj->getCOFFSection(Section);
17978bcb0991SDimitry Andric ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
17988bcb0991SDimitry Andric Relocs.reserve(OrigRelocs.size());
17998bcb0991SDimitry Andric for (const coff_relocation &R : OrigRelocs)
18008bcb0991SDimitry Andric Relocs.push_back(&R);
1801af732203SDimitry Andric llvm::sort(Relocs, [](const coff_relocation *A, const coff_relocation *B) {
18028bcb0991SDimitry Andric return A->VirtualAddress < B->VirtualAddress;
18038bcb0991SDimitry Andric });
18048bcb0991SDimitry Andric return Error::success();
18058bcb0991SDimitry Andric }
18068bcb0991SDimitry Andric
18078bcb0991SDimitry Andric Expected<StringRef>
getContents(const coff_resource_data_entry & Entry)18088bcb0991SDimitry Andric ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
18098bcb0991SDimitry Andric if (!Obj)
18108bcb0991SDimitry Andric return createStringError(object_error::parse_failed, "no object provided");
18118bcb0991SDimitry Andric
18128bcb0991SDimitry Andric // Find a potential relocation at the DataRVA field (first member of
18138bcb0991SDimitry Andric // the coff_resource_data_entry struct).
18148bcb0991SDimitry Andric const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
18158bcb0991SDimitry Andric ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
18168bcb0991SDimitry Andric coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
18178bcb0991SDimitry Andric ulittle16_t(0)};
18188bcb0991SDimitry Andric auto RelocsForOffset =
18198bcb0991SDimitry Andric std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
18208bcb0991SDimitry Andric [](const coff_relocation *A, const coff_relocation *B) {
18218bcb0991SDimitry Andric return A->VirtualAddress < B->VirtualAddress;
18228bcb0991SDimitry Andric });
18238bcb0991SDimitry Andric
18248bcb0991SDimitry Andric if (RelocsForOffset.first != RelocsForOffset.second) {
18258bcb0991SDimitry Andric // We found a relocation with the right offset. Check that it does have
18268bcb0991SDimitry Andric // the expected type.
18278bcb0991SDimitry Andric const coff_relocation &R = **RelocsForOffset.first;
18288bcb0991SDimitry Andric uint16_t RVAReloc;
18298bcb0991SDimitry Andric switch (Obj->getMachine()) {
18308bcb0991SDimitry Andric case COFF::IMAGE_FILE_MACHINE_I386:
18318bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
18328bcb0991SDimitry Andric break;
18338bcb0991SDimitry Andric case COFF::IMAGE_FILE_MACHINE_AMD64:
18348bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
18358bcb0991SDimitry Andric break;
18368bcb0991SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARMNT:
18378bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
18388bcb0991SDimitry Andric break;
18398bcb0991SDimitry Andric case COFF::IMAGE_FILE_MACHINE_ARM64:
18408bcb0991SDimitry Andric RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
18418bcb0991SDimitry Andric break;
18428bcb0991SDimitry Andric default:
18438bcb0991SDimitry Andric return createStringError(object_error::parse_failed,
18448bcb0991SDimitry Andric "unsupported architecture");
18458bcb0991SDimitry Andric }
18468bcb0991SDimitry Andric if (R.Type != RVAReloc)
18478bcb0991SDimitry Andric return createStringError(object_error::parse_failed,
18488bcb0991SDimitry Andric "unexpected relocation type");
18498bcb0991SDimitry Andric // Get the relocation's symbol
18508bcb0991SDimitry Andric Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
18518bcb0991SDimitry Andric if (!Sym)
18528bcb0991SDimitry Andric return Sym.takeError();
18538bcb0991SDimitry Andric // And the symbol's section
18545ffd83dbSDimitry Andric Expected<const coff_section *> Section =
18555ffd83dbSDimitry Andric Obj->getSection(Sym->getSectionNumber());
18565ffd83dbSDimitry Andric if (!Section)
18575ffd83dbSDimitry Andric return Section.takeError();
18588bcb0991SDimitry Andric // Add the initial value of DataRVA to the symbol's offset to find the
18598bcb0991SDimitry Andric // data it points at.
18608bcb0991SDimitry Andric uint64_t Offset = Entry.DataRVA + Sym->getValue();
18618bcb0991SDimitry Andric ArrayRef<uint8_t> Contents;
18625ffd83dbSDimitry Andric if (Error E = Obj->getSectionContents(*Section, Contents))
18638bcb0991SDimitry Andric return std::move(E);
18648bcb0991SDimitry Andric if (Offset + Entry.DataSize > Contents.size())
18658bcb0991SDimitry Andric return createStringError(object_error::parse_failed,
18668bcb0991SDimitry Andric "data outside of section");
18678bcb0991SDimitry Andric // Return a reference to the data inside the section.
18688bcb0991SDimitry Andric return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
18698bcb0991SDimitry Andric Entry.DataSize);
18708bcb0991SDimitry Andric } else {
18718bcb0991SDimitry Andric // Relocatable objects need a relocation for the DataRVA field.
18728bcb0991SDimitry Andric if (Obj->isRelocatableObject())
18738bcb0991SDimitry Andric return createStringError(object_error::parse_failed,
18748bcb0991SDimitry Andric "no relocation found for DataRVA");
18758bcb0991SDimitry Andric
18768bcb0991SDimitry Andric // Locate the section that contains the address that DataRVA points at.
18778bcb0991SDimitry Andric uint64_t VA = Entry.DataRVA + Obj->getImageBase();
18788bcb0991SDimitry Andric for (const SectionRef &S : Obj->sections()) {
18798bcb0991SDimitry Andric if (VA >= S.getAddress() &&
18808bcb0991SDimitry Andric VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
18818bcb0991SDimitry Andric uint64_t Offset = VA - S.getAddress();
18828bcb0991SDimitry Andric Expected<StringRef> Contents = S.getContents();
18838bcb0991SDimitry Andric if (!Contents)
18848bcb0991SDimitry Andric return Contents.takeError();
18858bcb0991SDimitry Andric return Contents->slice(Offset, Offset + Entry.DataSize);
18868bcb0991SDimitry Andric }
18878bcb0991SDimitry Andric }
18888bcb0991SDimitry Andric return createStringError(object_error::parse_failed,
18898bcb0991SDimitry Andric "address not found in image");
18908bcb0991SDimitry Andric }
18918bcb0991SDimitry Andric }
1892