1//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_OBJECT_ELF_TYPES_H
11#define LLVM_OBJECT_ELF_TYPES_H
12
13#include "llvm/Support/AlignOf.h"
14#include "llvm/Support/DataTypes.h"
15#include "llvm/Support/ELF.h"
16#include "llvm/Support/Endian.h"
17
18namespace llvm {
19namespace object {
20
21using support::endianness;
22
23template <endianness target_endianness, std::size_t max_alignment,
24          bool is64Bits>
25struct ELFType {
26  static const endianness TargetEndianness = target_endianness;
27  static const std::size_t MaxAlignment = max_alignment;
28  static const bool Is64Bits = is64Bits;
29};
30
31template <typename T, int max_align> struct MaximumAlignment {
32  enum { value = AlignOf<T>::Alignment > max_align ? max_align
33                                                   : AlignOf<T>::Alignment
34  };
35};
36
37// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
38template <endianness target_endianness, std::size_t max_alignment>
39struct ELFDataTypeTypedefHelperCommon {
40  typedef support::detail::packed_endian_specific_integral<
41      uint16_t, target_endianness,
42      MaximumAlignment<uint16_t, max_alignment>::value> Elf_Half;
43  typedef support::detail::packed_endian_specific_integral<
44      uint32_t, target_endianness,
45      MaximumAlignment<uint32_t, max_alignment>::value> Elf_Word;
46  typedef support::detail::packed_endian_specific_integral<
47      int32_t, target_endianness,
48      MaximumAlignment<int32_t, max_alignment>::value> Elf_Sword;
49  typedef support::detail::packed_endian_specific_integral<
50      uint64_t, target_endianness,
51      MaximumAlignment<uint64_t, max_alignment>::value> Elf_Xword;
52  typedef support::detail::packed_endian_specific_integral<
53      int64_t, target_endianness,
54      MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword;
55};
56
57template <class ELFT> struct ELFDataTypeTypedefHelper;
58
59/// ELF 32bit types.
60template <endianness TargetEndianness, std::size_t MaxAlign>
61struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> >
62    : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> {
63  typedef uint32_t value_type;
64  typedef support::detail::packed_endian_specific_integral<
65      value_type, TargetEndianness,
66      MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr;
67  typedef support::detail::packed_endian_specific_integral<
68      value_type, TargetEndianness,
69      MaximumAlignment<value_type, MaxAlign>::value> Elf_Off;
70};
71
72/// ELF 64bit types.
73template <endianness TargetEndianness, std::size_t MaxAlign>
74struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> >
75    : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> {
76  typedef uint64_t value_type;
77  typedef support::detail::packed_endian_specific_integral<
78      value_type, TargetEndianness,
79      MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr;
80  typedef support::detail::packed_endian_specific_integral<
81      value_type, TargetEndianness,
82      MaximumAlignment<value_type, MaxAlign>::value> Elf_Off;
83};
84
85// I really don't like doing this, but the alternative is copypasta.
86#define LLVM_ELF_IMPORT_TYPES(E, M, W)                                         \
87typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Addr         \
88    Elf_Addr;                                                                  \
89typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Off          \
90    Elf_Off;                                                                   \
91typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Half         \
92    Elf_Half;                                                                  \
93typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Word         \
94    Elf_Word;                                                                  \
95typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sword        \
96    Elf_Sword;                                                                 \
97typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Xword        \
98    Elf_Xword;                                                                 \
99typedef typename ELFDataTypeTypedefHelper<ELFType<E, M, W> >::Elf_Sxword       \
100    Elf_Sxword;
101
102#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)                                       \
103  LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment,            \
104                        ELFT::Is64Bits)
105
106// Section header.
107template <class ELFT> struct Elf_Shdr_Base;
108
109template <endianness TargetEndianness, std::size_t MaxAlign>
110struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > {
111  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
112  Elf_Word sh_name;      // Section name (index into string table)
113  Elf_Word sh_type;      // Section type (SHT_*)
114  Elf_Word sh_flags;     // Section flags (SHF_*)
115  Elf_Addr sh_addr;      // Address where section is to be loaded
116  Elf_Off sh_offset;     // File offset of section data, in bytes
117  Elf_Word sh_size;      // Size of section, in bytes
118  Elf_Word sh_link;      // Section type-specific header table index link
119  Elf_Word sh_info;      // Section type-specific extra information
120  Elf_Word sh_addralign; // Section address alignment
121  Elf_Word sh_entsize;   // Size of records contained within the section
122};
123
124template <endianness TargetEndianness, std::size_t MaxAlign>
125struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > {
126  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
127  Elf_Word sh_name;       // Section name (index into string table)
128  Elf_Word sh_type;       // Section type (SHT_*)
129  Elf_Xword sh_flags;     // Section flags (SHF_*)
130  Elf_Addr sh_addr;       // Address where section is to be loaded
131  Elf_Off sh_offset;      // File offset of section data, in bytes
132  Elf_Xword sh_size;      // Size of section, in bytes
133  Elf_Word sh_link;       // Section type-specific header table index link
134  Elf_Word sh_info;       // Section type-specific extra information
135  Elf_Xword sh_addralign; // Section address alignment
136  Elf_Xword sh_entsize;   // Size of records contained within the section
137};
138
139template <class ELFT>
140struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
141  using Elf_Shdr_Base<ELFT>::sh_entsize;
142  using Elf_Shdr_Base<ELFT>::sh_size;
143
144  /// @brief Get the number of entities this section contains if it has any.
145  unsigned getEntityCount() const {
146    if (sh_entsize == 0)
147      return 0;
148    return sh_size / sh_entsize;
149  }
150};
151
152template <class ELFT> struct Elf_Sym_Base;
153
154template <endianness TargetEndianness, std::size_t MaxAlign>
155struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > {
156  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
157  Elf_Word st_name;       // Symbol name (index into string table)
158  Elf_Addr st_value;      // Value or address associated with the symbol
159  Elf_Word st_size;       // Size of the symbol
160  unsigned char st_info;  // Symbol's type and binding attributes
161  unsigned char st_other; // Must be zero; reserved
162  Elf_Half st_shndx;      // Which section (header table index) it's defined in
163};
164
165template <endianness TargetEndianness, std::size_t MaxAlign>
166struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > {
167  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
168  Elf_Word st_name;       // Symbol name (index into string table)
169  unsigned char st_info;  // Symbol's type and binding attributes
170  unsigned char st_other; // Must be zero; reserved
171  Elf_Half st_shndx;      // Which section (header table index) it's defined in
172  Elf_Addr st_value;      // Value or address associated with the symbol
173  Elf_Xword st_size;      // Size of the symbol
174};
175
176template <class ELFT>
177struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
178  using Elf_Sym_Base<ELFT>::st_info;
179
180  // These accessors and mutators correspond to the ELF32_ST_BIND,
181  // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
182  unsigned char getBinding() const { return st_info >> 4; }
183  unsigned char getType() const { return st_info & 0x0f; }
184  void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
185  void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
186  void setBindingAndType(unsigned char b, unsigned char t) {
187    st_info = (b << 4) + (t & 0x0f);
188  }
189};
190
191/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
192/// (.gnu.version). This structure is identical for ELF32 and ELF64.
193template <class ELFT>
194struct Elf_Versym_Impl {
195  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
196  Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN)
197};
198
199template <class ELFT> struct Elf_Verdaux_Impl;
200
201/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section
202/// (.gnu.version_d). This structure is identical for ELF32 and ELF64.
203template <class ELFT>
204struct Elf_Verdef_Impl {
205  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
206  typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux;
207  Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT)
208  Elf_Half vd_flags;   // Bitwise flags (VER_DEF_*)
209  Elf_Half vd_ndx;     // Version index, used in .gnu.version entries
210  Elf_Half vd_cnt;     // Number of Verdaux entries
211  Elf_Word vd_hash;    // Hash of name
212  Elf_Word vd_aux;     // Offset to the first Verdaux entry (in bytes)
213  Elf_Word vd_next;    // Offset to the next Verdef entry (in bytes)
214
215  /// Get the first Verdaux entry for this Verdef.
216  const Elf_Verdaux *getAux() const {
217    return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux);
218  }
219};
220
221/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef
222/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64.
223template <class ELFT>
224struct Elf_Verdaux_Impl {
225  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
226  Elf_Word vda_name; // Version name (offset in string table)
227  Elf_Word vda_next; // Offset to next Verdaux entry (in bytes)
228};
229
230/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed
231/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64.
232template <class ELFT>
233struct Elf_Verneed_Impl {
234  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
235  Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT)
236  Elf_Half vn_cnt;     // Number of associated Vernaux entries
237  Elf_Word vn_file;    // Library name (string table offset)
238  Elf_Word vn_aux;     // Offset to first Vernaux entry (in bytes)
239  Elf_Word vn_next;    // Offset to next Verneed entry (in bytes)
240};
241
242/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed
243/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64.
244template <class ELFT>
245struct Elf_Vernaux_Impl {
246  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
247  Elf_Word vna_hash;  // Hash of dependency name
248  Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*)
249  Elf_Half vna_other; // Version index, used in .gnu.version entries
250  Elf_Word vna_name;  // Dependency name
251  Elf_Word vna_next;  // Offset to next Vernaux entry (in bytes)
252};
253
254/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic
255///               table section (.dynamic) look like.
256template <class ELFT> struct Elf_Dyn_Base;
257
258template <endianness TargetEndianness, std::size_t MaxAlign>
259struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > {
260  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
261  Elf_Sword d_tag;
262  union {
263    Elf_Word d_val;
264    Elf_Addr d_ptr;
265  } d_un;
266};
267
268template <endianness TargetEndianness, std::size_t MaxAlign>
269struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > {
270  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
271  Elf_Sxword d_tag;
272  union {
273    Elf_Xword d_val;
274    Elf_Addr d_ptr;
275  } d_un;
276};
277
278/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters.
279template <class ELFT>
280struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
281  using Elf_Dyn_Base<ELFT>::d_tag;
282  using Elf_Dyn_Base<ELFT>::d_un;
283  int64_t getTag() const { return d_tag; }
284  uint64_t getVal() const { return d_un.d_val; }
285  uint64_t getPtr() const { return d_un.ptr; }
286};
287
288// Elf_Rel: Elf Relocation
289template <class ELFT, bool isRela> struct Elf_Rel_Base;
290
291template <endianness TargetEndianness, std::size_t MaxAlign>
292struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> {
293  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
294  Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
295  Elf_Word r_info;   // Symbol table index and type of relocation to apply
296
297  uint32_t getRInfo(bool isMips64EL) const {
298    assert(!isMips64EL);
299    return r_info;
300  }
301  void setRInfo(uint32_t R) { r_info = R; }
302};
303
304template <endianness TargetEndianness, std::size_t MaxAlign>
305struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> {
306  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
307  Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
308  Elf_Xword r_info;  // Symbol table index and type of relocation to apply
309
310  uint64_t getRInfo(bool isMips64EL) const {
311    uint64_t t = r_info;
312    if (!isMips64EL)
313      return t;
314    // Mips64 little endian has a "special" encoding of r_info. Instead of one
315    // 64 bit little endian number, it is a little endian 32 bit number followed
316    // by a 32 bit big endian number.
317    return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
318           ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
319  }
320  void setRInfo(uint64_t R) {
321    // FIXME: Add mips64el support.
322    r_info = R;
323  }
324};
325
326template <endianness TargetEndianness, std::size_t MaxAlign>
327struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> {
328  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
329  Elf_Addr r_offset;  // Location (file byte offset, or program virtual addr)
330  Elf_Word r_info;    // Symbol table index and type of relocation to apply
331  Elf_Sword r_addend; // Compute value for relocatable field by adding this
332
333  uint32_t getRInfo(bool isMips64EL) const {
334    assert(!isMips64EL);
335    return r_info;
336  }
337  void setRInfo(uint32_t R) { r_info = R; }
338};
339
340template <endianness TargetEndianness, std::size_t MaxAlign>
341struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> {
342  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
343  Elf_Addr r_offset;   // Location (file byte offset, or program virtual addr)
344  Elf_Xword r_info;    // Symbol table index and type of relocation to apply
345  Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
346
347  uint64_t getRInfo(bool isMips64EL) const {
348    // Mips64 little endian has a "special" encoding of r_info. Instead of one
349    // 64 bit little endian number, it is a little endian 32 bit number followed
350    // by a 32 bit big endian number.
351    uint64_t t = r_info;
352    if (!isMips64EL)
353      return t;
354    return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
355           ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
356  }
357  void setRInfo(uint64_t R) {
358    // FIXME: Add mips64el support.
359    r_info = R;
360  }
361};
362
363template <class ELFT, bool isRela> struct Elf_Rel_Impl;
364
365template <endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
366struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>,
367                    isRela> : Elf_Rel_Base<
368    ELFType<TargetEndianness, MaxAlign, true>, isRela> {
369  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
370
371  // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
372  // and ELF64_R_INFO macros defined in the ELF specification:
373  uint32_t getSymbol(bool isMips64EL) const {
374    return (uint32_t)(this->getRInfo(isMips64EL) >> 32);
375  }
376  uint32_t getType(bool isMips64EL) const {
377    return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL);
378  }
379  void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
380  void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); }
381  void setSymbolAndType(uint32_t s, uint32_t t) {
382    this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL));
383  }
384};
385
386template <endianness TargetEndianness, std::size_t MaxAlign, bool isRela>
387struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>,
388                    isRela> : Elf_Rel_Base<
389    ELFType<TargetEndianness, MaxAlign, false>, isRela> {
390  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
391
392  // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
393  // and ELF32_R_INFO macros defined in the ELF specification:
394  uint32_t getSymbol(bool isMips64EL) const {
395    return this->getRInfo(isMips64EL) >> 8;
396  }
397  unsigned char getType(bool isMips64EL) const {
398    return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
399  }
400  void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
401  void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
402  void setSymbolAndType(uint32_t s, unsigned char t) {
403    this->setRInfo((s << 8) + t);
404  }
405};
406
407template <class ELFT>
408struct Elf_Ehdr_Impl {
409  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
410  unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes
411  Elf_Half e_type;                       // Type of file (see ET_*)
412  Elf_Half e_machine;   // Required architecture for this file (see EM_*)
413  Elf_Word e_version;   // Must be equal to 1
414  Elf_Addr e_entry;     // Address to jump to in order to start program
415  Elf_Off e_phoff;      // Program header table's file offset, in bytes
416  Elf_Off e_shoff;      // Section header table's file offset, in bytes
417  Elf_Word e_flags;     // Processor-specific flags
418  Elf_Half e_ehsize;    // Size of ELF header, in bytes
419  Elf_Half e_phentsize; // Size of an entry in the program header table
420  Elf_Half e_phnum;     // Number of entries in the program header table
421  Elf_Half e_shentsize; // Size of an entry in the section header table
422  Elf_Half e_shnum;     // Number of entries in the section header table
423  Elf_Half e_shstrndx;  // Section header table index of section name
424                        // string table
425  bool checkMagic() const {
426    return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
427  }
428  unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
429  unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
430};
431
432template <class ELFT> struct Elf_Phdr_Impl;
433
434template <endianness TargetEndianness, std::size_t MaxAlign>
435struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > {
436  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
437  Elf_Word p_type;   // Type of segment
438  Elf_Off p_offset;  // FileOffset where segment is located, in bytes
439  Elf_Addr p_vaddr;  // Virtual Address of beginning of segment
440  Elf_Addr p_paddr;  // Physical address of beginning of segment (OS-specific)
441  Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero)
442  Elf_Word p_memsz;  // Num. of bytes in mem image of segment (may be zero)
443  Elf_Word p_flags;  // Segment flags
444  Elf_Word p_align;  // Segment alignment constraint
445};
446
447template <endianness TargetEndianness, std::size_t MaxAlign>
448struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > {
449  LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
450  Elf_Word p_type;    // Type of segment
451  Elf_Word p_flags;   // Segment flags
452  Elf_Off p_offset;   // FileOffset where segment is located, in bytes
453  Elf_Addr p_vaddr;   // Virtual Address of beginning of segment
454  Elf_Addr p_paddr;   // Physical address of beginning of segment (OS-specific)
455  Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero)
456  Elf_Xword p_memsz;  // Num. of bytes in mem image of segment (may be zero)
457  Elf_Xword p_align;  // Segment alignment constraint
458};
459
460} // end namespace object.
461} // end namespace llvm.
462
463#endif
464