COFFObjectFile.cpp revision 9b2b812fea4df160437e7b7d56e38f6335189ad0
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" 154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#include "llvm/ADT/SmallString.h" 16a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h" 17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.h" 18a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 19a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace llvm; 20a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace object; 21a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 22a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace { 23a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle8_t; 24a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t; 25a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_t; 26a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::little16_t; 27a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 28a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 2925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencernamespace { 3025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if size is greater than the buffer size. And sets ec. 3125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { 3225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (m->getBufferSize() < size) { 3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::unexpected_eof; 3425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 3525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 3625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 3725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if any bytes in [addr, addr + size) fall outsize of m. 4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkAddr(const MemoryBuffer *m, 4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code &ec, 4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t addr, 4325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t size) { 4425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (addr + size < addr || 4525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer addr + size < size || 4625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer addr + size > uintptr_t(m->getBufferEnd())) { 4725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::unexpected_eof; 4825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 4925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 5025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 5125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 5425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { 5525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); 5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 5725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 5825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 5925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); 6025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (offset < Header->PointerToSymbolTable 6125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || offset >= Header->PointerToSymbolTable 6225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + (Header->NumberOfSymbols * sizeof(coff_symbol))) 6325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 6425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 6525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol) 6625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer == 0 && "Symbol did not point to the beginning of a symbol"); 6725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 6825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 6925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return addr; 7025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 7125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { 7325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); 7425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 7625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the section points to a valid entry in the section table. 7725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (addr < SectionTable 7825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || addr >= (SectionTable + Header->NumberOfSections)) 7925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Section was outside of section table."); 8025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); 8225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer assert(offset % sizeof(coff_section) == 0 && 8325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer "Section did not point to the beginning of a section"); 8425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 8525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return addr; 8725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 8825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, 9025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer SymbolRef &Result) const { 9125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 92a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer symb += 1 + symb->NumberOfAuxSymbols; 9325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Symb.p = reinterpret_cast<uintptr_t>(symb); 9425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SymbolRef(Symb, this); 9525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 96a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 97a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 9825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, 9925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 10025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 1010e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return getSymbolName(symb, Result); 102a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 103a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 104ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb, 10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 10625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 10764388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 10825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 10925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char Type; 11125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 113a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Type == 'U' || Type == 'w') 11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 11525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 11625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = Section->VirtualAddress + symb->Value; 11725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = symb->Value; 11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 120a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 121a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 122ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, 123ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer uint64_t &Result) const { 124ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 125ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_section *Section = NULL; 126ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSection(symb->SectionNumber, Section)) 127ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 128ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer char Type; 129ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 130ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 131ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (Type == 'U' || Type == 'w') 132ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = UnknownAddressOrSize; 133ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else if (Section) 134ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = reinterpret_cast<uintptr_t>(base() + 135ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Section->PointerToRawData + 136ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer symb->Value); 137ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else 138ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = reinterpret_cast<uintptr_t>(base() + symb->Value); 139ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 140ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 141ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 142ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolType(DataRefImpl Symb, 1431130a799ab2fd7042625163a2506518960394884Michael J. Spencer SymbolRef::Type &Result) const { 144ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 145ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Other; 146ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 147ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 148ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_External; 149ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 150ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) { 151ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Function; 152ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 153ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer char Type; 154ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 155ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 156ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (Type == 'r' || Type == 'R') { 157ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Data; 158ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 159ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 160ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 161ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 162ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 163ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 164ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb, 165ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer bool &Result) const { 166ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 167ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL); 168ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 169ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 170ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 171c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencererror_code COFFObjectFile::isSymbolWeak(DataRefImpl Symb, 172c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer bool &Result) const { 173c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 174c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL); 175c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer return object_error::success; 176c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer} 177c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer 17825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, 17925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 180a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 181a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // in the same section as this symbol, and looking for either the next 182a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // symbol, or the end of the section. 18325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 18464388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 18525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 18625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 18725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char Type; 18825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 18925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 190a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Type == 'U' || Type == 'w') 19125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 19225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 19325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = Section->SizeOfRawData - symb->Value; 19425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 19525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 0; 19625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 197a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 198a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 19925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 20025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char &Result) const { 20125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 20225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef name; 20325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 20425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 20525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char ret = StringSwitch<char>(name) 206a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .StartsWith(".debug", 'N') 207a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .StartsWith(".sxdata", 'N') 208a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .Default('?'); 209a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 21025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (ret != '?') { 21125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = ret; 21225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 21325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 214a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 215a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer uint32_t Characteristics = 0; 21625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (symb->SectionNumber > 0) { 21764388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 21825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 21925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 220a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer Characteristics = Section->Characteristics; 221a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 222a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 223a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch (symb->SectionNumber) { 224a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_UNDEFINED: 225a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check storage classes. 22625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { 22725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 'w'; 22825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; // Don't do ::toupper. 22925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } else 230a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'u'; 231a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 232a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_ABSOLUTE: 233a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'a'; 234a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 235a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_DEBUG: 236a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'n'; 237a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 238a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 239a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check section type. 240a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 241a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 't'; 242a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 243a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 244a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'r'; 245a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'd'; 247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 248a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'b'; 249a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 250a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'i'; 251a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check for section symbol. 253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 254a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer && symb->Value == 0) 255a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 's'; 256a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 257a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 258a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = ::toupper(ret); 260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 26125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = ret; 26225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 263a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 264a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 26525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb, 26625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer bool &Result) const { 26725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = false; 26825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 269a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 270a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 2719b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencererror_code COFFObjectFile::isSymbolAbsolute(DataRefImpl Symb, 2729b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer bool &Result) const { 2739b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 2749b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Result = symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; 2759b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer return object_error::success; 2769b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer} 2779b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer 2789b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencererror_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, 2799b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer section_iterator &Result) const { 2809b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 2819b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) 2829b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Result = end_sections(); 2839b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer else { 2849b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer const coff_section *sec; 2859b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; 2869b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer DataRefImpl Sec; 2879b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 2889b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Result = section_iterator(SectionRef(Sec, this)); 2899b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer } 2909b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer return object_error::success; 2919b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer} 2929b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer 29325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 29425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer SectionRef &Result) const { 29525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 296a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer sec += 1; 29725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 29825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SectionRef(Sec, this); 29925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 300a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 301a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 30225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionName(DataRefImpl Sec, 30325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 30425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 305a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer StringRef name; 306a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (sec->Name[7] == 0) 307a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Null terminated, let ::strlen figure out the length. 308a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer name = sec->Name; 309a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else 310a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Not null terminated, use all 8 bytes. 311a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer name = StringRef(sec->Name, 8); 312a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 313a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check for string table entry. First byte is '/'. 314a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (name[0] == '/') { 315a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer uint32_t Offset; 316539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher name.substr(1).getAsInteger(10, Offset); 31725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getString(Offset, name)) 31825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 319a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 320a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 32125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = name; 32225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 323a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 324a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 32525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 32625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 32725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 32825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->VirtualAddress; 32925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 330a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 331a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 33225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 33325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 33425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 33525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->SizeOfRawData; 33625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 337a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 338a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 33925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 34025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 34125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 34225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // The only thing that we need to verify is that the contents is contained 34325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 34425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // data, as there's nothing that says that is not allowed. 34525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData; 34625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t con_end = con_start + sec->SizeOfRawData; 34725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (con_end >= uintptr_t(Data->getBufferEnd())) 34825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 34925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(reinterpret_cast<const char*>(con_start), 35025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer sec->SizeOfRawData); 35125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 352a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 353a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 354e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencererror_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, 355e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer uint64_t &Res) const { 356e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer const coff_section *sec = toSec(Sec); 357e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer if (!sec) 358e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer return object_error::parse_failed; 359e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); 360e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer return object_error::success; 361e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer} 362e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer 36325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSectionText(DataRefImpl Sec, 36425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer bool &Result) const { 36525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 36625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 36713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 36813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 36913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 37013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionData(DataRefImpl Sec, 37113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer bool &Result) const { 37213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer const coff_section *sec = toSec(Sec); 37313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 37413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 37513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 37613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 37713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 37813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer bool &Result) const { 37913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer const coff_section *sec = toSec(Sec); 38013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 38125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 382a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 383a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 38407ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramererror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 38507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer DataRefImpl Symb, 38607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer bool &Result) const { 387bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer const coff_section *sec = toSec(Sec); 388bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 389bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer const coff_section *symb_sec; 390bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; 391bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer if (symb_sec == sec) 392bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer Result = true; 393bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer else 394bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer Result = false; 39507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer return object_error::success; 39607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer} 39707ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer 3984344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 3994344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_section *sec = toSec(Sec); 4004344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer DataRefImpl ret; 4014344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer std::memset(&ret, 0, sizeof(ret)); 4024344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (sec->NumberOfRelocations == 0) 4034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = 0; 4044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 4054344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); 4064344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 4074344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return relocation_iterator(RelocationRef(ret, this)); 4084344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 4094344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 4104344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 4114344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_section *sec = toSec(Sec); 4124344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer DataRefImpl ret; 4134344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer std::memset(&ret, 0, sizeof(ret)); 4144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (sec->NumberOfRelocations == 0) 4154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = 0; 4164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 4174344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = reinterpret_cast<uintptr_t>( 4184344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer reinterpret_cast<const coff_relocation*>( 4194344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer base() + sec->PointerToRelocations) 4204344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer + sec->NumberOfRelocations); 4214344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 4224344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return relocation_iterator(RelocationRef(ret, this)); 4234344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 4244344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 425001c9205fca2220480589ec355cb6ec701a37e08Michael J. SpencerCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 426001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer : ObjectFile(Binary::isCOFF, Object, ec) { 42725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that we at least have enough room for a header. 42825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 429539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 43025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // The actual starting location of the COFF header in the file. This can be 43125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // non-zero in PE/COFF files. 43225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t HeaderStart = 0; 433539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 43425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check if this is a PE/COFF file. 435001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 436539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 437539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE signature to find 'normal' COFF header. 43825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkSize(Data, ec, 0x3c + 8)) return; 43925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c); 44025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check the PE header. ("PE\0\0") 4413209a03dafe1a23fe74c933cebd9f9c92a2a3616Benjamin Kramer if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) { 44225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::parse_failed; 44325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 44425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 44525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer HeaderStart += 4; // Skip the PE Header. 446539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher } 447539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 44825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart); 44925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) 45025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 4510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 452a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer SectionTable = 453001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer reinterpret_cast<const coff_section *>( base() 45425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + HeaderStart 455a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer + sizeof(coff_file_header) 456a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer + Header->SizeOfOptionalHeader); 45725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(SectionTable), 45825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header->NumberOfSections * sizeof(coff_section))) 45925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 46025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 461a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer SymbolTable = 462001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer reinterpret_cast<const coff_symbol *>(base() 46325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + Header->PointerToSymbolTable); 46425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(SymbolTable), 46525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header->NumberOfSymbols * sizeof(coff_symbol))) 46625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 467a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 468a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Find string table. 469001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer StringTable = reinterpret_cast<const char *>(base()) 47025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + Header->PointerToSymbolTable 47125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + Header->NumberOfSymbols * sizeof(coff_symbol); 47225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) 47325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 47425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 47525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable); 47625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) 47725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 47825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that the string table is null terminated if has any in it. 47925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize < 4 48025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 48125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::parse_failed; 48225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 48325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 4840fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 48525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::success; 486a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 487a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 4884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::begin_symbols() const { 4897acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 49025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4917acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SymbolTable); 4927acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 493a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 494a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 4954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::end_symbols() const { 496a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // The symbol table ends where the string table begins. 4977acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 49825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4997acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(StringTable); 5007acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 501a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 502a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::begin_sections() const { 5047acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 50525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 5067acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable); 5077acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return section_iterator(SectionRef(ret, this)); 508a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 509a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5104344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::end_sections() const { 5117acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 51225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 5137acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections); 5147acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return section_iterator(SectionRef(ret, this)); 515a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 516a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 517a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const { 5187acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 519a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 520a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 521a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const { 522a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch(Header->Machine) { 523a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 524a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-i386"; 525a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 526a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-x86-64"; 527a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 528a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-<unknown arch>"; 529a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 530a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 531a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 532a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const { 533a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch(Header->Machine) { 534a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 535a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86; 536a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 537a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86_64; 538a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 539a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::UnknownArch; 540a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 541a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 542a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5430e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 5440e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = Header; 5450e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 5460e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 5470e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 54825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSection(int32_t index, 54925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *&Result) const { 55025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check for special index values. 55125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (index == COFF::IMAGE_SYM_UNDEFINED || 55225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer index == COFF::IMAGE_SYM_ABSOLUTE || 55325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer index == COFF::IMAGE_SYM_DEBUG) 55425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = NULL; 55525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (index > 0 && index <= Header->NumberOfSections) 55625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // We already verified the section table data, so no need to check again. 55725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SectionTable + (index - 1); 55825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 55925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 56025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 561a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 562a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 56325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getString(uint32_t offset, 56425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 56525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize <= 4) 56625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Tried to get a string from an empty string table. 56725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 56825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (offset >= StringTableSize) 56925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::unexpected_eof; 57025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(StringTable + offset); 57125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 572a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 573a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getSymbol(uint32_t index, 5754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_symbol *&Result) const { 5760e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (index >= 0 && index < Header->NumberOfSymbols) 5774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Result = SymbolTable + index; 5784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 5794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::parse_failed; 5804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 5814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 5824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 5830e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 5840e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer StringRef &Res) const { 5850e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Check for string table entry. First 4 bytes are 0. 5860e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (symbol->Name.Offset.Zeroes == 0) { 5870e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer uint32_t Offset = symbol->Name.Offset.Offset; 5880e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (error_code ec = getString(Offset, Res)) 5890e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return ec; 5900e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 5910e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer } 5920e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 5930e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (symbol->Name.ShortName[7] == 0) 5940e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Null terminated, let ::strlen figure out the length. 5950e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = StringRef(symbol->Name.ShortName); 5960e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer else 5970e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Not null terminated, use all 8 bytes. 5980e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = StringRef(symbol->Name.ShortName, 8); 5990e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 6000e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 6010e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 6020fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 6034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 6040fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6050fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 6060fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer RelocationRef &Res) const { 6074344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 6084344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 6090fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = RelocationRef(Rel, this); 6100fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6110fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6120fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 6130fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer uint64_t &Res) const { 6144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Res = toRel(Rel)->VirtualAddress; 6150fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6160fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6170fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, 6180fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer SymbolRef &Res) const { 6190fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 6200fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer DataRefImpl Symb; 6210fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 6220fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = SymbolRef(Symb, this); 6230fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6240fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6250fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 6260fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer uint32_t &Res) const { 6270fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 6280fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = R->Type; 6290fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6300fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6314344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 6324344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 6334344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::enum: res = #enum; break; 6344344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 6354344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 6364344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer SmallVectorImpl<char> &Result) const { 6374344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_relocation *reloc = toRel(Rel); 6384344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer StringRef res; 6394344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer switch (Header->Machine) { 6404344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 6414344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer switch (reloc->Type) { 6424344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 6434344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 6444344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 6454344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 6464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 6474344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 6484344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 6494344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 6504344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 6514344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 6524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 6534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 6544344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 6554344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 6564344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 6574344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 6584344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 6594344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 6604344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer res = "Unknown"; 6614344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 6624344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 6634344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 6644344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer switch (reloc->Type) { 6654344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 6664344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 6674344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 6684344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 6694344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 6704344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 6714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 6724344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 6734344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 6744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 6754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 6764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 6774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer res = "Unknown"; 6784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 6794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 6804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 6814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer res = "Unknown"; 6824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 6834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Result.append(res.begin(), res.end()); 6844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 6854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 6864344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 6874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 6884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 6890fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 6900fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer int64_t &Res) const { 6910fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = 0; 6920fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6930fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6944344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 6954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer SmallVectorImpl<char> &Result) const { 6964344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_relocation *reloc = toRel(Rel); 69748f248ad5f9e435f3aeaa3aa9bca890687085540NAKAMURA Takumi const coff_symbol *symb = 0; 6984344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 6994344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer DataRefImpl sym; 7004344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ::memset(&sym, 0, sizeof(sym)); 7014344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer sym.p = reinterpret_cast<uintptr_t>(symb); 7024344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer StringRef symname; 7034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (error_code ec = getSymbolName(sym, symname)) return ec; 7044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Result.append(symname.begin(), symname.end()); 7054344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 706a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling} 707a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling 708a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace llvm { 709a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 710a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 711001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer error_code ec; 712001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer return new COFFObjectFile(Object, ec); 713a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 714a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 715a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} // end namespace llvm 716