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" 164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#include "llvm/ADT/SmallString.h" 17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h" 18a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.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::ulittle8_t; 29a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t; 30a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_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. 34cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic bool checkSize(const MemoryBuffer &M, std::error_code &EC, 35cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t Size) { 36cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (M.getBufferSize() < Size) { 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EC = object_error::unexpected_eof; 3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 432f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 442f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama// Returns unexpected_eof if error. 45cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinestemplate <typename T> 46cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::error_code getObject(const T *&Obj, const MemoryBuffer &M, 47cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const uint8_t *Ptr, 48cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const size_t Size = sizeof(T)) { 492f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama uintptr_t Addr = uintptr_t(Ptr); 50cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (Addr + Size < Addr || Addr + Size < Size || 51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines Addr + Size > uintptr_t(M.getBufferEnd())) { 522f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama return object_error::unexpected_eof; 5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 542f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama Obj = reinterpret_cast<const T *>(Addr); 552f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama return object_error::success; 5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without 5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// prefixed slashes. 6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { 6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Str.size() <= 6 && "String too long, possible overflow."); 6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Str.size() > 6) 6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Value = 0; 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines while (!Str.empty()) { 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned CharVal; 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = Str[0] - 'A'; 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = Str[0] - 'a' + 26; 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = Str[0] - '0' + 52; 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] == '+') // 62 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = 62; 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Str[0] == '/') // 63 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CharVal = 63; 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Value = (Value * 64) + CharVal; 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Str = Str.substr(1); 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Value > std::numeric_limits<uint32_t>::max()) 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return true; 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = static_cast<uint32_t>(Value); 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 9025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 9125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const { 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Addr = reinterpret_cast<const coff_symbol*>(Ref.p); 9425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 9525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 9625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); 9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Offset < COFFHeader->PointerToSymbolTable 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || Offset >= COFFHeader->PointerToSymbolTable 1004bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 10125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 10225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 10425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer == 0 && "Symbol did not point to the beginning of a symbol"); 10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 10625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Addr; 10825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 10925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); 11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 11325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the section points to a valid entry in the section table. 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Addr < SectionTable 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || Addr >= (SectionTable + COFFHeader->NumberOfSections)) 11725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Section was outside of section table."); 11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Offset % sizeof(coff_section) == 0 && 12125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer "Section did not point to the beginning of a section"); 12225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 12325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Addr; 125a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 126a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { 12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Symb += 1 + Symb->NumberOfAuxSymbols; 13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(Symb); 131a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 132a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, 134cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Result) const { 13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return getSymbolName(Symb, Result); 137a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 138a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, 140cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Result) const { 14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 142dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const coff_section *Section = nullptr; 143cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSection(Symb->SectionNumber, Section)) 14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 1451b6c8d1f6c834d8c3de4f78a4c99f8800f581b73Rafael Espindola 14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 147ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = UnknownAddressOrSize; 148ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else if (Section) 14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Section->VirtualAddress + Symb->Value; 150ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else 15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Symb->Value; 152ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 153ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 154ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 155cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, 156cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines SymbolRef::Type &Result) const { 15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 158ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Other; 15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 1612c67727046234ad9702ab5acb72700b5ac99a676David Meyer Result = SymbolRef::ST_Unknown; 16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else if (Symb->isFunctionDefinition()) { 16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = SymbolRef::ST_Function; 164ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Characteristics = 0; 16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) { 167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const coff_section *Section = nullptr; 168cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSection(Symb->SectionNumber, Section)) 16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Characteristics = Section->Characteristics; 171ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Characteristics & COFF::IMAGE_SCN_MEM_READ && 17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = SymbolRef::ST_Data; 175ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 176ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 177ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 178ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesuint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { 18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Result = SymbolRef::SF_None; 182c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // TODO: Correctly set SF_FormatSpecific, SF_Common 18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->Value == 0) 18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result |= SymbolRef::SF_Undefined; 18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result |= SymbolRef::SF_Common; 19036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 1912c67727046234ad9702ab5acb72700b5ac99a676David Meyer 192c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 193c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer // TODO: This are certainly too restrictive. 19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 195c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Global; 196c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 198c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Weak; 199c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) 201c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Absolute; 202ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Result; 204c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer} 205c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer 206cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, 207cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Result) const { 208a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 209a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // in the same section as this symbol, and looking for either the next 210a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // symbol, or the end of the section. 21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 212dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const coff_section *Section = nullptr; 213cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSection(Symb->SectionNumber, Section)) 21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 2151b6c8d1f6c834d8c3de4f78a4c99f8800f581b73Rafael Espindola 21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 21725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 21825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Section->SizeOfRawData - Symb->Value; 22025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 22125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 0; 22225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 223a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 224a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 225cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 226cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::getSymbolSection(DataRefImpl Ref, 227cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines section_iterator &Result) const { 22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(Ref); 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (COFF::isReservedSectionNumber(Symb->SectionNumber)) { 23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = section_end(); 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 232dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const coff_section *Sec = nullptr; 233cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSection(Symb->SectionNumber, Sec)) 234cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return EC; 23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ref; 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(Sec); 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = section_iterator(SectionRef(Ref, this)); 2389b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer } 2399b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer return object_error::success; 2409b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer} 2419b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { 24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Sec += 1; 24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(Sec); 246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 248cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, 249cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Result) const { 25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return getSectionName(Sec, Result); 252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 254cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, 255cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Result) const { 25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Sec->VirtualAddress; 25825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 261cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, 262cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Result) const { 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Sec->SizeOfRawData; 26525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 266a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 267a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 268cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, 269cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Result) const { 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 2711f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer ArrayRef<uint8_t> Res; 272cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::error_code EC = getSectionContents(Sec, Res); 2731f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 2741f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return EC; 275a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 276a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 277cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, 278cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Res) const { 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Sec) 281e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer return object_error::parse_failed; 28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); 283e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer return object_error::success; 284e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer} 285e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer 286cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::isSectionText(DataRefImpl Ref, 287cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 29013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 29113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 29213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 293cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::isSectionData(DataRefImpl Ref, 294cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 29713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 29813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 29913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 300cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, 301cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 30236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 30336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 30425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 305a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 306a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 307cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 308cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, 309cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 310c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd // FIXME: Unimplemented 311c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd Result = true; 312c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd return object_error::success; 313c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd} 314c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 315cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, 316cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 31736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 31836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 319c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd return object_error::success; 320c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd} 321c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 322cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, 323cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 32430b20ebdd3a41e103c6aa35849a33ed299332bc9Andrew Kaylor // FIXME: Unimplemented. 325c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd Result = false; 326c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd return object_error::success; 327c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd} 328c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 329cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, 330cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 3313a129c85920404e7ccdb7e655c89fa60a0309cfdAndrew Kaylor // FIXME: Unimplemented. 332c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd Result = false; 333c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd return object_error::success; 334c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd} 335c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 336cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, 337cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines DataRefImpl SymbRef, 338cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines bool &Result) const { 33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(SecRef); 34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symb = toSymb(SymbRef); 341dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const coff_section *SymbSec = nullptr; 342cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSection(Symb->SectionNumber, SymbSec)) 343cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return EC; 34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SymbSec == Sec) 345bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer Result = true; 346bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer else 347bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer Result = false; 34807ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer return object_error::success; 34907ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer} 35007ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesrelocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Sec->NumberOfRelocations == 0) { 35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = 0; 35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto begin = reinterpret_cast<const coff_relocation*>( 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines base() + Sec->PointerToRelocations); 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Sec->hasExtendedRelocations()) { 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Skip the first relocation entry repurposed to store the number of 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // relocations. 36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines begin++; 36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(begin); 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return relocation_iterator(RelocationRef(Ret, this)); 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic uint32_t getNumberOfRelocations(const coff_section *Sec, 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const uint8_t *base) { 37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The field for the number of relocations in COFF section table is only 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to 37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // NumberOfRelocations field, and the actual relocation count is stored in the 37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // VirtualAddress field in the first relocation entry. 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Sec->hasExtendedRelocations()) { 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto *FirstReloc = reinterpret_cast<const coff_relocation*>( 37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines base + Sec->PointerToRelocations); 37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return FirstReloc->VirtualAddress; 37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Sec->NumberOfRelocations; 3814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 3824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesrelocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { 38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Sec = toSec(Ref); 38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 38636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Sec->NumberOfRelocations == 0) { 38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = 0; 38836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 38936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines auto begin = reinterpret_cast<const coff_relocation*>( 39036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines base() + Sec->PointerToRelocations); 39136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t NumReloc = getNumberOfRelocations(Sec, base()); 39236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); 39336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return relocation_iterator(RelocationRef(Ret, this)); 39536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 3964344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 397a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Initialize the pointer to the symbol table. 398cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::initSymbolTablePtr() { 399cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getObject( 400cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines SymbolTable, *Data, base() + COFFHeader->PointerToSymbolTable, 401a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 40236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 403a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 404a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Find string table. The first four byte of the string table contains the 405a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // total size of the string table, including the size field itself. If the 406a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // string table is empty, the value of the first four byte would be 4. 407a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const uint8_t *StringTableAddr = 408a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama base() + COFFHeader->PointerToSymbolTable + 409a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama COFFHeader->NumberOfSymbols * sizeof(coff_symbol); 410a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const ulittle32_t *StringTableSizePtr; 411cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 412cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines getObject(StringTableSizePtr, *Data, StringTableAddr)) 41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 414a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama StringTableSize = *StringTableSizePtr; 415cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 416cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines getObject(StringTable, *Data, StringTableAddr, StringTableSize)) 41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some 42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // tools like cvtres write a size of 0 for an empty table instead of 4. 42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (StringTableSize < 4) 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringTableSize = 4; 423a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 424a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Check that the string table is null terminated if has any in it. 42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) 426a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::parse_failed; 427a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 428a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 429a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the file offset for the given VA. 431cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { 43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase 43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : (uint64_t)PE32PlusHeader->ImageBase; 43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Rva = Addr - ImageBase; 43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Rva <= UINT32_MAX); 43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return getRvaPtr((uint32_t)Rva, Res); 43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 43836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 439a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Returns the file offset for the given RVA. 440cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { 44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const SectionRef &S : sections()) { 44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_section *Section = getCOFFSection(S); 443a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint32_t SectionStart = Section->VirtualAddress; 444a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; 44536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SectionStart <= Addr && Addr < SectionEnd) { 44636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Offset = Addr - SectionStart; 447a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Res = uintptr_t(base()) + Section->PointerToRawData + Offset; 448a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 449a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 450a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama } 451a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::parse_failed; 452a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 453a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 454a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name 455a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// table entry. 456cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, 457cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Name) const { 458a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 459cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getRvaPtr(Rva, IntPtr)) 46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 461a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); 462a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); 463a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); 464a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 465a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 466a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 467a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama// Find the import table. 468cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::initImportTablePtr() { 469a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // First, we get the RVA of the import table. If the file lacks a pointer to 470a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // the import table, do nothing. 471a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const data_directory *DataEntry; 472a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) 473a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 474a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 475a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Do nothing if the pointer to import table is NULL. 476a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (DataEntry->RelativeVirtualAddress == 0) 477a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 478a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 479a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; 480a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama NumberOfImportDirectory = DataEntry->Size / 481a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama sizeof(import_directory_table_entry); 482a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 483a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Find the section that contains the RVA. This is needed because the RVA is 484a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // the import table's memory address which is different from its file offset. 485a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 486cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) 48736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 488a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama ImportDirectory = reinterpret_cast< 489a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const import_directory_table_entry *>(IntPtr); 49036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 49136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 492a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 49336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Find the export table. 494cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::initExportTablePtr() { 49536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // First, we get the RVA of the export table. If the file lacks a pointer to 49636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // the export table, do nothing. 49736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const data_directory *DataEntry; 49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 50036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Do nothing if the pointer to export table is NULL. 50236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (DataEntry->RelativeVirtualAddress == 0) 50336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 50436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 507cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectory = 51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines reinterpret_cast<const export_directory_table_entry *>(IntPtr); 51136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 512a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 513a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 514cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, 515cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::error_code &EC) 516cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines : ObjectFile(Binary::ID_COFF, std::move(Object)), COFFHeader(nullptr), 517dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr), 518dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr), 519dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0), 520dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ExportDirectory(nullptr) { 52125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that we at least have enough room for a header. 522cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (!checkSize(*Data, EC, sizeof(coff_file_header))) 523cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return; 524539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 5254bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // The current location in the file where we are looking at. 5264bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama uint64_t CurPtr = 0; 5274bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama 5284bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // PE header is optional and is present only in executables. If it exists, 5294bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // it is placed right after COFF header. 53036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool HasPEHeader = false; 531539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 53225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check if this is a PE/COFF file. 533001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 534539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 535539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE signature to find 'normal' COFF header. 536cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (!checkSize(*Data, EC, 0x3c + 8)) 537cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return; 5384bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 5394bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama // Check the PE magic bytes. ("PE\0\0") 5404bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { 54136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EC = object_error::parse_failed; 54225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 54325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 5444bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama CurPtr += 4; // Skip the PE magic bytes. 54536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines HasPEHeader = true; 546539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher } 547539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 548cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if ((EC = getObject(COFFHeader, *Data, base() + CurPtr))) 54925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 5504bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama CurPtr += sizeof(coff_file_header); 5510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 55236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (HasPEHeader) { 55336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const pe32_header *Header; 554cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if ((EC = getObject(Header, *Data, base() + CurPtr))) 55536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 55636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 55736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const uint8_t *DataDirAddr; 55836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t DataDirSize; 55936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Header->Magic == 0x10b) { 56036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PE32Header = Header; 56136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirAddr = base() + CurPtr + sizeof(pe32_header); 56236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 56336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else if (Header->Magic == 0x20b) { 56436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); 56536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); 56636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; 56736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 56836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // It's neither PE32 nor PE32+. 56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EC = object_error::parse_failed; 5704bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama return; 5712f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama } 572cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if ((EC = getObject(DataDirectory, *Data, DataDirAddr, DataDirSize))) 57336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 5744bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 5754bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama } 5760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 57736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (COFFHeader->isImportLibrary()) 57836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 57936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 580cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if ((EC = getObject(SectionTable, *Data, base() + CurPtr, 58136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines COFFHeader->NumberOfSections * sizeof(coff_section)))) 58236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 583a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 584a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Initialize the pointer to the symbol table. 585a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama if (COFFHeader->PointerToSymbolTable != 0) 58636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((EC = initSymbolTablePtr())) 5877151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer return; 5882f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama 589a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama // Initialize the pointer to the beginning of the import table. 59036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((EC = initImportTablePtr())) 591a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return; 5920fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 59336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Initialize the pointer to the export table. 59436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((EC = initExportTablePtr())) 59536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 596a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 59736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EC = object_error::success; 598a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 599a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 60036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbasic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { 60136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 60236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(SymbolTable); 60336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return basic_symbol_iterator(SymbolRef(Ret, this)); 604dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer} 605dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer 60636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbasic_symbol_iterator COFFObjectFile::symbol_end_impl() const { 60736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // The symbol table ends where the string table begins. 60836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 60936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(StringTable); 61036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return basic_symbol_iterator(SymbolRef(Ret, this)); 611dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer} 612dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer 61336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineslibrary_iterator COFFObjectFile::needed_library_begin() const { 6145c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer // TODO: implement 6155c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 6165c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 6175c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 61836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineslibrary_iterator COFFObjectFile::needed_library_end() const { 6195c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer // TODO: implement 6205c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 6215c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 6225c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 62397f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid MeyerStringRef COFFObjectFile::getLoadName() const { 62497f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer // COFF does not have this field. 62597f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer return ""; 62697f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer} 62797f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer 62829552222c2e7cbeb37fcd15d247597467f7b8544Rui Ueyamaimport_directory_iterator COFFObjectFile::import_directory_begin() const { 62936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return import_directory_iterator( 63036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ImportDirectoryEntryRef(ImportDirectory, 0, this)); 631a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 632a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 63329552222c2e7cbeb37fcd15d247597467f7b8544Rui Ueyamaimport_directory_iterator COFFObjectFile::import_directory_end() const { 63436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return import_directory_iterator( 63536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); 63636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 63736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 63836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesexport_directory_iterator COFFObjectFile::export_directory_begin() const { 63936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return export_directory_iterator( 64036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectoryEntryRef(ExportDirectory, 0, this)); 64136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 64236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 64336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesexport_directory_iterator COFFObjectFile::export_directory_end() const { 644dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!ExportDirectory) 645dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); 64636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectoryEntryRef Ref(ExportDirectory, 64736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExportDirectory->AddressTableEntries, this); 64836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return export_directory_iterator(Ref); 649a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 65097f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer 65136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinessection_iterator COFFObjectFile::section_begin() const { 65236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 65336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(SectionTable); 65436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return section_iterator(SectionRef(Ret, this)); 655a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 656a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 65736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinessection_iterator COFFObjectFile::section_end() const { 65836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ret; 65936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int NumSections = COFFHeader->isImportLibrary() 6603a226015a0ca52936763a079da582656164c2908Rui Ueyama ? 0 : COFFHeader->NumberOfSections; 66136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); 66236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return section_iterator(SectionRef(Ret, this)); 663a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 664a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 665a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const { 6667acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 667a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 668a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 669a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const { 6704bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama switch(COFFHeader->Machine) { 671a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 672a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-i386"; 673a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 674a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-x86-64"; 67536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case COFF::IMAGE_FILE_MACHINE_ARMNT: 67636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return "COFF-ARM"; 677a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 678a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-<unknown arch>"; 679a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 680a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 681a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 682a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const { 6834bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama switch(COFFHeader->Machine) { 684a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 685a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86; 686a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 687a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86_64; 68836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case COFF::IMAGE_FILE_MACHINE_ARMNT: 68936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Triple::thumb; 690a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 691a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::UnknownArch; 692a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 693a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 694a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 6954bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama// This method is kept here because lld uses this. As soon as we make 6964bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama// lld to use getCOFFHeader, this method will be removed. 697cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 6984bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama return getCOFFHeader(Res); 6994bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama} 7004bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama 701cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 702cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 7034bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama Res = COFFHeader; 7044bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama return object_error::success; 7054bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama} 7064bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama 707cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 7084bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama Res = PE32Header; 7090e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 7100e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 7110e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 712cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 71336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { 71436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = PE32PlusHeader; 71536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 71636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 71736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 718cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 719cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::getDataDirectory(uint32_t Index, 720cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const data_directory *&Res) const { 7212f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama // Error if if there's no data directory or the index is out of range. 72236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!DataDirectory) 72336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 72436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(PE32Header || PE32PlusHeader); 72536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize 72636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : PE32PlusHeader->NumberOfRvaAndSize; 72736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Index > NumEnt) 7282f6c0484d68270f09eecac03b7e56053153203f3Rui Ueyama return object_error::parse_failed; 72936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = &DataDirectory[Index]; 7300e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 7310e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 7320e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 733cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSection(int32_t Index, 734cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const coff_section *&Result) const { 73525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check for special index values. 73636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (COFF::isReservedSectionNumber(Index)) 737dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result = nullptr; 73836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (Index > 0 && Index <= COFFHeader->NumberOfSections) 73925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // We already verified the section table data, so no need to check again. 74036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = SectionTable + (Index - 1); 74125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 74225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 74325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 744a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 745a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 746cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getString(uint32_t Offset, 747cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Result) const { 74825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize <= 4) 74925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Tried to get a string from an empty string table. 75025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 75136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Offset >= StringTableSize) 75225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::unexpected_eof; 75336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(StringTable + Offset); 75425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 755a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 756a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 757cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSymbol(uint32_t Index, 758cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const coff_symbol *&Result) const { 75936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Index < COFFHeader->NumberOfSymbols) 76036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = SymbolTable + Index; 7614344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 7624344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::parse_failed; 7634344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 7644344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 7654344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 766cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol, 767cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Res) const { 7680e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Check for string table entry. First 4 bytes are 0. 76936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symbol->Name.Offset.Zeroes == 0) { 77036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Offset = Symbol->Name.Offset.Offset; 771cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getString(Offset, Res)) 77236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 7730e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 7740e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer } 7750e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 77636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symbol->Name.ShortName[7] == 0) 7770e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Null terminated, let ::strlen figure out the length. 77836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = StringRef(Symbol->Name.ShortName); 7790e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer else 7800e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Not null terminated, use all 8 bytes. 78136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = StringRef(Symbol->Name.ShortName, 8); 7820e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 7830e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 7840e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 785d4d03e09d3686d317da1166b578ca5ca35593970Marshall ClowArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( 78636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_symbol *Symbol) const { 787dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const uint8_t *Aux = nullptr; 788a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 78936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Symbol->NumberOfAuxSymbols > 0) { 790d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow // AUX data comes immediately after the symbol in COFF 79136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Aux = reinterpret_cast<const uint8_t *>(Symbol + 1); 792d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow# ifndef NDEBUG 79336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Verify that the Aux symbol points to a valid entry in the symbol table. 79436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); 79536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Offset < COFFHeader->PointerToSymbolTable 79636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || Offset >= COFFHeader->PointerToSymbolTable 7974bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 798d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 799d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 80036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 801d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow == 0 && "Aux Symbol data did not point to the beginning of a symbol"); 802d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow# endif 80345aad162c68ee58ba1aa8984499064f6b9c8d0f9Marshall Clow } 80436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ArrayRef<uint8_t>(Aux, 80536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); 806d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow} 807d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 808cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getSectionName(const coff_section *Sec, 809cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Res) const { 810b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer StringRef Name; 811b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer if (Sec->Name[7] == 0) 812b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Null terminated, let ::strlen figure out the length. 813b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Name = Sec->Name; 814b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer else 815b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Not null terminated, use all 8 bytes. 816b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Name = StringRef(Sec->Name, 8); 817b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 818b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Check for string table entry. First byte is '/'. 819b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer if (Name[0] == '/') { 820b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer uint32_t Offset; 82136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Name[1] == '/') { 82236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (decodeBase64StringEntry(Name.substr(2), Offset)) 82336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 82436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 82536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Name.substr(1).getAsInteger(10, Offset)) 82636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::parse_failed; 82736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 828cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getString(Offset, Name)) 82936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 830b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer } 831b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 832b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Res = Name; 833b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer return object_error::success; 834b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer} 835b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 836cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 837cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::getSectionContents(const coff_section *Sec, 838cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ArrayRef<uint8_t> &Res) const { 8391f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // The only thing that we need to verify is that the contents is contained 8401f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 8411f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // data, as there's nothing that says that is not allowed. 8421f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 8431f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 8441f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer if (ConEnd > uintptr_t(Data->getBufferEnd())) 8451f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return object_error::parse_failed; 8461f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 8471f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Sec->SizeOfRawData); 8481f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return object_error::success; 8491f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer} 8501f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer 8510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 8524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 8530fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 85436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 85536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 8564344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 8574344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 8580fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 85936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 860cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 861cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Res) const { 862956ca7265c697107708468b7e1b2fd21f4185baeRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 863b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev} 86436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 865cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 866cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Res) const { 8674344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Res = toRel(Rel)->VirtualAddress; 8680fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 8690fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 87036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8716c1202c459ffa6d693ad92fa84e43902bc780bcaRafael Espindolasymbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 8720fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 87336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Ref; 87436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Ref.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 87536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return symbol_iterator(SymbolRef(Ref, this)); 8760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 87736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 878cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 879cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t &Res) const { 8800fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 8810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = R->Type; 8820fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 8830fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 8844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 88536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_section * 88636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getCOFFSection(const SectionRef &Section) const { 88736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return toSec(Section.getRawDataRefImpl()); 888d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow} 889d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 89036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_symbol * 89136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { 89236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return toSymb(Symbol.getRawDataRefImpl()); 893d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow} 894d4d03e09d3686d317da1166b578ca5ca35593970Marshall Clow 89536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst coff_relocation * 89636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen HinesCOFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { 89736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return toRel(Reloc.getRawDataRefImpl()); 8989ac0f1d7255d7941c331b0a62a830a3b033358fdMarshall Clow} 8999ac0f1d7255d7941c331b0a62a830a3b033358fdMarshall Clow 90036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ 90136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case COFF::reloc_type: \ 90236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = #reloc_type; \ 90336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 9044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 905cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 906cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 907cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines SmallVectorImpl<char> &Result) const { 90836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_relocation *Reloc = toRel(Rel); 90936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef Res; 9104bf771b4e6d37ae1d6ae08ea27c4070a3a09784dRui Ueyama switch (COFFHeader->Machine) { 9114344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 91236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (Reloc->Type) { 9134344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 9144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 9154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 9164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 9174344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 9184344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 9194344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 9204344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 9214344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 9224344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 9234344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 9244344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 9254344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 9264344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 9274344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 9284344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 9294344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 9304344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 93136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = "Unknown"; 9324344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 9334344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 934dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines case COFF::IMAGE_FILE_MACHINE_ARMNT: 935dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines switch (Reloc->Type) { 936dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); 937dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); 938dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); 939dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); 940dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); 941dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); 942dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); 943dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); 944dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); 945dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); 946dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); 947dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); 948dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); 949dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); 950dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); 951dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines default: 952dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Res = "Unknown"; 953dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 954dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 9554344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 95636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (Reloc->Type) { 9574344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 9584344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 9594344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 9604344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 9614344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 9624344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 9634344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 9644344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 9654344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 9664344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 9674344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 9684344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 96936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = "Unknown"; 9704344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 9714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 9724344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 97336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Res = "Unknown"; 9744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 97536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result.append(Res.begin(), Res.end()); 9764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 9774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 9784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 9794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 9804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 981cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 982cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesCOFFObjectFile::getRelocationValueString(DataRefImpl Rel, 983cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines SmallVectorImpl<char> &Result) const { 98436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const coff_relocation *Reloc = toRel(Rel); 985dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const coff_symbol *Symb = nullptr; 986cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSymbol(Reloc->SymbolTableIndex, Symb)) 987cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return EC; 98836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DataRefImpl Sym; 98936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Sym.p = reinterpret_cast<uintptr_t>(Symb); 99036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef SymName; 991cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = getSymbolName(Sym, SymName)) 992cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return EC; 99336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result.append(SymName.begin(), SymName.end()); 9944344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 995a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling} 996a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling 997cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 998cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines LibraryRef &Result) const { 9995c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 10005c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 10015c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 1002cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 1003cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines StringRef &Result) const { 10045c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 10055c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 10065c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 1007a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamabool ImportDirectoryEntryRef:: 1008a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyamaoperator==(const ImportDirectoryEntryRef &Other) const { 100936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ImportTable == Other.ImportTable && Index == Other.Index; 1010a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1011a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 101236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid ImportDirectoryEntryRef::moveNext() { 101336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Index; 1014a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1015a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 1016cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code ImportDirectoryEntryRef::getImportTableEntry( 1017cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines const import_directory_table_entry *&Result) const { 101836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ImportTable; 1019a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 1020a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1021a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 1022cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { 1023a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 1024cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 1025cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) 102636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 102736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 1028a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 1029a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1030a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 1031cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code ImportDirectoryEntryRef::getImportLookupEntry( 1032a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama const import_lookup_table_entry32 *&Result) const { 1033a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama uintptr_t IntPtr = 0; 1034cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 103536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) 103636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 1037a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); 1038a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama return object_error::success; 1039a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama} 1040a6610ee882fcb8bcad60d53fc52b80f00a3fddaeRui Ueyama 104136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool ExportDirectoryEntryRef:: 104236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesoperator==(const ExportDirectoryEntryRef &Other) const { 104336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ExportTable == Other.ExportTable && Index == Other.Index; 104436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 104536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 104636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid ExportDirectoryEntryRef::moveNext() { 104736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Index; 104836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 1049a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 105036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the name of the current export symbol. If the symbol is exported only 105136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// by ordinal, the empty string is set as a result. 1052cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { 105336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 1054cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 1055cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) 105636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 105736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 105836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 105936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 106036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 106136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the starting ordinal number. 1062cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 1063cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { 106436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ExportTable->OrdinalBase; 106536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 106636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 106736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 106836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the export ordinal of the current export symbol. 1069cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { 107036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ExportTable->OrdinalBase + Index; 107136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 107236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 107336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 107436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the address of the current export symbol. 1075cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { 107636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 1077cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 1078cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) 107936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 108036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const export_address_table_entry *entry = 108136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines reinterpret_cast<const export_address_table_entry *>(IntPtr); 108236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = entry[Index].ExportRVA; 108336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 108436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 108536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 108636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Returns the name of the current export symbol. If the symbol is exported only 108736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// by ordinal, the empty string is set as a result. 1088cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code 1089cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { 109036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uintptr_t IntPtr = 0; 1091cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 1092cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) 109336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 109436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); 109536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 109636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t NumEntries = ExportTable->NumberOfNamePointers; 109736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int Offset = 0; 109836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const ulittle16_t *I = Start, *E = Start + NumEntries; 109936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines I < E; ++I, ++Offset) { 110036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (*I != Index) 110136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines continue; 1102cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = 1103cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) 110436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 110536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); 1106cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) 110736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 110836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 110936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 1110a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 111136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Result = ""; 111236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return object_error::success; 111336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 1114a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 1115cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesErrorOr<ObjectFile *> 1116cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesObjectFile::createCOFFObjectFile(std::unique_ptr<MemoryBuffer> Object) { 1117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines std::error_code EC; 111836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<COFFObjectFile> Ret( 1119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines new COFFObjectFile(std::move(Object), EC)); 112036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (EC) 112136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EC; 112236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Ret.release(); 112336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 1124