18e90adafSMichael J. Spencer //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// 28e90adafSMichael J. Spencer // 38e90adafSMichael J. Spencer // The LLVM Compiler Infrastructure 48e90adafSMichael J. Spencer // 58e90adafSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 68e90adafSMichael J. Spencer // License. See LICENSE.TXT for details. 78e90adafSMichael J. Spencer // 88e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 98e90adafSMichael J. Spencer // 108e90adafSMichael J. Spencer // This file declares the COFFObjectFile class. 118e90adafSMichael J. Spencer // 128e90adafSMichael J. Spencer //===----------------------------------------------------------------------===// 138e90adafSMichael J. Spencer 14ec29b121SMichael J. Spencer #include "llvm/Object/COFF.h" 159da9e693SMichael J. Spencer #include "llvm/ADT/ArrayRef.h" 16e5fd0047SMichael J. Spencer #include "llvm/ADT/SmallString.h" 178e90adafSMichael J. Spencer #include "llvm/ADT/StringSwitch.h" 188e90adafSMichael J. Spencer #include "llvm/ADT/Triple.h" 198e90adafSMichael J. Spencer 208e90adafSMichael J. Spencer using namespace llvm; 218e90adafSMichael J. Spencer using namespace object; 228e90adafSMichael J. Spencer 238e90adafSMichael J. Spencer namespace { 248e90adafSMichael J. Spencer using support::ulittle8_t; 258e90adafSMichael J. Spencer using support::ulittle16_t; 268e90adafSMichael J. Spencer using support::ulittle32_t; 278e90adafSMichael J. Spencer using support::little16_t; 288e90adafSMichael J. Spencer } 298e90adafSMichael J. Spencer 301d6167fdSMichael J. Spencer namespace { 311d6167fdSMichael J. Spencer // Returns false if size is greater than the buffer size. And sets ec. 321d6167fdSMichael J. Spencer bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { 331d6167fdSMichael J. Spencer if (m->getBufferSize() < size) { 341d6167fdSMichael J. Spencer ec = object_error::unexpected_eof; 351d6167fdSMichael J. Spencer return false; 361d6167fdSMichael J. Spencer } 371d6167fdSMichael J. Spencer return true; 388e90adafSMichael J. Spencer } 398e90adafSMichael J. Spencer 40*ed64342bSRui Ueyama // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. 41*ed64342bSRui Ueyama // Returns unexpected_eof if error. 42*ed64342bSRui Ueyama template<typename T> 43*ed64342bSRui Ueyama error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, 44*ed64342bSRui Ueyama const size_t Size = sizeof(T)) { 45*ed64342bSRui Ueyama uintptr_t Addr = uintptr_t(Ptr); 46*ed64342bSRui Ueyama if (Addr + Size < Addr || 47*ed64342bSRui Ueyama Addr + Size < Size || 48*ed64342bSRui Ueyama Addr + Size > uintptr_t(M->getBufferEnd())) { 49*ed64342bSRui Ueyama return object_error::unexpected_eof; 501d6167fdSMichael J. Spencer } 51*ed64342bSRui Ueyama Obj = reinterpret_cast<const T *>(Addr); 52*ed64342bSRui Ueyama return object_error::success; 531d6167fdSMichael J. Spencer } 541d6167fdSMichael J. Spencer } 551d6167fdSMichael J. Spencer 561d6167fdSMichael J. Spencer const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { 571d6167fdSMichael J. Spencer const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); 581d6167fdSMichael J. Spencer 591d6167fdSMichael J. Spencer # ifndef NDEBUG 601d6167fdSMichael J. Spencer // Verify that the symbol points to a valid entry in the symbol table. 611d6167fdSMichael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); 6282ebd8e3SRui Ueyama if (offset < COFFHeader->PointerToSymbolTable 6382ebd8e3SRui Ueyama || offset >= COFFHeader->PointerToSymbolTable 6482ebd8e3SRui Ueyama + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 651d6167fdSMichael J. Spencer report_fatal_error("Symbol was outside of symbol table."); 661d6167fdSMichael J. Spencer 6782ebd8e3SRui Ueyama assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 681d6167fdSMichael J. Spencer == 0 && "Symbol did not point to the beginning of a symbol"); 691d6167fdSMichael J. Spencer # endif 701d6167fdSMichael J. Spencer 711d6167fdSMichael J. Spencer return addr; 721d6167fdSMichael J. Spencer } 731d6167fdSMichael J. Spencer 741d6167fdSMichael J. Spencer const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { 751d6167fdSMichael J. Spencer const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); 761d6167fdSMichael J. Spencer 771d6167fdSMichael J. Spencer # ifndef NDEBUG 781d6167fdSMichael J. Spencer // Verify that the section points to a valid entry in the section table. 791d6167fdSMichael J. Spencer if (addr < SectionTable 8082ebd8e3SRui Ueyama || addr >= (SectionTable + COFFHeader->NumberOfSections)) 811d6167fdSMichael J. Spencer report_fatal_error("Section was outside of section table."); 821d6167fdSMichael J. Spencer 831d6167fdSMichael J. Spencer uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); 841d6167fdSMichael J. Spencer assert(offset % sizeof(coff_section) == 0 && 851d6167fdSMichael J. Spencer "Section did not point to the beginning of a section"); 861d6167fdSMichael J. Spencer # endif 871d6167fdSMichael J. Spencer 881d6167fdSMichael J. Spencer return addr; 891d6167fdSMichael J. Spencer } 901d6167fdSMichael J. Spencer 911d6167fdSMichael J. Spencer error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, 921d6167fdSMichael J. Spencer SymbolRef &Result) const { 931d6167fdSMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 941d6167fdSMichael J. Spencer symb += 1 + symb->NumberOfAuxSymbols; 951d6167fdSMichael J. Spencer Symb.p = reinterpret_cast<uintptr_t>(symb); 961d6167fdSMichael J. Spencer Result = SymbolRef(Symb, this); 971d6167fdSMichael J. Spencer return object_error::success; 981d6167fdSMichael J. Spencer } 991d6167fdSMichael J. Spencer 1001d6167fdSMichael J. Spencer error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, 1011d6167fdSMichael J. Spencer StringRef &Result) const { 1021d6167fdSMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 10389a7a5eaSMichael J. Spencer return getSymbolName(symb, Result); 1048e90adafSMichael J. Spencer } 1058e90adafSMichael J. Spencer 106cbe72fc9SDanil Malyshev error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, 1071d6167fdSMichael J. Spencer uint64_t &Result) const { 1081d6167fdSMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 1095ebaed24SMichael J. Spencer const coff_section *Section = NULL; 1101d6167fdSMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 1111d6167fdSMichael J. Spencer return ec; 1121d6167fdSMichael J. Spencer char Type; 1131d6167fdSMichael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 1141d6167fdSMichael J. Spencer return ec; 1158e90adafSMichael J. Spencer if (Type == 'U' || Type == 'w') 1161d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 1171d6167fdSMichael J. Spencer else if (Section) 118cbe72fc9SDanil Malyshev Result = Section->PointerToRawData + symb->Value; 1191d6167fdSMichael J. Spencer else 1201d6167fdSMichael J. Spencer Result = symb->Value; 1211d6167fdSMichael J. Spencer return object_error::success; 1228e90adafSMichael J. Spencer } 1238e90adafSMichael J. Spencer 12475d1cf33SBenjamin Kramer error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, 12575d1cf33SBenjamin Kramer uint64_t &Result) const { 12675d1cf33SBenjamin Kramer const coff_symbol *symb = toSymb(Symb); 12775d1cf33SBenjamin Kramer const coff_section *Section = NULL; 12875d1cf33SBenjamin Kramer if (error_code ec = getSection(symb->SectionNumber, Section)) 12975d1cf33SBenjamin Kramer return ec; 13075d1cf33SBenjamin Kramer char Type; 13175d1cf33SBenjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 13275d1cf33SBenjamin Kramer return ec; 13375d1cf33SBenjamin Kramer if (Type == 'U' || Type == 'w') 13475d1cf33SBenjamin Kramer Result = UnknownAddressOrSize; 13575d1cf33SBenjamin Kramer else if (Section) 136cbe72fc9SDanil Malyshev Result = Section->VirtualAddress + symb->Value; 13775d1cf33SBenjamin Kramer else 138cbe72fc9SDanil Malyshev Result = symb->Value; 13975d1cf33SBenjamin Kramer return object_error::success; 14075d1cf33SBenjamin Kramer } 14175d1cf33SBenjamin Kramer 14275d1cf33SBenjamin Kramer error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, 143d3946676SMichael J. Spencer SymbolRef::Type &Result) const { 14475d1cf33SBenjamin Kramer const coff_symbol *symb = toSymb(Symb); 14575d1cf33SBenjamin Kramer Result = SymbolRef::ST_Other; 14675d1cf33SBenjamin Kramer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 14775d1cf33SBenjamin Kramer symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { 1487e4b976cSDavid Meyer Result = SymbolRef::ST_Unknown; 14975d1cf33SBenjamin Kramer } else { 150097be9f6SMichael J. Spencer if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { 15175d1cf33SBenjamin Kramer Result = SymbolRef::ST_Function; 15275d1cf33SBenjamin Kramer } else { 15375d1cf33SBenjamin Kramer char Type; 15475d1cf33SBenjamin Kramer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 15575d1cf33SBenjamin Kramer return ec; 15675d1cf33SBenjamin Kramer if (Type == 'r' || Type == 'R') { 15775d1cf33SBenjamin Kramer Result = SymbolRef::ST_Data; 15875d1cf33SBenjamin Kramer } 15975d1cf33SBenjamin Kramer } 16075d1cf33SBenjamin Kramer } 16175d1cf33SBenjamin Kramer return object_error::success; 16275d1cf33SBenjamin Kramer } 16375d1cf33SBenjamin Kramer 1641df4b84dSDavid Meyer error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, 1651df4b84dSDavid Meyer uint32_t &Result) const { 16675d1cf33SBenjamin Kramer const coff_symbol *symb = toSymb(Symb); 1671df4b84dSDavid Meyer Result = SymbolRef::SF_None; 16875d1cf33SBenjamin Kramer 1697e4b976cSDavid Meyer // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common 1707e4b976cSDavid Meyer 1717e4b976cSDavid Meyer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && 1727e4b976cSDavid Meyer symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) 1737e4b976cSDavid Meyer Result |= SymbolRef::SF_Undefined; 1741df4b84dSDavid Meyer 1751df4b84dSDavid Meyer // TODO: This are certainly too restrictive. 1761df4b84dSDavid Meyer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 1771df4b84dSDavid Meyer Result |= SymbolRef::SF_Global; 1781df4b84dSDavid Meyer 1791df4b84dSDavid Meyer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) 1801df4b84dSDavid Meyer Result |= SymbolRef::SF_Weak; 1811df4b84dSDavid Meyer 1821df4b84dSDavid Meyer if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) 1831df4b84dSDavid Meyer Result |= SymbolRef::SF_Absolute; 1841df4b84dSDavid Meyer 18501759754SMichael J. Spencer return object_error::success; 18601759754SMichael J. Spencer } 18701759754SMichael J. Spencer 1881d6167fdSMichael J. Spencer error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, 1891d6167fdSMichael J. Spencer uint64_t &Result) const { 1908e90adafSMichael J. Spencer // FIXME: Return the correct size. This requires looking at all the symbols 1918e90adafSMichael J. Spencer // in the same section as this symbol, and looking for either the next 1928e90adafSMichael J. Spencer // symbol, or the end of the section. 1931d6167fdSMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 1945ebaed24SMichael J. Spencer const coff_section *Section = NULL; 1951d6167fdSMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 1961d6167fdSMichael J. Spencer return ec; 1971d6167fdSMichael J. Spencer char Type; 1981d6167fdSMichael J. Spencer if (error_code ec = getSymbolNMTypeChar(Symb, Type)) 1991d6167fdSMichael J. Spencer return ec; 2008e90adafSMichael J. Spencer if (Type == 'U' || Type == 'w') 2011d6167fdSMichael J. Spencer Result = UnknownAddressOrSize; 2021d6167fdSMichael J. Spencer else if (Section) 2031d6167fdSMichael J. Spencer Result = Section->SizeOfRawData - symb->Value; 2041d6167fdSMichael J. Spencer else 2051d6167fdSMichael J. Spencer Result = 0; 2061d6167fdSMichael J. Spencer return object_error::success; 2078e90adafSMichael J. Spencer } 2088e90adafSMichael J. Spencer 2091d6167fdSMichael J. Spencer error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 2101d6167fdSMichael J. Spencer char &Result) const { 2111d6167fdSMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 2121d6167fdSMichael J. Spencer StringRef name; 2131d6167fdSMichael J. Spencer if (error_code ec = getSymbolName(Symb, name)) 2141d6167fdSMichael J. Spencer return ec; 2151d6167fdSMichael J. Spencer char ret = StringSwitch<char>(name) 2168e90adafSMichael J. Spencer .StartsWith(".debug", 'N') 2178e90adafSMichael J. Spencer .StartsWith(".sxdata", 'N') 2188e90adafSMichael J. Spencer .Default('?'); 2198e90adafSMichael J. Spencer 2201d6167fdSMichael J. Spencer if (ret != '?') { 2211d6167fdSMichael J. Spencer Result = ret; 2221d6167fdSMichael J. Spencer return object_error::success; 2231d6167fdSMichael J. Spencer } 2248e90adafSMichael J. Spencer 2258e90adafSMichael J. Spencer uint32_t Characteristics = 0; 2261d6167fdSMichael J. Spencer if (symb->SectionNumber > 0) { 2275ebaed24SMichael J. Spencer const coff_section *Section = NULL; 2281d6167fdSMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, Section)) 2291d6167fdSMichael J. Spencer return ec; 2308e90adafSMichael J. Spencer Characteristics = Section->Characteristics; 2318e90adafSMichael J. Spencer } 2328e90adafSMichael J. Spencer 2338e90adafSMichael J. Spencer switch (symb->SectionNumber) { 2348e90adafSMichael J. Spencer case COFF::IMAGE_SYM_UNDEFINED: 2358e90adafSMichael J. Spencer // Check storage classes. 2361d6167fdSMichael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { 2371d6167fdSMichael J. Spencer Result = 'w'; 2381d6167fdSMichael J. Spencer return object_error::success; // Don't do ::toupper. 239d27d51fbSMichael J. Spencer } else if (symb->Value != 0) // Check for common symbols. 240d27d51fbSMichael J. Spencer ret = 'c'; 241d27d51fbSMichael J. Spencer else 2428e90adafSMichael J. Spencer ret = 'u'; 2438e90adafSMichael J. Spencer break; 2448e90adafSMichael J. Spencer case COFF::IMAGE_SYM_ABSOLUTE: 2458e90adafSMichael J. Spencer ret = 'a'; 2468e90adafSMichael J. Spencer break; 2478e90adafSMichael J. Spencer case COFF::IMAGE_SYM_DEBUG: 2488e90adafSMichael J. Spencer ret = 'n'; 2498e90adafSMichael J. Spencer break; 2508e90adafSMichael J. Spencer default: 2518e90adafSMichael J. Spencer // Check section type. 2528e90adafSMichael J. Spencer if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 2538e90adafSMichael J. Spencer ret = 't'; 2548e90adafSMichael J. Spencer else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ 2558e90adafSMichael J. Spencer && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. 2568e90adafSMichael J. Spencer ret = 'r'; 2578e90adafSMichael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 2588e90adafSMichael J. Spencer ret = 'd'; 2598e90adafSMichael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 2608e90adafSMichael J. Spencer ret = 'b'; 2618e90adafSMichael J. Spencer else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 2628e90adafSMichael J. Spencer ret = 'i'; 2638e90adafSMichael J. Spencer 2648e90adafSMichael J. Spencer // Check for section symbol. 2658e90adafSMichael J. Spencer else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC 2668e90adafSMichael J. Spencer && symb->Value == 0) 2678e90adafSMichael J. Spencer ret = 's'; 2688e90adafSMichael J. Spencer } 2698e90adafSMichael J. Spencer 2708e90adafSMichael J. Spencer if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) 27183c74e9fSGuy Benyei ret = ::toupper(static_cast<unsigned char>(ret)); 2728e90adafSMichael J. Spencer 2731d6167fdSMichael J. Spencer Result = ret; 2741d6167fdSMichael J. Spencer return object_error::success; 2758e90adafSMichael J. Spencer } 2768e90adafSMichael J. Spencer 27732173153SMichael J. Spencer error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, 27832173153SMichael J. Spencer section_iterator &Result) const { 27932173153SMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 28032173153SMichael J. Spencer if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) 28132173153SMichael J. Spencer Result = end_sections(); 28232173153SMichael J. Spencer else { 2839339d455SDaniel Dunbar const coff_section *sec = 0; 28432173153SMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; 28532173153SMichael J. Spencer DataRefImpl Sec; 28632173153SMichael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 28732173153SMichael J. Spencer Result = section_iterator(SectionRef(Sec, this)); 28832173153SMichael J. Spencer } 28932173153SMichael J. Spencer return object_error::success; 29032173153SMichael J. Spencer } 29132173153SMichael J. Spencer 2924f223bf7STim Northover error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, 2934f223bf7STim Northover uint64_t &Val) const { 2944f223bf7STim Northover report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); 2954f223bf7STim Northover } 2964f223bf7STim Northover 2971d6167fdSMichael J. Spencer error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, 2981d6167fdSMichael J. Spencer SectionRef &Result) const { 2991d6167fdSMichael J. Spencer const coff_section *sec = toSec(Sec); 3008e90adafSMichael J. Spencer sec += 1; 3011d6167fdSMichael J. Spencer Sec.p = reinterpret_cast<uintptr_t>(sec); 3021d6167fdSMichael J. Spencer Result = SectionRef(Sec, this); 3031d6167fdSMichael J. Spencer return object_error::success; 3048e90adafSMichael J. Spencer } 3058e90adafSMichael J. Spencer 3061d6167fdSMichael J. Spencer error_code COFFObjectFile::getSectionName(DataRefImpl Sec, 3071d6167fdSMichael J. Spencer StringRef &Result) const { 3081d6167fdSMichael J. Spencer const coff_section *sec = toSec(Sec); 30953c2d547SMichael J. Spencer return getSectionName(sec, Result); 3108e90adafSMichael J. Spencer } 3118e90adafSMichael J. Spencer 3121d6167fdSMichael J. Spencer error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, 3131d6167fdSMichael J. Spencer uint64_t &Result) const { 3141d6167fdSMichael J. Spencer const coff_section *sec = toSec(Sec); 3151d6167fdSMichael J. Spencer Result = sec->VirtualAddress; 3161d6167fdSMichael J. Spencer return object_error::success; 3178e90adafSMichael J. Spencer } 3188e90adafSMichael J. Spencer 3191d6167fdSMichael J. Spencer error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, 3201d6167fdSMichael J. Spencer uint64_t &Result) const { 3211d6167fdSMichael J. Spencer const coff_section *sec = toSec(Sec); 3221d6167fdSMichael J. Spencer Result = sec->SizeOfRawData; 3231d6167fdSMichael J. Spencer return object_error::success; 3248e90adafSMichael J. Spencer } 3258e90adafSMichael J. Spencer 3261d6167fdSMichael J. Spencer error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, 3271d6167fdSMichael J. Spencer StringRef &Result) const { 3281d6167fdSMichael J. Spencer const coff_section *sec = toSec(Sec); 3299da9e693SMichael J. Spencer ArrayRef<uint8_t> Res; 3309da9e693SMichael J. Spencer error_code EC = getSectionContents(sec, Res); 3319da9e693SMichael J. Spencer Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); 3329da9e693SMichael J. Spencer return EC; 3338e90adafSMichael J. Spencer } 3348e90adafSMichael J. Spencer 3357989460aSMichael J. Spencer error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, 3367989460aSMichael J. Spencer uint64_t &Res) const { 3377989460aSMichael J. Spencer const coff_section *sec = toSec(Sec); 3387989460aSMichael J. Spencer if (!sec) 3397989460aSMichael J. Spencer return object_error::parse_failed; 3407989460aSMichael J. Spencer Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); 3417989460aSMichael J. Spencer return object_error::success; 3427989460aSMichael J. Spencer } 3437989460aSMichael J. Spencer 3441d6167fdSMichael J. Spencer error_code COFFObjectFile::isSectionText(DataRefImpl Sec, 3451d6167fdSMichael J. Spencer bool &Result) const { 3461d6167fdSMichael J. Spencer const coff_section *sec = toSec(Sec); 3471d6167fdSMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; 3481d6167fdSMichael J. Spencer return object_error::success; 3498e90adafSMichael J. Spencer } 3508e90adafSMichael J. Spencer 351800619f2SMichael J. Spencer error_code COFFObjectFile::isSectionData(DataRefImpl Sec, 352800619f2SMichael J. Spencer bool &Result) const { 353800619f2SMichael J. Spencer const coff_section *sec = toSec(Sec); 354800619f2SMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 355800619f2SMichael J. Spencer return object_error::success; 356800619f2SMichael J. Spencer } 357800619f2SMichael J. Spencer 358800619f2SMichael J. Spencer error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, 359800619f2SMichael J. Spencer bool &Result) const { 360800619f2SMichael J. Spencer const coff_section *sec = toSec(Sec); 361800619f2SMichael J. Spencer Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 362800619f2SMichael J. Spencer return object_error::success; 363800619f2SMichael J. Spencer } 364800619f2SMichael J. Spencer 3652138ef6dSPreston Gurd error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 3662138ef6dSPreston Gurd bool &Result) const { 3672138ef6dSPreston Gurd // FIXME: Unimplemented 3682138ef6dSPreston Gurd Result = true; 3692138ef6dSPreston Gurd return object_error::success; 3702138ef6dSPreston Gurd } 3712138ef6dSPreston Gurd 3722138ef6dSPreston Gurd error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, 3732138ef6dSPreston Gurd bool &Result) const { 3742138ef6dSPreston Gurd const coff_section *sec = toSec(Sec); 3752138ef6dSPreston Gurd Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 3762138ef6dSPreston Gurd return object_error::success; 3772138ef6dSPreston Gurd } 3782138ef6dSPreston Gurd 3792138ef6dSPreston Gurd error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, 3802138ef6dSPreston Gurd bool &Result) const { 381b96a320aSAndrew Kaylor // FIXME: Unimplemented. 3822138ef6dSPreston Gurd Result = false; 3832138ef6dSPreston Gurd return object_error::success; 3842138ef6dSPreston Gurd } 3852138ef6dSPreston Gurd 3863f31fa05SAndrew Kaylor error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 3873f31fa05SAndrew Kaylor bool &Result) const { 3883f31fa05SAndrew Kaylor // FIXME: Unimplemented. 3893f31fa05SAndrew Kaylor Result = false; 3903f31fa05SAndrew Kaylor return object_error::success; 3913f31fa05SAndrew Kaylor } 3923f31fa05SAndrew Kaylor 393f6f3e81cSBenjamin Kramer error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, 394f6f3e81cSBenjamin Kramer DataRefImpl Symb, 395f6f3e81cSBenjamin Kramer bool &Result) const { 3969a28851eSMichael J. Spencer const coff_section *sec = toSec(Sec); 3979a28851eSMichael J. Spencer const coff_symbol *symb = toSymb(Symb); 3989339d455SDaniel Dunbar const coff_section *symb_sec = 0; 3999a28851eSMichael J. Spencer if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; 4009a28851eSMichael J. Spencer if (symb_sec == sec) 4019a28851eSMichael J. Spencer Result = true; 4029a28851eSMichael J. Spencer else 403f6f3e81cSBenjamin Kramer Result = false; 404f6f3e81cSBenjamin Kramer return object_error::success; 405f6f3e81cSBenjamin Kramer } 406f6f3e81cSBenjamin Kramer 407e5fd0047SMichael J. Spencer relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 408e5fd0047SMichael J. Spencer const coff_section *sec = toSec(Sec); 409e5fd0047SMichael J. Spencer DataRefImpl ret; 410e5fd0047SMichael J. Spencer if (sec->NumberOfRelocations == 0) 411e5fd0047SMichael J. Spencer ret.p = 0; 412e5fd0047SMichael J. Spencer else 413e5fd0047SMichael J. Spencer ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); 414e5fd0047SMichael J. Spencer 415e5fd0047SMichael J. Spencer return relocation_iterator(RelocationRef(ret, this)); 416e5fd0047SMichael J. Spencer } 417e5fd0047SMichael J. Spencer 418e5fd0047SMichael J. Spencer relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 419e5fd0047SMichael J. Spencer const coff_section *sec = toSec(Sec); 420e5fd0047SMichael J. Spencer DataRefImpl ret; 421e5fd0047SMichael J. Spencer if (sec->NumberOfRelocations == 0) 422e5fd0047SMichael J. Spencer ret.p = 0; 423e5fd0047SMichael J. Spencer else 424e5fd0047SMichael J. Spencer ret.p = reinterpret_cast<uintptr_t>( 425e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>( 426e5fd0047SMichael J. Spencer base() + sec->PointerToRelocations) 427e5fd0047SMichael J. Spencer + sec->NumberOfRelocations); 428e5fd0047SMichael J. Spencer 429e5fd0047SMichael J. Spencer return relocation_iterator(RelocationRef(ret, this)); 430e5fd0047SMichael J. Spencer } 431e5fd0047SMichael J. Spencer 432ec29b121SMichael J. Spencer COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) 433717c4d44SRafael Espindola : ObjectFile(Binary::ID_COFF, Object) 43482ebd8e3SRui Ueyama , COFFHeader(0) 43582ebd8e3SRui Ueyama , PE32Header(0) 436*ed64342bSRui Ueyama , DataDirectory(0) 437d5930ca9SMichael J. Spencer , SectionTable(0) 438d5930ca9SMichael J. Spencer , SymbolTable(0) 439d5930ca9SMichael J. Spencer , StringTable(0) 440d5930ca9SMichael J. Spencer , StringTableSize(0) { 4411d6167fdSMichael J. Spencer // Check that we at least have enough room for a header. 4421d6167fdSMichael J. Spencer if (!checkSize(Data, ec, sizeof(coff_file_header))) return; 443ee066fc4SEric Christopher 44482ebd8e3SRui Ueyama // The current location in the file where we are looking at. 44582ebd8e3SRui Ueyama uint64_t CurPtr = 0; 44682ebd8e3SRui Ueyama 44782ebd8e3SRui Ueyama // PE header is optional and is present only in executables. If it exists, 44882ebd8e3SRui Ueyama // it is placed right after COFF header. 44982ebd8e3SRui Ueyama bool hasPEHeader = false; 450ee066fc4SEric Christopher 4511d6167fdSMichael J. Spencer // Check if this is a PE/COFF file. 452ec29b121SMichael J. Spencer if (base()[0] == 0x4d && base()[1] == 0x5a) { 453ee066fc4SEric Christopher // PE/COFF, seek through MS-DOS compatibility stub and 4-byte 454ee066fc4SEric Christopher // PE signature to find 'normal' COFF header. 4551d6167fdSMichael J. Spencer if (!checkSize(Data, ec, 0x3c + 8)) return; 45682ebd8e3SRui Ueyama CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); 45782ebd8e3SRui Ueyama // Check the PE magic bytes. ("PE\0\0") 45882ebd8e3SRui Ueyama if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { 4591d6167fdSMichael J. Spencer ec = object_error::parse_failed; 4601d6167fdSMichael J. Spencer return; 4611d6167fdSMichael J. Spencer } 46282ebd8e3SRui Ueyama CurPtr += 4; // Skip the PE magic bytes. 46382ebd8e3SRui Ueyama hasPEHeader = true; 464ee066fc4SEric Christopher } 465ee066fc4SEric Christopher 466*ed64342bSRui Ueyama if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) 4671d6167fdSMichael J. Spencer return; 46882ebd8e3SRui Ueyama CurPtr += sizeof(coff_file_header); 46982ebd8e3SRui Ueyama 47082ebd8e3SRui Ueyama if (hasPEHeader) { 471*ed64342bSRui Ueyama if ((ec = getObject(PE32Header, Data, base() + CurPtr))) 47282ebd8e3SRui Ueyama return; 473*ed64342bSRui Ueyama if (PE32Header->Magic != 0x10b) { 47482ebd8e3SRui Ueyama // We only support PE32. If this is PE32 (not PE32+), the magic byte 47582ebd8e3SRui Ueyama // should be 0x10b. If this is not PE32, continue as if there's no PE 47682ebd8e3SRui Ueyama // header in this file. 47782ebd8e3SRui Ueyama PE32Header = 0; 478*ed64342bSRui Ueyama } else if (PE32Header->NumberOfRvaAndSize > 0) { 479*ed64342bSRui Ueyama const uint8_t *addr = base() + CurPtr + sizeof(pe32_header); 480*ed64342bSRui Ueyama uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; 481*ed64342bSRui Ueyama if ((ec = getObject(DataDirectory, Data, addr, size))) 482*ed64342bSRui Ueyama return; 483*ed64342bSRui Ueyama } 48482ebd8e3SRui Ueyama CurPtr += COFFHeader->SizeOfOptionalHeader; 48582ebd8e3SRui Ueyama } 4861d6167fdSMichael J. Spencer 487*ed64342bSRui Ueyama if ((ec = getObject(SectionTable, Data, base() + CurPtr, 488*ed64342bSRui Ueyama COFFHeader->NumberOfSections * sizeof(coff_section)))) 4891d6167fdSMichael J. Spencer return; 4901d6167fdSMichael J. Spencer 49182ebd8e3SRui Ueyama if (COFFHeader->PointerToSymbolTable != 0) { 492*ed64342bSRui Ueyama if ((ec = getObject(SymbolTable, Data, 493*ed64342bSRui Ueyama base() + COFFHeader->PointerToSymbolTable, 494*ed64342bSRui Ueyama COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))) 4951d6167fdSMichael J. Spencer return; 4968e90adafSMichael J. Spencer 497*ed64342bSRui Ueyama // Find string table. The first four byte of the string table contains the 498*ed64342bSRui Ueyama // total size of the string table, including the size field itself. If the 499*ed64342bSRui Ueyama // string table is empty, the value of the first four byte would be 4. 500*ed64342bSRui Ueyama const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable 50182ebd8e3SRui Ueyama + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); 502*ed64342bSRui Ueyama const ulittle32_t *StringTableSizePtr; 503*ed64342bSRui Ueyama if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr))) 504*ed64342bSRui Ueyama return; 505*ed64342bSRui Ueyama StringTableSize = *StringTableSizePtr; 506*ed64342bSRui Ueyama if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize))) 5071d6167fdSMichael J. Spencer return; 5081d6167fdSMichael J. Spencer 5091d6167fdSMichael J. Spencer // Check that the string table is null terminated if has any in it. 5101d6167fdSMichael J. Spencer if (StringTableSize < 4 5111d6167fdSMichael J. Spencer || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { 5121d6167fdSMichael J. Spencer ec = object_error::parse_failed; 5131d6167fdSMichael J. Spencer return; 5141d6167fdSMichael J. Spencer } 515d5930ca9SMichael J. Spencer } 5161d6167fdSMichael J. Spencer 5171d6167fdSMichael J. Spencer ec = object_error::success; 5188e90adafSMichael J. Spencer } 5198e90adafSMichael J. Spencer 520e5fd0047SMichael J. Spencer symbol_iterator COFFObjectFile::begin_symbols() const { 5210324b672SMichael J. Spencer DataRefImpl ret; 5220324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(SymbolTable); 5230324b672SMichael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 5248e90adafSMichael J. Spencer } 5258e90adafSMichael J. Spencer 526e5fd0047SMichael J. Spencer symbol_iterator COFFObjectFile::end_symbols() const { 5278e90adafSMichael J. Spencer // The symbol table ends where the string table begins. 5280324b672SMichael J. Spencer DataRefImpl ret; 5290324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(StringTable); 5300324b672SMichael J. Spencer return symbol_iterator(SymbolRef(ret, this)); 5318e90adafSMichael J. Spencer } 5328e90adafSMichael J. Spencer 5338c4729fdSMichael J. Spencer symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { 5348c4729fdSMichael J. Spencer // TODO: implement 5358c4729fdSMichael J. Spencer report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 5368c4729fdSMichael J. Spencer } 5378c4729fdSMichael J. Spencer 5388c4729fdSMichael J. Spencer symbol_iterator COFFObjectFile::end_dynamic_symbols() const { 5398c4729fdSMichael J. Spencer // TODO: implement 5408c4729fdSMichael J. Spencer report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); 5418c4729fdSMichael J. Spencer } 5428c4729fdSMichael J. Spencer 5432fc34c5fSDavid Meyer library_iterator COFFObjectFile::begin_libraries_needed() const { 5442fc34c5fSDavid Meyer // TODO: implement 5452fc34c5fSDavid Meyer report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 5462fc34c5fSDavid Meyer } 5472fc34c5fSDavid Meyer 5482fc34c5fSDavid Meyer library_iterator COFFObjectFile::end_libraries_needed() const { 5492fc34c5fSDavid Meyer // TODO: implement 5502fc34c5fSDavid Meyer report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); 5512fc34c5fSDavid Meyer } 5522fc34c5fSDavid Meyer 553c429b80dSDavid Meyer StringRef COFFObjectFile::getLoadName() const { 554c429b80dSDavid Meyer // COFF does not have this field. 555c429b80dSDavid Meyer return ""; 556c429b80dSDavid Meyer } 557c429b80dSDavid Meyer 558c429b80dSDavid Meyer 559e5fd0047SMichael J. Spencer section_iterator COFFObjectFile::begin_sections() const { 5600324b672SMichael J. Spencer DataRefImpl ret; 5610324b672SMichael J. Spencer ret.p = reinterpret_cast<intptr_t>(SectionTable); 5620324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 5638e90adafSMichael J. Spencer } 5648e90adafSMichael J. Spencer 565e5fd0047SMichael J. Spencer section_iterator COFFObjectFile::end_sections() const { 5660324b672SMichael J. Spencer DataRefImpl ret; 56782ebd8e3SRui Ueyama ret.p = reinterpret_cast<intptr_t>(SectionTable + COFFHeader->NumberOfSections); 5680324b672SMichael J. Spencer return section_iterator(SectionRef(ret, this)); 5698e90adafSMichael J. Spencer } 5708e90adafSMichael J. Spencer 5718e90adafSMichael J. Spencer uint8_t COFFObjectFile::getBytesInAddress() const { 5720324b672SMichael J. Spencer return getArch() == Triple::x86_64 ? 8 : 4; 5738e90adafSMichael J. Spencer } 5748e90adafSMichael J. Spencer 5758e90adafSMichael J. Spencer StringRef COFFObjectFile::getFileFormatName() const { 57682ebd8e3SRui Ueyama switch(COFFHeader->Machine) { 5778e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 5788e90adafSMichael J. Spencer return "COFF-i386"; 5798e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 5808e90adafSMichael J. Spencer return "COFF-x86-64"; 5818e90adafSMichael J. Spencer default: 5828e90adafSMichael J. Spencer return "COFF-<unknown arch>"; 5838e90adafSMichael J. Spencer } 5848e90adafSMichael J. Spencer } 5858e90adafSMichael J. Spencer 5868e90adafSMichael J. Spencer unsigned COFFObjectFile::getArch() const { 58782ebd8e3SRui Ueyama switch(COFFHeader->Machine) { 5888e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 5898e90adafSMichael J. Spencer return Triple::x86; 5908e90adafSMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 5918e90adafSMichael J. Spencer return Triple::x86_64; 5928e90adafSMichael J. Spencer default: 5938e90adafSMichael J. Spencer return Triple::UnknownArch; 5948e90adafSMichael J. Spencer } 5958e90adafSMichael J. Spencer } 5968e90adafSMichael J. Spencer 59782ebd8e3SRui Ueyama // This method is kept here because lld uses this. As soon as we make 59882ebd8e3SRui Ueyama // lld to use getCOFFHeader, this method will be removed. 59989a7a5eaSMichael J. Spencer error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { 60082ebd8e3SRui Ueyama return getCOFFHeader(Res); 60182ebd8e3SRui Ueyama } 60282ebd8e3SRui Ueyama 60382ebd8e3SRui Ueyama error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { 60482ebd8e3SRui Ueyama Res = COFFHeader; 60582ebd8e3SRui Ueyama return object_error::success; 60682ebd8e3SRui Ueyama } 60782ebd8e3SRui Ueyama 60882ebd8e3SRui Ueyama error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 60982ebd8e3SRui Ueyama Res = PE32Header; 61089a7a5eaSMichael J. Spencer return object_error::success; 61189a7a5eaSMichael J. Spencer } 61289a7a5eaSMichael J. Spencer 613*ed64342bSRui Ueyama error_code COFFObjectFile::getDataDirectory(uint32_t index, 614*ed64342bSRui Ueyama const data_directory *&Res) const { 615*ed64342bSRui Ueyama // Error if if there's no data directory or the index is out of range. 616*ed64342bSRui Ueyama if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize) 617*ed64342bSRui Ueyama return object_error::parse_failed; 618*ed64342bSRui Ueyama Res = &DataDirectory[index]; 619*ed64342bSRui Ueyama return object_error::success; 620*ed64342bSRui Ueyama } 621*ed64342bSRui Ueyama 6221d6167fdSMichael J. Spencer error_code COFFObjectFile::getSection(int32_t index, 6231d6167fdSMichael J. Spencer const coff_section *&Result) const { 6241d6167fdSMichael J. Spencer // Check for special index values. 6251d6167fdSMichael J. Spencer if (index == COFF::IMAGE_SYM_UNDEFINED || 6261d6167fdSMichael J. Spencer index == COFF::IMAGE_SYM_ABSOLUTE || 6271d6167fdSMichael J. Spencer index == COFF::IMAGE_SYM_DEBUG) 6281d6167fdSMichael J. Spencer Result = NULL; 62982ebd8e3SRui Ueyama else if (index > 0 && index <= COFFHeader->NumberOfSections) 6301d6167fdSMichael J. Spencer // We already verified the section table data, so no need to check again. 6311d6167fdSMichael J. Spencer Result = SectionTable + (index - 1); 6321d6167fdSMichael J. Spencer else 6331d6167fdSMichael J. Spencer return object_error::parse_failed; 6341d6167fdSMichael J. Spencer return object_error::success; 6358e90adafSMichael J. Spencer } 6368e90adafSMichael J. Spencer 6371d6167fdSMichael J. Spencer error_code COFFObjectFile::getString(uint32_t offset, 6381d6167fdSMichael J. Spencer StringRef &Result) const { 6391d6167fdSMichael J. Spencer if (StringTableSize <= 4) 6401d6167fdSMichael J. Spencer // Tried to get a string from an empty string table. 6411d6167fdSMichael J. Spencer return object_error::parse_failed; 6421d6167fdSMichael J. Spencer if (offset >= StringTableSize) 6431d6167fdSMichael J. Spencer return object_error::unexpected_eof; 6441d6167fdSMichael J. Spencer Result = StringRef(StringTable + offset); 6451d6167fdSMichael J. Spencer return object_error::success; 6468e90adafSMichael J. Spencer } 647022ecdf2SBenjamin Kramer 648e5fd0047SMichael J. Spencer error_code COFFObjectFile::getSymbol(uint32_t index, 649e5fd0047SMichael J. Spencer const coff_symbol *&Result) const { 65082ebd8e3SRui Ueyama if (index < COFFHeader->NumberOfSymbols) 651e5fd0047SMichael J. Spencer Result = SymbolTable + index; 652e5fd0047SMichael J. Spencer else 653e5fd0047SMichael J. Spencer return object_error::parse_failed; 654e5fd0047SMichael J. Spencer return object_error::success; 655e5fd0047SMichael J. Spencer } 656e5fd0047SMichael J. Spencer 65789a7a5eaSMichael J. Spencer error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, 65889a7a5eaSMichael J. Spencer StringRef &Res) const { 65989a7a5eaSMichael J. Spencer // Check for string table entry. First 4 bytes are 0. 66089a7a5eaSMichael J. Spencer if (symbol->Name.Offset.Zeroes == 0) { 66189a7a5eaSMichael J. Spencer uint32_t Offset = symbol->Name.Offset.Offset; 66289a7a5eaSMichael J. Spencer if (error_code ec = getString(Offset, Res)) 66389a7a5eaSMichael J. Spencer return ec; 66489a7a5eaSMichael J. Spencer return object_error::success; 66589a7a5eaSMichael J. Spencer } 66689a7a5eaSMichael J. Spencer 66789a7a5eaSMichael J. Spencer if (symbol->Name.ShortName[7] == 0) 66889a7a5eaSMichael J. Spencer // Null terminated, let ::strlen figure out the length. 66989a7a5eaSMichael J. Spencer Res = StringRef(symbol->Name.ShortName); 67089a7a5eaSMichael J. Spencer else 67189a7a5eaSMichael J. Spencer // Not null terminated, use all 8 bytes. 67289a7a5eaSMichael J. Spencer Res = StringRef(symbol->Name.ShortName, 8); 67389a7a5eaSMichael J. Spencer return object_error::success; 67489a7a5eaSMichael J. Spencer } 67589a7a5eaSMichael J. Spencer 67671757ef3SMarshall Clow ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( 67771757ef3SMarshall Clow const coff_symbol *symbol) const { 67871757ef3SMarshall Clow const uint8_t *aux = NULL; 67971757ef3SMarshall Clow 68071757ef3SMarshall Clow if ( symbol->NumberOfAuxSymbols > 0 ) { 68171757ef3SMarshall Clow // AUX data comes immediately after the symbol in COFF 68271757ef3SMarshall Clow aux = reinterpret_cast<const uint8_t *>(symbol + 1); 68371757ef3SMarshall Clow # ifndef NDEBUG 68471757ef3SMarshall Clow // Verify that the aux symbol points to a valid entry in the symbol table. 68571757ef3SMarshall Clow uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); 68682ebd8e3SRui Ueyama if (offset < COFFHeader->PointerToSymbolTable 68782ebd8e3SRui Ueyama || offset >= COFFHeader->PointerToSymbolTable 68882ebd8e3SRui Ueyama + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) 68971757ef3SMarshall Clow report_fatal_error("Aux Symbol data was outside of symbol table."); 69071757ef3SMarshall Clow 69182ebd8e3SRui Ueyama assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) 69271757ef3SMarshall Clow == 0 && "Aux Symbol data did not point to the beginning of a symbol"); 69371757ef3SMarshall Clow # endif 694bfb85e67SMarshall Clow } 69571757ef3SMarshall Clow return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); 69671757ef3SMarshall Clow } 69771757ef3SMarshall Clow 69853c2d547SMichael J. Spencer error_code COFFObjectFile::getSectionName(const coff_section *Sec, 69953c2d547SMichael J. Spencer StringRef &Res) const { 70053c2d547SMichael J. Spencer StringRef Name; 70153c2d547SMichael J. Spencer if (Sec->Name[7] == 0) 70253c2d547SMichael J. Spencer // Null terminated, let ::strlen figure out the length. 70353c2d547SMichael J. Spencer Name = Sec->Name; 70453c2d547SMichael J. Spencer else 70553c2d547SMichael J. Spencer // Not null terminated, use all 8 bytes. 70653c2d547SMichael J. Spencer Name = StringRef(Sec->Name, 8); 70753c2d547SMichael J. Spencer 70853c2d547SMichael J. Spencer // Check for string table entry. First byte is '/'. 70953c2d547SMichael J. Spencer if (Name[0] == '/') { 71053c2d547SMichael J. Spencer uint32_t Offset; 71153c2d547SMichael J. Spencer if (Name.substr(1).getAsInteger(10, Offset)) 71253c2d547SMichael J. Spencer return object_error::parse_failed; 71353c2d547SMichael J. Spencer if (error_code ec = getString(Offset, Name)) 71453c2d547SMichael J. Spencer return ec; 71553c2d547SMichael J. Spencer } 71653c2d547SMichael J. Spencer 71753c2d547SMichael J. Spencer Res = Name; 71853c2d547SMichael J. Spencer return object_error::success; 71953c2d547SMichael J. Spencer } 72053c2d547SMichael J. Spencer 7219da9e693SMichael J. Spencer error_code COFFObjectFile::getSectionContents(const coff_section *Sec, 7229da9e693SMichael J. Spencer ArrayRef<uint8_t> &Res) const { 7239da9e693SMichael J. Spencer // The only thing that we need to verify is that the contents is contained 7249da9e693SMichael J. Spencer // within the file bounds. We don't need to make sure it doesn't cover other 7259da9e693SMichael J. Spencer // data, as there's nothing that says that is not allowed. 7269da9e693SMichael J. Spencer uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; 7279da9e693SMichael J. Spencer uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; 7289da9e693SMichael J. Spencer if (ConEnd > uintptr_t(Data->getBufferEnd())) 7299da9e693SMichael J. Spencer return object_error::parse_failed; 7309da9e693SMichael J. Spencer Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), 7319da9e693SMichael J. Spencer Sec->SizeOfRawData); 7329da9e693SMichael J. Spencer return object_error::success; 7339da9e693SMichael J. Spencer } 7349da9e693SMichael J. Spencer 735022ecdf2SBenjamin Kramer const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { 736e5fd0047SMichael J. Spencer return reinterpret_cast<const coff_relocation*>(Rel.p); 737022ecdf2SBenjamin Kramer } 738022ecdf2SBenjamin Kramer error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, 739022ecdf2SBenjamin Kramer RelocationRef &Res) const { 740e5fd0047SMichael J. Spencer Rel.p = reinterpret_cast<uintptr_t>( 741e5fd0047SMichael J. Spencer reinterpret_cast<const coff_relocation*>(Rel.p) + 1); 742022ecdf2SBenjamin Kramer Res = RelocationRef(Rel, this); 743022ecdf2SBenjamin Kramer return object_error::success; 744022ecdf2SBenjamin Kramer } 745022ecdf2SBenjamin Kramer error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, 746022ecdf2SBenjamin Kramer uint64_t &Res) const { 7471e483879SRafael Espindola report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); 748022ecdf2SBenjamin Kramer } 749cbe72fc9SDanil Malyshev error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, 750cbe72fc9SDanil Malyshev uint64_t &Res) const { 751cbe72fc9SDanil Malyshev Res = toRel(Rel)->VirtualAddress; 752cbe72fc9SDanil Malyshev return object_error::success; 753cbe72fc9SDanil Malyshev } 754806f0064SRafael Espindola symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 755022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 756022ecdf2SBenjamin Kramer DataRefImpl Symb; 757022ecdf2SBenjamin Kramer Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); 758806f0064SRafael Espindola return symbol_iterator(SymbolRef(Symb, this)); 759022ecdf2SBenjamin Kramer } 760022ecdf2SBenjamin Kramer error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, 7617be76590SOwen Anderson uint64_t &Res) const { 762022ecdf2SBenjamin Kramer const coff_relocation* R = toRel(Rel); 763022ecdf2SBenjamin Kramer Res = R->Type; 764022ecdf2SBenjamin Kramer return object_error::success; 765022ecdf2SBenjamin Kramer } 766e5fd0047SMichael J. Spencer 76771757ef3SMarshall Clow const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { 76871757ef3SMarshall Clow return toSec(It->getRawDataRefImpl()); 76971757ef3SMarshall Clow } 77071757ef3SMarshall Clow 77171757ef3SMarshall Clow const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { 77271757ef3SMarshall Clow return toSymb(It->getRawDataRefImpl()); 77371757ef3SMarshall Clow } 77471757ef3SMarshall Clow 775d3e2a76cSMarshall Clow const coff_relocation *COFFObjectFile::getCOFFRelocation( 776d3e2a76cSMarshall Clow relocation_iterator &It) const { 777d3e2a76cSMarshall Clow return toRel(It->getRawDataRefImpl()); 778d3e2a76cSMarshall Clow } 779d3e2a76cSMarshall Clow 78071757ef3SMarshall Clow 781e5fd0047SMichael J. Spencer #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ 782e5fd0047SMichael J. Spencer case COFF::enum: res = #enum; break; 783e5fd0047SMichael J. Spencer 784e5fd0047SMichael J. Spencer error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 785e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 786e5fd0047SMichael J. Spencer const coff_relocation *reloc = toRel(Rel); 787e5fd0047SMichael J. Spencer StringRef res; 78882ebd8e3SRui Ueyama switch (COFFHeader->Machine) { 789e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_AMD64: 790e5fd0047SMichael J. Spencer switch (reloc->Type) { 791e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); 792e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); 793e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); 794e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); 795e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); 796e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); 797e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); 798e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); 799e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); 800e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); 801e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); 802e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); 803e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); 804e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); 805e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); 806e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); 807e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); 808e5fd0047SMichael J. Spencer default: 809e5fd0047SMichael J. Spencer res = "Unknown"; 810e5fd0047SMichael J. Spencer } 811e5fd0047SMichael J. Spencer break; 812e5fd0047SMichael J. Spencer case COFF::IMAGE_FILE_MACHINE_I386: 813e5fd0047SMichael J. Spencer switch (reloc->Type) { 814e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); 815e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); 816e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); 817e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); 818e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); 819e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); 820e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); 821e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); 822e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); 823e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); 824e5fd0047SMichael J. Spencer LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); 825e5fd0047SMichael J. Spencer default: 826e5fd0047SMichael J. Spencer res = "Unknown"; 827e5fd0047SMichael J. Spencer } 828e5fd0047SMichael J. Spencer break; 829e5fd0047SMichael J. Spencer default: 830e5fd0047SMichael J. Spencer res = "Unknown"; 831e5fd0047SMichael J. Spencer } 832e5fd0047SMichael J. Spencer Result.append(res.begin(), res.end()); 833e5fd0047SMichael J. Spencer return object_error::success; 834e5fd0047SMichael J. Spencer } 835e5fd0047SMichael J. Spencer 836e5fd0047SMichael J. Spencer #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME 837e5fd0047SMichael J. Spencer 838e5fd0047SMichael J. Spencer error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, 839e5fd0047SMichael J. Spencer SmallVectorImpl<char> &Result) const { 840e5fd0047SMichael J. Spencer const coff_relocation *reloc = toRel(Rel); 841648b2fafSNAKAMURA Takumi const coff_symbol *symb = 0; 842e5fd0047SMichael J. Spencer if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; 843e5fd0047SMichael J. Spencer DataRefImpl sym; 844e5fd0047SMichael J. Spencer sym.p = reinterpret_cast<uintptr_t>(symb); 845e5fd0047SMichael J. Spencer StringRef symname; 846e5fd0047SMichael J. Spencer if (error_code ec = getSymbolName(sym, symname)) return ec; 847e5fd0047SMichael J. Spencer Result.append(symname.begin(), symname.end()); 848e5fd0047SMichael J. Spencer return object_error::success; 849022ecdf2SBenjamin Kramer } 8508e90adafSMichael J. Spencer 8512fc34c5fSDavid Meyer error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, 8522fc34c5fSDavid Meyer LibraryRef &Result) const { 8532fc34c5fSDavid Meyer report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); 8542fc34c5fSDavid Meyer } 8552fc34c5fSDavid Meyer 8562fc34c5fSDavid Meyer error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, 8572fc34c5fSDavid Meyer StringRef &Result) const { 8582fc34c5fSDavid Meyer report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); 8592fc34c5fSDavid Meyer } 8602fc34c5fSDavid Meyer 8618e90adafSMichael J. Spencer namespace llvm { 8628e90adafSMichael J. Spencer 8638e90adafSMichael J. Spencer ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { 864ec29b121SMichael J. Spencer error_code ec; 865ec29b121SMichael J. Spencer return new COFFObjectFile(Object, ec); 8668e90adafSMichael J. Spencer } 8678e90adafSMichael J. Spencer 8688e90adafSMichael J. Spencer } // end namespace llvm 869