1b60a18deSMichael J. Spencer //===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===//
2b60a18deSMichael J. Spencer //
3b60a18deSMichael J. Spencer //                     The LLVM Compiler Infrastructure
4b60a18deSMichael J. Spencer //
5b60a18deSMichael J. Spencer // This file is distributed under the University of Illinois Open Source
6b60a18deSMichael J. Spencer // License. See LICENSE.TXT for details.
7b60a18deSMichael J. Spencer //
8b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===//
9b60a18deSMichael J. Spencer //
10b60a18deSMichael J. Spencer // This file defines the ELFObjectFile class.
11b60a18deSMichael J. Spencer //
12b60a18deSMichael J. Spencer //===----------------------------------------------------------------------===//
13b60a18deSMichael J. Spencer 
14b60a18deSMichael J. Spencer #include "llvm/ADT/SmallVector.h"
15b60a18deSMichael J. Spencer #include "llvm/ADT/StringSwitch.h"
16b60a18deSMichael J. Spencer #include "llvm/ADT/Triple.h"
17*022ecdf2SBenjamin Kramer #include "llvm/ADT/DenseMap.h"
18b60a18deSMichael J. Spencer #include "llvm/Object/ObjectFile.h"
19b60a18deSMichael J. Spencer #include "llvm/Support/ELF.h"
20b60a18deSMichael J. Spencer #include "llvm/Support/Endian.h"
21b60a18deSMichael J. Spencer #include "llvm/Support/ErrorHandling.h"
22b60a18deSMichael J. Spencer #include "llvm/Support/MemoryBuffer.h"
23b60a18deSMichael J. Spencer #include <limits>
24b60a18deSMichael J. Spencer #include <utility>
25b60a18deSMichael J. Spencer 
26b60a18deSMichael J. Spencer using namespace llvm;
27b60a18deSMichael J. Spencer using namespace object;
28b60a18deSMichael J. Spencer 
29b60a18deSMichael J. Spencer // Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
30b60a18deSMichael J. Spencer namespace {
31b60a18deSMichael J. Spencer template<support::endianness target_endianness>
32b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelperCommon {
33b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
34b60a18deSMichael J. Spencer     <uint16_t, target_endianness, support::aligned> Elf_Half;
35b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
36b60a18deSMichael J. Spencer     <uint32_t, target_endianness, support::aligned> Elf_Word;
37b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
38b60a18deSMichael J. Spencer     <int32_t, target_endianness, support::aligned> Elf_Sword;
39b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
40b60a18deSMichael J. Spencer     <uint64_t, target_endianness, support::aligned> Elf_Xword;
41b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
42b60a18deSMichael J. Spencer     <int64_t, target_endianness, support::aligned> Elf_Sxword;
43b60a18deSMichael J. Spencer };
44b60a18deSMichael J. Spencer }
45b60a18deSMichael J. Spencer 
46b60a18deSMichael J. Spencer namespace {
47b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
48b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper;
49b60a18deSMichael J. Spencer 
50b60a18deSMichael J. Spencer /// ELF 32bit types.
51b60a18deSMichael J. Spencer template<support::endianness target_endianness>
52b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, false>
53b60a18deSMichael J. Spencer   : ELFDataTypeTypedefHelperCommon<target_endianness> {
54b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
55b60a18deSMichael J. Spencer     <uint32_t, target_endianness, support::aligned> Elf_Addr;
56b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
57b60a18deSMichael J. Spencer     <uint32_t, target_endianness, support::aligned> Elf_Off;
58b60a18deSMichael J. Spencer };
59b60a18deSMichael J. Spencer 
60b60a18deSMichael J. Spencer /// ELF 64bit types.
61b60a18deSMichael J. Spencer template<support::endianness target_endianness>
62b60a18deSMichael J. Spencer struct ELFDataTypeTypedefHelper<target_endianness, true>
63b60a18deSMichael J. Spencer   : ELFDataTypeTypedefHelperCommon<target_endianness>{
64b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
65b60a18deSMichael J. Spencer     <uint64_t, target_endianness, support::aligned> Elf_Addr;
66b60a18deSMichael J. Spencer   typedef support::detail::packed_endian_specific_integral
67b60a18deSMichael J. Spencer     <uint64_t, target_endianness, support::aligned> Elf_Off;
68b60a18deSMichael J. Spencer };
69b60a18deSMichael J. Spencer }
70b60a18deSMichael J. Spencer 
71b60a18deSMichael J. Spencer // I really don't like doing this, but the alternative is copypasta.
72b60a18deSMichael J. Spencer #define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \
73b60a18deSMichael J. Spencer typedef typename \
74b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \
75b60a18deSMichael J. Spencer typedef typename \
76b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \
77b60a18deSMichael J. Spencer typedef typename \
78b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \
79b60a18deSMichael J. Spencer typedef typename \
80b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \
81b60a18deSMichael J. Spencer typedef typename \
82b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \
83b60a18deSMichael J. Spencer typedef typename \
84b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \
85b60a18deSMichael J. Spencer typedef typename \
86b60a18deSMichael J. Spencer   ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword;
87b60a18deSMichael J. Spencer 
88b60a18deSMichael J. Spencer   // Section header.
89b60a18deSMichael J. Spencer namespace {
90b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
91b60a18deSMichael J. Spencer struct Elf_Shdr_Base;
92b60a18deSMichael J. Spencer 
93b60a18deSMichael J. Spencer template<support::endianness target_endianness>
94b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, false> {
95b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
96b60a18deSMichael J. Spencer   Elf_Word sh_name;     // Section name (index into string table)
97b60a18deSMichael J. Spencer   Elf_Word sh_type;     // Section type (SHT_*)
98b60a18deSMichael J. Spencer   Elf_Word sh_flags;    // Section flags (SHF_*)
99b60a18deSMichael J. Spencer   Elf_Addr sh_addr;     // Address where section is to be loaded
100b60a18deSMichael J. Spencer   Elf_Off  sh_offset;   // File offset of section data, in bytes
101b60a18deSMichael J. Spencer   Elf_Word sh_size;     // Size of section, in bytes
102b60a18deSMichael J. Spencer   Elf_Word sh_link;     // Section type-specific header table index link
103b60a18deSMichael J. Spencer   Elf_Word sh_info;     // Section type-specific extra information
104b60a18deSMichael J. Spencer   Elf_Word sh_addralign;// Section address alignment
105b60a18deSMichael J. Spencer   Elf_Word sh_entsize;  // Size of records contained within the section
106b60a18deSMichael J. Spencer };
107b60a18deSMichael J. Spencer 
108b60a18deSMichael J. Spencer template<support::endianness target_endianness>
109b60a18deSMichael J. Spencer struct Elf_Shdr_Base<target_endianness, true> {
110b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
111b60a18deSMichael J. Spencer   Elf_Word  sh_name;     // Section name (index into string table)
112b60a18deSMichael J. Spencer   Elf_Word  sh_type;     // Section type (SHT_*)
113b60a18deSMichael J. Spencer   Elf_Xword sh_flags;    // Section flags (SHF_*)
114b60a18deSMichael J. Spencer   Elf_Addr  sh_addr;     // Address where section is to be loaded
115b60a18deSMichael J. Spencer   Elf_Off   sh_offset;   // File offset of section data, in bytes
116b60a18deSMichael J. Spencer   Elf_Xword sh_size;     // Size of section, in bytes
117b60a18deSMichael J. Spencer   Elf_Word  sh_link;     // Section type-specific header table index link
118b60a18deSMichael J. Spencer   Elf_Word  sh_info;     // Section type-specific extra information
119b60a18deSMichael J. Spencer   Elf_Xword sh_addralign;// Section address alignment
120b60a18deSMichael J. Spencer   Elf_Xword sh_entsize;  // Size of records contained within the section
121b60a18deSMichael J. Spencer };
122b60a18deSMichael J. Spencer 
123b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
124b60a18deSMichael J. Spencer struct Elf_Shdr_Impl : Elf_Shdr_Base<target_endianness, is64Bits> {
125b60a18deSMichael J. Spencer   using Elf_Shdr_Base<target_endianness, is64Bits>::sh_entsize;
126b60a18deSMichael J. Spencer   using Elf_Shdr_Base<target_endianness, is64Bits>::sh_size;
127b60a18deSMichael J. Spencer 
128b60a18deSMichael J. Spencer   /// @brief Get the number of entities this section contains if it has any.
129b60a18deSMichael J. Spencer   unsigned getEntityCount() const {
130b60a18deSMichael J. Spencer     if (sh_entsize == 0)
131b60a18deSMichael J. Spencer       return 0;
132b60a18deSMichael J. Spencer     return sh_size / sh_entsize;
133b60a18deSMichael J. Spencer   }
134b60a18deSMichael J. Spencer };
135b60a18deSMichael J. Spencer }
136b60a18deSMichael J. Spencer 
137b60a18deSMichael J. Spencer namespace {
138b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
139b60a18deSMichael J. Spencer struct Elf_Sym_Base;
140b60a18deSMichael J. Spencer 
141b60a18deSMichael J. Spencer template<support::endianness target_endianness>
142b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, false> {
143b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
144b60a18deSMichael J. Spencer   Elf_Word      st_name;  // Symbol name (index into string table)
145b60a18deSMichael J. Spencer   Elf_Addr      st_value; // Value or address associated with the symbol
146b60a18deSMichael J. Spencer   Elf_Word      st_size;  // Size of the symbol
147b60a18deSMichael J. Spencer   unsigned char st_info;  // Symbol's type and binding attributes
148b60a18deSMichael J. Spencer   unsigned char st_other; // Must be zero; reserved
149b60a18deSMichael J. Spencer   Elf_Half      st_shndx; // Which section (header table index) it's defined in
150b60a18deSMichael J. Spencer };
151b60a18deSMichael J. Spencer 
152b60a18deSMichael J. Spencer template<support::endianness target_endianness>
153b60a18deSMichael J. Spencer struct Elf_Sym_Base<target_endianness, true> {
154b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
155b60a18deSMichael J. Spencer   Elf_Word      st_name;  // Symbol name (index into string table)
156b60a18deSMichael J. Spencer   unsigned char st_info;  // Symbol's type and binding attributes
157b60a18deSMichael J. Spencer   unsigned char st_other; // Must be zero; reserved
158b60a18deSMichael J. Spencer   Elf_Half      st_shndx; // Which section (header table index) it's defined in
159b60a18deSMichael J. Spencer   Elf_Addr      st_value; // Value or address associated with the symbol
160b60a18deSMichael J. Spencer   Elf_Xword     st_size;  // Size of the symbol
161b60a18deSMichael J. Spencer };
162b60a18deSMichael J. Spencer 
163b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
164b60a18deSMichael J. Spencer struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> {
165b60a18deSMichael J. Spencer   using Elf_Sym_Base<target_endianness, is64Bits>::st_info;
166b60a18deSMichael J. Spencer 
167b60a18deSMichael J. Spencer   // These accessors and mutators correspond to the ELF32_ST_BIND,
168b60a18deSMichael J. Spencer   // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
169b60a18deSMichael J. Spencer   unsigned char getBinding() const { return st_info >> 4; }
170b60a18deSMichael J. Spencer   unsigned char getType() const { return st_info & 0x0f; }
171b60a18deSMichael J. Spencer   void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
172b60a18deSMichael J. Spencer   void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
173b60a18deSMichael J. Spencer   void setBindingAndType(unsigned char b, unsigned char t) {
174b60a18deSMichael J. Spencer     st_info = (b << 4) + (t & 0x0f);
175b60a18deSMichael J. Spencer   }
176b60a18deSMichael J. Spencer };
177b60a18deSMichael J. Spencer }
178b60a18deSMichael J. Spencer 
179b60a18deSMichael J. Spencer namespace {
180*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela>
181*022ecdf2SBenjamin Kramer struct Elf_Rel_Base;
182*022ecdf2SBenjamin Kramer 
183*022ecdf2SBenjamin Kramer template<support::endianness target_endianness>
184*022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, false> {
185*022ecdf2SBenjamin Kramer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
186*022ecdf2SBenjamin Kramer   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
187*022ecdf2SBenjamin Kramer   Elf_Word      r_info;  // Symbol table index and type of relocation to apply
188*022ecdf2SBenjamin Kramer };
189*022ecdf2SBenjamin Kramer 
190*022ecdf2SBenjamin Kramer template<support::endianness target_endianness>
191*022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, false> {
192*022ecdf2SBenjamin Kramer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
193*022ecdf2SBenjamin Kramer   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
194*022ecdf2SBenjamin Kramer   Elf_Xword     r_info;   // Symbol table index and type of relocation to apply
195*022ecdf2SBenjamin Kramer };
196*022ecdf2SBenjamin Kramer 
197*022ecdf2SBenjamin Kramer template<support::endianness target_endianness>
198*022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, false, true> {
199*022ecdf2SBenjamin Kramer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
200*022ecdf2SBenjamin Kramer   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
201*022ecdf2SBenjamin Kramer   Elf_Word      r_info;   // Symbol table index and type of relocation to apply
202*022ecdf2SBenjamin Kramer   Elf_Sword     r_addend; // Compute value for relocatable field by adding this
203*022ecdf2SBenjamin Kramer };
204*022ecdf2SBenjamin Kramer 
205*022ecdf2SBenjamin Kramer template<support::endianness target_endianness>
206*022ecdf2SBenjamin Kramer struct Elf_Rel_Base<target_endianness, true, true> {
207*022ecdf2SBenjamin Kramer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
208*022ecdf2SBenjamin Kramer   Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
209*022ecdf2SBenjamin Kramer   Elf_Xword     r_info;   // Symbol table index and type of relocation to apply
210*022ecdf2SBenjamin Kramer   Elf_Sxword    r_addend; // Compute value for relocatable field by adding this.
211*022ecdf2SBenjamin Kramer };
212*022ecdf2SBenjamin Kramer 
213*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits, bool isRela>
214*022ecdf2SBenjamin Kramer struct Elf_Rel_Impl;
215*022ecdf2SBenjamin Kramer 
216*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela>
217*022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, true, isRela>
218*022ecdf2SBenjamin Kramer        : Elf_Rel_Base<target_endianness, true, isRela> {
219*022ecdf2SBenjamin Kramer   using Elf_Rel_Base<target_endianness, true, isRela>::r_info;
220*022ecdf2SBenjamin Kramer   LLVM_ELF_IMPORT_TYPES(target_endianness, true)
221*022ecdf2SBenjamin Kramer 
222*022ecdf2SBenjamin Kramer   // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
223*022ecdf2SBenjamin Kramer   // and ELF64_R_INFO macros defined in the ELF specification:
224*022ecdf2SBenjamin Kramer   uint64_t getSymbol() const { return (r_info >> 32); }
225*022ecdf2SBenjamin Kramer   unsigned char getType() const {
226*022ecdf2SBenjamin Kramer     return (unsigned char) (r_info & 0xffffffffL);
227*022ecdf2SBenjamin Kramer   }
228*022ecdf2SBenjamin Kramer   void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); }
229*022ecdf2SBenjamin Kramer   void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
230*022ecdf2SBenjamin Kramer   void setSymbolAndType(uint64_t s, unsigned char t) {
231*022ecdf2SBenjamin Kramer     r_info = (s << 32) + (t&0xffffffffL);
232*022ecdf2SBenjamin Kramer   }
233*022ecdf2SBenjamin Kramer };
234*022ecdf2SBenjamin Kramer 
235*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool isRela>
236*022ecdf2SBenjamin Kramer struct Elf_Rel_Impl<target_endianness, false, isRela>
237*022ecdf2SBenjamin Kramer        : Elf_Rel_Base<target_endianness, false, isRela> {
238*022ecdf2SBenjamin Kramer   using Elf_Rel_Base<target_endianness, false, isRela>::r_info;
239*022ecdf2SBenjamin Kramer   LLVM_ELF_IMPORT_TYPES(target_endianness, false)
240*022ecdf2SBenjamin Kramer 
241*022ecdf2SBenjamin Kramer   // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
242*022ecdf2SBenjamin Kramer   // and ELF32_R_INFO macros defined in the ELF specification:
243*022ecdf2SBenjamin Kramer   uint32_t getSymbol() const { return (r_info >> 8); }
244*022ecdf2SBenjamin Kramer   unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
245*022ecdf2SBenjamin Kramer   void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
246*022ecdf2SBenjamin Kramer   void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
247*022ecdf2SBenjamin Kramer   void setSymbolAndType(uint32_t s, unsigned char t) {
248*022ecdf2SBenjamin Kramer     r_info = (s << 8) + t;
249*022ecdf2SBenjamin Kramer   }
250*022ecdf2SBenjamin Kramer };
251*022ecdf2SBenjamin Kramer 
252*022ecdf2SBenjamin Kramer }
253*022ecdf2SBenjamin Kramer 
254*022ecdf2SBenjamin Kramer namespace {
255b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
256b60a18deSMichael J. Spencer class ELFObjectFile : public ObjectFile {
257b60a18deSMichael J. Spencer   LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
258b60a18deSMichael J. Spencer 
259b60a18deSMichael J. Spencer   typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
260b60a18deSMichael J. Spencer   typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
261*022ecdf2SBenjamin Kramer   typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
262*022ecdf2SBenjamin Kramer   typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
263b60a18deSMichael J. Spencer 
264b60a18deSMichael J. Spencer   struct Elf_Ehdr {
265b60a18deSMichael J. Spencer     unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes
266b60a18deSMichael J. Spencer     Elf_Half e_type;     // Type of file (see ET_*)
267b60a18deSMichael J. Spencer     Elf_Half e_machine;  // Required architecture for this file (see EM_*)
268b60a18deSMichael J. Spencer     Elf_Word e_version;  // Must be equal to 1
269b60a18deSMichael J. Spencer     Elf_Addr e_entry;    // Address to jump to in order to start program
270b60a18deSMichael J. Spencer     Elf_Off  e_phoff;    // Program header table's file offset, in bytes
271b60a18deSMichael J. Spencer     Elf_Off  e_shoff;    // Section header table's file offset, in bytes
272b60a18deSMichael J. Spencer     Elf_Word e_flags;    // Processor-specific flags
273b60a18deSMichael J. Spencer     Elf_Half e_ehsize;   // Size of ELF header, in bytes
274b60a18deSMichael J. Spencer     Elf_Half e_phentsize;// Size of an entry in the program header table
275b60a18deSMichael J. Spencer     Elf_Half e_phnum;    // Number of entries in the program header table
276b60a18deSMichael J. Spencer     Elf_Half e_shentsize;// Size of an entry in the section header table
277b60a18deSMichael J. Spencer     Elf_Half e_shnum;    // Number of entries in the section header table
278b60a18deSMichael J. Spencer     Elf_Half e_shstrndx; // Section header table index of section name
279b60a18deSMichael J. Spencer                                   // string table
280b60a18deSMichael J. Spencer     bool checkMagic() const {
281b60a18deSMichael J. Spencer       return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
282b60a18deSMichael J. Spencer     }
283b60a18deSMichael J. Spencer     unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
284b60a18deSMichael J. Spencer     unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
285b60a18deSMichael J. Spencer   };
286b60a18deSMichael J. Spencer 
287*022ecdf2SBenjamin Kramer   typedef SmallVector<const Elf_Shdr*, 1> Sections_t;
288*022ecdf2SBenjamin Kramer   typedef DenseMap<unsigned, unsigned> IndexMap_t;
289b60a18deSMichael J. Spencer 
290b60a18deSMichael J. Spencer   const Elf_Ehdr *Header;
291b60a18deSMichael J. Spencer   const Elf_Shdr *SectionHeaderTable;
292b60a18deSMichael J. Spencer   const Elf_Shdr *dot_shstrtab_sec; // Section header string table.
293b60a18deSMichael J. Spencer   const Elf_Shdr *dot_strtab_sec;   // Symbol header string table.
294*022ecdf2SBenjamin Kramer   Sections_t SymbolTableSections;
295*022ecdf2SBenjamin Kramer   IndexMap_t SymbolTableSectionsIndexMap;
296*022ecdf2SBenjamin Kramer   Sections_t RelocationTableSections;
297b60a18deSMichael J. Spencer 
298b60a18deSMichael J. Spencer   void            validateSymbol(DataRefImpl Symb) const;
299*022ecdf2SBenjamin Kramer   bool            isRelocationHasAddend(DataRefImpl Rel) const;
300*022ecdf2SBenjamin Kramer   template<typename T>
301*022ecdf2SBenjamin Kramer   const T        *getEntry(DataRefImpl Entry, Sections_t Sections) const;
302b60a18deSMichael J. Spencer   const Elf_Sym  *getSymbol(DataRefImpl Symb) const;
303b60a18deSMichael J. Spencer   const Elf_Shdr *getSection(DataRefImpl index) const;
304b60a18deSMichael J. Spencer   const Elf_Shdr *getSection(uint16_t index) const;
305*022ecdf2SBenjamin Kramer   const Elf_Rel  *getRel(DataRefImpl Rel) const;
306*022ecdf2SBenjamin Kramer   const Elf_Rela *getRela(DataRefImpl Rela) const;
307b60a18deSMichael J. Spencer   const char     *getString(uint16_t section, uint32_t offset) const;
308b60a18deSMichael J. Spencer   const char     *getString(const Elf_Shdr *section, uint32_t offset) const;
309b60a18deSMichael J. Spencer 
310b60a18deSMichael J. Spencer protected:
3111d6167fdSMichael J. Spencer   virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
3121d6167fdSMichael J. Spencer   virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
3131d6167fdSMichael J. Spencer   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
3141d6167fdSMichael J. Spencer   virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
3151d6167fdSMichael J. Spencer   virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
3161d6167fdSMichael J. Spencer   virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const;
317b60a18deSMichael J. Spencer 
3181d6167fdSMichael J. Spencer   virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
3191d6167fdSMichael J. Spencer   virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
3201d6167fdSMichael J. Spencer   virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
3211d6167fdSMichael J. Spencer   virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
3221d6167fdSMichael J. Spencer   virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
3231d6167fdSMichael J. Spencer   virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
324f6f3e81cSBenjamin Kramer   virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
325f6f3e81cSBenjamin Kramer                                            bool &Result) const;
326b60a18deSMichael J. Spencer 
327*022ecdf2SBenjamin Kramer   virtual error_code getRelocationNext(DataRefImpl Rel,
328*022ecdf2SBenjamin Kramer                                        RelocationRef &Res) const;
329*022ecdf2SBenjamin Kramer   virtual error_code getRelocationAddress(DataRefImpl Rel,
330*022ecdf2SBenjamin Kramer                                           uint64_t &Res) const;
331*022ecdf2SBenjamin Kramer   virtual error_code getRelocationSymbol(DataRefImpl Rel,
332*022ecdf2SBenjamin Kramer                                          SymbolRef &Res) const;
333*022ecdf2SBenjamin Kramer   virtual error_code getRelocationType(DataRefImpl Rel,
334*022ecdf2SBenjamin Kramer                                        uint32_t &Res) const;
335*022ecdf2SBenjamin Kramer   virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
336*022ecdf2SBenjamin Kramer                                                  int64_t &Res) const;
337*022ecdf2SBenjamin Kramer 
338b60a18deSMichael J. Spencer public:
339ec29b121SMichael J. Spencer   ELFObjectFile(MemoryBuffer *Object, error_code &ec);
340b60a18deSMichael J. Spencer   virtual symbol_iterator begin_symbols() const;
341b60a18deSMichael J. Spencer   virtual symbol_iterator end_symbols() const;
342b60a18deSMichael J. Spencer   virtual section_iterator begin_sections() const;
343b60a18deSMichael J. Spencer   virtual section_iterator end_sections() const;
344*022ecdf2SBenjamin Kramer   virtual relocation_iterator begin_relocations() const;
345*022ecdf2SBenjamin Kramer   virtual relocation_iterator end_relocations() const;
346b60a18deSMichael J. Spencer 
347b60a18deSMichael J. Spencer   virtual uint8_t getBytesInAddress() const;
348b60a18deSMichael J. Spencer   virtual StringRef getFileFormatName() const;
349b60a18deSMichael J. Spencer   virtual unsigned getArch() const;
350b60a18deSMichael J. Spencer };
351b60a18deSMichael J. Spencer } // end namespace
352b60a18deSMichael J. Spencer 
353b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
354b60a18deSMichael J. Spencer void ELFObjectFile<target_endianness, is64Bits>
355b60a18deSMichael J. Spencer                   ::validateSymbol(DataRefImpl Symb) const {
356b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
3570324b672SMichael J. Spencer   const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
358b60a18deSMichael J. Spencer   // FIXME: We really need to do proper error handling in the case of an invalid
359b60a18deSMichael J. Spencer   //        input file. Because we don't use exceptions, I think we'll just pass
360b60a18deSMichael J. Spencer   //        an error object around.
361b60a18deSMichael J. Spencer   if (!(  symb
362b60a18deSMichael J. Spencer         && SymbolTableSection
363ec29b121SMichael J. Spencer         && symb >= (const Elf_Sym*)(base()
364b60a18deSMichael J. Spencer                    + SymbolTableSection->sh_offset)
365ec29b121SMichael J. Spencer         && symb <  (const Elf_Sym*)(base()
366b60a18deSMichael J. Spencer                    + SymbolTableSection->sh_offset
367b60a18deSMichael J. Spencer                    + SymbolTableSection->sh_size)))
368b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
369b60a18deSMichael J. Spencer     report_fatal_error("Symb must point to a valid symbol!");
370b60a18deSMichael J. Spencer }
371b60a18deSMichael J. Spencer 
372b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
3731d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
3741d6167fdSMichael J. Spencer                         ::getSymbolNext(DataRefImpl Symb,
3751d6167fdSMichael J. Spencer                                         SymbolRef &Result) const {
376b60a18deSMichael J. Spencer   validateSymbol(Symb);
3770324b672SMichael J. Spencer   const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b];
378b60a18deSMichael J. Spencer 
3790324b672SMichael J. Spencer   ++Symb.d.a;
380b60a18deSMichael J. Spencer   // Check to see if we are at the end of this symbol table.
3810324b672SMichael J. Spencer   if (Symb.d.a >= SymbolTableSection->getEntityCount()) {
382b60a18deSMichael J. Spencer     // We are at the end. If there are other symbol tables, jump to them.
3830324b672SMichael J. Spencer     ++Symb.d.b;
3840324b672SMichael J. Spencer     Symb.d.a = 1; // The 0th symbol in ELF is fake.
385b60a18deSMichael J. Spencer     // Otherwise return the terminator.
3860324b672SMichael J. Spencer     if (Symb.d.b >= SymbolTableSections.size()) {
3870324b672SMichael J. Spencer       Symb.d.a = std::numeric_limits<uint32_t>::max();
3880324b672SMichael J. Spencer       Symb.d.b = std::numeric_limits<uint32_t>::max();
389b60a18deSMichael J. Spencer     }
390b60a18deSMichael J. Spencer   }
391b60a18deSMichael J. Spencer 
3921d6167fdSMichael J. Spencer   Result = SymbolRef(Symb, this);
3931d6167fdSMichael J. Spencer   return object_error::success;
394b60a18deSMichael J. Spencer }
395b60a18deSMichael J. Spencer 
396b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
3971d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
3981d6167fdSMichael J. Spencer                         ::getSymbolName(DataRefImpl Symb,
3991d6167fdSMichael J. Spencer                                         StringRef &Result) const {
400b60a18deSMichael J. Spencer   validateSymbol(Symb);
401b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
402b60a18deSMichael J. Spencer   if (symb->st_name == 0) {
403b60a18deSMichael J. Spencer     const Elf_Shdr *section = getSection(symb->st_shndx);
404b60a18deSMichael J. Spencer     if (!section)
4051d6167fdSMichael J. Spencer       Result = "";
4061d6167fdSMichael J. Spencer     else
4071d6167fdSMichael J. Spencer       Result = getString(dot_shstrtab_sec, section->sh_name);
4081d6167fdSMichael J. Spencer     return object_error::success;
409b60a18deSMichael J. Spencer   }
410b60a18deSMichael J. Spencer 
411b60a18deSMichael J. Spencer   // Use the default symbol table name section.
4121d6167fdSMichael J. Spencer   Result = getString(dot_strtab_sec, symb->st_name);
4131d6167fdSMichael J. Spencer   return object_error::success;
414b60a18deSMichael J. Spencer }
415b60a18deSMichael J. Spencer 
416b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
4171d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
4181d6167fdSMichael J. Spencer                         ::getSymbolAddress(DataRefImpl Symb,
4191d6167fdSMichael J. Spencer                                            uint64_t &Result) const {
420b60a18deSMichael J. Spencer   validateSymbol(Symb);
421b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
422b60a18deSMichael J. Spencer   const Elf_Shdr *Section;
423b60a18deSMichael J. Spencer   switch (symb->st_shndx) {
424b60a18deSMichael J. Spencer   case ELF::SHN_COMMON:
425b60a18deSMichael J. Spencer    // Undefined symbols have no address yet.
4261d6167fdSMichael J. Spencer   case ELF::SHN_UNDEF:
4271d6167fdSMichael J. Spencer     Result = UnknownAddressOrSize;
4281d6167fdSMichael J. Spencer     return object_error::success;
4291d6167fdSMichael J. Spencer   case ELF::SHN_ABS:
4301d6167fdSMichael J. Spencer     Result = symb->st_value;
4311d6167fdSMichael J. Spencer     return object_error::success;
432b60a18deSMichael J. Spencer   default: Section = getSection(symb->st_shndx);
433b60a18deSMichael J. Spencer   }
434b60a18deSMichael J. Spencer 
435b60a18deSMichael J. Spencer   switch (symb->getType()) {
4361d6167fdSMichael J. Spencer   case ELF::STT_SECTION:
4371d6167fdSMichael J. Spencer     Result = Section ? Section->sh_addr : UnknownAddressOrSize;
4381d6167fdSMichael J. Spencer     return object_error::success;
439b60a18deSMichael J. Spencer   case ELF::STT_FUNC:
440b60a18deSMichael J. Spencer   case ELF::STT_OBJECT:
441b60a18deSMichael J. Spencer   case ELF::STT_NOTYPE:
4421d6167fdSMichael J. Spencer     Result = symb->st_value;
4431d6167fdSMichael J. Spencer     return object_error::success;
4441d6167fdSMichael J. Spencer   default:
4451d6167fdSMichael J. Spencer     Result = UnknownAddressOrSize;
4461d6167fdSMichael J. Spencer     return object_error::success;
447b60a18deSMichael J. Spencer   }
448b60a18deSMichael J. Spencer }
449b60a18deSMichael J. Spencer 
450b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
4511d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
4521d6167fdSMichael J. Spencer                         ::getSymbolSize(DataRefImpl Symb,
4531d6167fdSMichael J. Spencer                                         uint64_t &Result) const {
454b60a18deSMichael J. Spencer   validateSymbol(Symb);
455b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
456b60a18deSMichael J. Spencer   if (symb->st_size == 0)
4571d6167fdSMichael J. Spencer     Result = UnknownAddressOrSize;
4581d6167fdSMichael J. Spencer   Result = symb->st_size;
4591d6167fdSMichael J. Spencer   return object_error::success;
460b60a18deSMichael J. Spencer }
461b60a18deSMichael J. Spencer 
462b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
4631d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
4641d6167fdSMichael J. Spencer                         ::getSymbolNMTypeChar(DataRefImpl Symb,
4651d6167fdSMichael J. Spencer                                               char &Result) const {
466b60a18deSMichael J. Spencer   validateSymbol(Symb);
467b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
468b60a18deSMichael J. Spencer   const Elf_Shdr *Section = getSection(symb->st_shndx);
469b60a18deSMichael J. Spencer 
470b60a18deSMichael J. Spencer   char ret = '?';
471b60a18deSMichael J. Spencer 
472b60a18deSMichael J. Spencer   if (Section) {
473b60a18deSMichael J. Spencer     switch (Section->sh_type) {
474b60a18deSMichael J. Spencer     case ELF::SHT_PROGBITS:
475b60a18deSMichael J. Spencer     case ELF::SHT_DYNAMIC:
476b60a18deSMichael J. Spencer       switch (Section->sh_flags) {
477b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR):
478b60a18deSMichael J. Spencer         ret = 't'; break;
479b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_WRITE):
480b60a18deSMichael J. Spencer         ret = 'd'; break;
481b60a18deSMichael J. Spencer       case ELF::SHF_ALLOC:
482b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_MERGE):
483b60a18deSMichael J. Spencer       case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS):
484b60a18deSMichael J. Spencer         ret = 'r'; break;
485b60a18deSMichael J. Spencer       }
486b60a18deSMichael J. Spencer       break;
487b60a18deSMichael J. Spencer     case ELF::SHT_NOBITS: ret = 'b';
488b60a18deSMichael J. Spencer     }
489b60a18deSMichael J. Spencer   }
490b60a18deSMichael J. Spencer 
491b60a18deSMichael J. Spencer   switch (symb->st_shndx) {
492b60a18deSMichael J. Spencer   case ELF::SHN_UNDEF:
493b60a18deSMichael J. Spencer     if (ret == '?')
494b60a18deSMichael J. Spencer       ret = 'U';
495b60a18deSMichael J. Spencer     break;
496b60a18deSMichael J. Spencer   case ELF::SHN_ABS: ret = 'a'; break;
497b60a18deSMichael J. Spencer   case ELF::SHN_COMMON: ret = 'c'; break;
498b60a18deSMichael J. Spencer   }
499b60a18deSMichael J. Spencer 
500b60a18deSMichael J. Spencer   switch (symb->getBinding()) {
501b60a18deSMichael J. Spencer   case ELF::STB_GLOBAL: ret = ::toupper(ret); break;
502b60a18deSMichael J. Spencer   case ELF::STB_WEAK:
503b60a18deSMichael J. Spencer     if (symb->st_shndx == ELF::SHN_UNDEF)
504b60a18deSMichael J. Spencer       ret = 'w';
505b60a18deSMichael J. Spencer     else
506b60a18deSMichael J. Spencer       if (symb->getType() == ELF::STT_OBJECT)
507b60a18deSMichael J. Spencer         ret = 'V';
508b60a18deSMichael J. Spencer       else
509b60a18deSMichael J. Spencer         ret = 'W';
510b60a18deSMichael J. Spencer   }
511b60a18deSMichael J. Spencer 
5121d6167fdSMichael J. Spencer   if (ret == '?' && symb->getType() == ELF::STT_SECTION) {
5131d6167fdSMichael J. Spencer     StringRef name;
5141d6167fdSMichael J. Spencer     if (error_code ec = getSymbolName(Symb, name))
5151d6167fdSMichael J. Spencer       return ec;
5161d6167fdSMichael J. Spencer     Result = StringSwitch<char>(name)
517b60a18deSMichael J. Spencer       .StartsWith(".debug", 'N')
518*022ecdf2SBenjamin Kramer       .StartsWith(".note", 'n')
519*022ecdf2SBenjamin Kramer       .Default('?');
5201d6167fdSMichael J. Spencer     return object_error::success;
5211d6167fdSMichael J. Spencer   }
522b60a18deSMichael J. Spencer 
5231d6167fdSMichael J. Spencer   Result = ret;
5241d6167fdSMichael J. Spencer   return object_error::success;
525b60a18deSMichael J. Spencer }
526b60a18deSMichael J. Spencer 
527b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5281d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5291d6167fdSMichael J. Spencer                         ::isSymbolInternal(DataRefImpl Symb,
5301d6167fdSMichael J. Spencer                                            bool &Result) const {
531b60a18deSMichael J. Spencer   validateSymbol(Symb);
532b60a18deSMichael J. Spencer   const Elf_Sym  *symb = getSymbol(Symb);
533b60a18deSMichael J. Spencer 
534b60a18deSMichael J. Spencer   if (  symb->getType() == ELF::STT_FILE
535b60a18deSMichael J. Spencer      || symb->getType() == ELF::STT_SECTION)
5361d6167fdSMichael J. Spencer     Result = true;
5371d6167fdSMichael J. Spencer   Result = false;
5381d6167fdSMichael J. Spencer   return object_error::success;
539b60a18deSMichael J. Spencer }
540b60a18deSMichael J. Spencer 
541b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5421d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5431d6167fdSMichael J. Spencer                         ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const {
5440324b672SMichael J. Spencer   const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p);
545b60a18deSMichael J. Spencer   sec += Header->e_shentsize;
5460324b672SMichael J. Spencer   Sec.p = reinterpret_cast<intptr_t>(sec);
5471d6167fdSMichael J. Spencer   Result = SectionRef(Sec, this);
5481d6167fdSMichael J. Spencer   return object_error::success;
549b60a18deSMichael J. Spencer }
550b60a18deSMichael J. Spencer 
551b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5521d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5531d6167fdSMichael J. Spencer                         ::getSectionName(DataRefImpl Sec,
5541d6167fdSMichael J. Spencer                                          StringRef &Result) const {
5550324b672SMichael J. Spencer   const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
5561d6167fdSMichael J. Spencer   Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name));
5571d6167fdSMichael J. Spencer   return object_error::success;
558b60a18deSMichael J. Spencer }
559b60a18deSMichael J. Spencer 
560b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5611d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5621d6167fdSMichael J. Spencer                         ::getSectionAddress(DataRefImpl Sec,
5631d6167fdSMichael J. Spencer                                             uint64_t &Result) const {
5640324b672SMichael J. Spencer   const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
5651d6167fdSMichael J. Spencer   Result = sec->sh_addr;
5661d6167fdSMichael J. Spencer   return object_error::success;
567b60a18deSMichael J. Spencer }
568b60a18deSMichael J. Spencer 
569b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5701d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5711d6167fdSMichael J. Spencer                         ::getSectionSize(DataRefImpl Sec,
5721d6167fdSMichael J. Spencer                                          uint64_t &Result) const {
5730324b672SMichael J. Spencer   const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
5741d6167fdSMichael J. Spencer   Result = sec->sh_size;
5751d6167fdSMichael J. Spencer   return object_error::success;
576b60a18deSMichael J. Spencer }
577b60a18deSMichael J. Spencer 
578b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5791d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5801d6167fdSMichael J. Spencer                         ::getSectionContents(DataRefImpl Sec,
5811d6167fdSMichael J. Spencer                                              StringRef &Result) const {
5820324b672SMichael J. Spencer   const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
5831d6167fdSMichael J. Spencer   const char *start = (const char*)base() + sec->sh_offset;
5841d6167fdSMichael J. Spencer   Result = StringRef(start, sec->sh_size);
5851d6167fdSMichael J. Spencer   return object_error::success;
586b60a18deSMichael J. Spencer }
587b60a18deSMichael J. Spencer 
588b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
5891d6167fdSMichael J. Spencer error_code ELFObjectFile<target_endianness, is64Bits>
5901d6167fdSMichael J. Spencer                         ::isSectionText(DataRefImpl Sec,
5911d6167fdSMichael J. Spencer                                         bool &Result) const {
5920324b672SMichael J. Spencer   const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);
593b60a18deSMichael J. Spencer   if (sec->sh_flags & ELF::SHF_EXECINSTR)
5941d6167fdSMichael J. Spencer     Result = true;
5951d6167fdSMichael J. Spencer   else
5961d6167fdSMichael J. Spencer     Result = false;
5971d6167fdSMichael J. Spencer   return object_error::success;
598b60a18deSMichael J. Spencer }
599b60a18deSMichael J. Spencer 
600b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
601f6f3e81cSBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits>
602f6f3e81cSBenjamin Kramer                           ::sectionContainsSymbol(DataRefImpl Sec,
603f6f3e81cSBenjamin Kramer                                                   DataRefImpl Symb,
604f6f3e81cSBenjamin Kramer                                                   bool &Result) const {
605f6f3e81cSBenjamin Kramer   // FIXME: Unimplemented.
606f6f3e81cSBenjamin Kramer   Result = false;
607f6f3e81cSBenjamin Kramer   return object_error::success;
608f6f3e81cSBenjamin Kramer }
609f6f3e81cSBenjamin Kramer 
610*022ecdf2SBenjamin Kramer // Relocations
611*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
612*022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits>
613*022ecdf2SBenjamin Kramer                         ::getRelocationNext(DataRefImpl Rel,
614*022ecdf2SBenjamin Kramer                                             RelocationRef &Result) const {
615*022ecdf2SBenjamin Kramer   const Elf_Shdr *RelocationTableSection = RelocationTableSections[Rel.d.b];
616*022ecdf2SBenjamin Kramer 
617*022ecdf2SBenjamin Kramer   // Check to see if we are at the end of this relocation table.
618*022ecdf2SBenjamin Kramer   if (++Rel.d.a >= RelocationTableSection->getEntityCount()) {
619*022ecdf2SBenjamin Kramer     // We are at the end. If there are other relocation tables, jump to them.
620*022ecdf2SBenjamin Kramer     Rel.d.a = 0;
621*022ecdf2SBenjamin Kramer     // Otherwise return the terminator.
622*022ecdf2SBenjamin Kramer     if (++Rel.d.b >= SymbolTableSections.size()) {
623*022ecdf2SBenjamin Kramer       Rel.d.a = std::numeric_limits<uint32_t>::max();
624*022ecdf2SBenjamin Kramer       Rel.d.b = std::numeric_limits<uint32_t>::max();
625*022ecdf2SBenjamin Kramer     }
626*022ecdf2SBenjamin Kramer   }
627*022ecdf2SBenjamin Kramer 
628*022ecdf2SBenjamin Kramer   Result = RelocationRef(Rel, this);
629*022ecdf2SBenjamin Kramer   return object_error::success;
630*022ecdf2SBenjamin Kramer }
631*022ecdf2SBenjamin Kramer 
632*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
633*022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits>
634*022ecdf2SBenjamin Kramer                         ::getRelocationSymbol(DataRefImpl Rel,
635*022ecdf2SBenjamin Kramer                                               SymbolRef &Result) const {
636*022ecdf2SBenjamin Kramer   uint32_t symbolIdx;
637*022ecdf2SBenjamin Kramer   const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
638*022ecdf2SBenjamin Kramer   switch (sec->sh_type) {
639*022ecdf2SBenjamin Kramer     default :
640*022ecdf2SBenjamin Kramer       report_fatal_error("Invalid section type in Rel!");
641*022ecdf2SBenjamin Kramer     case ELF::SHT_REL : {
642*022ecdf2SBenjamin Kramer       symbolIdx = getRel(Rel)->getSymbol();
643*022ecdf2SBenjamin Kramer       break;
644*022ecdf2SBenjamin Kramer     }
645*022ecdf2SBenjamin Kramer     case ELF::SHT_RELA : {
646*022ecdf2SBenjamin Kramer       symbolIdx = getRela(Rel)->getSymbol();
647*022ecdf2SBenjamin Kramer       break;
648*022ecdf2SBenjamin Kramer     }
649*022ecdf2SBenjamin Kramer   }
650*022ecdf2SBenjamin Kramer   DataRefImpl SymbolData;
651*022ecdf2SBenjamin Kramer   IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link);
652*022ecdf2SBenjamin Kramer   if (it == SymbolTableSectionsIndexMap.end())
653*022ecdf2SBenjamin Kramer     report_fatal_error("Relocation symbol table not found!");
654*022ecdf2SBenjamin Kramer   SymbolData.d.a = symbolIdx;
655*022ecdf2SBenjamin Kramer   SymbolData.d.b = it->second;
656*022ecdf2SBenjamin Kramer   Result = SymbolRef(SymbolData, this);
657*022ecdf2SBenjamin Kramer   return object_error::success;
658*022ecdf2SBenjamin Kramer }
659*022ecdf2SBenjamin Kramer 
660*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
661*022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits>
662*022ecdf2SBenjamin Kramer                         ::getRelocationAddress(DataRefImpl Rel,
663*022ecdf2SBenjamin Kramer                                                uint64_t &Result) const {
664*022ecdf2SBenjamin Kramer   uint64_t offset;
665*022ecdf2SBenjamin Kramer   const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
666*022ecdf2SBenjamin Kramer   switch (sec->sh_type) {
667*022ecdf2SBenjamin Kramer     default :
668*022ecdf2SBenjamin Kramer       report_fatal_error("Invalid section type in Rel!");
669*022ecdf2SBenjamin Kramer     case ELF::SHT_REL : {
670*022ecdf2SBenjamin Kramer       offset = getRel(Rel)->r_offset;
671*022ecdf2SBenjamin Kramer       break;
672*022ecdf2SBenjamin Kramer     }
673*022ecdf2SBenjamin Kramer     case ELF::SHT_RELA : {
674*022ecdf2SBenjamin Kramer       offset = getRela(Rel)->r_offset;
675*022ecdf2SBenjamin Kramer       break;
676*022ecdf2SBenjamin Kramer     }
677*022ecdf2SBenjamin Kramer   }
678*022ecdf2SBenjamin Kramer 
679*022ecdf2SBenjamin Kramer   const Elf_Shdr *secAddr = getSection(sec->sh_info);
680*022ecdf2SBenjamin Kramer   Result = offset + reinterpret_cast<uintptr_t>(base() + secAddr->sh_offset);
681*022ecdf2SBenjamin Kramer   return object_error::success;
682*022ecdf2SBenjamin Kramer }
683*022ecdf2SBenjamin Kramer 
684*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
685*022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits>
686*022ecdf2SBenjamin Kramer                         ::getRelocationType(DataRefImpl Rel,
687*022ecdf2SBenjamin Kramer                                             uint32_t &Result) const {
688*022ecdf2SBenjamin Kramer   const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
689*022ecdf2SBenjamin Kramer   switch (sec->sh_type) {
690*022ecdf2SBenjamin Kramer     default :
691*022ecdf2SBenjamin Kramer       report_fatal_error("Invalid section type in Rel!");
692*022ecdf2SBenjamin Kramer     case ELF::SHT_REL : {
693*022ecdf2SBenjamin Kramer       Result = getRel(Rel)->getType();
694*022ecdf2SBenjamin Kramer       break;
695*022ecdf2SBenjamin Kramer     }
696*022ecdf2SBenjamin Kramer     case ELF::SHT_RELA : {
697*022ecdf2SBenjamin Kramer       Result = getRela(Rel)->getType();
698*022ecdf2SBenjamin Kramer       break;
699*022ecdf2SBenjamin Kramer     }
700*022ecdf2SBenjamin Kramer   }
701*022ecdf2SBenjamin Kramer   return object_error::success;
702*022ecdf2SBenjamin Kramer }
703*022ecdf2SBenjamin Kramer 
704*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
705*022ecdf2SBenjamin Kramer error_code ELFObjectFile<target_endianness, is64Bits>
706*022ecdf2SBenjamin Kramer                         ::getRelocationAdditionalInfo(DataRefImpl Rel,
707*022ecdf2SBenjamin Kramer                                                       int64_t &Result) const {
708*022ecdf2SBenjamin Kramer   const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
709*022ecdf2SBenjamin Kramer   switch (sec->sh_type) {
710*022ecdf2SBenjamin Kramer     default :
711*022ecdf2SBenjamin Kramer       report_fatal_error("Invalid section type in Rel!");
712*022ecdf2SBenjamin Kramer     case ELF::SHT_REL : {
713*022ecdf2SBenjamin Kramer       Result = 0;
714*022ecdf2SBenjamin Kramer       return object_error::success;
715*022ecdf2SBenjamin Kramer     }
716*022ecdf2SBenjamin Kramer     case ELF::SHT_RELA : {
717*022ecdf2SBenjamin Kramer       Result = getRela(Rel)->r_addend;
718*022ecdf2SBenjamin Kramer       return object_error::success;
719*022ecdf2SBenjamin Kramer     }
720*022ecdf2SBenjamin Kramer   }
721*022ecdf2SBenjamin Kramer }
722*022ecdf2SBenjamin Kramer 
723*022ecdf2SBenjamin Kramer 
724*022ecdf2SBenjamin Kramer 
725f6f3e81cSBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
726ec29b121SMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
727ec29b121SMichael J. Spencer                                                           , error_code &ec)
728ec29b121SMichael J. Spencer   : ObjectFile(Binary::isELF, Object, ec)
729b60a18deSMichael J. Spencer   , SectionHeaderTable(0)
730b60a18deSMichael J. Spencer   , dot_shstrtab_sec(0)
731b60a18deSMichael J. Spencer   , dot_strtab_sec(0) {
732ec29b121SMichael J. Spencer   Header = reinterpret_cast<const Elf_Ehdr *>(base());
733b60a18deSMichael J. Spencer 
734b60a18deSMichael J. Spencer   if (Header->e_shoff == 0)
735b60a18deSMichael J. Spencer     return;
736b60a18deSMichael J. Spencer 
737b60a18deSMichael J. Spencer   SectionHeaderTable =
738ec29b121SMichael J. Spencer     reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff);
739b60a18deSMichael J. Spencer   uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize;
740b60a18deSMichael J. Spencer   if (!(  (const uint8_t *)SectionHeaderTable + SectionTableSize
741ec29b121SMichael J. Spencer          <= base() + Data->getBufferSize()))
742b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
743b60a18deSMichael J. Spencer     report_fatal_error("Section table goes past end of file!");
744b60a18deSMichael J. Spencer 
745b60a18deSMichael J. Spencer 
746b60a18deSMichael J. Spencer   // To find the symbol tables we walk the section table to find SHT_STMTAB.
747*022ecdf2SBenjamin Kramer   const Elf_Shdr* sh =
748*022ecdf2SBenjamin Kramer                     reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable);
749*022ecdf2SBenjamin Kramer   for (unsigned i = 0; i < Header->e_shnum; ++i) {
750b60a18deSMichael J. Spencer     if (sh->sh_type == ELF::SHT_SYMTAB) {
751*022ecdf2SBenjamin Kramer       SymbolTableSectionsIndexMap[i] = SymbolTableSections.size();
752b60a18deSMichael J. Spencer       SymbolTableSections.push_back(sh);
753b60a18deSMichael J. Spencer     }
754*022ecdf2SBenjamin Kramer     if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) {
755*022ecdf2SBenjamin Kramer       RelocationTableSections.push_back(sh);
756*022ecdf2SBenjamin Kramer     }
757*022ecdf2SBenjamin Kramer     ++sh;
758b60a18deSMichael J. Spencer   }
759b60a18deSMichael J. Spencer 
760b60a18deSMichael J. Spencer   // Get string table sections.
761b60a18deSMichael J. Spencer   dot_shstrtab_sec = getSection(Header->e_shstrndx);
762b60a18deSMichael J. Spencer   if (dot_shstrtab_sec) {
763b60a18deSMichael J. Spencer     // Verify that the last byte in the string table in a null.
764ec29b121SMichael J. Spencer     if (((const char*)base() + dot_shstrtab_sec->sh_offset)
765b60a18deSMichael J. Spencer         [dot_shstrtab_sec->sh_size - 1] != 0)
766b60a18deSMichael J. Spencer       // FIXME: Proper error handling.
767b60a18deSMichael J. Spencer       report_fatal_error("String table must end with a null terminator!");
768b60a18deSMichael J. Spencer   }
769b60a18deSMichael J. Spencer 
770b60a18deSMichael J. Spencer   // Merge this into the above loop.
771b60a18deSMichael J. Spencer   for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable),
772b60a18deSMichael J. Spencer                   *e = i + Header->e_shnum * Header->e_shentsize;
773b60a18deSMichael J. Spencer                    i != e; i += Header->e_shentsize) {
774b60a18deSMichael J. Spencer     const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i);
775b60a18deSMichael J. Spencer     if (sh->sh_type == ELF::SHT_STRTAB) {
776b60a18deSMichael J. Spencer       StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name));
777b60a18deSMichael J. Spencer       if (SectionName == ".strtab") {
778b60a18deSMichael J. Spencer         if (dot_strtab_sec != 0)
779b60a18deSMichael J. Spencer           // FIXME: Proper error handling.
780b60a18deSMichael J. Spencer           report_fatal_error("Already found section named .strtab!");
781b60a18deSMichael J. Spencer         dot_strtab_sec = sh;
782ec29b121SMichael J. Spencer         const char *dot_strtab = (const char*)base() + sh->sh_offset;
783b60a18deSMichael J. Spencer           if (dot_strtab[sh->sh_size - 1] != 0)
784b60a18deSMichael J. Spencer             // FIXME: Proper error handling.
785b60a18deSMichael J. Spencer             report_fatal_error("String table must end with a null terminator!");
786b60a18deSMichael J. Spencer       }
787b60a18deSMichael J. Spencer     }
788b60a18deSMichael J. Spencer   }
789b60a18deSMichael J. Spencer }
790b60a18deSMichael J. Spencer 
791b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
792b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
793b60a18deSMichael J. Spencer                                          ::begin_symbols() const {
7940324b672SMichael J. Spencer   DataRefImpl SymbolData;
795b60a18deSMichael J. Spencer   memset(&SymbolData, 0, sizeof(SymbolData));
796b60a18deSMichael J. Spencer   if (SymbolTableSections.size() == 0) {
7970324b672SMichael J. Spencer     SymbolData.d.a = std::numeric_limits<uint32_t>::max();
7980324b672SMichael J. Spencer     SymbolData.d.b = std::numeric_limits<uint32_t>::max();
799b60a18deSMichael J. Spencer   } else {
8000324b672SMichael J. Spencer     SymbolData.d.a = 1; // The 0th symbol in ELF is fake.
8010324b672SMichael J. Spencer     SymbolData.d.b = 0;
802b60a18deSMichael J. Spencer   }
8030324b672SMichael J. Spencer   return symbol_iterator(SymbolRef(SymbolData, this));
804b60a18deSMichael J. Spencer }
805b60a18deSMichael J. Spencer 
806b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
807b60a18deSMichael J. Spencer ObjectFile::symbol_iterator ELFObjectFile<target_endianness, is64Bits>
808b60a18deSMichael J. Spencer                                          ::end_symbols() const {
8090324b672SMichael J. Spencer   DataRefImpl SymbolData;
810b60a18deSMichael J. Spencer   memset(&SymbolData, 0, sizeof(SymbolData));
8110324b672SMichael J. Spencer   SymbolData.d.a = std::numeric_limits<uint32_t>::max();
8120324b672SMichael J. Spencer   SymbolData.d.b = std::numeric_limits<uint32_t>::max();
8130324b672SMichael J. Spencer   return symbol_iterator(SymbolRef(SymbolData, this));
814b60a18deSMichael J. Spencer }
815b60a18deSMichael J. Spencer 
816b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
817b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
818b60a18deSMichael J. Spencer                                           ::begin_sections() const {
8190324b672SMichael J. Spencer   DataRefImpl ret;
820ee066fc4SEric Christopher   memset(&ret, 0, sizeof(DataRefImpl));
821ec29b121SMichael J. Spencer   ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff);
8220324b672SMichael J. Spencer   return section_iterator(SectionRef(ret, this));
823b60a18deSMichael J. Spencer }
824b60a18deSMichael J. Spencer 
825b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
826b60a18deSMichael J. Spencer ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
827b60a18deSMichael J. Spencer                                           ::end_sections() const {
8280324b672SMichael J. Spencer   DataRefImpl ret;
829ee066fc4SEric Christopher   memset(&ret, 0, sizeof(DataRefImpl));
830ec29b121SMichael J. Spencer   ret.p = reinterpret_cast<intptr_t>(base()
831b60a18deSMichael J. Spencer                                      + Header->e_shoff
8320324b672SMichael J. Spencer                                      + (Header->e_shentsize * Header->e_shnum));
8330324b672SMichael J. Spencer   return section_iterator(SectionRef(ret, this));
834b60a18deSMichael J. Spencer }
835b60a18deSMichael J. Spencer 
836b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
837*022ecdf2SBenjamin Kramer ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits>
838*022ecdf2SBenjamin Kramer                                          ::begin_relocations() const {
839*022ecdf2SBenjamin Kramer   DataRefImpl RelData;
840*022ecdf2SBenjamin Kramer   memset(&RelData, 0, sizeof(RelData));
841*022ecdf2SBenjamin Kramer   if (RelocationTableSections.size() == 0) {
842*022ecdf2SBenjamin Kramer     RelData.d.a = std::numeric_limits<uint32_t>::max();
843*022ecdf2SBenjamin Kramer     RelData.d.b = std::numeric_limits<uint32_t>::max();
844*022ecdf2SBenjamin Kramer   } else {
845*022ecdf2SBenjamin Kramer     RelData.d.a = 0;
846*022ecdf2SBenjamin Kramer     RelData.d.b = 0;
847*022ecdf2SBenjamin Kramer   }
848*022ecdf2SBenjamin Kramer   return relocation_iterator(RelocationRef(RelData, this));
849*022ecdf2SBenjamin Kramer }
850*022ecdf2SBenjamin Kramer 
851*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
852*022ecdf2SBenjamin Kramer ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits>
853*022ecdf2SBenjamin Kramer                                          ::end_relocations() const {
854*022ecdf2SBenjamin Kramer   DataRefImpl RelData;
855*022ecdf2SBenjamin Kramer   memset(&RelData, 0, sizeof(RelData));
856*022ecdf2SBenjamin Kramer   RelData.d.a = std::numeric_limits<uint32_t>::max();
857*022ecdf2SBenjamin Kramer   RelData.d.b = std::numeric_limits<uint32_t>::max();
858*022ecdf2SBenjamin Kramer   return relocation_iterator(RelocationRef(RelData, this));
859*022ecdf2SBenjamin Kramer }
860*022ecdf2SBenjamin Kramer 
861*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
862b60a18deSMichael J. Spencer uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const {
8630324b672SMichael J. Spencer   return is64Bits ? 8 : 4;
864b60a18deSMichael J. Spencer }
865b60a18deSMichael J. Spencer 
866b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
867b60a18deSMichael J. Spencer StringRef ELFObjectFile<target_endianness, is64Bits>
868b60a18deSMichael J. Spencer                        ::getFileFormatName() const {
869b60a18deSMichael J. Spencer   switch(Header->e_ident[ELF::EI_CLASS]) {
870b60a18deSMichael J. Spencer   case ELF::ELFCLASS32:
871b60a18deSMichael J. Spencer     switch(Header->e_machine) {
872b60a18deSMichael J. Spencer     case ELF::EM_386:
873b60a18deSMichael J. Spencer       return "ELF32-i386";
874b60a18deSMichael J. Spencer     case ELF::EM_X86_64:
875b60a18deSMichael J. Spencer       return "ELF32-x86-64";
876*022ecdf2SBenjamin Kramer     case ELF::EM_ARM:
877*022ecdf2SBenjamin Kramer       return "ELF32-arm";
878b60a18deSMichael J. Spencer     default:
879b60a18deSMichael J. Spencer       return "ELF32-unknown";
880b60a18deSMichael J. Spencer     }
881b60a18deSMichael J. Spencer   case ELF::ELFCLASS64:
882b60a18deSMichael J. Spencer     switch(Header->e_machine) {
883b60a18deSMichael J. Spencer     case ELF::EM_386:
884b60a18deSMichael J. Spencer       return "ELF64-i386";
885b60a18deSMichael J. Spencer     case ELF::EM_X86_64:
886b60a18deSMichael J. Spencer       return "ELF64-x86-64";
887b60a18deSMichael J. Spencer     default:
888b60a18deSMichael J. Spencer       return "ELF64-unknown";
889b60a18deSMichael J. Spencer     }
890b60a18deSMichael J. Spencer   default:
891b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
892b60a18deSMichael J. Spencer     report_fatal_error("Invalid ELFCLASS!");
893b60a18deSMichael J. Spencer   }
894b60a18deSMichael J. Spencer }
895b60a18deSMichael J. Spencer 
896b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
897b60a18deSMichael J. Spencer unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const {
898b60a18deSMichael J. Spencer   switch(Header->e_machine) {
899b60a18deSMichael J. Spencer   case ELF::EM_386:
900b60a18deSMichael J. Spencer     return Triple::x86;
901b60a18deSMichael J. Spencer   case ELF::EM_X86_64:
902b60a18deSMichael J. Spencer     return Triple::x86_64;
903*022ecdf2SBenjamin Kramer   case ELF::EM_ARM:
904*022ecdf2SBenjamin Kramer     return Triple::arm;
905b60a18deSMichael J. Spencer   default:
906b60a18deSMichael J. Spencer     return Triple::UnknownArch;
907b60a18deSMichael J. Spencer   }
908b60a18deSMichael J. Spencer }
909b60a18deSMichael J. Spencer 
910b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
911*022ecdf2SBenjamin Kramer template<typename T>
912*022ecdf2SBenjamin Kramer inline const T *
913*022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getEntry(DataRefImpl Entry,
914*022ecdf2SBenjamin Kramer                                                      Sections_t Sections) const {
915*022ecdf2SBenjamin Kramer   const Elf_Shdr *sec = Sections[Entry.d.b];
916*022ecdf2SBenjamin Kramer   return reinterpret_cast<const T *>(
917ec29b121SMichael J. Spencer            base()
918b60a18deSMichael J. Spencer            + sec->sh_offset
919*022ecdf2SBenjamin Kramer            + (Entry.d.a * sec->sh_entsize));
920*022ecdf2SBenjamin Kramer }
921*022ecdf2SBenjamin Kramer 
922*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
923*022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
924*022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
925*022ecdf2SBenjamin Kramer   return getEntry<Elf_Sym>(Symb, SymbolTableSections);
926*022ecdf2SBenjamin Kramer }
927*022ecdf2SBenjamin Kramer 
928*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
929*022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel *
930*022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const {
931*022ecdf2SBenjamin Kramer   return getEntry<Elf_Rel>(Rel, RelocationTableSections);
932*022ecdf2SBenjamin Kramer }
933*022ecdf2SBenjamin Kramer 
934*022ecdf2SBenjamin Kramer template<support::endianness target_endianness, bool is64Bits>
935*022ecdf2SBenjamin Kramer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela *
936*022ecdf2SBenjamin Kramer ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const {
937*022ecdf2SBenjamin Kramer   return getEntry<Elf_Rela>(Rela, RelocationTableSections);
938b60a18deSMichael J. Spencer }
939b60a18deSMichael J. Spencer 
940b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
941b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
942b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(DataRefImpl Symb) const {
9430324b672SMichael J. Spencer   const Elf_Shdr *sec = getSection(Symb.d.b);
944b60a18deSMichael J. Spencer   if (sec->sh_type != ELF::SHT_SYMTAB)
945b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
946b60a18deSMichael J. Spencer     report_fatal_error("Invalid symbol table section!");
947b60a18deSMichael J. Spencer   return sec;
948b60a18deSMichael J. Spencer }
949b60a18deSMichael J. Spencer 
950b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
951b60a18deSMichael J. Spencer const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr *
952b60a18deSMichael J. Spencer ELFObjectFile<target_endianness, is64Bits>::getSection(uint16_t index) const {
953b60a18deSMichael J. Spencer   if (index == 0 || index >= ELF::SHN_LORESERVE)
954b60a18deSMichael J. Spencer     return 0;
955b60a18deSMichael J. Spencer   if (!SectionHeaderTable || index >= Header->e_shnum)
956b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
957b60a18deSMichael J. Spencer     report_fatal_error("Invalid section index!");
958b60a18deSMichael J. Spencer 
959b60a18deSMichael J. Spencer   return reinterpret_cast<const Elf_Shdr *>(
960b60a18deSMichael J. Spencer          reinterpret_cast<const char *>(SectionHeaderTable)
961b60a18deSMichael J. Spencer          + (index * Header->e_shentsize));
962b60a18deSMichael J. Spencer }
963b60a18deSMichael J. Spencer 
964b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
965b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits>
966b60a18deSMichael J. Spencer                          ::getString(uint16_t section,
967b60a18deSMichael J. Spencer                                      ELF::Elf32_Word offset) const {
968b60a18deSMichael J. Spencer   return getString(getSection(section), offset);
969b60a18deSMichael J. Spencer }
970b60a18deSMichael J. Spencer 
971b60a18deSMichael J. Spencer template<support::endianness target_endianness, bool is64Bits>
972b60a18deSMichael J. Spencer const char *ELFObjectFile<target_endianness, is64Bits>
973b60a18deSMichael J. Spencer                          ::getString(const Elf_Shdr *section,
974b60a18deSMichael J. Spencer                                      ELF::Elf32_Word offset) const {
975b60a18deSMichael J. Spencer   assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!");
976b60a18deSMichael J. Spencer   if (offset >= section->sh_size)
977b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
978ec29b121SMichael J. Spencer     report_fatal_error("Symbol name offset outside of string table!");
979ec29b121SMichael J. Spencer   return (const char *)base() + section->sh_offset + offset;
980b60a18deSMichael J. Spencer }
981b60a18deSMichael J. Spencer 
982b60a18deSMichael J. Spencer // EI_CLASS, EI_DATA.
983b60a18deSMichael J. Spencer static std::pair<unsigned char, unsigned char>
984b60a18deSMichael J. Spencer getElfArchType(MemoryBuffer *Object) {
985b60a18deSMichael J. Spencer   if (Object->getBufferSize() < ELF::EI_NIDENT)
986b60a18deSMichael J. Spencer     return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
987b60a18deSMichael J. Spencer   return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
988b60a18deSMichael J. Spencer                        , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
989b60a18deSMichael J. Spencer }
990b60a18deSMichael J. Spencer 
991b60a18deSMichael J. Spencer namespace llvm {
992b60a18deSMichael J. Spencer 
993b60a18deSMichael J. Spencer   ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
994b60a18deSMichael J. Spencer     std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);
995ec29b121SMichael J. Spencer     error_code ec;
996b60a18deSMichael J. Spencer     if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
997ec29b121SMichael J. Spencer       return new ELFObjectFile<support::little, false>(Object, ec);
998b60a18deSMichael J. Spencer     else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
999ec29b121SMichael J. Spencer       return new ELFObjectFile<support::big, false>(Object, ec);
1000b60a18deSMichael J. Spencer     else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB)
1001ec29b121SMichael J. Spencer       return new ELFObjectFile<support::little, true>(Object, ec);
1002b60a18deSMichael J. Spencer     else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
1003ec29b121SMichael J. Spencer       return new ELFObjectFile<support::big, true>(Object, ec);
1004b60a18deSMichael J. Spencer     // FIXME: Proper error handling.
1005b60a18deSMichael J. Spencer     report_fatal_error("Not an ELF object file!");
1006b60a18deSMichael J. Spencer   }
1007b60a18deSMichael J. Spencer 
1008b60a18deSMichael J. Spencer } // end namespace llvm
1009