1*b60a18deSMichael J. Spencer //===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===//
2*b60a18deSMichael J. Spencer //
3*b60a18deSMichael J. Spencer //                     The LLVM Compiler Infrastructure
4*b60a18deSMichael J. Spencer //
5*b60a18deSMichael J. Spencer // This file is distributed under the University of Illinois Open Source
6*b60a18deSMichael J. Spencer // License. See LICENSE.TXT for details.
7*b60a18deSMichael J. Spencer //
8*b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===//
9*b60a18deSMichael J. Spencer //
10*b60a18deSMichael J. Spencer // This file defines the ELFObjectFile class.
11*b60a18deSMichael J. Spencer //
12*b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===//
13*b60a18deSMichael J. Spencer 
14*b60a18deSMichael J. Spencer #include "llvm/ADT/SmallVector.h"
15*b60a18deSMichael J. Spencer #include "llvm/ADT/StringSwitch.h"
16*b60a18deSMichael J. Spencer #include "llvm/ADT/Triple.h"
17*b60a18deSMichael J. Spencer #include "llvm/Object/ObjectFile.h"
18*b60a18deSMichael J. Spencer #include "llvm/Support/ELF.h"
19*b60a18deSMichael J. Spencer #include "llvm/Support/Endian.h"
20*b60a18deSMichael J. Spencer #include "llvm/Support/ErrorHandling.h"
21*b60a18deSMichael J. Spencer #include "llvm/Support/MemoryBuffer.h"
22*b60a18deSMichael J. Spencer #include <limits>
23*b60a18deSMichael J. Spencer #include <utility>
24*b60a18deSMichael J. Spencer 
25*b60a18deSMichael J. Spencer using namespace llvm;
26*b60a18deSMichael J. Spencer using namespace object;
27*b60a18deSMichael J. Spencer 
28*b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
29*b60a18deSMichael J. Spencer namespace {
30*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
31*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon {
32*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
33*b60a18deSMichael J. Spencer     <uint16_t, target_endianness, support::aligned> Elf_Half;
34*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
35*b60a18deSMichael J. Spencer     <uint32_t, target_endianness, support::aligned> Elf_Word;
36*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
37*b60a18deSMichael J. Spencer     <int32_t, target_endianness, support::aligned> Elf_Sword;
38*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
39*b60a18deSMichael J. Spencer     <uint64_t, target_endianness, support::aligned> Elf_Xword;
40*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
41*b60a18deSMichael J. Spencer     <int64_t, target_endianness, support::aligned> Elf_Sxword;
42*b60a18deSMichael J. Spencer };
43*b60a18deSMichael J. Spencer }
44*b60a18deSMichael J. Spencer 
45*b60a18deSMichael J. Spencer namespace {
46*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
47*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper;
48*b60a18deSMichael J. Spencer 
49*b60a18deSMichael J. Spencer /// ELF 32bit types.
50*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
51*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false>
52*b60a18deSMichael J. Spencer   : ELFDataTypeTypedefHelperCommon<target_endianness> {
53*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
54*b60a18deSMichael J. Spencer     <uint32_t, target_endianness, support::aligned> Elf_Addr;
55*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
56*b60a18deSMichael J. Spencer     <uint32_t, target_endianness, support::aligned> Elf_Off;
57*b60a18deSMichael J. Spencer };
58*b60a18deSMichael J. Spencer 
59*b60a18deSMichael J. Spencer /// ELF 64bit types.
60*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
61*b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true>
62*b60a18deSMichael J. Spencer   : ELFDataTypeTypedefHelperCommon<target_endianness>{
63*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
64*b60a18deSMichael J. Spencer     <uint64_t, target_endianness, support::aligned> Elf_Addr;
65*b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
66*b60a18deSMichael J. Spencer     <uint64_t, target_endianness, support::aligned> Elf_Off;
67*b60a18deSMichael J. Spencer };
68*b60a18deSMichael J. Spencer }
69*b60a18deSMichael J. Spencer 
70*b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta.
71*b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \
72*b60a18deSMichael J. Spencer typedef typename \
73*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \
74*b60a18deSMichael J. Spencer typedef typename \
75*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \
76*b60a18deSMichael J. Spencer typedef typename \
77*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \
78*b60a18deSMichael J. Spencer typedef typename \
79*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \
80*b60a18deSMichael J. Spencer typedef typename \
81*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \
82*b60a18deSMichael J. Spencer typedef typename \
83*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \
84*b60a18deSMichael J. Spencer typedef typename \
85*b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword;
86*b60a18deSMichael J. Spencer 
87*b60a18deSMichael J. Spencer   // Section header.
88*b60a18deSMichael J. Spencer namespace {
89*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
90*b60a18deSMichael J. Spencer struct Elf_Shdr_Base;
91*b60a18deSMichael J. Spencer 
92*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
93*b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> {
94*b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
95*b60a18deSMichael J. Spencer   Elf_Word sh_name;     // Section name (index into string table)
96*b60a18deSMichael J. Spencer   Elf_Word sh_type;     // Section type (SHT_*)
97*b60a18deSMichael J. Spencer   Elf_Word sh_flags;    // Section flags (SHF_*)
98*b60a18deSMichael J. Spencer   Elf_Addr sh_addr;     // Address where section is to be loaded
99*b60a18deSMichael J. Spencer   Elf_Off  sh_offset;   // File offset of section data, in bytes
100*b60a18deSMichael J. Spencer   Elf_Word sh_size;     // Size of section, in bytes
101*b60a18deSMichael J. Spencer   Elf_Word sh_link;     // Section type-specific header table index link
102*b60a18deSMichael J. Spencer   Elf_Word sh_info;     // Section type-specific extra information
103*b60a18deSMichael J. Spencer   Elf_Word sh_addralign;// Section address alignment
104*b60a18deSMichael J. Spencer   Elf_Word sh_entsize;  // Size of records contained within the section
105*b60a18deSMichael J. Spencer };
106*b60a18deSMichael J. Spencer 
107*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
108*b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> {
109*b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
110*b60a18deSMichael J. Spencer   Elf_Word  sh_name;     // Section name (index into string table)
111*b60a18deSMichael J. Spencer   Elf_Word  sh_type;     // Section type (SHT_*)
112*b60a18deSMichael J. Spencer   Elf_Xword sh_flags;    // Section flags (SHF_*)
113*b60a18deSMichael J. Spencer   Elf_Addr  sh_addr;     // Address where section is to be loaded
114*b60a18deSMichael J. Spencer   Elf_Off   sh_offset;   // File offset of section data, in bytes
115*b60a18deSMichael J. Spencer   Elf_Xword sh_size;     // Size of section, in bytes
116*b60a18deSMichael J. Spencer   Elf_Word  sh_link;     // Section type-specific header table index link
117*b60a18deSMichael J. Spencer   Elf_Word  sh_info;     // Section type-specific extra information
118*b60a18deSMichael J. Spencer   Elf_Xword sh_addralign;// Section address alignment
119*b60a18deSMichael J. Spencer   Elf_Xword sh_entsize;  // Size of records contained within the section
120*b60a18deSMichael J. Spencer };
121*b60a18deSMichael J. Spencer 
122*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
123*b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> {
124*b60a18deSMichael J. Spencer   using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize;
125*b60a18deSMichael J. Spencer   using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size;
126*b60a18deSMichael J. Spencer 
127*b60a18deSMichael J. Spencer   /// @brief Get the number of entities this section contains if it has any.
128*b60a18deSMichael J. Spencer   unsigned getEntityCount() const {
129*b60a18deSMichael J. Spencer     if (sh_entsize == 0)
130*b60a18deSMichael J. Spencer       return 0;
131*b60a18deSMichael J. Spencer     else
132*b60a18deSMichael J. Spencer       return sh_size / sh_entsize;
133*b60a18deSMichael J. Spencer   }
134*b60a18deSMichael J. Spencer };
135*b60a18deSMichael J. Spencer }
136*b60a18deSMichael J. Spencer 
137*b60a18deSMichael J. Spencer namespace {
138*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
139*b60a18deSMichael J. Spencer struct Elf_Sym_Base;
140*b60a18deSMichael J. Spencer 
141*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
142*b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> {
143*b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
144*b60a18deSMichael J. Spencer   Elf_Word      st_name;  // Symbol name (index into string table)
145*b60a18deSMichael J. Spencer   Elf_Addr      st_value; // Value or address associated with the symbol
146*b60a18deSMichael J. Spencer   Elf_Word      st_size;  // Size of the symbol
147*b60a18deSMichael J. Spencer   unsigned char st_info;  // Symbol's type and binding attributes
148*b60a18deSMichael J. Spencer   unsigned char st_other; // Must be zero; reserved
149*b60a18deSMichael J. Spencer   Elf_Half      st_shndx; // Which section (header table index) it's defined in
150*b60a18deSMichael J. Spencer };
151*b60a18deSMichael J. Spencer 
152*b60a18deSMichael J. Spencer template<support::endianness target_endianness>
153*b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> {
154*b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
155*b60a18deSMichael J. Spencer   Elf_Word      st_name;  // Symbol name (index into string table)
156*b60a18deSMichael J. Spencer   unsigned char st_info;  // Symbol's type and binding attributes
157*b60a18deSMichael J. Spencer   unsigned char st_other; // Must be zero; reserved
158*b60a18deSMichael J. Spencer   Elf_Half      st_shndx; // Which section (header table index) it's defined in
159*b60a18deSMichael J. Spencer   Elf_Addr      st_value; // Value or address associated with the symbol
160*b60a18deSMichael J. Spencer   Elf_Xword     st_size;  // Size of the symbol
161*b60a18deSMichael J. Spencer };
162*b60a18deSMichael J. Spencer 
163*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
164*b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> {
165*b60a18deSMichael J. Spencer   using Elf_Sym_Base<target_endianness, is64Bits>::st_info;
166*b60a18deSMichael J. Spencer 
167*b60a18deSMichael J. Spencer   // These accessors and mutators correspond to the ELF32_ST_BIND,
168*b60a18deSMichael J. Spencer   // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
169*b60a18deSMichael J. Spencer   unsigned char getBinding() const { return st_info >> 4; }
170*b60a18deSMichael J. Spencer   unsigned char getType() const { return st_info & 0x0f; }
171*b60a18deSMichael J. Spencer   void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
172*b60a18deSMichael J. Spencer   void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
173*b60a18deSMichael J. Spencer   void setBindingAndType(unsigned char b, unsigned char t) {
174*b60a18deSMichael J. Spencer     st_info = (b << 4) + (t & 0x0f);
175*b60a18deSMichael J. Spencer   }
176*b60a18deSMichael J. Spencer };
177*b60a18deSMichael J. Spencer }
178*b60a18deSMichael J. Spencer 
179*b60a18deSMichael J. Spencer namespace {
180*b60a18deSMichael J. Spencer struct ELFDataRefImpl {
181*b60a18deSMichael J. Spencer   uint32_t SymbolIndex;
182*b60a18deSMichael J. Spencer   uint16_t SymbolTableSectionIndex;
183*b60a18deSMichael J. Spencer   uint16_t Unused;
184*b60a18deSMichael J. Spencer };
185*b60a18deSMichael J. Spencer }
186*b60a18deSMichael J. Spencer 
187*b60a18deSMichael J. Spencer namespace {
188*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
189*b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile {
190*b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
191*b60a18deSMichael J. Spencer 
192*b60a18deSMichael J. Spencer   typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
193*b60a18deSMichael J. Spencer   typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
194*b60a18deSMichael J. Spencer 
195*b60a18deSMichael J. Spencer   struct Elf_Ehdr {
196*b60a18deSMichael J. Spencer     unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes
197*b60a18deSMichael J. Spencer     Elf_Half e_type;     // Type of file (see ET_*)
198*b60a18deSMichael J. Spencer     Elf_Half e_machine;  // Required architecture for this file (see EM_*)
199*b60a18deSMichael J. Spencer     Elf_Word e_version;  // Must be equal to 1
200*b60a18deSMichael J. Spencer     Elf_Addr e_entry;    // Address to jump to in order to start program
201*b60a18deSMichael J. Spencer     Elf_Off  e_phoff;    // Program header table's file offset, in bytes
202*b60a18deSMichael J. Spencer     Elf_Off  e_shoff;    // Section header table's file offset, in bytes
203*b60a18deSMichael J. Spencer     Elf_Word e_flags;    // Processor-specific flags
204*b60a18deSMichael J. Spencer     Elf_Half e_ehsize;   // Size of ELF header, in bytes
205*b60a18deSMichael J. Spencer     Elf_Half e_phentsize;// Size of an entry in the program header table
206*b60a18deSMichael J. Spencer     Elf_Half e_phnum;    // Number of entries in the program header table
207*b60a18deSMichael J. Spencer     Elf_Half e_shentsize;// Size of an entry in the section header table
208*b60a18deSMichael J. Spencer     Elf_Half e_shnum;    // Number of entries in the section header table
209*b60a18deSMichael J. Spencer     Elf_Half e_shstrndx; // Section header table index of section name
210*b60a18deSMichael J. Spencer                                   // string table
211*b60a18deSMichael J. Spencer     bool checkMagic() const {
212*b60a18deSMichael J. Spencer       return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
213*b60a18deSMichael J. Spencer     }
214*b60a18deSMichael J. Spencer     unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
215*b60a18deSMichael J. Spencer     unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
216*b60a18deSMichael J. Spencer   };
217*b60a18deSMichael J. Spencer 
218*b60a18deSMichael J. Spencer   typedef SmallVector<const Elf_Shdr*, 1> SymbolTableSections_t;
219*b60a18deSMichael J. Spencer 
220*b60a18deSMichael J. Spencer   const Elf_Ehdr *Header;
221*b60a18deSMichael J. Spencer   const Elf_Shdr *SectionHeaderTable;
222*b60a18deSMichael J. Spencer   const Elf_Shdr *dot_shstrtab_sec; // Section header string table.
223*b60a18deSMichael J. Spencer   const Elf_Shdr *dot_strtab_sec;   // Symbol header string table.
224*b60a18deSMichael J. Spencer   SymbolTableSections_t SymbolTableSections;
225*b60a18deSMichael J. Spencer 
226*b60a18deSMichael J. Spencer   void            validateSymbol(DataRefImpl Symb) const;
227*b60a18deSMichael J. Spencer   const Elf_Sym  *getSymbol(DataRefImpl Symb) const;
228*b60a18deSMichael J. Spencer   const Elf_Shdr *getSection(DataRefImpl index) const;
229*b60a18deSMichael J. Spencer   const Elf_Shdr *getSection(uint16_t index) const;
230*b60a18deSMichael J. Spencer   const char     *getString(uint16_t section, uint32_t offset) const;
231*b60a18deSMichael J. Spencer   const char     *getString(const Elf_Shdr *section, uint32_t offset) const;
232*b60a18deSMichael J. Spencer 
233*b60a18deSMichael J. Spencer protected:
234*b60a18deSMichael J. Spencer   virtual SymbolRef getSymbolNext(DataRefImpl Symb) const;
235*b60a18deSMichael J. Spencer   virtual StringRef getSymbolName(DataRefImpl Symb) const;
236*b60a18deSMichael J. Spencer   virtual uint64_t  getSymbolAddress(DataRefImpl Symb) const;
237*b60a18deSMichael J. Spencer   virtual uint64_t  getSymbolSize(DataRefImpl Symb) const;
238*b60a18deSMichael J. Spencer   virtual char      getSymbolNMTypeChar(DataRefImpl Symb) const;
239*b60a18deSMichael J. Spencer   virtual bool      isSymbolInternal(DataRefImpl Symb) const;
240*b60a18deSMichael J. Spencer 
241*b60a18deSMichael J. Spencer   virtual SectionRef getSectionNext(DataRefImpl Sec) const;
242*b60a18deSMichael J. Spencer   virtual StringRef  getSectionName(DataRefImpl Sec) const;
243*b60a18deSMichael J. Spencer   virtual uint64_t   getSectionAddress(DataRefImpl Sec) const;
244*b60a18deSMichael J. Spencer   virtual uint64_t   getSectionSize(DataRefImpl Sec) const;
245*b60a18deSMichael J. Spencer   virtual StringRef  getSectionContents(DataRefImpl Sec) const;
246*b60a18deSMichael J. Spencer   virtual bool       isSectionText(DataRefImpl Sec) const;
247*b60a18deSMichael J. Spencer 
248*b60a18deSMichael J. Spencer public:
249*b60a18deSMichael J. Spencer   ELFObjectFile(MemoryBuffer *Object);
250*b60a18deSMichael J. Spencer   virtual symbol_iterator begin_symbols() const;
251*b60a18deSMichael J. Spencer   virtual symbol_iterator end_symbols() const;
252*b60a18deSMichael J. Spencer   virtual section_iterator begin_sections() const;
253*b60a18deSMichael J. Spencer   virtual section_iterator end_sections() const;
254*b60a18deSMichael J. Spencer 
255*b60a18deSMichael J. Spencer   virtual uint8_t getBytesInAddress() const;
256*b60a18deSMichael J. Spencer   virtual StringRef getFileFormatName() const;
257*b60a18deSMichael J. Spencer   virtual unsigned getArch() const;
258*b60a18deSMichael J. Spencer };
259*b60a18deSMichael J. Spencer } // end namespace
260*b60a18deSMichael J. Spencer 
261*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
262*b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits>
263*b60a18deSMichael J. Spencer                   ::validateSymbol(DataRefImpl Symb) const {
264*b60a18deSMichael J. Spencer   const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
265*b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
266*b60a18deSMichael J. Spencer   const Elf_Shdr *SymbolTableSection =
267*b60a18deSMichael J. Spencer     SymbolTableSections[SymbolData.SymbolTableSectionIndex];
268*b60a18deSMichael J. Spencer   // FIXME: We really need to do proper error handling in the case of an invalid
269*b60a18deSMichael J. Spencer   //        input file. Because we don't use exceptions, I think we'll just pass
270*b60a18deSMichael J. Spencer   //        an error object around.
271*b60a18deSMichael J. Spencer   if (!(  symb
272*b60a18deSMichael J. Spencer         && SymbolTableSection
273*b60a18deSMichael J. Spencer         && symb >= (const Elf_Sym*)(base
274*b60a18deSMichael J. Spencer                    + SymbolTableSection->sh_offset)
275*b60a18deSMichael J. Spencer         && symb <  (const Elf_Sym*)(base
276*b60a18deSMichael J. Spencer                    + SymbolTableSection->sh_offset
277*b60a18deSMichael J. Spencer                    + SymbolTableSection->sh_size)))
278*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
279*b60a18deSMichael J. Spencer     report_fatal_error("Symb must point to a valid symbol!");
280*b60a18deSMichael J. Spencer }
281*b60a18deSMichael J. Spencer 
282*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
283*b60a18deSMichael J. Spencer SymbolRef ELFObjectFile<target_endianness, is64Bits>
284*b60a18deSMichael J. Spencer                        ::getSymbolNext(DataRefImpl Symb) const {
285*b60a18deSMichael J. Spencer   validateSymbol(Symb);
286*b60a18deSMichael J. Spencer   ELFDataRefImpl &SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
287*b60a18deSMichael J. Spencer   const Elf_Shdr *SymbolTableSection =
288*b60a18deSMichael J. Spencer     SymbolTableSections[SymbolData.SymbolTableSectionIndex];
289*b60a18deSMichael J. Spencer 
290*b60a18deSMichael J. Spencer   ++SymbolData.SymbolIndex;
291*b60a18deSMichael J. Spencer   // Check to see if we are at the end of this symbol table.
292*b60a18deSMichael J. Spencer   if (SymbolData.SymbolIndex >= SymbolTableSection->getEntityCount()) {
293*b60a18deSMichael J. Spencer     // We are at the end. If there are other symbol tables, jump to them.
294*b60a18deSMichael J. Spencer     ++SymbolData.SymbolTableSectionIndex;
295*b60a18deSMichael J. Spencer     SymbolData.SymbolIndex = 1; // The 0th symbol in ELF is fake.
296*b60a18deSMichael J. Spencer     // Otherwise return the terminator.
297*b60a18deSMichael J. Spencer     if (SymbolData.SymbolTableSectionIndex >= SymbolTableSections.size()) {
298*b60a18deSMichael J. Spencer       SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max();
299*b60a18deSMichael J. Spencer       SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max();
300*b60a18deSMichael J. Spencer     }
301*b60a18deSMichael J. Spencer   }
302*b60a18deSMichael J. Spencer 
303*b60a18deSMichael J. Spencer   return SymbolRef(Symb, this);
304*b60a18deSMichael J. Spencer }
305*b60a18deSMichael J. Spencer 
306*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
307*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits>
308*b60a18deSMichael J. Spencer                        ::getSymbolName(DataRefImpl Symb) const {
309*b60a18deSMichael J. Spencer   validateSymbol(Symb);
310*b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
311*b60a18deSMichael J. Spencer   if (symb->st_name == 0) {
312*b60a18deSMichael J. Spencer     const Elf_Shdr *section = getSection(symb->st_shndx);
313*b60a18deSMichael J. Spencer     if (!section)
314*b60a18deSMichael J. Spencer       return "";
315*b60a18deSMichael J. Spencer     return getString(dot_shstrtab_sec, section->sh_name);
316*b60a18deSMichael J. Spencer   }
317*b60a18deSMichael J. Spencer 
318*b60a18deSMichael J. Spencer   // Use the default symbol table name section.
319*b60a18deSMichael J. Spencer   return getString(dot_strtab_sec, symb->st_name);
320*b60a18deSMichael J. Spencer }
321*b60a18deSMichael J. Spencer 
322*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
323*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits>
324*b60a18deSMichael J. Spencer                       ::getSymbolAddress(DataRefImpl Symb) const {
325*b60a18deSMichael J. Spencer   validateSymbol(Symb);
326*b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
327*b60a18deSMichael J. Spencer   const Elf_Shdr *Section;
328*b60a18deSMichael J. Spencer   switch (symb->st_shndx) {
329*b60a18deSMichael J. Spencer   case ELF::SHN_COMMON:
330*b60a18deSMichael J. Spencer    // Undefined symbols have no address yet.
331*b60a18deSMichael J. Spencer   case ELF::SHN_UNDEF: return UnknownAddressOrSize;
332*b60a18deSMichael J. Spencer   case ELF::SHN_ABS: return symb->st_value;
333*b60a18deSMichael J. Spencer   default: Section = getSection(symb->st_shndx);
334*b60a18deSMichael J. Spencer   }
335*b60a18deSMichael J. Spencer 
336*b60a18deSMichael J. Spencer   switch (symb->getType()) {
337*b60a18deSMichael J. Spencer   case ELF::STT_SECTION: return Section ? Section->sh_addr
338*b60a18deSMichael J. Spencer                                         : UnknownAddressOrSize;
339*b60a18deSMichael J. Spencer   case ELF::STT_FUNC:
340*b60a18deSMichael J. Spencer   case ELF::STT_OBJECT:
341*b60a18deSMichael J. Spencer   case ELF::STT_NOTYPE:
342*b60a18deSMichael J. Spencer     return symb->st_value;
343*b60a18deSMichael J. Spencer   default: return UnknownAddressOrSize;
344*b60a18deSMichael J. Spencer   }
345*b60a18deSMichael J. Spencer }
346*b60a18deSMichael J. Spencer 
347*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
348*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits>
349*b60a18deSMichael J. Spencer                       ::getSymbolSize(DataRefImpl Symb) const {
350*b60a18deSMichael J. Spencer   validateSymbol(Symb);
351*b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
352*b60a18deSMichael J. Spencer   if (symb->st_size == 0)
353*b60a18deSMichael J. Spencer     return UnknownAddressOrSize;
354*b60a18deSMichael J. Spencer   return symb->st_size;
355*b60a18deSMichael J. Spencer }
356*b60a18deSMichael J. Spencer 
357*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
358*b60a18deSMichael J. Spencer char ELFObjectFile<target_endianness, is64Bits>
359*b60a18deSMichael J. Spencer                   ::getSymbolNMTypeChar(DataRefImpl Symb) const {
360*b60a18deSMichael J. Spencer   validateSymbol(Symb);
361*b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
362*b60a18deSMichael J. Spencer   const Elf_Shdr *Section = getSection(symb->st_shndx);
363*b60a18deSMichael J. Spencer 
364*b60a18deSMichael J. Spencer   char ret = '?';
365*b60a18deSMichael J. Spencer 
366*b60a18deSMichael J. Spencer   if (Section) {
367*b60a18deSMichael J. Spencer     switch (Section->sh_type) {
368*b60a18deSMichael J. Spencer     case ELF::SHT_PROGBITS:
369*b60a18deSMichael J. Spencer     case ELF::SHT_DYNAMIC:
370*b60a18deSMichael J. Spencer       switch (Section->sh_flags) {
371*b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR):
372*b60a18deSMichael J. Spencer         ret = 't'; break;
373*b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_WRITE):
374*b60a18deSMichael J. Spencer         ret = 'd'; break;
375*b60a18deSMichael J. Spencer       case ELF::SHF_ALLOC:
376*b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_MERGE):
377*b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS):
378*b60a18deSMichael J. Spencer         ret = 'r'; break;
379*b60a18deSMichael J. Spencer       }
380*b60a18deSMichael J. Spencer       break;
381*b60a18deSMichael J. Spencer     case ELF::SHT_NOBITS: ret = 'b';
382*b60a18deSMichael J. Spencer     }
383*b60a18deSMichael J. Spencer   }
384*b60a18deSMichael J. Spencer 
385*b60a18deSMichael J. Spencer   switch (symb->st_shndx) {
386*b60a18deSMichael J. Spencer   case ELF::SHN_UNDEF:
387*b60a18deSMichael J. Spencer     if (ret == '?')
388*b60a18deSMichael J. Spencer       ret = 'U';
389*b60a18deSMichael J. Spencer     break;
390*b60a18deSMichael J. Spencer   case ELF::SHN_ABS: ret = 'a'; break;
391*b60a18deSMichael J. Spencer   case ELF::SHN_COMMON: ret = 'c'; break;
392*b60a18deSMichael J. Spencer   }
393*b60a18deSMichael J. Spencer 
394*b60a18deSMichael J. Spencer   switch (symb->getBinding()) {
395*b60a18deSMichael J. Spencer   case ELF::STB_GLOBAL: ret = ::toupper(ret); break;
396*b60a18deSMichael J. Spencer   case ELF::STB_WEAK:
397*b60a18deSMichael J. Spencer     if (symb->st_shndx == ELF::SHN_UNDEF)
398*b60a18deSMichael J. Spencer       ret = 'w';
399*b60a18deSMichael J. Spencer     else
400*b60a18deSMichael J. Spencer       if (symb->getType() == ELF::STT_OBJECT)
401*b60a18deSMichael J. Spencer         ret = 'V';
402*b60a18deSMichael J. Spencer       else
403*b60a18deSMichael J. Spencer         ret = 'W';
404*b60a18deSMichael J. Spencer   }
405*b60a18deSMichael J. Spencer 
406*b60a18deSMichael J. Spencer   if (ret == '?' && symb->getType() == ELF::STT_SECTION)
407*b60a18deSMichael J. Spencer     return StringSwitch<char>(getSymbolName(Symb))
408*b60a18deSMichael J. Spencer       .StartsWith(".debug", 'N')
409*b60a18deSMichael J. Spencer       .StartsWith(".note", 'n');
410*b60a18deSMichael J. Spencer 
411*b60a18deSMichael J. Spencer   return ret;
412*b60a18deSMichael J. Spencer }
413*b60a18deSMichael J. Spencer 
414*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
415*b60a18deSMichael J. Spencer bool ELFObjectFile<target_endianness, is64Bits>
416*b60a18deSMichael J. Spencer                   ::isSymbolInternal(DataRefImpl Symb) const {
417*b60a18deSMichael J. Spencer   validateSymbol(Symb);
418*b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
419*b60a18deSMichael J. Spencer 
420*b60a18deSMichael J. Spencer   if (  symb->getType() == ELF::STT_FILE
421*b60a18deSMichael J. Spencer      || symb->getType() == ELF::STT_SECTION)
422*b60a18deSMichael J. Spencer     return true;
423*b60a18deSMichael J. Spencer   return false;
424*b60a18deSMichael J. Spencer }
425*b60a18deSMichael J. Spencer 
426*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
427*b60a18deSMichael J. Spencer SectionRef ELFObjectFile<target_endianness, is64Bits>
428*b60a18deSMichael J. Spencer                         ::getSectionNext(DataRefImpl Sec) const {
429*b60a18deSMichael J. Spencer   const uint8_t *sec = *reinterpret_cast<const uint8_t **>(&Sec);
430*b60a18deSMichael J. Spencer   sec += Header->e_shentsize;
431*b60a18deSMichael J. Spencer   return SectionRef(DataRefImpl(sec), this);
432*b60a18deSMichael J. Spencer }
433*b60a18deSMichael J. Spencer 
434*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
435*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits>
436*b60a18deSMichael J. Spencer                        ::getSectionName(DataRefImpl Sec) const {
437*b60a18deSMichael J. Spencer   const Elf_Shdr *sec =
438*b60a18deSMichael J. Spencer     *reinterpret_cast<const Elf_Shdr **>(&Sec);
439*b60a18deSMichael J. Spencer   return StringRef(getString(dot_shstrtab_sec, sec->sh_name));
440*b60a18deSMichael J. Spencer }
441*b60a18deSMichael J. Spencer 
442*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
443*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits>
444*b60a18deSMichael J. Spencer                       ::getSectionAddress(DataRefImpl Sec) const {
445*b60a18deSMichael J. Spencer   const Elf_Shdr *sec =
446*b60a18deSMichael J. Spencer     *reinterpret_cast<const Elf_Shdr **>(&Sec);
447*b60a18deSMichael J. Spencer   return sec->sh_addr;
448*b60a18deSMichael J. Spencer }
449*b60a18deSMichael J. Spencer 
450*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
451*b60a18deSMichael J. Spencer uint64_t ELFObjectFile<target_endianness, is64Bits>
452*b60a18deSMichael J. Spencer                       ::getSectionSize(DataRefImpl Sec) const {
453*b60a18deSMichael J. Spencer   const Elf_Shdr *sec =
454*b60a18deSMichael J. Spencer     *reinterpret_cast<const Elf_Shdr **>(&Sec);
455*b60a18deSMichael J. Spencer   return sec->sh_size;
456*b60a18deSMichael J. Spencer }
457*b60a18deSMichael J. Spencer 
458*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
459*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits>
460*b60a18deSMichael J. Spencer                        ::getSectionContents(DataRefImpl Sec) const {
461*b60a18deSMichael J. Spencer   const Elf_Shdr *sec =
462*b60a18deSMichael J. Spencer     *reinterpret_cast<const Elf_Shdr **>(&Sec);
463*b60a18deSMichael J. Spencer   const char *start = (char*)base + sec->sh_offset;
464*b60a18deSMichael J. Spencer   return StringRef(start, sec->sh_size);
465*b60a18deSMichael J. Spencer }
466*b60a18deSMichael J. Spencer 
467*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
468*b60a18deSMichael J. Spencer bool ELFObjectFile<target_endianness, is64Bits>
469*b60a18deSMichael J. Spencer                   ::isSectionText(DataRefImpl Sec) const {
470*b60a18deSMichael J. Spencer   const Elf_Shdr *sec =
471*b60a18deSMichael J. Spencer     *reinterpret_cast<const Elf_Shdr **>(&Sec);
472*b60a18deSMichael J. Spencer   if (sec->sh_flags & ELF::SHF_EXECINSTR)
473*b60a18deSMichael J. Spencer     return true;
474*b60a18deSMichael J. Spencer   return false;
475*b60a18deSMichael J. Spencer }
476*b60a18deSMichael J. Spencer 
477*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
478*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object)
479*b60a18deSMichael J. Spencer   : ObjectFile(Object)
480*b60a18deSMichael J. Spencer   , SectionHeaderTable(0)
481*b60a18deSMichael J. Spencer   , dot_shstrtab_sec(0)
482*b60a18deSMichael J. Spencer   , dot_strtab_sec(0) {
483*b60a18deSMichael J. Spencer   Header = reinterpret_cast<const Elf_Ehdr *>(base);
484*b60a18deSMichael J. Spencer 
485*b60a18deSMichael J. Spencer   if (Header->e_shoff == 0)
486*b60a18deSMichael J. Spencer     return;
487*b60a18deSMichael J. Spencer 
488*b60a18deSMichael J. Spencer   SectionHeaderTable =
489*b60a18deSMichael J. Spencer     reinterpret_cast<const Elf_Shdr *>(base + Header->e_shoff);
490*b60a18deSMichael J. Spencer   uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize;
491*b60a18deSMichael J. Spencer   if (!(  (const uint8_t *)SectionHeaderTable + SectionTableSize
492*b60a18deSMichael J. Spencer          <= base + MapFile->getBufferSize()))
493*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
494*b60a18deSMichael J. Spencer     report_fatal_error("Section table goes past end of file!");
495*b60a18deSMichael J. Spencer 
496*b60a18deSMichael J. Spencer 
497*b60a18deSMichael J. Spencer   // To find the symbol tables we walk the section table to find SHT_STMTAB.
498*b60a18deSMichael J. Spencer   for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable),
499*b60a18deSMichael J. Spencer                   *e = i + Header->e_shnum * Header->e_shentsize;
500*b60a18deSMichael J. Spencer                    i != e; i += Header->e_shentsize) {
501*b60a18deSMichael J. Spencer     const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i);
502*b60a18deSMichael J. Spencer     if (sh->sh_type == ELF::SHT_SYMTAB) {
503*b60a18deSMichael J. Spencer       SymbolTableSections.push_back(sh);
504*b60a18deSMichael J. Spencer     }
505*b60a18deSMichael J. Spencer   }
506*b60a18deSMichael J. Spencer 
507*b60a18deSMichael J. Spencer   // Get string table sections.
508*b60a18deSMichael J. Spencer   dot_shstrtab_sec = getSection(Header->e_shstrndx);
509*b60a18deSMichael J. Spencer   if (dot_shstrtab_sec) {
510*b60a18deSMichael J. Spencer     // Verify that the last byte in the string table in a null.
511*b60a18deSMichael J. Spencer     if (((const char*)base + dot_shstrtab_sec->sh_offset)
512*b60a18deSMichael J. Spencer         [dot_shstrtab_sec->sh_size - 1] != 0)
513*b60a18deSMichael J. Spencer       // FIXME: Proper error handling.
514*b60a18deSMichael J. Spencer       report_fatal_error("String table must end with a null terminator!");
515*b60a18deSMichael J. Spencer   }
516*b60a18deSMichael J. Spencer 
517*b60a18deSMichael J. Spencer   // Merge this into the above loop.
518*b60a18deSMichael J. Spencer   for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable),
519*b60a18deSMichael J. Spencer                   *e = i + Header->e_shnum * Header->e_shentsize;
520*b60a18deSMichael J. Spencer                    i != e; i += Header->e_shentsize) {
521*b60a18deSMichael J. Spencer     const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i);
522*b60a18deSMichael J. Spencer     if (sh->sh_type == ELF::SHT_STRTAB) {
523*b60a18deSMichael J. Spencer       StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name));
524*b60a18deSMichael J. Spencer       if (SectionName == ".strtab") {
525*b60a18deSMichael J. Spencer         if (dot_strtab_sec != 0)
526*b60a18deSMichael J. Spencer           // FIXME: Proper error handling.
527*b60a18deSMichael J. Spencer           report_fatal_error("Already found section named .strtab!");
528*b60a18deSMichael J. Spencer         dot_strtab_sec = sh;
529*b60a18deSMichael J. Spencer         const char *dot_strtab = (const char*)base + sh->sh_offset;
530*b60a18deSMichael J. Spencer           if (dot_strtab[sh->sh_size - 1] != 0)
531*b60a18deSMichael J. Spencer             // FIXME: Proper error handling.
532*b60a18deSMichael J. Spencer             report_fatal_error("String table must end with a null terminator!");
533*b60a18deSMichael J. Spencer       }
534*b60a18deSMichael J. Spencer     }
535*b60a18deSMichael J. Spencer   }
536*b60a18deSMichael J. Spencer }
537*b60a18deSMichael J. Spencer 
538*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
539*b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
540*b60a18deSMichael J. Spencer                                          ::begin_symbols() const {
541*b60a18deSMichael J. Spencer   ELFDataRefImpl SymbolData;
542*b60a18deSMichael J. Spencer   memset(&SymbolData, 0, sizeof(SymbolData));
543*b60a18deSMichael J. Spencer   if (SymbolTableSections.size() == 0) {
544*b60a18deSMichael J. Spencer     SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max();
545*b60a18deSMichael J. Spencer     SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max();
546*b60a18deSMichael J. Spencer   } else {
547*b60a18deSMichael J. Spencer     SymbolData.SymbolIndex = 1; // The 0th symbol in ELF is fake.
548*b60a18deSMichael J. Spencer     SymbolData.SymbolTableSectionIndex = 0;
549*b60a18deSMichael J. Spencer   }
550*b60a18deSMichael J. Spencer   return symbol_iterator(
551*b60a18deSMichael J. Spencer     SymbolRef(DataRefImpl(*reinterpret_cast<DataRefImpl*>(&SymbolData)), this));
552*b60a18deSMichael J. Spencer }
553*b60a18deSMichael J. Spencer 
554*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
555*b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
556*b60a18deSMichael J. Spencer                                          ::end_symbols() const {
557*b60a18deSMichael J. Spencer   ELFDataRefImpl SymbolData;
558*b60a18deSMichael J. Spencer   memset(&SymbolData, 0, sizeof(SymbolData));
559*b60a18deSMichael J. Spencer   SymbolData.SymbolIndex = std::numeric_limits<uint32_t>::max();
560*b60a18deSMichael J. Spencer   SymbolData.SymbolTableSectionIndex = std::numeric_limits<uint32_t>::max();
561*b60a18deSMichael J. Spencer   return symbol_iterator(
562*b60a18deSMichael J. Spencer     SymbolRef(DataRefImpl(*reinterpret_cast<DataRefImpl*>(&SymbolData)), this));
563*b60a18deSMichael J. Spencer }
564*b60a18deSMichael J. Spencer 
565*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
566*b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
567*b60a18deSMichael J. Spencer                                           ::begin_sections() const {
568*b60a18deSMichael J. Spencer   return section_iterator(
569*b60a18deSMichael J. Spencer     SectionRef(DataRefImpl(base + Header->e_shoff), this));
570*b60a18deSMichael J. Spencer }
571*b60a18deSMichael J. Spencer 
572*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
573*b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
574*b60a18deSMichael J. Spencer                                           ::end_sections() const {
575*b60a18deSMichael J. Spencer   return section_iterator(
576*b60a18deSMichael J. Spencer     SectionRef(DataRefImpl(base
577*b60a18deSMichael J. Spencer                            + Header->e_shoff
578*b60a18deSMichael J. Spencer                            + (Header->e_shentsize * Header->e_shnum)), this));
579*b60a18deSMichael J. Spencer }
580*b60a18deSMichael J. Spencer 
581*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
582*b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const {
583*b60a18deSMichael J. Spencer   return 4;
584*b60a18deSMichael J. Spencer }
585*b60a18deSMichael J. Spencer 
586*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
587*b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits>
588*b60a18deSMichael J. Spencer                        ::getFileFormatName() const {
589*b60a18deSMichael J. Spencer   switch(Header->e_ident[ELF::EI_CLASS]) {
590*b60a18deSMichael J. Spencer   case ELF::ELFCLASS32:
591*b60a18deSMichael J. Spencer     switch(Header->e_machine) {
592*b60a18deSMichael J. Spencer     case ELF::EM_386:
593*b60a18deSMichael J. Spencer       return "ELF32-i386";
594*b60a18deSMichael J. Spencer     case ELF::EM_X86_64:
595*b60a18deSMichael J. Spencer       return "ELF32-x86-64";
596*b60a18deSMichael J. Spencer     default:
597*b60a18deSMichael J. Spencer       return "ELF32-unknown";
598*b60a18deSMichael J. Spencer     }
599*b60a18deSMichael J. Spencer   case ELF::ELFCLASS64:
600*b60a18deSMichael J. Spencer     switch(Header->e_machine) {
601*b60a18deSMichael J. Spencer     case ELF::EM_386:
602*b60a18deSMichael J. Spencer       return "ELF64-i386";
603*b60a18deSMichael J. Spencer     case ELF::EM_X86_64:
604*b60a18deSMichael J. Spencer       return "ELF64-x86-64";
605*b60a18deSMichael J. Spencer     default:
606*b60a18deSMichael J. Spencer       return "ELF64-unknown";
607*b60a18deSMichael J. Spencer     }
608*b60a18deSMichael J. Spencer   default:
609*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
610*b60a18deSMichael J. Spencer     report_fatal_error("Invalid ELFCLASS!");
611*b60a18deSMichael J. Spencer   }
612*b60a18deSMichael J. Spencer }
613*b60a18deSMichael J. Spencer 
614*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
615*b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const {
616*b60a18deSMichael J. Spencer   switch(Header->e_machine) {
617*b60a18deSMichael J. Spencer   case ELF::EM_386:
618*b60a18deSMichael J. Spencer     return Triple::x86;
619*b60a18deSMichael J. Spencer   case ELF::EM_X86_64:
620*b60a18deSMichael J. Spencer     return Triple::x86_64;
621*b60a18deSMichael J. Spencer   default:
622*b60a18deSMichael J. Spencer     return Triple::UnknownArch;
623*b60a18deSMichael J. Spencer   }
624*b60a18deSMichael J. Spencer }
625*b60a18deSMichael J. Spencer 
626*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
627*b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
628*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
629*b60a18deSMichael J. Spencer   const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
630*b60a18deSMichael J. Spencer   const Elf_Shdr *sec =
631*b60a18deSMichael J. Spencer     SymbolTableSections[SymbolData.SymbolTableSectionIndex];
632*b60a18deSMichael J. Spencer   return reinterpret_cast<const Elf_Sym *>(
633*b60a18deSMichael J. Spencer            base
634*b60a18deSMichael J. Spencer            + sec->sh_offset
635*b60a18deSMichael J. Spencer            + (SymbolData.SymbolIndex * sec->sh_entsize));
636*b60a18deSMichael J. Spencer }
637*b60a18deSMichael J. Spencer 
638*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
639*b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
640*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const {
641*b60a18deSMichael J. Spencer   const ELFDataRefImpl SymbolData = *reinterpret_cast<ELFDataRefImpl *>(&Symb);
642*b60a18deSMichael J. Spencer   const Elf_Shdr *sec = getSection(SymbolData.SymbolTableSectionIndex);
643*b60a18deSMichael J. Spencer   if (sec->sh_type != ELF::SHT_SYMTAB)
644*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
645*b60a18deSMichael J. Spencer     report_fatal_error("Invalid symbol table section!");
646*b60a18deSMichael J. Spencer   return sec;
647*b60a18deSMichael J. Spencer }
648*b60a18deSMichael J. Spencer 
649*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
650*b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
651*b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const {
652*b60a18deSMichael J. Spencer   if (index == 0 || index >= ELF::SHN_LORESERVE)
653*b60a18deSMichael J. Spencer     return 0;
654*b60a18deSMichael J. Spencer   if (!SectionHeaderTable || index >= Header->e_shnum)
655*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
656*b60a18deSMichael J. Spencer     report_fatal_error("Invalid section index!");
657*b60a18deSMichael J. Spencer 
658*b60a18deSMichael J. Spencer   return reinterpret_cast<const Elf_Shdr *>(
659*b60a18deSMichael J. Spencer          reinterpret_cast<const char *>(SectionHeaderTable)
660*b60a18deSMichael J. Spencer          + (index * Header->e_shentsize));
661*b60a18deSMichael J. Spencer }
662*b60a18deSMichael J. Spencer 
663*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
664*b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits>
665*b60a18deSMichael J. Spencer                          ::getString(uint16_t section,
666*b60a18deSMichael J. Spencer                                      ELF::Elf32_Word offset) const {
667*b60a18deSMichael J. Spencer   return getString(getSection(section), offset);
668*b60a18deSMichael J. Spencer }
669*b60a18deSMichael J. Spencer 
670*b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
671*b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits>
672*b60a18deSMichael J. Spencer                          ::getString(const Elf_Shdr *section,
673*b60a18deSMichael J. Spencer                                      ELF::Elf32_Word offset) const {
674*b60a18deSMichael J. Spencer   assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!");
675*b60a18deSMichael J. Spencer   if (offset >= section->sh_size)
676*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
677*b60a18deSMichael J. Spencer     report_fatal_error("Sybol name offset outside of string table!");
678*b60a18deSMichael J. Spencer   return (const char *)base + section->sh_offset + offset;
679*b60a18deSMichael J. Spencer }
680*b60a18deSMichael J. Spencer 
681*b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA.
682*b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char>
683*b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) {
684*b60a18deSMichael J. Spencer   if (Object->getBufferSize() < ELF::EI_NIDENT)
685*b60a18deSMichael J. Spencer     return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
686*b60a18deSMichael J. Spencer   return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
687*b60a18deSMichael J. Spencer                        , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
688*b60a18deSMichael J. Spencer }
689*b60a18deSMichael J. Spencer 
690*b60a18deSMichael J. Spencer namespace llvm {
691*b60a18deSMichael J. Spencer 
692*b60a18deSMichael J. Spencer   ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
693*b60a18deSMichael J. Spencer     std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);
694*b60a18deSMichael J. Spencer     if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
695*b60a18deSMichael J. Spencer       return new ELFObjectFile<support::little, false>(Object);
696*b60a18deSMichael J. Spencer     else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
697*b60a18deSMichael J. Spencer       return new ELFObjectFile<support::big, false>(Object);
698*b60a18deSMichael J. Spencer     else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB)
699*b60a18deSMichael J. Spencer       return new ELFObjectFile<support::little, true>(Object);
700*b60a18deSMichael J. Spencer     else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
701*b60a18deSMichael J. Spencer       return new ELFObjectFile<support::big, true>(Object);
702*b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
703*b60a18deSMichael J. Spencer     report_fatal_error("Not an ELF object file!");
704*b60a18deSMichael J. Spencer   }
705*b60a18deSMichael J. Spencer 
706*b60a18deSMichael J. Spencer } // end namespace llvm
707