/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Object/ELFTypes.h
Line | Count | Source (jump to first uncovered line) |
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_ELFTYPES_H |
11 | | #define LLVM_OBJECT_ELFTYPES_H |
12 | | |
13 | | #include "llvm/ADT/ArrayRef.h" |
14 | | #include "llvm/Object/Error.h" |
15 | | #include "llvm/Support/ELF.h" |
16 | | #include "llvm/Support/Endian.h" |
17 | | #include "llvm/Support/ErrorOr.h" |
18 | | |
19 | | namespace llvm { |
20 | | namespace object { |
21 | | |
22 | | using support::endianness; |
23 | | |
24 | | template <class ELFT> struct Elf_Ehdr_Impl; |
25 | | template <class ELFT> struct Elf_Shdr_Impl; |
26 | | template <class ELFT> struct Elf_Sym_Impl; |
27 | | template <class ELFT> struct Elf_Dyn_Impl; |
28 | | template <class ELFT> struct Elf_Phdr_Impl; |
29 | | template <class ELFT, bool isRela> struct Elf_Rel_Impl; |
30 | | template <class ELFT> struct Elf_Verdef_Impl; |
31 | | template <class ELFT> struct Elf_Verdaux_Impl; |
32 | | template <class ELFT> struct Elf_Verneed_Impl; |
33 | | template <class ELFT> struct Elf_Vernaux_Impl; |
34 | | template <class ELFT> struct Elf_Versym_Impl; |
35 | | template <class ELFT> struct Elf_Hash_Impl; |
36 | | template <class ELFT> struct Elf_GnuHash_Impl; |
37 | | template <class ELFT> struct Elf_Chdr_Impl; |
38 | | |
39 | | template <endianness E, bool Is64> struct ELFType { |
40 | | private: |
41 | | template <typename Ty> |
42 | | using packed = support::detail::packed_endian_specific_integral<Ty, E, 2>; |
43 | | |
44 | | public: |
45 | | static const endianness TargetEndianness = E; |
46 | | static const bool Is64Bits = Is64; |
47 | | |
48 | | typedef typename std::conditional<Is64, uint64_t, uint32_t>::type uint; |
49 | | typedef Elf_Ehdr_Impl<ELFType<E, Is64>> Ehdr; |
50 | | typedef Elf_Shdr_Impl<ELFType<E, Is64>> Shdr; |
51 | | typedef Elf_Sym_Impl<ELFType<E, Is64>> Sym; |
52 | | typedef Elf_Dyn_Impl<ELFType<E, Is64>> Dyn; |
53 | | typedef Elf_Phdr_Impl<ELFType<E, Is64>> Phdr; |
54 | | typedef Elf_Rel_Impl<ELFType<E, Is64>, false> Rel; |
55 | | typedef Elf_Rel_Impl<ELFType<E, Is64>, true> Rela; |
56 | | typedef Elf_Verdef_Impl<ELFType<E, Is64>> Verdef; |
57 | | typedef Elf_Verdaux_Impl<ELFType<E, Is64>> Verdaux; |
58 | | typedef Elf_Verneed_Impl<ELFType<E, Is64>> Verneed; |
59 | | typedef Elf_Vernaux_Impl<ELFType<E, Is64>> Vernaux; |
60 | | typedef Elf_Versym_Impl<ELFType<E, Is64>> Versym; |
61 | | typedef Elf_Hash_Impl<ELFType<E, Is64>> Hash; |
62 | | typedef Elf_GnuHash_Impl<ELFType<E, Is64>> GnuHash; |
63 | | typedef Elf_Chdr_Impl<ELFType<E, Is64>> Chdr; |
64 | | typedef ArrayRef<Dyn> DynRange; |
65 | | typedef ArrayRef<Shdr> ShdrRange; |
66 | | typedef ArrayRef<Sym> SymRange; |
67 | | typedef ArrayRef<Rel> RelRange; |
68 | | typedef ArrayRef<Rela> RelaRange; |
69 | | typedef ArrayRef<Phdr> PhdrRange; |
70 | | |
71 | | typedef packed<uint16_t> Half; |
72 | | typedef packed<uint32_t> Word; |
73 | | typedef packed<int32_t> Sword; |
74 | | typedef packed<uint64_t> Xword; |
75 | | typedef packed<int64_t> Sxword; |
76 | | typedef packed<uint> Addr; |
77 | | typedef packed<uint> Off; |
78 | | }; |
79 | | |
80 | | typedef ELFType<support::little, false> ELF32LE; |
81 | | typedef ELFType<support::big, false> ELF32BE; |
82 | | typedef ELFType<support::little, true> ELF64LE; |
83 | | typedef ELFType<support::big, true> ELF64BE; |
84 | | |
85 | | // Use an alignment of 2 for the typedefs since that is the worst case for |
86 | | // ELF files in archives. |
87 | | |
88 | | // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. |
89 | | template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon { |
90 | | typedef support::detail::packed_endian_specific_integral< |
91 | | uint16_t, target_endianness, 2> Elf_Half; |
92 | | typedef support::detail::packed_endian_specific_integral< |
93 | | uint32_t, target_endianness, 2> Elf_Word; |
94 | | typedef support::detail::packed_endian_specific_integral< |
95 | | int32_t, target_endianness, 2> Elf_Sword; |
96 | | typedef support::detail::packed_endian_specific_integral< |
97 | | uint64_t, target_endianness, 2> Elf_Xword; |
98 | | typedef support::detail::packed_endian_specific_integral< |
99 | | int64_t, target_endianness, 2> Elf_Sxword; |
100 | | }; |
101 | | |
102 | | template <class ELFT> struct ELFDataTypeTypedefHelper; |
103 | | |
104 | | /// ELF 32bit types. |
105 | | template <endianness TargetEndianness> |
106 | | struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>> |
107 | | : ELFDataTypeTypedefHelperCommon<TargetEndianness> { |
108 | | typedef uint32_t value_type; |
109 | | typedef support::detail::packed_endian_specific_integral< |
110 | | value_type, TargetEndianness, 2> Elf_Addr; |
111 | | typedef support::detail::packed_endian_specific_integral< |
112 | | value_type, TargetEndianness, 2> Elf_Off; |
113 | | }; |
114 | | |
115 | | /// ELF 64bit types. |
116 | | template <endianness TargetEndianness> |
117 | | struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>> |
118 | | : ELFDataTypeTypedefHelperCommon<TargetEndianness> { |
119 | | typedef uint64_t value_type; |
120 | | typedef support::detail::packed_endian_specific_integral< |
121 | | value_type, TargetEndianness, 2> Elf_Addr; |
122 | | typedef support::detail::packed_endian_specific_integral< |
123 | | value_type, TargetEndianness, 2> Elf_Off; |
124 | | }; |
125 | | |
126 | | // I really don't like doing this, but the alternative is copypasta. |
127 | | |
128 | | #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ |
129 | | typedef typename ELFT::Addr Elf_Addr; \ |
130 | | typedef typename ELFT::Off Elf_Off; \ |
131 | | typedef typename ELFT::Half Elf_Half; \ |
132 | | typedef typename ELFT::Word Elf_Word; \ |
133 | | typedef typename ELFT::Sword Elf_Sword; \ |
134 | | typedef typename ELFT::Xword Elf_Xword; \ |
135 | | typedef typename ELFT::Sxword Elf_Sxword; |
136 | | |
137 | | #define LLD_ELF_COMMA , |
138 | | #define LLVM_ELF_IMPORT_TYPES(E, W) \ |
139 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLD_ELF_COMMA W>) |
140 | | |
141 | | // Section header. |
142 | | template <class ELFT> struct Elf_Shdr_Base; |
143 | | |
144 | | template <endianness TargetEndianness> |
145 | | struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> { |
146 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
147 | | Elf_Word sh_name; // Section name (index into string table) |
148 | | Elf_Word sh_type; // Section type (SHT_*) |
149 | | Elf_Word sh_flags; // Section flags (SHF_*) |
150 | | Elf_Addr sh_addr; // Address where section is to be loaded |
151 | | Elf_Off sh_offset; // File offset of section data, in bytes |
152 | | Elf_Word sh_size; // Size of section, in bytes |
153 | | Elf_Word sh_link; // Section type-specific header table index link |
154 | | Elf_Word sh_info; // Section type-specific extra information |
155 | | Elf_Word sh_addralign; // Section address alignment |
156 | | Elf_Word sh_entsize; // Size of records contained within the section |
157 | | }; |
158 | | |
159 | | template <endianness TargetEndianness> |
160 | | struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> { |
161 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
162 | | Elf_Word sh_name; // Section name (index into string table) |
163 | | Elf_Word sh_type; // Section type (SHT_*) |
164 | | Elf_Xword sh_flags; // Section flags (SHF_*) |
165 | | Elf_Addr sh_addr; // Address where section is to be loaded |
166 | | Elf_Off sh_offset; // File offset of section data, in bytes |
167 | | Elf_Xword sh_size; // Size of section, in bytes |
168 | | Elf_Word sh_link; // Section type-specific header table index link |
169 | | Elf_Word sh_info; // Section type-specific extra information |
170 | | Elf_Xword sh_addralign; // Section address alignment |
171 | | Elf_Xword sh_entsize; // Size of records contained within the section |
172 | | }; |
173 | | |
174 | | template <class ELFT> |
175 | | struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { |
176 | | using Elf_Shdr_Base<ELFT>::sh_entsize; |
177 | | using Elf_Shdr_Base<ELFT>::sh_size; |
178 | | |
179 | | /// @brief Get the number of entities this section contains if it has any. |
180 | | unsigned getEntityCount() const { |
181 | | if (sh_entsize == 0) |
182 | | return 0; |
183 | | return sh_size / sh_entsize; |
184 | | } |
185 | | }; |
186 | | |
187 | | template <class ELFT> struct Elf_Sym_Base; |
188 | | |
189 | | template <endianness TargetEndianness> |
190 | | struct Elf_Sym_Base<ELFType<TargetEndianness, false>> { |
191 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
192 | | Elf_Word st_name; // Symbol name (index into string table) |
193 | | Elf_Addr st_value; // Value or address associated with the symbol |
194 | | Elf_Word st_size; // Size of the symbol |
195 | | unsigned char st_info; // Symbol's type and binding attributes |
196 | | unsigned char st_other; // Must be zero; reserved |
197 | | Elf_Half st_shndx; // Which section (header table index) it's defined in |
198 | | }; |
199 | | |
200 | | template <endianness TargetEndianness> |
201 | | struct Elf_Sym_Base<ELFType<TargetEndianness, true>> { |
202 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
203 | | Elf_Word st_name; // Symbol name (index into string table) |
204 | | unsigned char st_info; // Symbol's type and binding attributes |
205 | | unsigned char st_other; // Must be zero; reserved |
206 | | Elf_Half st_shndx; // Which section (header table index) it's defined in |
207 | | Elf_Addr st_value; // Value or address associated with the symbol |
208 | | Elf_Xword st_size; // Size of the symbol |
209 | | }; |
210 | | |
211 | | template <class ELFT> |
212 | | struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { |
213 | | using Elf_Sym_Base<ELFT>::st_info; |
214 | | using Elf_Sym_Base<ELFT>::st_shndx; |
215 | | using Elf_Sym_Base<ELFT>::st_other; |
216 | | using Elf_Sym_Base<ELFT>::st_value; |
217 | | |
218 | | // These accessors and mutators correspond to the ELF32_ST_BIND, |
219 | | // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: |
220 | | unsigned char getBinding() const { return st_info >> 4; } |
221 | | unsigned char getType() const { return st_info & 0x0f; } |
222 | | uint64_t getValue() const { return st_value; } |
223 | | void setBinding(unsigned char b) { setBindingAndType(b, getType()); } |
224 | | void setType(unsigned char t) { setBindingAndType(getBinding(), t); } |
225 | | void setBindingAndType(unsigned char b, unsigned char t) { |
226 | | st_info = (b << 4) + (t & 0x0f); |
227 | | } |
228 | | |
229 | | /// Access to the STV_xxx flag stored in the first two bits of st_other. |
230 | | /// STV_DEFAULT: 0 |
231 | | /// STV_INTERNAL: 1 |
232 | | /// STV_HIDDEN: 2 |
233 | | /// STV_PROTECTED: 3 |
234 | | unsigned char getVisibility() const { return st_other & 0x3; } |
235 | | void setVisibility(unsigned char v) { |
236 | | assert(v < 4 && "Invalid value for visibility"); |
237 | | st_other = (st_other & ~0x3) | v; |
238 | | } |
239 | | |
240 | | bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; } |
241 | | bool isCommon() const { |
242 | | return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON; |
243 | | } |
244 | | bool isDefined() const { return !isUndefined(); } |
245 | | bool isProcessorSpecific() const { |
246 | | return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC; |
247 | | } |
248 | | bool isOSSpecific() const { |
249 | | return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS; |
250 | | } |
251 | | bool isReserved() const { |
252 | | // ELF::SHN_HIRESERVE is 0xffff so st_shndx <= ELF::SHN_HIRESERVE is always |
253 | | // true and some compilers warn about it. |
254 | | return st_shndx >= ELF::SHN_LORESERVE; |
255 | | } |
256 | | bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; } |
257 | | bool isExternal() const { |
258 | | return getBinding() != ELF::STB_LOCAL; |
259 | | } |
260 | | |
261 | | Expected<StringRef> getName(StringRef StrTab) const; |
262 | | }; |
263 | | |
264 | | template <class ELFT> |
265 | | Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const { |
266 | | uint32_t Offset = this->st_name; |
267 | | if (Offset >= StrTab.size()) |
268 | | return errorCodeToError(object_error::parse_failed); |
269 | | return StringRef(StrTab.data() + Offset); |
270 | | } |
271 | | |
272 | | /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section |
273 | | /// (.gnu.version). This structure is identical for ELF32 and ELF64. |
274 | | template <class ELFT> |
275 | | struct Elf_Versym_Impl { |
276 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
277 | | Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) |
278 | | }; |
279 | | |
280 | | template <class ELFT> struct Elf_Verdaux_Impl; |
281 | | |
282 | | /// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section |
283 | | /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. |
284 | | template <class ELFT> |
285 | | struct Elf_Verdef_Impl { |
286 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
287 | | typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; |
288 | | Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) |
289 | | Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) |
290 | | Elf_Half vd_ndx; // Version index, used in .gnu.version entries |
291 | | Elf_Half vd_cnt; // Number of Verdaux entries |
292 | | Elf_Word vd_hash; // Hash of name |
293 | | Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) |
294 | | Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) |
295 | | |
296 | | /// Get the first Verdaux entry for this Verdef. |
297 | | const Elf_Verdaux *getAux() const { |
298 | | return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux); |
299 | | } |
300 | | }; |
301 | | |
302 | | /// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef |
303 | | /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. |
304 | | template <class ELFT> |
305 | | struct Elf_Verdaux_Impl { |
306 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
307 | | Elf_Word vda_name; // Version name (offset in string table) |
308 | | Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) |
309 | | }; |
310 | | |
311 | | /// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed |
312 | | /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. |
313 | | template <class ELFT> |
314 | | struct Elf_Verneed_Impl { |
315 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
316 | | Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) |
317 | | Elf_Half vn_cnt; // Number of associated Vernaux entries |
318 | | Elf_Word vn_file; // Library name (string table offset) |
319 | | Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) |
320 | | Elf_Word vn_next; // Offset to next Verneed entry (in bytes) |
321 | | }; |
322 | | |
323 | | /// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed |
324 | | /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. |
325 | | template <class ELFT> |
326 | | struct Elf_Vernaux_Impl { |
327 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
328 | | Elf_Word vna_hash; // Hash of dependency name |
329 | | Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) |
330 | | Elf_Half vna_other; // Version index, used in .gnu.version entries |
331 | | Elf_Word vna_name; // Dependency name |
332 | | Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) |
333 | | }; |
334 | | |
335 | | /// Elf_Dyn_Base: This structure matches the form of entries in the dynamic |
336 | | /// table section (.dynamic) look like. |
337 | | template <class ELFT> struct Elf_Dyn_Base; |
338 | | |
339 | | template <endianness TargetEndianness> |
340 | | struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> { |
341 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
342 | | Elf_Sword d_tag; |
343 | | union { |
344 | | Elf_Word d_val; |
345 | | Elf_Addr d_ptr; |
346 | | } d_un; |
347 | | }; |
348 | | |
349 | | template <endianness TargetEndianness> |
350 | | struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> { |
351 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
352 | | Elf_Sxword d_tag; |
353 | | union { |
354 | | Elf_Xword d_val; |
355 | | Elf_Addr d_ptr; |
356 | | } d_un; |
357 | | }; |
358 | | |
359 | | /// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters. |
360 | | template <class ELFT> |
361 | | struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { |
362 | | using Elf_Dyn_Base<ELFT>::d_tag; |
363 | | using Elf_Dyn_Base<ELFT>::d_un; |
364 | | typedef typename std::conditional<ELFT::Is64Bits, |
365 | | int64_t, int32_t>::type intX_t; |
366 | | typedef typename std::conditional<ELFT::Is64Bits, |
367 | | uint64_t, uint32_t>::type uintX_t; |
368 | | intX_t getTag() const { return d_tag; } |
369 | | uintX_t getVal() const { return d_un.d_val; } |
370 | | uintX_t getPtr() const { return d_un.d_ptr; } |
371 | | }; |
372 | | |
373 | | template <endianness TargetEndianness> |
374 | | struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { |
375 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
376 | | static const bool IsRela = false; |
377 | | Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) |
378 | | Elf_Word r_info; // Symbol table index and type of relocation to apply |
379 | | |
380 | 0 | uint32_t getRInfo(bool isMips64EL) const { |
381 | 0 | assert(!isMips64EL); |
382 | 0 | return r_info; |
383 | 0 | } |
384 | 0 | void setRInfo(uint32_t R, bool IsMips64EL) { |
385 | 0 | assert(!IsMips64EL); |
386 | 0 | r_info = R; |
387 | 0 | } |
388 | | |
389 | | // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, |
390 | | // and ELF32_R_INFO macros defined in the ELF specification: |
391 | 0 | uint32_t getSymbol(bool isMips64EL) const { |
392 | 0 | return this->getRInfo(isMips64EL) >> 8; |
393 | 0 | } |
394 | 0 | unsigned char getType(bool isMips64EL) const { |
395 | 0 | return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); |
396 | 0 | } |
397 | 0 | void setSymbol(uint32_t s, bool IsMips64EL) { |
398 | 0 | setSymbolAndType(s, getType(), IsMips64EL); |
399 | 0 | } |
400 | 0 | void setType(unsigned char t, bool IsMips64EL) { |
401 | 0 | setSymbolAndType(getSymbol(), t, IsMips64EL); |
402 | 0 | } |
403 | 0 | void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { |
404 | 0 | this->setRInfo((s << 8) + t, IsMips64EL); |
405 | 0 | } |
406 | | }; |
407 | | |
408 | | template <endianness TargetEndianness> |
409 | | struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true> |
410 | | : public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { |
411 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
412 | | static const bool IsRela = true; |
413 | | Elf_Sword r_addend; // Compute value for relocatable field by adding this |
414 | | }; |
415 | | |
416 | | template <endianness TargetEndianness> |
417 | | struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { |
418 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
419 | | static const bool IsRela = false; |
420 | | Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) |
421 | | Elf_Xword r_info; // Symbol table index and type of relocation to apply |
422 | | |
423 | 0 | uint64_t getRInfo(bool isMips64EL) const { |
424 | 0 | uint64_t t = r_info; |
425 | 0 | if (!isMips64EL) |
426 | 0 | return t; |
427 | 0 | // Mips64 little endian has a "special" encoding of r_info. Instead of one |
428 | 0 | // 64 bit little endian number, it is a little endian 32 bit number followed |
429 | 0 | // by a 32 bit big endian number. |
430 | 0 | return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | |
431 | 0 | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); |
432 | 0 | } |
433 | 0 | void setRInfo(uint64_t R, bool IsMips64EL) { |
434 | 0 | if (IsMips64EL) |
435 | 0 | r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | |
436 | 0 | ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); |
437 | 0 | else |
438 | 0 | r_info = R; |
439 | 0 | } |
440 | | |
441 | | // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, |
442 | | // and ELF64_R_INFO macros defined in the ELF specification: |
443 | 0 | uint32_t getSymbol(bool isMips64EL) const { |
444 | 0 | return (uint32_t)(this->getRInfo(isMips64EL) >> 32); |
445 | 0 | } |
446 | 0 | uint32_t getType(bool isMips64EL) const { |
447 | 0 | return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); |
448 | 0 | } |
449 | 0 | void setSymbol(uint32_t s, bool IsMips64EL) { |
450 | 0 | setSymbolAndType(s, getType(), IsMips64EL); |
451 | 0 | } |
452 | 0 | void setType(uint32_t t, bool IsMips64EL) { |
453 | 0 | setSymbolAndType(getSymbol(), t, IsMips64EL); |
454 | 0 | } |
455 | 0 | void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { |
456 | 0 | this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); |
457 | 0 | } |
458 | | }; |
459 | | |
460 | | template <endianness TargetEndianness> |
461 | | struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true> |
462 | | : public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { |
463 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
464 | | static const bool IsRela = true; |
465 | | Elf_Sxword r_addend; // Compute value for relocatable field by adding this. |
466 | | }; |
467 | | |
468 | | template <class ELFT> |
469 | | struct Elf_Ehdr_Impl { |
470 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
471 | | unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes |
472 | | Elf_Half e_type; // Type of file (see ET_*) |
473 | | Elf_Half e_machine; // Required architecture for this file (see EM_*) |
474 | | Elf_Word e_version; // Must be equal to 1 |
475 | | Elf_Addr e_entry; // Address to jump to in order to start program |
476 | | Elf_Off e_phoff; // Program header table's file offset, in bytes |
477 | | Elf_Off e_shoff; // Section header table's file offset, in bytes |
478 | | Elf_Word e_flags; // Processor-specific flags |
479 | | Elf_Half e_ehsize; // Size of ELF header, in bytes |
480 | | Elf_Half e_phentsize; // Size of an entry in the program header table |
481 | | Elf_Half e_phnum; // Number of entries in the program header table |
482 | | Elf_Half e_shentsize; // Size of an entry in the section header table |
483 | | Elf_Half e_shnum; // Number of entries in the section header table |
484 | | Elf_Half e_shstrndx; // Section header table index of section name |
485 | | // string table |
486 | | bool checkMagic() const { |
487 | | return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; |
488 | | } |
489 | | unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } |
490 | | unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } |
491 | | }; |
492 | | |
493 | | template <class ELFT> struct Elf_Phdr_Impl; |
494 | | |
495 | | template <endianness TargetEndianness> |
496 | | struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> { |
497 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
498 | | Elf_Word p_type; // Type of segment |
499 | | Elf_Off p_offset; // FileOffset where segment is located, in bytes |
500 | | Elf_Addr p_vaddr; // Virtual Address of beginning of segment |
501 | | Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) |
502 | | Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) |
503 | | Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) |
504 | | Elf_Word p_flags; // Segment flags |
505 | | Elf_Word p_align; // Segment alignment constraint |
506 | | }; |
507 | | |
508 | | template <endianness TargetEndianness> |
509 | | struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> { |
510 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
511 | | Elf_Word p_type; // Type of segment |
512 | | Elf_Word p_flags; // Segment flags |
513 | | Elf_Off p_offset; // FileOffset where segment is located, in bytes |
514 | | Elf_Addr p_vaddr; // Virtual Address of beginning of segment |
515 | | Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) |
516 | | Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) |
517 | | Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) |
518 | | Elf_Xword p_align; // Segment alignment constraint |
519 | | }; |
520 | | |
521 | | // ELFT needed for endianness. |
522 | | template <class ELFT> |
523 | | struct Elf_Hash_Impl { |
524 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
525 | | Elf_Word nbucket; |
526 | | Elf_Word nchain; |
527 | | |
528 | | ArrayRef<Elf_Word> buckets() const { |
529 | | return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket); |
530 | | } |
531 | | |
532 | | ArrayRef<Elf_Word> chains() const { |
533 | | return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket, |
534 | | &nbucket + 2 + nbucket + nchain); |
535 | | } |
536 | | }; |
537 | | |
538 | | // .gnu.hash section |
539 | | template <class ELFT> |
540 | | struct Elf_GnuHash_Impl { |
541 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
542 | | Elf_Word nbuckets; |
543 | | Elf_Word symndx; |
544 | | Elf_Word maskwords; |
545 | | Elf_Word shift2; |
546 | | |
547 | | ArrayRef<Elf_Off> filter() const { |
548 | | return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1), |
549 | | maskwords); |
550 | | } |
551 | | |
552 | | ArrayRef<Elf_Word> buckets() const { |
553 | | return ArrayRef<Elf_Word>( |
554 | | reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets); |
555 | | } |
556 | | |
557 | | ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const { |
558 | | return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx); |
559 | | } |
560 | | }; |
561 | | |
562 | | // Compressed section headers. |
563 | | // http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header |
564 | | template <endianness TargetEndianness> |
565 | | struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> { |
566 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
567 | | Elf_Word ch_type; |
568 | | Elf_Word ch_size; |
569 | | Elf_Word ch_addralign; |
570 | | }; |
571 | | |
572 | | template <endianness TargetEndianness> |
573 | | struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> { |
574 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
575 | | Elf_Word ch_type; |
576 | | Elf_Word ch_reserved; |
577 | | Elf_Xword ch_size; |
578 | | Elf_Xword ch_addralign; |
579 | | }; |
580 | | |
581 | | // MIPS .reginfo section |
582 | | template <class ELFT> |
583 | | struct Elf_Mips_RegInfo; |
584 | | |
585 | | template <llvm::support::endianness TargetEndianness> |
586 | | struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> { |
587 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) |
588 | | Elf_Word ri_gprmask; // bit-mask of used general registers |
589 | | Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers |
590 | | Elf_Addr ri_gp_value; // gp register value |
591 | | }; |
592 | | |
593 | | template <llvm::support::endianness TargetEndianness> |
594 | | struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> { |
595 | | LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) |
596 | | Elf_Word ri_gprmask; // bit-mask of used general registers |
597 | | Elf_Word ri_pad; // unused padding field |
598 | | Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers |
599 | | Elf_Addr ri_gp_value; // gp register value |
600 | | }; |
601 | | |
602 | | // .MIPS.options section |
603 | | template <class ELFT> struct Elf_Mips_Options { |
604 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
605 | | uint8_t kind; // Determines interpretation of variable part of descriptor |
606 | | uint8_t size; // Byte size of descriptor, including this header |
607 | | Elf_Half section; // Section header index of section affected, |
608 | | // or 0 for global options |
609 | | Elf_Word info; // Kind-specific information |
610 | | |
611 | | Elf_Mips_RegInfo<ELFT> &getRegInfo() { |
612 | | assert(kind == llvm::ELF::ODK_REGINFO); |
613 | | return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>( |
614 | | (uint8_t *)this + sizeof(Elf_Mips_Options)); |
615 | | } |
616 | | const Elf_Mips_RegInfo<ELFT> &getRegInfo() const { |
617 | | return const_cast<Elf_Mips_Options *>(this)->getRegInfo(); |
618 | | } |
619 | | }; |
620 | | |
621 | | // .MIPS.abiflags section content |
622 | | template <class ELFT> struct Elf_Mips_ABIFlags { |
623 | | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
624 | | Elf_Half version; // Version of the structure |
625 | | uint8_t isa_level; // ISA level: 1-5, 32, and 64 |
626 | | uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V) |
627 | | uint8_t gpr_size; // General purpose registers size |
628 | | uint8_t cpr1_size; // Co-processor 1 registers size |
629 | | uint8_t cpr2_size; // Co-processor 2 registers size |
630 | | uint8_t fp_abi; // Floating-point ABI flag |
631 | | Elf_Word isa_ext; // Processor-specific extension |
632 | | Elf_Word ases; // ASEs flags |
633 | | Elf_Word flags1; // General flags |
634 | | Elf_Word flags2; // General flags |
635 | | }; |
636 | | |
637 | | } // end namespace object. |
638 | | } // end namespace llvm. |
639 | | |
640 | | #endif |