COFFObjectFile.cpp revision 1f6e3f9544c93213111a2f8b314c926c0d0e30e5
1a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 2a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 3a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// The LLVM Compiler Infrastructure 4a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 5a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file is distributed under the University of Illinois Open Source 6a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// License. See LICENSE.TXT for details. 7a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 8a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===// 9a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 10a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// This file declares the COFFObjectFile class. 11a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer// 12a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer//===----------------------------------------------------------------------===// 13a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 14001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer#include "llvm/Object/COFF.h" 151f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer#include "llvm/ADT/ArrayRef.h" 164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#include "llvm/ADT/SmallString.h" 17a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/StringSwitch.h" 18a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer#include "llvm/ADT/Triple.h" 19a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 20a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace llvm; 21a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing namespace object; 22a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 23a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace { 24a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle8_t; 25a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle16_t; 26a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::ulittle32_t; 27a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerusing support::little16_t; 28a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 29a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 3025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencernamespace { 3125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if size is greater than the buffer size. And sets ec. 3225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { 3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (m->getBufferSize() < size) { 3425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::unexpected_eof; 3525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 3625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 3725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 3825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 3925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 4025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer// Returns false if any bytes in [addr, addr + size) fall outsize of m. 4125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerbool checkAddr(const MemoryBuffer *m, 4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code &ec, 4325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t addr, 4425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t size) { 4525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (addr + size < addr || 4625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer addr + size < size || 4725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer addr + size > uintptr_t(m->getBufferEnd())) { 4825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::unexpected_eof; 4925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return false; 5025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 5125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return true; 5225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 5425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 5525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { 5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); 5725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 5825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 5925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 6025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); 6125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (offset < Header->PointerToSymbolTable 6225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || offset >= Header->PointerToSymbolTable 6325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + (Header->NumberOfSymbols * sizeof(coff_symbol))) 6425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 6525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 6625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol) 6725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer == 0 && "Symbol did not point to the beginning of a symbol"); 6825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 6925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return addr; 7125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 7225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { 7425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); 7525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 7625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# ifndef NDEBUG 7725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Verify that the section points to a valid entry in the section table. 7825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (addr < SectionTable 7925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer || addr >= (SectionTable + Header->NumberOfSections)) 8025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer report_fatal_error("Section was outside of section table."); 8125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); 8325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer assert(offset % sizeof(coff_section) == 0 && 8425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer "Section did not point to the beginning of a section"); 8525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer# endif 8625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 8725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return addr; 8825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer} 8925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 9025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, 9125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer SymbolRef &Result) const { 9225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 93a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer symb += 1 + symb->NumberOfAuxSymbols; 9425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Symb.p = reinterpret_cast<uintptr_t>(symb); 9525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SymbolRef(Symb, this); 9625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 97a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 98a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 9925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, 10025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 10125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 1020e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return getSymbolName(symb, Result); 103a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 104a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 105b0436a73054fe676b216a0cf872d1fc433125c62Danil Malysheverror_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, 10625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 10725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 10864388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 10925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 11125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char Type; 11225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 11325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 114a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Type == 'U' || Type == 'w') 11525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 11625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 117b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev Result = Section->PointerToRawData + symb->Value; 11825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 11925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = symb->Value; 12025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 121a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 122a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 123ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, 124ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer uint64_t &Result) const { 125ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 126ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_section *Section = NULL; 127ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSection(symb->SectionNumber, Section)) 128ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 129ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer char Type; 130ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 131ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 132ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (Type == 'U' || Type == 'w') 133ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = UnknownAddressOrSize; 134ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else if (Section) 135b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev Result = Section->VirtualAddress + symb->Value; 136ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer else 137b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev Result = symb->Value; 138ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 139ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 140ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 141ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramererror_code COFFObjectFile::getSymbolType(DataRefImpl Symb, 1421130a799ab2fd7042625163a2506518960394884Michael J. Spencer SymbolRef::Type &Result) const { 143ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 144ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Other; 145ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 146ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 1472c67727046234ad9702ab5acb72700b5ac99a676David Meyer Result = SymbolRef::ST_Unknown; 148ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 1495e3a082c797f0214d44858b05a13543872dfd413Michael J. Spencer if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { 150ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Function; 151ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } else { 152ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer char Type; 153ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 154ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return ec; 155ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer if (Type == 'r' || Type == 'R') { 156ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer Result = SymbolRef::ST_Data; 157ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 158ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 159ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer } 160ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer return object_error::success; 161ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer} 162ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 163c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyererror_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, 164c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer uint32_t &Result) const { 165ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer const coff_symbol *symb = toSymb(Symb); 166c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result = SymbolRef::SF_None; 167c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 1682c67727046234ad9702ab5acb72700b5ac99a676David Meyer // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common 1692c67727046234ad9702ab5acb72700b5ac99a676David Meyer 1702c67727046234ad9702ab5acb72700b5ac99a676David Meyer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 1712c67727046234ad9702ab5acb72700b5ac99a676David Meyer symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 1722c67727046234ad9702ab5acb72700b5ac99a676David Meyer Result |= SymbolRef::SF_Undefined; 173c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 174c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer // TODO: This are certainly too restrictive. 175c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 176c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Global; 177c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 178c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 179c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Weak; 180c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer 181c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) 182c46255a32ec92c427e621b6d7eabd887962ce4a4David Meyer Result |= SymbolRef::SF_Absolute; 183ac241fe9f0d73c6f632e4f7f89e06b698d39da54Benjamin Kramer 184c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer return object_error::success; 185c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer} 186c38c36a8c44bd32bdfc2e48ab3e447f6dc1547bdMichael J. Spencer 18725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, 18825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 189a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 190a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // in the same section as this symbol, and looking for either the next 191a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // symbol, or the end of the section. 19225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 19364388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 19425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 19525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 19625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char Type; 19725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 19825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 199a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Type == 'U' || Type == 'w') 20025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = UnknownAddressOrSize; 20125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (Section) 20225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = Section->SizeOfRawData - symb->Value; 20325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 20425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 0; 20525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 206a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 207a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 20825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 20925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char &Result) const { 21025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 21125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef name; 21225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 21325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 21425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer char ret = StringSwitch<char>(name) 215a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .StartsWith(".debug", 'N') 216a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .StartsWith(".sxdata", 'N') 217a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer .Default('?'); 218a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 21925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (ret != '?') { 22025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = ret; 22125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 22225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 223a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 224a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer uint32_t Characteristics = 0; 22525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (symb->SectionNumber > 0) { 22664388ceee00d5e8fc8750ce7967c07a83af3a5a8Michael J. Spencer const coff_section *Section = NULL; 22725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 22825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return ec; 229a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer Characteristics = Section->Characteristics; 230a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 231a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 232a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch (symb->SectionNumber) { 233a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_UNDEFINED: 234a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check storage classes. 23525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { 23625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = 'w'; 23725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; // Don't do ::toupper. 23811ba26db13698a4567730be13a154c5690ef5e75Michael J. Spencer } else if (symb->Value != 0) // Check for common symbols. 23911ba26db13698a4567730be13a154c5690ef5e75Michael J. Spencer ret = 'c'; 24011ba26db13698a4567730be13a154c5690ef5e75Michael J. Spencer else 241a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'u'; 242a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 243a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_ABSOLUTE: 244a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'a'; 245a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 246a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_SYM_DEBUG: 247a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'n'; 248a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer break; 249a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 250a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check section type. 251a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 252a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 't'; 253a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 254a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 255a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'r'; 256a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 257a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'd'; 258a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 259a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'b'; 260a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 261a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 'i'; 262a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 263a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // Check for section symbol. 264a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 265a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer && symb->Value == 0) 266a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = 's'; 267a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 268a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 269a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 270a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ret = ::toupper(ret); 271a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 27225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = ret; 27325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 274a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 275a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 2769b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencererror_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, 2779b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer section_iterator &Result) const { 2789b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer const coff_symbol *symb = toSymb(Symb); 2799b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) 2809b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Result = end_sections(); 2819b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer else { 282a483fc8e6f9533317f517f2d03f3a41ec0aee663Daniel Dunbar const coff_section *sec = 0; 2839b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; 2849b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer DataRefImpl Sec; 285783d88793afe4b4e42460c139ab742fbd26f39f7Michael J. Spencer std::memset(&Sec, 0, sizeof(Sec)); 2869b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 2879b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer Result = section_iterator(SectionRef(Sec, this)); 2889b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer } 2899b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer return object_error::success; 2909b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer} 2919b2b812fea4df160437e7b7d56e38f6335189ad0Michael J. Spencer 29225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 29325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer SectionRef &Result) const { 29425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 295a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer sec += 1; 29625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 29725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SectionRef(Sec, this); 29825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 299a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 300a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 30125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionName(DataRefImpl Sec, 30225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 30325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 304b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer return getSectionName(sec, Result); 305a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 306a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 30725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 30825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 30925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 31025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->VirtualAddress; 31125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 312a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 313a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 31425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 31525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t &Result) const { 31625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 31725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->SizeOfRawData; 31825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 319a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 320a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 32125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 32225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 32325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 3241f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer ArrayRef<uint8_t> Res; 3251f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer error_code EC = getSectionContents(sec, Res); 3261f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3271f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return EC; 328a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 329a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 330e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencererror_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, 331e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer uint64_t &Res) const { 332e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer const coff_section *sec = toSec(Sec); 333e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer if (!sec) 334e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer return object_error::parse_failed; 335e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); 336e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer return object_error::success; 337e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer} 338e2f2f07be7cf2b55b7e5501291bbcede87e43fd6Michael J. Spencer 33925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::isSectionText(DataRefImpl Sec, 34025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer bool &Result) const { 34125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *sec = toSec(Sec); 34225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 34313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 34413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 34513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 34613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionData(DataRefImpl Sec, 34713afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer bool &Result) const { 34813afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer const coff_section *sec = toSec(Sec); 34913afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 35013afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer return object_error::success; 35113afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer} 35213afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer 35313afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencererror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 35413afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer bool &Result) const { 35513afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer const coff_section *sec = toSec(Sec); 35613afc5eff2d7370ab486d5039886ab8bbf9039daMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 35725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 358a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 359a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 36007ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramererror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 36107ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer DataRefImpl Symb, 36207ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer bool &Result) const { 363bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer const coff_section *sec = toSec(Sec); 364bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 365a483fc8e6f9533317f517f2d03f3a41ec0aee663Daniel Dunbar const coff_section *symb_sec = 0; 366bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; 367bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer if (symb_sec == sec) 368bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer Result = true; 369bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer else 370bff6f8679a3e4006653157ca11cee9dc58c68f8bMichael J. Spencer Result = false; 37107ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer return object_error::success; 37207ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer} 37307ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer 3744344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 3754344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_section *sec = toSec(Sec); 3764344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer DataRefImpl ret; 3774344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer std::memset(&ret, 0, sizeof(ret)); 3784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (sec->NumberOfRelocations == 0) 3794344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = 0; 3804344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 3814344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); 3824344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 3834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return relocation_iterator(RelocationRef(ret, this)); 3844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 3854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 3864344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencerrelocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 3874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_section *sec = toSec(Sec); 3884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer DataRefImpl ret; 3894344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer std::memset(&ret, 0, sizeof(ret)); 3904344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (sec->NumberOfRelocations == 0) 3914344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = 0; 3924344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 3934344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ret.p = reinterpret_cast<uintptr_t>( 3944344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer reinterpret_cast<const coff_relocation*>( 3954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer base() + sec->PointerToRelocations) 3964344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer + sec->NumberOfRelocations); 3974344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 3984344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return relocation_iterator(RelocationRef(ret, this)); 3994344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 4004344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 401001c9205fca2220480589ec355cb6ec701a37e08Michael J. SpencerCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 4026f9489a86f33624f9ff5388411d12359ce9cef20David Meyer : ObjectFile(Binary::ID_COFF, Object, ec) 4037151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer , Header(0) 4047151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer , SectionTable(0) 4057151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer , SymbolTable(0) 4067151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer , StringTable(0) 4077151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer , StringTableSize(0) { 40825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check that we at least have enough room for a header. 40925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 410539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 41125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // The actual starting location of the COFF header in the file. This can be 41225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // non-zero in PE/COFF files. 41325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer uint64_t HeaderStart = 0; 414539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 41525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check if this is a PE/COFF file. 416001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 417539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 418539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher // PE signature to find 'normal' COFF header. 41925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkSize(Data, ec, 0x3c + 8)) return; 4207151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer HeaderStart = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 42125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check the PE header. ("PE\0\0") 4223209a03dafe1a23fe74c933cebd9f9c92a2a3616Benjamin Kramer if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) { 42325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::parse_failed; 42425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 42525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 42625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer HeaderStart += 4; // Skip the PE Header. 427539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher } 428539d8d8a72995d08afe7b986fe98a1dc7fec4b0aEric Christopher 42925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart); 43025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) 43125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 4320fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 433a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer SectionTable = 434001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer reinterpret_cast<const coff_section *>( base() 43525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer + HeaderStart 436a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer + sizeof(coff_file_header) 437a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer + Header->SizeOfOptionalHeader); 43825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (!checkAddr(Data, ec, uintptr_t(SectionTable), 43925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Header->NumberOfSections * sizeof(coff_section))) 44025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return; 44125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 4427151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer if (Header->PointerToSymbolTable != 0) { 4437151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer SymbolTable = 4447151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer reinterpret_cast<const coff_symbol *>(base() 4457151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer + Header->PointerToSymbolTable); 4467151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer if (!checkAddr(Data, ec, uintptr_t(SymbolTable), 4477151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer Header->NumberOfSymbols * sizeof(coff_symbol))) 4487151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer return; 449a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 4507151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer // Find string table. 4517151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer StringTable = reinterpret_cast<const char *>(base()) 4527151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer + Header->PointerToSymbolTable 4537151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer + Header->NumberOfSymbols * sizeof(coff_symbol); 4547151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) 4557151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer return; 45625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer 4577151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable); 4587151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) 4597151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer return; 4607151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer // Check that the string table is null terminated if has any in it. 4617151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer if (StringTableSize < 4 4627151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 4637151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer ec = object_error::parse_failed; 4647151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer return; 4657151ddd6efb2f3f51297b35f27a30ddfa8a76a7eMichael J. Spencer } 46625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer } 4670fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer 46825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer ec = object_error::success; 469a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 470a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 4714344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::begin_symbols() const { 4727acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 47325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4747acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SymbolTable); 4757acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 476a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 477a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 4784344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersymbol_iterator COFFObjectFile::end_symbols() const { 479a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer // The symbol table ends where the string table begins. 4807acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 48125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 4827acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(StringTable); 4837acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 484a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 485a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 486dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencersymbol_iterator COFFObjectFile::begin_dynamic_symbols() const { 487dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer // TODO: implement 488dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 489dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer} 490dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer 491dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencersymbol_iterator COFFObjectFile::end_dynamic_symbols() const { 492dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer // TODO: implement 493dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 494dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer} 495dfa1896b6b61e708f002b814794890ff308172eeMichael J. Spencer 4965c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyerlibrary_iterator COFFObjectFile::begin_libraries_needed() const { 4975c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer // TODO: implement 4985c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 4995c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 5005c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 5015c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyerlibrary_iterator COFFObjectFile::end_libraries_needed() const { 5025c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer // TODO: implement 5035c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 5045c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 5055c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 50697f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid MeyerStringRef COFFObjectFile::getLoadName() const { 50797f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer // COFF does not have this field. 50897f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer return ""; 50997f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer} 51097f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer 51197f7787bfb56ad31fe20ec0bb9c3c9f3253d14fbDavid Meyer 5124344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::begin_sections() const { 5137acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 51425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 5157acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable); 5167acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return section_iterator(SectionRef(ret, this)); 517a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 518a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5194344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencersection_iterator COFFObjectFile::end_sections() const { 5207acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer DataRefImpl ret; 52125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer std::memset(&ret, 0, sizeof(DataRefImpl)); 5227acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections); 5237acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return section_iterator(SectionRef(ret, this)); 524a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 525a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 526a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spenceruint8_t COFFObjectFile::getBytesInAddress() const { 5277acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 528a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 529a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 530a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. SpencerStringRef COFFObjectFile::getFileFormatName() const { 531a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch(Header->Machine) { 532a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 533a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-i386"; 534a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 535a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-x86-64"; 536a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 537a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return "COFF-<unknown arch>"; 538a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 539a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 540a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 541a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencerunsigned COFFObjectFile::getArch() const { 542a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer switch(Header->Machine) { 543a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 544a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86; 545a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 546a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::x86_64; 547a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer default: 548a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer return Triple::UnknownArch; 549a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 550a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 551a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5520e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 5530e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = Header; 5540e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 5550e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 5560e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 55725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getSection(int32_t index, 55825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer const coff_section *&Result) const { 55925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Check for special index values. 56025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (index == COFF::IMAGE_SYM_UNDEFINED || 56125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer index == COFF::IMAGE_SYM_ABSOLUTE || 56225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer index == COFF::IMAGE_SYM_DEBUG) 56325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = NULL; 56425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else if (index > 0 && index <= Header->NumberOfSections) 56525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // We already verified the section table data, so no need to check again. 56625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = SectionTable + (index - 1); 56725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer else 56825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 56925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 570a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 571a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 57225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencererror_code COFFObjectFile::getString(uint32_t offset, 57325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer StringRef &Result) const { 57425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (StringTableSize <= 4) 57525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer // Tried to get a string from an empty string table. 57625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::parse_failed; 57725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer if (offset >= StringTableSize) 57825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::unexpected_eof; 57925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer Result = StringRef(StringTable + offset); 58025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer return object_error::success; 581a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} 582a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 5834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getSymbol(uint32_t index, 5844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_symbol *&Result) const { 5857c24665390a79ee05a0a562ff689e52d4135063eMichael J. Spencer if (index < Header->NumberOfSymbols) 5864344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Result = SymbolTable + index; 5874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer else 5884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::parse_failed; 5894344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 5904344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 5914344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 5920e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencererror_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 5930e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer StringRef &Res) const { 5940e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Check for string table entry. First 4 bytes are 0. 5950e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (symbol->Name.Offset.Zeroes == 0) { 5960e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer uint32_t Offset = symbol->Name.Offset.Offset; 5970e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (error_code ec = getString(Offset, Res)) 5980e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return ec; 5990e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 6000e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer } 6010e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 6020e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer if (symbol->Name.ShortName[7] == 0) 6030e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Null terminated, let ::strlen figure out the length. 6040e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = StringRef(symbol->Name.ShortName); 6050e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer else 6060e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer // Not null terminated, use all 8 bytes. 6070e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer Res = StringRef(symbol->Name.ShortName, 8); 6080e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer return object_error::success; 6090e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer} 6100e752cb4b4eb5676aace4d9f3d7c2e2334c13777Michael J. Spencer 611b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencererror_code COFFObjectFile::getSectionName(const coff_section *Sec, 612b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer StringRef &Res) const { 613b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer StringRef Name; 614b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer if (Sec->Name[7] == 0) 615b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Null terminated, let ::strlen figure out the length. 616b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Name = Sec->Name; 617b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer else 618b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Not null terminated, use all 8 bytes. 619b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Name = StringRef(Sec->Name, 8); 620b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 621b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer // Check for string table entry. First byte is '/'. 622b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer if (Name[0] == '/') { 623b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer uint32_t Offset; 624b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 625b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer return object_error::parse_failed; 626b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer if (error_code ec = getString(Offset, Name)) 627b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer return ec; 628b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer } 629b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 630b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer Res = Name; 631b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer return object_error::success; 632b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer} 633b35a896e072ff46c38905419b7f55aaccdb1d702Michael J. Spencer 6341f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencererror_code COFFObjectFile::getSectionContents(const coff_section *Sec, 6351f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer ArrayRef<uint8_t> &Res) const { 6361f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // The only thing that we need to verify is that the contents is contained 6371f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 6381f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer // data, as there's nothing that says that is not allowed. 6391f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 6401f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 6411f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer if (ConEnd > uintptr_t(Data->getBufferEnd())) 6421f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return object_error::parse_failed; 6431f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 6441f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer Sec->SizeOfRawData); 6451f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer return object_error::success; 6461f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer} 6471f6e3f9544c93213111a2f8b314c926c0d0e30e5Michael J. Spencer 6480fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramerconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 6494344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 6500fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6510fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 6520fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer RelocationRef &Res) const { 6534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 6544344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 6550fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = RelocationRef(Rel, this); 6560fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6570fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6580fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 6590fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer uint64_t &Res) const { 660b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev Res = toRel(Rel)->VirtualAddress; 661b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev return object_error::success; 662b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev} 663b0436a73054fe676b216a0cf872d1fc433125c62Danil Malysheverror_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 664b0436a73054fe676b216a0cf872d1fc433125c62Danil Malyshev uint64_t &Res) const { 6654344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Res = toRel(Rel)->VirtualAddress; 6660fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6670fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6680fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, 6690fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer SymbolRef &Res) const { 6700fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 6710fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer DataRefImpl Symb; 672783d88793afe4b4e42460c139ab742fbd26f39f7Michael J. Spencer std::memset(&Symb, 0, sizeof(Symb)); 6730fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 6740fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = SymbolRef(Symb, this); 6750fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6760fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6770fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 6789472b8d220fc746498429f430cb4c4dbfbd38f2aOwen Anderson uint64_t &Res) const { 6790fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer const coff_relocation* R = toRel(Rel); 6800fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = R->Type; 6810fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 6820fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 6834344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 6844344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 6854344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::enum: res = #enum; break; 6864344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 6874344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 6884344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer SmallVectorImpl<char> &Result) const { 6894344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_relocation *reloc = toRel(Rel); 6904344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer StringRef res; 6914344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer switch (Header->Machine) { 6924344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 6934344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer switch (reloc->Type) { 6944344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 6954344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 6964344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 6974344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 6984344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 6994344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 7004344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 7014344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 7024344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 7034344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 7044344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 7054344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 7064344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 7074344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 7084344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 7094344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 7104344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 7114344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 7124344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer res = "Unknown"; 7134344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 7144344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 7154344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 7164344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer switch (reloc->Type) { 7174344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 7184344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 7194344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 7204344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 7214344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 7224344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 7234344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 7244344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 7254344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 7264344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 7274344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 7284344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 7294344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer res = "Unknown"; 7304344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 7314344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer break; 7324344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer default: 7334344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer res = "Unknown"; 7344344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer } 7354344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Result.append(res.begin(), res.end()); 7364344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 7374344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer} 7384344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 7394344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 7404344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer 7410fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramererror_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, 7420fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer int64_t &Res) const { 7430fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer Res = 0; 7440fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer return object_error::success; 7450fcab076f0358890e2f1b213f4303c780e05d99dBenjamin Kramer} 7464344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencererror_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 7474344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer SmallVectorImpl<char> &Result) const { 7484344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer const coff_relocation *reloc = toRel(Rel); 74948f248ad5f9e435f3aeaa3aa9bca890687085540NAKAMURA Takumi const coff_symbol *symb = 0; 7504344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 7514344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer DataRefImpl sym; 7524344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer ::memset(&sym, 0, sizeof(sym)); 7534344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer sym.p = reinterpret_cast<uintptr_t>(symb); 7544344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer StringRef symname; 7554344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer if (error_code ec = getSymbolName(sym, symname)) return ec; 7564344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer Result.append(symname.begin(), symname.end()); 7574344b1ef9b3721a5ebc2e024f753772a1e4ddd92Michael J. Spencer return object_error::success; 758a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling} 759a48ad1333999e2fb483d23096349138af5a51ec6Bill Wendling 7605c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyererror_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 7615c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer LibraryRef &Result) const { 7625c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 7635c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 7645c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 7655c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyererror_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 7665c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer StringRef &Result) const { 7675c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 7685c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer} 7695c2b4ea73c8f48bb5f96c86fe437385b8fb3dcdaDavid Meyer 770a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencernamespace llvm { 771a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 772a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 773001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer error_code ec; 774001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer return new COFFObjectFile(Object, ec); 775a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer } 776a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer 777a1ef8ef66075e28e020e5d2f408e0a9bae9eb9d3Michael J. Spencer} // end namespace llvm 778