COFFObjectFile.cpp revision 13afc5eff2d7370ab486d5039886ab8bbf9039da
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" 15a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h" 16a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.h" 17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 18a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace llvm; 19a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace object; 20a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 21a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace { 22a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle8_t; 23a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t; 24a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_t; 25a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::little16_t; 26a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 27a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 2825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencernamespace { 2925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if size is greater than the buffer size. And sets ec. 3025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { 3125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (m->getBufferSize() < size) { 3225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::unexpected_eof; 3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 3425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 3525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 3625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 3725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if any bytes in [addr, addr + size) fall outsize of m. 3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkAddr(const MemoryBuffer *m, 4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code &ec, 4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t addr, 4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t size) { 4325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (addr + size < addr || 4425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer addr + size < size || 4525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer addr + size > uintptr_t(m->getBufferEnd())) { 4625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::unexpected_eof; 4725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 4825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 4925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 5025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { 5425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); 5525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 5725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 5825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); 5925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (offset < Header->PointerToSymbolTable 6025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || offset >= Header->PointerToSymbolTable 6125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + (Header->NumberOfSymbols * sizeof(coff_symbol))) 6225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 6325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 6425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol) 6525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer == 0 && "Symbol did not point to the beginning of a symbol"); 6625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 6725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 6825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return addr; 6925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 7025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { 7225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); 7325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 7525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the section points to a valid entry in the section table. 7625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (addr < SectionTable 7725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || addr >= (SectionTable + Header->NumberOfSections)) 7825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Section was outside of section table."); 7925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); 8125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer assert(offset % sizeof(coff_section) == 0 && 8225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer "Section did not point to the beginning of a section"); 8325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 8425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return addr; 8625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 8725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, 8925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer SymbolRef &Result) const { 9025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 91a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer symb += 1 + symb->NumberOfAuxSymbols; 9225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Symb.p = reinterpret_cast<uintptr_t>(symb); 9325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SymbolRef(Symb, this); 9425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 95a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 96a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 9725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, 9825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 9925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 100a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check for string table entry. First 4 bytes are 0. 101a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (symb->Name.Offset.Zeroes == 0) { 102a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer uint32_t Offset = symb->Name.Offset.Offset; 10325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getString(Offset, Result)) 10425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 106a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 107a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 108a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (symb->Name.ShortName[7] == 0) 109a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Null terminated, let ::strlen figure out the length. 11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(symb->Name.ShortName); 11125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Not null terminated, use all 8 bytes. 11325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(symb->Name.ShortName, 8); 11425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 115a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 116a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 117ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb, 11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 12064388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 12125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 12225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 12325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char Type; 12425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 12525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 126a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Type == 'U' || Type == 'w') 12725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 12825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 12925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = Section->VirtualAddress + symb->Value; 13025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 13125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = symb->Value; 13225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 133a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 134a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 135ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, 136ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer uint64_t &Result) const { 137ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 138ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_section *Section = NULL; 139ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSection(symb->SectionNumber, Section)) 140ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 141ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer char Type; 142ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 143ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 144ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (Type == 'U' || Type == 'w') 145ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = UnknownAddressOrSize; 146ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else if (Section) 147ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = reinterpret_cast<uintptr_t>(base() + 148ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Section->PointerToRawData + 149ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer symb->Value); 150ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else 151ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = reinterpret_cast<uintptr_t>(base() + symb->Value); 152ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 153ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 154ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 155ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolType(DataRefImpl Symb, 156ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer SymbolRef::SymbolType &Result) const { 157ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 158ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Other; 159ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 160ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 161ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_External; 162ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 163ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) { 164ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Function; 165ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 166ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer char Type; 167ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 168ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 169ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (Type == 'r' || Type == 'R') { 170ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Data; 171ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 172ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 173ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 174ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 175ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 176ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 177ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb, 178ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer bool &Result) const { 179ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 180ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL); 181ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 182ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 183ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 18425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, 18525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 186a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 187a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // in the same section as this symbol, and looking for either the next 188a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // symbol, or the end of the section. 18925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 19064388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 19125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 19225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 19325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char Type; 19425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 19525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 196a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Type == 'U' || Type == 'w') 19725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 19825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 19925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = Section->SizeOfRawData - symb->Value; 20025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 20125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 0; 20225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 203a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 204a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 20525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 20625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char &Result) const { 20725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 20825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef name; 20925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 21025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 21125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char ret = StringSwitch<char>(name) 212a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .StartsWith(".debug", 'N') 213a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .StartsWith(".sxdata", 'N') 214a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .Default('?'); 215a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 21625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (ret != '?') { 21725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = ret; 21825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 21925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 220a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 221a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer uint32_t Characteristics = 0; 22225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (symb->SectionNumber > 0) { 22364388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 22425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 22525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 226a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer Characteristics = Section->Characteristics; 227a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 228a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 229a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch (symb->SectionNumber) { 230a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_UNDEFINED: 231a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check storage classes. 23225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { 23325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 'w'; 23425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; // Don't do ::toupper. 23525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } else 236a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'u'; 237a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 238a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_ABSOLUTE: 239a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'a'; 240a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 241a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_DEBUG: 242a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'n'; 243a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 244a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 245a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check section type. 246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 't'; 248a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 249a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 250a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'r'; 251a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'd'; 253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 254a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'b'; 255a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 256a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'i'; 257a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 258a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check for section symbol. 259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer && symb->Value == 0) 261a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 's'; 262a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 263a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 264a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 265a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = ::toupper(ret); 266a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 26725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = ret; 26825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 269a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 270a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 27125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb, 27225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer bool &Result) const { 27325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = false; 27425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 275a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 276a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 27725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 27825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer SectionRef &Result) const { 27925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 280a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer sec += 1; 28125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 28225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SectionRef(Sec, this); 28325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 284a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 285a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 28625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionName(DataRefImpl Sec, 28725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 28825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 289a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer StringRef name; 290a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (sec->Name[7] == 0) 291a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Null terminated, let ::strlen figure out the length. 292a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer name = sec->Name; 293a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else 294a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Not null terminated, use all 8 bytes. 295a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer name = StringRef(sec->Name, 8); 296a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 297a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check for string table entry. First byte is '/'. 298a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (name[0] == '/') { 299a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer uint32_t Offset; 300539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher name.substr(1).getAsInteger(10, Offset); 30125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getString(Offset, name)) 30225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 303a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 304a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 30525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = name; 30625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 307a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 308a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 30925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 31025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 31125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 31225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->VirtualAddress; 31325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 314a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 315a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 31625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 31725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 31825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 31925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->SizeOfRawData; 32025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 321a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 322a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 32325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 32425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 32525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 32625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // The only thing that we need to verify is that the contents is contained 32725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 32825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // data, as there's nothing that says that is not allowed. 32925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData; 33025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t con_end = con_start + sec->SizeOfRawData; 33125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (con_end >= uintptr_t(Data->getBufferEnd())) 33225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 33325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(reinterpret_cast<const char*>(con_start), 33425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer sec->SizeOfRawData); 33525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 336a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 337a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 33825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSectionText(DataRefImpl Sec, 33925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer bool &Result) const { 34025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 34125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 34213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 34313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 34413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 34513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionData(DataRefImpl Sec, 34613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer bool &Result) const { 34713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer const coff_section *sec = toSec(Sec); 34813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 34913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 35013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 35113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 35213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 35313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer bool &Result) const { 35413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer const coff_section *sec = toSec(Sec); 35513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 35625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 357a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 358a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 35907ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramererror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 36007ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer DataRefImpl Symb, 36107ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer bool &Result) const { 36207ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer // FIXME: Unimplemented. 36307ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer Result = false; 36407ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer return object_error::success; 36507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer} 36607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer 367001c9205fca2220480589ec355cb6ec701a37e08Michael J. SpencerCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 368001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer : ObjectFile(Binary::isCOFF, Object, ec) { 36925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that we at least have enough room for a header. 37025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 371539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 37225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // The actual starting location of the COFF header in the file. This can be 37325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // non-zero in PE/COFF files. 37425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t HeaderStart = 0; 375539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 37625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check if this is a PE/COFF file. 377001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 378539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 379539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE signature to find 'normal' COFF header. 38025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkSize(Data, ec, 0x3c + 8)) return; 38125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c); 38225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check the PE header. ("PE\0\0") 3833209a03dafe1a23fe74c933cebd9f9c92a2a3616Benjamin Kramer if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) { 38425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::parse_failed; 38525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 38625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 38725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer HeaderStart += 4; // Skip the PE Header. 388539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher } 389539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 39025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart); 39125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) 39225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 3930fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 394a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer SectionTable = 395001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer reinterpret_cast<const coff_section *>( base() 39625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + HeaderStart 397a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer + sizeof(coff_file_header) 398a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer + Header->SizeOfOptionalHeader); 39925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(SectionTable), 40025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header->NumberOfSections * sizeof(coff_section))) 40125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 40225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 403a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer SymbolTable = 404001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer reinterpret_cast<const coff_symbol *>(base() 40525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + Header->PointerToSymbolTable); 40625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(SymbolTable), 40725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header->NumberOfSymbols * sizeof(coff_symbol))) 40825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 409a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 410a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Find string table. 411001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer StringTable = reinterpret_cast<const char *>(base()) 41225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + Header->PointerToSymbolTable 41325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + Header->NumberOfSymbols * sizeof(coff_symbol); 41425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) 41525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 41625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 41725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable); 41825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) 41925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 42025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that the string table is null terminated if has any in it. 42125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize < 4 42225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 42325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::parse_failed; 42425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 42525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 4260fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 42725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::success; 428a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 429a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 430a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { 4317acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 43225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4337acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SymbolTable); 4347acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 435a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 436a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 437a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { 438a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // The symbol table ends where the string table begins. 4397acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 44025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4417acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(StringTable); 4427acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 443a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 444a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 445a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::section_iterator COFFObjectFile::begin_sections() const { 4467acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 44725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4487acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable); 4497acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return section_iterator(SectionRef(ret, this)); 450a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 451a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 452a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerObjectFile::section_iterator COFFObjectFile::end_sections() const { 4537acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 45425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4557acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections); 4567acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return section_iterator(SectionRef(ret, this)); 457a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 458a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 459a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const { 4607acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 461a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 462a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 463a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const { 464a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch(Header->Machine) { 465a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 466a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-i386"; 467a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 468a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-x86-64"; 469a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 470a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-<unknown arch>"; 471a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 472a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 473a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 474a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const { 475a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch(Header->Machine) { 476a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 477a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86; 478a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 479a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86_64; 480a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 481a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::UnknownArch; 482a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 483a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 484a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 48525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSection(int32_t index, 48625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *&Result) const { 48725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check for special index values. 48825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (index == COFF::IMAGE_SYM_UNDEFINED || 48925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer index == COFF::IMAGE_SYM_ABSOLUTE || 49025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer index == COFF::IMAGE_SYM_DEBUG) 49125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = NULL; 49225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (index > 0 && index <= Header->NumberOfSections) 49325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // We already verified the section table data, so no need to check again. 49425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SectionTable + (index - 1); 49525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 49625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 49725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 498a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 499a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 50025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getString(uint32_t offset, 50125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 50225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize <= 4) 50325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Tried to get a string from an empty string table. 50425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 50525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (offset >= StringTableSize) 50625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::unexpected_eof; 50725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(StringTable + offset); 50825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 509a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 510a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5110fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 5120fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer assert(Rel.d.b < Header->NumberOfSections && "Section index out of range!"); 513cee58a69fa3f0f291c0c88ce0d29099a95495ae7Benjamin Kramer const coff_section *Sect = NULL; 5140fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer getSection(Rel.d.b, Sect); 5150fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer assert(Rel.d.a < Sect->NumberOfRelocations && "Relocation index out of range!"); 5160fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return 5170fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer reinterpret_cast<const coff_relocation*>(base() + 5180fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Sect->PointerToRelocations) + 5190fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Rel.d.a; 5200fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5210fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 5220fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer RelocationRef &Res) const { 5230fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_section *Sect = NULL; 5240fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer if (error_code ec = getSection(Rel.d.b, Sect)) 5250fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return ec; 5260fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer if (++Rel.d.a >= Sect->NumberOfRelocations) { 5270fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Rel.d.a = 0; 5280fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer while (++Rel.d.b < Header->NumberOfSections) { 529cee58a69fa3f0f291c0c88ce0d29099a95495ae7Benjamin Kramer const coff_section *Sect = NULL; 5300fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer getSection(Rel.d.b, Sect); 5310fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer if (Sect->NumberOfRelocations > 0) 5320fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer break; 5330fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer } 5340fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer } 5350fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = RelocationRef(Rel, this); 5360fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 5370fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5380fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 5390fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer uint64_t &Res) const { 540cee58a69fa3f0f291c0c88ce0d29099a95495ae7Benjamin Kramer const coff_section *Sect = NULL; 5410fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer if (error_code ec = getSection(Rel.d.b, Sect)) 5420fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return ec; 5430fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 5440fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = reinterpret_cast<uintptr_t>(base() + 5450fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Sect->PointerToRawData + 5460fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer R->VirtualAddress); 5470fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 5480fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5490fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, 5500fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer SymbolRef &Res) const { 5510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 5520fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer DataRefImpl Symb; 5530fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 5540fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = SymbolRef(Symb, this); 5550fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 5560fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5570fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 5580fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer uint32_t &Res) const { 5590fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 5600fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = R->Type; 5610fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 5620fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5630fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 5640fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer int64_t &Res) const { 5650fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = 0; 5660fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 5670fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5680fcab076f0358890e2f1b213f4303c780e05d99dBenjamin KramerObjectFile::relocation_iterator COFFObjectFile::begin_relocations() const { 5690fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer DataRefImpl ret; 5700fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer ret.d.a = 0; 5710fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer ret.d.b = 1; 5720fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return relocation_iterator(RelocationRef(ret, this)); 5730fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5740fcab076f0358890e2f1b213f4303c780e05d99dBenjamin KramerObjectFile::relocation_iterator COFFObjectFile::end_relocations() const { 5750fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer DataRefImpl ret; 5760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer ret.d.a = 0; 5770fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer ret.d.b = Header->NumberOfSections; 5780fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return relocation_iterator(RelocationRef(ret, this)); 5790fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 5800fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 5810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 582a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace llvm { 583a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 584a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 585001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer error_code ec; 586001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer return new COFFObjectFile(Object, ec); 587a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 588a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 589a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} // end namespace llvm 590