1a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 2a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 3a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// The LLVM Compiler Infrastructure 4a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 5a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file is distributed under the University of Illinois Open Source 6a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// License. See LICENSE.TXT for details. 7a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 8a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===// 9a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 10a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file declares the COFFObjectFile class. 11a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 12a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===// 13a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 14001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Object/COFF.h" 151f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer#include "llvm/ADT/ArrayRef.h" 16a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h" 17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.h" 18f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar#include "llvm/ADT/iterator_range.h" 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/COFF.h" 20a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama#include "llvm/Support/Debug.h" 21a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama#include "llvm/Support/raw_ostream.h" 22e3ba15c794839abe076e3e2bdf6c626396a19d4dWill Dietz#include <cctype> 2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <limits> 24ca8b2c655eb4d283187cbbb4f0f3acd34f60fa1cLogan Chien 25a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace llvm; 26a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace object; 27a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 28a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t; 29a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_t; 3037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesusing support::ulittle64_t; 31a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::little16_t; 32a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if size is greater than the buffer size. And sets ec. 3437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { 35c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (M.getBufferSize() < Size) { 3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EC = object_error::unexpected_eof; 3725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 4237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, 4337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const uint64_t Size) { 4437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Addr + Size < Addr || Addr + Size < Size || 4537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Addr + Size > uintptr_t(M.getBufferEnd()) || 4637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Addr < uintptr_t(M.getBufferStart())) { 4737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return object_error::unexpected_eof; 4837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 496948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 5137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 522f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 532f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama// Returns unexpected_eof if error. 54c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinestemplate <typename T> 5537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic std::error_code getObject(const T *&Obj, MemoryBufferRef M, 5637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const void *Ptr, 5737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const uint64_t Size = sizeof(T)) { 582f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama uintptr_t Addr = uintptr_t(Ptr); 5937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = checkOffset(M, Addr, Size)) 6037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 612f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama Obj = reinterpret_cast<const T *>(Addr); 626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 6325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// prefixed slashes. 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Str.size() <= 6 && "String too long, possible overflow."); 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Str.size() > 6) 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Value = 0; 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines while (!Str.empty()) { 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned CharVal; 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = Str[0] - 'A'; 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = Str[0] - 'a' + 26; 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = Str[0] - '0' + 52; 8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] == '+') // 62 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = 62; 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] == '/') // 63 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = 63; 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value = (Value * 64) + CharVal; 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Str = Str.substr(1); 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Value > std::numeric_limits<uint32_t>::max()) 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = static_cast<uint32_t>(Value); 9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 9725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 9825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 9937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinestemplate <typename coff_symbol_type> 10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesconst coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { 10137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_symbol_type *Addr = 10237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines reinterpret_cast<const coff_symbol_type *>(Ref.p); 10325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 10437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); 10537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#ifndef NDEBUG 10625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 10825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 10937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && 11037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines "Symbol did not point to the beginning of a symbol"); 11137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#endif 11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Addr; 11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 11525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 12025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the section points to a valid entry in the section table. 12137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) 12225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Section was outside of section table."); 12325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Offset % sizeof(coff_section) == 0 && 12625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer "Section did not point to the beginning of a section"); 12725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 12825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Addr; 130a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 131a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 13337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto End = reinterpret_cast<uintptr_t>(StringTable); 13437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolTable16) { 13537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_symbol16 *Symb = toSymb<coff_symbol16>(Ref); 13637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Symb += 1 + Symb->NumberOfAuxSymbols; 13737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 13837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else if (SymbolTable32) { 13937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_symbol32 *Symb = toSymb<coff_symbol32>(Ref); 14037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Symb += 1 + Symb->NumberOfAuxSymbols; 14137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ref.p = std::min(reinterpret_cast<uintptr_t>(Symb), End); 14237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 14337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines llvm_unreachable("no symbol table pointer!"); 14437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 145a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 146a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { 14837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFSymbolRef Symb = getCOFFSymbol(Ref); 149f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StringRef Result; 150f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar std::error_code EC = getSymbolName(Symb, Result); 151f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (EC) 152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorCodeToError(EC); 153f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Result; 154a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 155a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 156f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainaruint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { 157f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return getCOFFSymbol(Ref).getValue(); 158f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 1591b6c8d1f6c834d8c3de4f78a4c99f8800f581b73Rafael Espindola 160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { 161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint64_t Result = getSymbolValue(Ref); 162f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar COFFSymbolRef Symb = getCOFFSymbol(Ref); 16337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int32_t SectionNumber = Symb.getSectionNumber(); 16437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 165f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symb.isAnyUndefined() || Symb.isCommon() || 166f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar COFF::isReservedSectionNumber(SectionNumber)) 167f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Result; 16837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 169f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const coff_section *Section = nullptr; 170f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (std::error_code EC = getSection(SectionNumber, Section)) 171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorCodeToError(EC); 172f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Result += Section->VirtualAddress; 173f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 174f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // The section VirtualAddress does not include ImageBase, and we want to 175f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // return virtual addresses. 176f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Result += getImageBase(); 177f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 178f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Result; 179ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 180ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 181de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { 18237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFSymbolRef Symb = getCOFFSymbol(Ref); 18337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int32_t SectionNumber = Symb.getSectionNumber(); 184f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 185f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) 186f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_Function; 187f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symb.isAnyUndefined()) 188f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_Unknown; 189f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symb.isCommon()) 190f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_Data; 191f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symb.isFileRecord()) 192f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_File; 193f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 194f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // TODO: perhaps we need a new symbol type ST_Section. 195f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) 196f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_Debug; 197f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 198f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (!COFF::isReservedSectionNumber(SectionNumber)) 199f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_Data; 200f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 201f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return SymbolRef::ST_Other; 202ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 203ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesuint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 20537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFSymbolRef Symb = getCOFFSymbol(Ref); 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Result = SymbolRef::SF_None; 207c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 20837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.isExternal() || Symb.isWeakExternal()) 209c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Global; 210c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 21137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.isWeakExternal()) 212c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Weak; 213c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 21437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) 215c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Absolute; 216ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 21737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.isFileRecord()) 21837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result |= SymbolRef::SF_FormatSpecific; 21937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 22037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.isSectionDefinition()) 22137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result |= SymbolRef::SF_FormatSpecific; 22237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 22337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.isCommon()) 22437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result |= SymbolRef::SF_Common; 22537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 22637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symb.isAnyUndefined()) 22737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result |= SymbolRef::SF_Undefined; 22837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Result; 230c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer} 231c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer 232f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainaruint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { 23337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFSymbolRef Symb = getCOFFSymbol(Ref); 234f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Symb.getValue(); 235a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 236a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 237de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<section_iterator> 238f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarCOFFObjectFile::getSymbolSection(DataRefImpl Ref) const { 23937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFSymbolRef Symb = getCOFFSymbol(Ref); 240f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) 241f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return section_end(); 242f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const coff_section *Sec = nullptr; 243f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) 244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorCodeToError(EC); 245f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DataRefImpl Ret; 246f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Ret.p = reinterpret_cast<uintptr_t>(Sec); 247f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return section_iterator(SectionRef(Ret, this)); 248f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 249f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 250f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarunsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 251f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); 252f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Symb.getSectionNumber(); 2539b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer} 2549b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer 25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Sec += 1; 25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(Sec); 259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 261c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 262c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StringRef &Result) const { 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return getSectionName(Sec, Result); 265a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 266a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 26737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesuint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 269f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint64_t Result = Sec->VirtualAddress; 270f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 271f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // The section VirtualAddress does not include ImageBase, and we want to 272f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // return virtual addresses. 273f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Result += getImageBase(); 274f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Result; 275a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 276a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 27737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesuint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { 27837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return getSectionSize(toSec(Ref)); 279a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 280a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 281c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 282c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StringRef &Result) const { 28336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 2841f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer ArrayRef<uint8_t> Res; 285c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines std::error_code EC = getSectionContents(Sec, Res); 2861f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2871f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return EC; 288a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 289a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 29037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesuint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { 29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 292de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Sec->getAlignment(); 293de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 294de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 295de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarbool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 296de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return false; 297e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer} 298e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer 29937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool COFFObjectFile::isSectionText(DataRefImpl Ref) const { 30036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 30137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 30213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 30313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 30437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool COFFObjectFile::isSectionData(DataRefImpl Ref) const { 30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 30637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 30713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 30813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 30937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { 31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 3114c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 3124c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar COFF::IMAGE_SCN_MEM_READ | 3134c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar COFF::IMAGE_SCN_MEM_WRITE; 3144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return (Sec->Characteristics & BssFlags) == BssFlags; 315a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 316a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 317f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarunsigned COFFObjectFile::getSectionID(SectionRef Sec) const { 318f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uintptr_t Offset = 319f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uintptr_t(Sec.getRawDataRefImpl().p) - uintptr_t(SectionTable); 320f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar assert((Offset % sizeof(coff_section)) == 0); 321f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return (Offset / sizeof(coff_section)) + 1; 322f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 323f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 32437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { 32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 3264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // In COFF, a virtual section won't have any in-file 3274c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // content, so the file pointer to the content will be zero. 3284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return Sec->PointerToRawData == 0; 329c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd} 330c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint32_t getNumberOfRelocations(const coff_section *Sec, 33237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines MemoryBufferRef M, const uint8_t *base) { 33336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The field for the number of relocations in COFF section table is only 33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // NumberOfRelocations field, and the actual relocation count is stored in the 33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // VirtualAddress field in the first relocation entry. 33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Sec->hasExtendedRelocations()) { 33837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_relocation *FirstReloc; 33937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (getObject(FirstReloc, M, reinterpret_cast<const coff_relocation*>( 34037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines base + Sec->PointerToRelocations))) 34137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return 0; 342ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // -1 to exclude this first relocation entry. 343ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return FirstReloc->VirtualAddress - 1; 34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Sec->NumberOfRelocations; 3464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 3474344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 34837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic const coff_relocation * 34937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesgetFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { 35037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); 35137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!NumRelocs) 35237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return nullptr; 35337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto begin = reinterpret_cast<const coff_relocation *>( 35437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Base + Sec->PointerToRelocations); 35537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Sec->hasExtendedRelocations()) { 35637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Skip the first relocation entry repurposed to store the number of 35737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // relocations. 35837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines begin++; 35937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 36037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) 36137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return nullptr; 36237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return begin; 36337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 36437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 36537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesrelocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 36637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_section *Sec = toSec(Ref); 36737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_relocation *begin = getFirstReloc(Sec, Data, base()); 368f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (begin && Sec->VirtualAddress != 0) 369f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar report_fatal_error("Sections with relocations should have an address of 0"); 37037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DataRefImpl Ret; 37137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(begin); 37237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return relocation_iterator(RelocationRef(Ret, this)); 37337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 37437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesrelocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 37737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_relocation *I = getFirstReloc(Sec, Data, base()); 37837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (I) 37937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines I += getNumberOfRelocations(Sec, Data, base()); 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 38137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(I); 38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return relocation_iterator(RelocationRef(Ret, this)); 38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 3844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 385a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Initialize the pointer to the symbol table. 386c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::initSymbolTablePtr() { 38737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (COFFHeader) 38837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = getObject( 38937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SymbolTable16, Data, base() + getPointerToSymbolTable(), 39037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 39137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 39237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 39337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (COFFBigObjHeader) 39437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = getObject( 39537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SymbolTable32, Data, base() + getPointerToSymbolTable(), 39637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) 39737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 398a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 399a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Find string table. The first four byte of the string table contains the 400a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // total size of the string table, including the size field itself. If the 401a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // string table is empty, the value of the first four byte would be 4. 40237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t StringTableOffset = getPointerToSymbolTable() + 40337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines getNumberOfSymbols() * getSymbolTableEntrySize(); 40437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const uint8_t *StringTableAddr = base() + StringTableOffset; 405a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const ulittle32_t *StringTableSizePtr; 40637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) 40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 408a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama StringTableSize = *StringTableSizePtr; 409c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = 41037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines getObject(StringTable, Data, StringTableAddr, StringTableSize)) 41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // tools like cvtres write a size of 0 for an empty table instead of 4. 41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (StringTableSize < 4) 41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringTableSize = 4; 417a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 418a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Check that the string table is null terminated if has any in it. 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 420a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::parse_failed; 4216948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 422a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 423a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 424f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainaruint64_t COFFObjectFile::getImageBase() const { 425f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (PE32Header) 426f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return PE32Header->ImageBase; 427f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar else if (PE32PlusHeader) 428f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return PE32PlusHeader->ImageBase; 429f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // This actually comes up in practice. 430f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return 0; 431f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 432f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the file offset for the given VA. 434c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 435f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint64_t ImageBase = getImageBase(); 43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Rva = Addr - ImageBase; 43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Rva <= UINT32_MAX); 43836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return getRvaPtr((uint32_t)Rva, Res); 43936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 44036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 441a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Returns the file offset for the given RVA. 442c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 44336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const SectionRef &S : sections()) { 44436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Section = getCOFFSection(S); 445a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 446a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 44736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SectionStart <= Addr && Addr < SectionEnd) { 44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Offset = Addr - SectionStart; 449a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 4506948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 451a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 452a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 453a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::parse_failed; 454a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 455a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 456de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code 457de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarCOFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, 458de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ArrayRef<uint8_t> &Contents) const { 459de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (const SectionRef &S : sections()) { 460de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const coff_section *Section = getCOFFSection(S); 461de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t SectionStart = Section->VirtualAddress; 462de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Check if this RVA is within the section bounds. Be careful about integer 463de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // overflow. 464de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t OffsetIntoSection = RVA - SectionStart; 465de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && 466de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Size <= Section->VirtualSize - OffsetIntoSection) { 467de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uintptr_t Begin = 468de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; 469de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Contents = 470de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); 471de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 472de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 473de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 474de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return object_error::parse_failed; 475de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 476de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 477a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 478a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// table entry. 479c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 480c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StringRef &Name) const { 481a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 482c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 48336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 484a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 485a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 486a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 4876948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 488a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 489a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 490de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, 491de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const debug_pdb_info *&PDBInfo, 492de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef &PDBFileName) const { 493de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ArrayRef<uint8_t> InfoBytes; 494de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (std::error_code EC = getRvaAndSizeAsBytes( 495de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) 496de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 497de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (InfoBytes.size() < sizeof(debug_pdb_info) + 1) 498de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return object_error::parse_failed; 499de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar PDBInfo = reinterpret_cast<const debug_pdb_info *>(InfoBytes.data()); 500de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar InfoBytes = InfoBytes.drop_front(sizeof(debug_pdb_info)); 501de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), 502de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar InfoBytes.size()); 503de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Truncate the name at the first null byte. Ignore any padding. 504de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar PDBFileName = PDBFileName.split('\0').first; 505de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 506de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 507de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 508de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code COFFObjectFile::getDebugPDBInfo(const debug_pdb_info *&PDBInfo, 509de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef &PDBFileName) const { 510de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (const debug_directory &D : debug_directories()) 511de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) 512de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return getDebugPDBInfo(&D, PDBInfo, PDBFileName); 513de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // If we get here, there is no PDB info to return. 514de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar PDBInfo = nullptr; 515de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar PDBFileName = StringRef(); 516de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 517de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 518de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 519a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Find the import table. 520c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::initImportTablePtr() { 521a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 522a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // the import table, do nothing. 523a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const data_directory *DataEntry; 524a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 5256948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 526a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 527a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Do nothing if the pointer to import table is NULL. 528a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 5296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 530a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 531a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 532a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 533a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 534a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // the import table's memory address which is different from its file offset. 535a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 536c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 53736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 538de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) 539de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 540a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama ImportDirectory = reinterpret_cast< 541a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const import_directory_table_entry *>(IntPtr); 5426948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 54336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 544a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 54537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Initializes DelayImportDirectory and NumberOfDelayImportDirectory. 54637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code COFFObjectFile::initDelayImportTablePtr() { 54737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const data_directory *DataEntry; 54837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) 5496948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 55037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (DataEntry->RelativeVirtualAddress == 0) 5516948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 55237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 55337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t RVA = DataEntry->RelativeVirtualAddress; 55437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines NumberOfDelayImportDirectory = DataEntry->Size / 55537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof(delay_import_directory_table_entry) - 1; 55637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 55737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 55837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = getRvaPtr(RVA, IntPtr)) 55937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 56037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DelayImportDirectory = reinterpret_cast< 56137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const delay_import_directory_table_entry *>(IntPtr); 5626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 56337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 56437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 56536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Find the export table. 566c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::initExportTablePtr() { 56736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // First, we get the RVA of the export table. If the file lacks a pointer to 56836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // the export table, do nothing. 56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const data_directory *DataEntry; 57036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 5716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 57236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 57336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Do nothing if the pointer to export table is NULL. 57436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (DataEntry->RelativeVirtualAddress == 0) 5756948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 57636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 57736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 57836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 579c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 58036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 58136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectory = 58236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines reinterpret_cast<const export_directory_table_entry *>(IntPtr); 5836948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 584a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 585a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 58637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code COFFObjectFile::initBaseRelocPtr() { 58737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const data_directory *DataEntry; 58837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) 5896948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 59037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (DataEntry->RelativeVirtualAddress == 0) 5916948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 59237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 59337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 59437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 59537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 59637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>( 59737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IntPtr); 59837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( 59937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines IntPtr + DataEntry->Size); 6006948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 60137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 60237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 603de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code COFFObjectFile::initDebugDirectoryPtr() { 604de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Get the RVA of the debug directory. Do nothing if it does not exist. 605de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const data_directory *DataEntry; 606de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) 607de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 608de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 609de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Do nothing if the RVA is NULL. 610de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (DataEntry->RelativeVirtualAddress == 0) 611de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 612de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 613de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Check that the size is a multiple of the entry size. 614de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (DataEntry->Size % sizeof(debug_directory) != 0) 615de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return object_error::parse_failed; 616de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 617de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uintptr_t IntPtr = 0; 618de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) 619de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 620de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); 621de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (std::error_code EC = getRvaPtr( 622de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) 623de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 624de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); 625de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 626de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 627de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 62837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) 62937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), 63037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), 63137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), 63237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), 633de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ImportDirectory(nullptr), 63437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), 635de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), 636de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { 63725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that we at least have enough room for a header. 63837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!checkSize(Data, EC, sizeof(coff_file_header))) 639c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return; 640539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 6414bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // The current location in the file where we are looking at. 6424bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama uint64_t CurPtr = 0; 6434bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama 6444bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // PE header is optional and is present only in executables. If it exists, 6454bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // it is placed right after COFF header. 64636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool HasPEHeader = false; 647539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 64825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check if this is a PE/COFF file. 64937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { 650539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 651539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE signature to find 'normal' COFF header. 65237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const auto *DH = reinterpret_cast<const dos_header *>(base()); 65337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { 65437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines CurPtr = DH->AddressOfNewExeHeader; 65537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Check the PE magic bytes. ("PE\0\0") 65637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { 65737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines EC = object_error::parse_failed; 65837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return; 65937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 66037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. 66137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines HasPEHeader = true; 66225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 663539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher } 664539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 66537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) 66625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 66737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 66837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // It might be a bigobj file, let's check. Note that COFF bigobj and COFF 66937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // import libraries share a common prefix but bigobj is more restrictive. 67037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && 67137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFHeader->NumberOfSections == uint16_t(0xffff) && 67237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { 67337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) 67437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return; 67537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 67637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Verify that we are dealing with bigobj. 67737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && 67837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, 67937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof(COFF::BigObjMagic)) == 0) { 68037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFHeader = nullptr; 68137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines CurPtr += sizeof(coff_bigobj_file_header); 68237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 68337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // It's not a bigobj. 68437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFBigObjHeader = nullptr; 68537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 68637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 68737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (COFFHeader) { 68837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // The prior checkSize call may have failed. This isn't a hard error 68937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // because we were just trying to sniff out bigobj. 6906948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar EC = std::error_code(); 69137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines CurPtr += sizeof(coff_file_header); 69237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 69337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (COFFHeader->isImportLibrary()) 69437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return; 69537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 6960fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 69736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (HasPEHeader) { 69836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const pe32_header *Header; 69937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = getObject(Header, Data, base() + CurPtr))) 70036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 70136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 70236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const uint8_t *DataDirAddr; 70336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t DataDirSize; 70437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Header->Magic == COFF::PE32Header::PE32) { 70536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PE32Header = Header; 70636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirAddr = base() + CurPtr + sizeof(pe32_header); 70736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 70837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { 70936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 71036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 71136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 71236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 71336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // It's neither PE32 nor PE32+. 71436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EC = object_error::parse_failed; 7154bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama return; 7162f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama } 71737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) 71836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 7194bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 7204bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama } 7210fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 72237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = getObject(SectionTable, Data, base() + CurPtr, 72337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (uint64_t)getNumberOfSections() * sizeof(coff_section)))) 72436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 725a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 726a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Initialize the pointer to the symbol table. 72737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (getPointerToSymbolTable() != 0) { 72836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((EC = initSymbolTablePtr())) 7297151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer return; 73037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 73137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // We had better not have any symbols if we don't have a symbol table. 73237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (getNumberOfSymbols() != 0) { 73337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines EC = object_error::parse_failed; 73437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return; 73537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 73637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 7372f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama 738a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Initialize the pointer to the beginning of the import table. 73936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((EC = initImportTablePtr())) 740a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return; 74137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = initDelayImportTablePtr())) 74237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return; 7430fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 74436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Initialize the pointer to the export table. 74536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((EC = initExportTablePtr())) 74636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 747a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 74837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Initialize the pointer to the base relocation table. 74937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if ((EC = initBaseRelocPtr())) 75037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return; 75137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 752de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Initialize the pointer to the export table. 753de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if ((EC = initDebugDirectoryPtr())) 754de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return; 755de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 7566948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar EC = std::error_code(); 757a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 758a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 75936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbasic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 76036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 76137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ret.p = getSymbolTable(); 76236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return basic_symbol_iterator(SymbolRef(Ret, this)); 763dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer} 764dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer 76536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbasic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 76636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The symbol table ends where the string table begins. 76736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 76836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(StringTable); 76936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return basic_symbol_iterator(SymbolRef(Ret, this)); 770dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer} 771dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer 77229552222c2e7cbeb37fcd15d247597467f7b8544Rui Ueyamaimport_directory_iterator COFFObjectFile::import_directory_begin() const { 773de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!ImportDirectory) 774de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return import_directory_end(); 775de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (ImportDirectory[0].ImportLookupTableRVA == 0) 776de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return import_directory_end(); 77736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return import_directory_iterator( 77836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ImportDirectoryEntryRef(ImportDirectory, 0, this)); 779a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 780a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 78129552222c2e7cbeb37fcd15d247597467f7b8544Rui Ueyamaimport_directory_iterator COFFObjectFile::import_directory_end() const { 78236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return import_directory_iterator( 783de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ImportDirectoryEntryRef(nullptr, -1, this)); 78436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 78536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 78637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesdelay_import_directory_iterator 78737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::delay_import_directory_begin() const { 78837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return delay_import_directory_iterator( 78937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); 79037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 79137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 79237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesdelay_import_directory_iterator 79337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::delay_import_directory_end() const { 79437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return delay_import_directory_iterator( 79537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DelayImportDirectoryEntryRef( 79637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DelayImportDirectory, NumberOfDelayImportDirectory, this)); 79737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 79837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 79936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesexport_directory_iterator COFFObjectFile::export_directory_begin() const { 80036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return export_directory_iterator( 80136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectoryEntryRef(ExportDirectory, 0, this)); 80236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 80336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 80436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesexport_directory_iterator COFFObjectFile::export_directory_end() const { 805dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!ExportDirectory) 806dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 80736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectoryEntryRef Ref(ExportDirectory, 80836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectory->AddressTableEntries, this); 80936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return export_directory_iterator(Ref); 810a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 81197f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer 81236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinessection_iterator COFFObjectFile::section_begin() const { 81336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 81436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 81536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return section_iterator(SectionRef(Ret, this)); 816a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 817a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 81836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinessection_iterator COFFObjectFile::section_end() const { 81936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 82037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int NumSections = 82137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); 82236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 82336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return section_iterator(SectionRef(Ret, this)); 824a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 825a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 82637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbase_reloc_iterator COFFObjectFile::base_reloc_begin() const { 82737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); 82837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 82937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 83037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbase_reloc_iterator COFFObjectFile::base_reloc_end() const { 83137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); 83237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 83337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 834a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const { 8357acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 836a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 837a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 838a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const { 83937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines switch(getMachine()) { 840a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 841a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-i386"; 842a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 843a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-x86-64"; 84436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case COFF::IMAGE_FILE_MACHINE_ARMNT: 84536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return "COFF-ARM"; 846f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar case COFF::IMAGE_FILE_MACHINE_ARM64: 847f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return "COFF-ARM64"; 848a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 849a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-<unknown arch>"; 850a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 851a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 852a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 853a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const { 85437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines switch (getMachine()) { 855a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 856a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86; 857a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 858a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86_64; 85936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case COFF::IMAGE_FILE_MACHINE_ARMNT: 86036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Triple::thumb; 861f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar case COFF::IMAGE_FILE_MACHINE_ARM64: 862f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Triple::aarch64; 863a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 864a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::UnknownArch; 865a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 866a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 867a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 86837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesiterator_range<import_directory_iterator> 86937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::import_directories() const { 87037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return make_range(import_directory_begin(), import_directory_end()); 8714bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama} 8724bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama 87337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesiterator_range<delay_import_directory_iterator> 87437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::delay_import_directories() const { 87537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return make_range(delay_import_directory_begin(), 87637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines delay_import_directory_end()); 87737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 87837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 87937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesiterator_range<export_directory_iterator> 88037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::export_directories() const { 88137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return make_range(export_directory_begin(), export_directory_end()); 88237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 88337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 88437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesiterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { 88537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return make_range(base_reloc_begin(), base_reloc_end()); 8864bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama} 8874bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama 888c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 8894bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama Res = PE32Header; 8906948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 8910e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 8920e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 893c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code 89436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 89536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = PE32PlusHeader; 8966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 89736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 89836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 899c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code 900c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesCOFFObjectFile::getDataDirectory(uint32_t Index, 901c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines const data_directory *&Res) const { 9022f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama // Error if if there's no data directory or the index is out of range. 90337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!DataDirectory) { 90437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Res = nullptr; 90536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 90637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 90736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(PE32Header || PE32PlusHeader); 90836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 90936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : PE32PlusHeader->NumberOfRvaAndSize; 91037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Index >= NumEnt) { 91137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Res = nullptr; 9122f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama return object_error::parse_failed; 91337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 91436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = &DataDirectory[Index]; 9156948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 9160e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 9170e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 918c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getSection(int32_t Index, 919c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines const coff_section *&Result) const { 92037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = nullptr; 92136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (COFF::isReservedSectionNumber(Index)) 9226948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 92337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { 92425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // We already verified the section table data, so no need to check again. 92536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = SectionTable + (Index - 1); 9266948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 92737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 92837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return object_error::parse_failed; 929a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 930a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 931c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getString(uint32_t Offset, 932c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StringRef &Result) const { 93325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize <= 4) 93425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Tried to get a string from an empty string table. 93525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 93636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Offset >= StringTableSize) 93725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::unexpected_eof; 93836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(StringTable + Offset); 9396948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 940a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 941a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 94237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, 943c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StringRef &Res) const { 944f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return getSymbolName(Symbol.getGeneric(), Res); 945f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 946f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 947f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarstd::error_code COFFObjectFile::getSymbolName(const coff_symbol_generic *Symbol, 948f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar StringRef &Res) const { 9490e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Check for string table entry. First 4 bytes are 0. 950f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symbol->Name.Offset.Zeroes == 0) { 951f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (std::error_code EC = getString(Symbol->Name.Offset.Offset, Res)) 95236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 9536948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 9540e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer } 9550e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 956f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (Symbol->Name.ShortName[COFF::NameSize - 1] == 0) 9570e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Null terminated, let ::strlen figure out the length. 958f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Res = StringRef(Symbol->Name.ShortName); 9590e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer else 9600e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Not null terminated, use all 8 bytes. 961f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Res = StringRef(Symbol->Name.ShortName, COFF::NameSize); 9626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 9630e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 9640e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 96537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesArrayRef<uint8_t> 96637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { 967dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const uint8_t *Aux = nullptr; 968a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 96937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines size_t SymbolSize = getSymbolTableEntrySize(); 97037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Symbol.getNumberOfAuxSymbols() > 0) { 97137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // AUX data comes immediately after the symbol in COFF 97237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; 973d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow# ifndef NDEBUG 97436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Verify that the Aux symbol points to a valid entry in the symbol table. 97536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 97637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Offset < getPointerToSymbolTable() || 97737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Offset >= 97837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) 979d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 980d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 98137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && 98237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines "Aux Symbol data did not point to the beginning of a symbol"); 983d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow# endif 98445aad162c68ee58ba1aa8984499064f6b9c8d0f9Marshall Clow } 98537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); 986d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow} 987d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 988c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 989c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines StringRef &Res) const { 990b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer StringRef Name; 99137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Sec->Name[COFF::NameSize - 1] == 0) 992b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Null terminated, let ::strlen figure out the length. 993b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Name = Sec->Name; 994b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer else 995b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Not null terminated, use all 8 bytes. 99637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Name = StringRef(Sec->Name, COFF::NameSize); 997b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 998b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Check for string table entry. First byte is '/'. 99937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Name.startswith("/")) { 1000b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer uint32_t Offset; 100137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Name.startswith("//")) { 100236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (decodeBase64StringEntry(Name.substr(2), Offset)) 100336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 100436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 100536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Name.substr(1).getAsInteger(10, Offset)) 100636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 100736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 1008c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = getString(Offset, Name)) 100936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 1010b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer } 1011b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 1012b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Res = Name; 10136948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 1014b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer} 1015b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 101637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesuint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { 101737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // SizeOfRawData and VirtualSize change what they represent depending on 101837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // whether or not we have an executable image. 101937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // 102037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // For object files, SizeOfRawData contains the size of section's data; 1021f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar // VirtualSize should be zero but isn't due to buggy COFF writers. 102237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // 102337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the 102437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // actual section size is in VirtualSize. It is possible for VirtualSize to 102537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // be greater than SizeOfRawData; the contents past that point should be 102637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // considered to be zero. 1027f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (getDOSHeader()) 1028f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 1029f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return Sec->SizeOfRawData; 103037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 103137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 1032c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code 1033c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesCOFFObjectFile::getSectionContents(const coff_section *Sec, 1034c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ArrayRef<uint8_t> &Res) const { 1035de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // In COFF, a virtual section won't have any in-file 1036de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // content, so the file pointer to the content will be zero. 1037de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Sec->PointerToRawData == 0) 1038de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return object_error::parse_failed; 10391f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // The only thing that we need to verify is that the contents is contained 10401f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 10411f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // data, as there's nothing that says that is not allowed. 10421f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 104337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t SectionSize = getSectionSize(Sec); 104437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (checkOffset(Data, ConStart, SectionSize)) 10451f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return object_error::parse_failed; 104637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); 10476948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 10481f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer} 10491f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer 10500fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 10514344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 10520fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 105336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 105436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 10554344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 10564344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 10570fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 105836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1059f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainaruint64_t COFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 106037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_relocation *R = toRel(Rel); 1061f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return R->VirtualAddress; 10620fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 106336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 10646c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindolasymbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 106537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const coff_relocation *R = toRel(Rel); 106636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ref; 106737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (R->SymbolTableIndex >= getNumberOfSymbols()) 106837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return symbol_end(); 106937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolTable16) 107037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(SymbolTable16 + R->SymbolTableIndex); 107137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines else if (SymbolTable32) 107237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(SymbolTable32 + R->SymbolTableIndex); 107337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines else 1074ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines llvm_unreachable("no symbol table pointer!"); 107536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return symbol_iterator(SymbolRef(Ref, this)); 10760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 107736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1078f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainaruint64_t COFFObjectFile::getRelocationType(DataRefImpl Rel) const { 10790fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 1080f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return R->Type; 10810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 10824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 108336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_section * 108436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getCOFFSection(const SectionRef &Section) const { 108536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return toSec(Section.getRawDataRefImpl()); 1086d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow} 1087d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 108837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { 108937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolTable16) 109037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return toSymb<coff_symbol16>(Ref); 109137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolTable32) 109237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return toSymb<coff_symbol32>(Ref); 109337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines llvm_unreachable("no symbol table pointer!"); 109437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 109537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 109637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesCOFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 109737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return getCOFFSymbol(Symbol.getRawDataRefImpl()); 1098d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow} 1099d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 110036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_relocation * 110136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 110236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return toRel(Reloc.getRawDataRefImpl()); 11039ac0f1d7255d7941c331b0a62a830a3b033358fdMarshall Clow} 11049ac0f1d7255d7941c331b0a62a830a3b033358fdMarshall Clow 1105f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainariterator_range<const coff_relocation *> 1106f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga NainarCOFFObjectFile::getRelocations(const coff_section *Sec) const { 1107f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const coff_relocation *I = getFirstReloc(Sec, Data, base()); 1108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar const coff_relocation *E = I; 1109f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar if (I) 1110f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar E += getNumberOfRelocations(Sec, Data, base()); 1111f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar return make_range(I, E); 1112f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar} 1113f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar 111436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 111536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case COFF::reloc_type: \ 111636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = #reloc_type; \ 111736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 11184344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 1119f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarvoid COFFObjectFile::getRelocationTypeName( 1120f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 112136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_relocation *Reloc = toRel(Rel); 112236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef Res; 112337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines switch (getMachine()) { 11244344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 112536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (Reloc->Type) { 11264344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 11274344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 11284344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 11294344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 11304344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 11314344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 11324344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 11334344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 11344344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 11354344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 11364344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 11374344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 11384344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 11394344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 11404344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 11414344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 11424344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 11434344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 114436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = "Unknown"; 11454344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 11464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 1147dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case COFF::IMAGE_FILE_MACHINE_ARMNT: 1148dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines switch (Reloc->Type) { 1149dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 1150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 1151dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 1152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 1153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 1154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 1155dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 1156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 1157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 1158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 1159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 1160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 1161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 1162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 1163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 1164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines default: 1165dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Res = "Unknown"; 1166dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 1167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 11684344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 116936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (Reloc->Type) { 11704344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 11714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 11724344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 11734344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 11744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 11754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 11764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 11774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 11784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 11794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 11804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 11814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 118236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = "Unknown"; 11834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 11844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 11854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 118636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = "Unknown"; 11874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 118836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result.append(Res.begin(), Res.end()); 11894344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 11904344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 11914344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 11924344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 119337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool COFFObjectFile::isRelocatableObject() const { 119437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return !DataDirectory; 11955c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 11965c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 1197a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamabool ImportDirectoryEntryRef:: 1198a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamaoperator==(const ImportDirectoryEntryRef &Other) const { 119936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ImportTable == Other.ImportTable && Index == Other.Index; 1200a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1201a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 120236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid ImportDirectoryEntryRef::moveNext() { 120336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Index; 1204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (ImportTable[Index].ImportLookupTableRVA == 0) { 1205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Index = -1; 1206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ImportTable = nullptr; 1207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 1208a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1209a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 1210c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code ImportDirectoryEntryRef::getImportTableEntry( 1211c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines const import_directory_table_entry *&Result) const { 1212de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return getObject(Result, OwningObject->Data, ImportTable + Index); 1213a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1214a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 121537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic imported_symbol_iterator 121637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesmakeImportedSymbolIterator(const COFFObjectFile *Object, 121737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t Ptr, int Index) { 121837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Object->getBytesInAddress() == 4) { 121937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr); 122037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 122137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 122237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr); 122337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); 122437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 122537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 122637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic imported_symbol_iterator 122737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesimportedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { 122837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 122937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Object->getRvaPtr(RVA, IntPtr); 123037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return makeImportedSymbolIterator(Object, IntPtr, 0); 123137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 123237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 123337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic imported_symbol_iterator 123437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesimportedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { 123537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 123637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Object->getRvaPtr(RVA, IntPtr); 123737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Forward the pointer to the last entry which is null. 123837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int Index = 0; 123937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Object->getBytesInAddress() == 4) { 124037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr); 124137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines while (*Entry++) 124237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++Index; 124337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 124437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr); 124537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines while (*Entry++) 124637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++Index; 124737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 124837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return makeImportedSymbolIterator(Object, IntPtr, Index); 124937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 125037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 125137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimported_symbol_iterator 125237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesImportDirectoryEntryRef::imported_symbol_begin() const { 125337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, 125437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningObject); 125537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 125637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 125737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimported_symbol_iterator 125837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesImportDirectoryEntryRef::imported_symbol_end() const { 125937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, 126037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningObject); 126137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 126237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 126337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesiterator_range<imported_symbol_iterator> 126437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesImportDirectoryEntryRef::imported_symbols() const { 126537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return make_range(imported_symbol_begin(), imported_symbol_end()); 126637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 126737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 1268c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1269a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 1270c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = 127137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) 127236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 127336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 12746948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 1275a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1276a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 127737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code 127837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { 127937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = ImportTable[Index].ImportLookupTableRVA; 12806948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 128137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 128237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 128337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code 128437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { 128537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = ImportTable[Index].ImportAddressTableRVA; 12866948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 128737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 128837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 128937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool DelayImportDirectoryEntryRef:: 129037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesoperator==(const DelayImportDirectoryEntryRef &Other) const { 129137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return Table == Other.Table && Index == Other.Index; 129237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 129337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 129437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid DelayImportDirectoryEntryRef::moveNext() { 129537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++Index; 129637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 129737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 129837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimported_symbol_iterator 129937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesDelayImportDirectoryEntryRef::imported_symbol_begin() const { 130037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return importedSymbolBegin(Table[Index].DelayImportNameTable, 130137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningObject); 130237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 130337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 130437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesimported_symbol_iterator 130537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesDelayImportDirectoryEntryRef::imported_symbol_end() const { 130637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return importedSymbolEnd(Table[Index].DelayImportNameTable, 130737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningObject); 130837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 130937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 131037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesiterator_range<imported_symbol_iterator> 131137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesDelayImportDirectoryEntryRef::imported_symbols() const { 131237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return make_range(imported_symbol_begin(), imported_symbol_end()); 131337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 131437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 131537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { 131637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 131737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) 131837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 131937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13206948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 132137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 132237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 132337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code DelayImportDirectoryEntryRef:: 132437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesgetDelayImportTable(const delay_import_directory_table_entry *&Result) const { 132537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = Table; 13266948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 132737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 132837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 132937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code DelayImportDirectoryEntryRef:: 133037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesgetImportAddress(int AddrIndex, uint64_t &Result) const { 133137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t RVA = Table[Index].DelayImportAddressTable + 133237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines AddrIndex * (OwningObject->is64() ? 8 : 4); 133337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 133437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 133537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 133637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (OwningObject->is64()) 133737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); 133837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines else 133937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); 13406948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 134137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 134237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 134336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool ExportDirectoryEntryRef:: 134436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesoperator==(const ExportDirectoryEntryRef &Other) const { 134536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ExportTable == Other.ExportTable && Index == Other.Index; 134636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 134736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 134836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid ExportDirectoryEntryRef::moveNext() { 134936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Index; 135036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 1351a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 135236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the name of the current export symbol. If the symbol is exported only 135336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// by ordinal, the empty string is set as a result. 1354c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 135536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 1356c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = 1357c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 135836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 135936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 13606948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 136136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 136236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 136336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the starting ordinal number. 1364c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code 1365c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 136636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ExportTable->OrdinalBase; 13676948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 136836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 136936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 137036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the export ordinal of the current export symbol. 1371c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 137236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ExportTable->OrdinalBase + Index; 13736948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 137436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 137536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 137636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the address of the current export symbol. 1377c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 137836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 1379c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = 1380c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 138136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 138236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const export_address_table_entry *entry = 138336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines reinterpret_cast<const export_address_table_entry *>(IntPtr); 138436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = entry[Index].ExportRVA; 13856948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 138636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 138736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 138836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the name of the current export symbol. If the symbol is exported only 138936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// by ordinal, the empty string is set as a result. 1390c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstd::error_code 1391c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen HinesExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 139236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 1393c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = 1394c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 139536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 139636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 139736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 139836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t NumEntries = ExportTable->NumberOfNamePointers; 139936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int Offset = 0; 140036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const ulittle16_t *I = Start, *E = Start + NumEntries; 140136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines I < E; ++I, ++Offset) { 140236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (*I != Index) 140336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 1404c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = 1405c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 140636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 140736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1408c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 140936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 141036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 14116948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 1412a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 141336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ""; 14146948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 141536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 1416a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 1417de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code ExportDirectoryEntryRef::isForwarder(bool &Result) const { 1418de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const data_directory *DataEntry; 1419de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = OwningObject->getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 1420de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 1421de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t RVA; 1422de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = getExportRVA(RVA)) 1423de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 1424de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t Begin = DataEntry->RelativeVirtualAddress; 1425de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t End = DataEntry->RelativeVirtualAddress + DataEntry->Size; 1426de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Result = (Begin <= RVA && RVA < End); 1427de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 1428de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 1429de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 1430de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code ExportDirectoryEntryRef::getForwardTo(StringRef &Result) const { 1431de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t RVA; 1432de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = getExportRVA(RVA)) 1433de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 1434de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uintptr_t IntPtr = 0; 1435de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = OwningObject->getRvaPtr(RVA, IntPtr)) 1436de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return EC; 1437de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1438de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 1439de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 1440de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 144137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool ImportedSymbolRef:: 144237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesoperator==(const ImportedSymbolRef &Other) const { 144337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 144437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines && Index == Other.Index; 144537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 144637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 144737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid ImportedSymbolRef::moveNext() { 144837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++Index; 144937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 145037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 145137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code 145237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesImportedSymbolRef::getSymbolName(StringRef &Result) const { 145337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t RVA; 145437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Entry32) { 145537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // If a symbol is imported only by ordinal, it has no name. 145637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Entry32[Index].isOrdinal()) 14576948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 145837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines RVA = Entry32[Index].getHintNameRVA(); 145937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 146037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Entry64[Index].isOrdinal()) 14616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 146237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines RVA = Entry64[Index].getHintNameRVA(); 146337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 146437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 146537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 146637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 146737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // +2 because the first two bytes is hint. 146837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); 14696948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 147037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 147137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 1472de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { 1473de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Entry32) 1474de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Result = Entry32[Index].isOrdinal(); 1475de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else 1476de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Result = Entry64[Index].isOrdinal(); 1477de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 1478de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 1479de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 1480de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { 1481de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Entry32) 1482de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Result = Entry32[Index].getHintNameRVA(); 1483de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar else 1484de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Result = Entry64[Index].getHintNameRVA(); 1485de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::error_code(); 1486de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 1487de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 148837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { 148937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t RVA; 149037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Entry32) { 149137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Entry32[Index].isOrdinal()) { 149237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = Entry32[Index].getOrdinal(); 14936948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 149437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 149537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines RVA = Entry32[Index].getHintNameRVA(); 149637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 149737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Entry64[Index].isOrdinal()) { 149837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = Entry64[Index].getOrdinal(); 14996948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 150037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 150137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines RVA = Entry64[Index].getHintNameRVA(); 150237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 150337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uintptr_t IntPtr = 0; 150437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) 150537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return EC; 150637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); 15076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 150837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 150937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 151037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesErrorOr<std::unique_ptr<COFFObjectFile>> 151137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { 1512c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines std::error_code EC; 151337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC)); 151436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (EC) 151536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 151637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return std::move(Ret); 151737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 151837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 151937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool BaseRelocRef::operator==(const BaseRelocRef &Other) const { 152037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return Header == Other.Header && Index == Other.Index; 152137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 152237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 152337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid BaseRelocRef::moveNext() { 152437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Header->BlockSize is the size of the current block, including the 152537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // size of the header itself. 152637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t Size = sizeof(*Header) + 152737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof(coff_base_reloc_block_entry) * (Index + 1); 152837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Size == Header->BlockSize) { 152937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // .reloc contains a list of base relocation blocks. Each block 153037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // consists of the header followed by entries. The header contains 153137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // how many entories will follow. When we reach the end of the 153237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // current block, proceed to the next block. 153337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Header = reinterpret_cast<const coff_base_reloc_block_header *>( 153437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines reinterpret_cast<const uint8_t *>(Header) + Size); 153537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Index = 0; 153637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else { 153737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++Index; 153837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 153937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 154037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 154137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code BaseRelocRef::getType(uint8_t &Type) const { 154237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 154337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Type = Entry[Index].getType(); 15446948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 154537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 154637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 154737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::error_code BaseRelocRef::getRVA(uint32_t &Result) const { 154837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); 154937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Result = Header->PageRVA + Entry[Index].getOffset(); 15506948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar return std::error_code(); 155136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 1552