OLD | NEW |
1 //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// | 1 //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file declares the ELFObjectFile template class. | 10 // This file declares the ELFObjectFile template class. |
11 // | 11 // |
12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
13 | 13 |
14 #ifndef LLVM_OBJECT_ELF_H | 14 #ifndef LLVM_OBJECT_ELF_H |
15 #define LLVM_OBJECT_ELF_H | 15 #define LLVM_OBJECT_ELF_H |
16 | 16 |
17 #include "llvm/ADT/SmallVector.h" | 17 #include "llvm/ADT/SmallVector.h" |
18 #include "llvm/ADT/StringSwitch.h" | 18 #include "llvm/ADT/StringSwitch.h" |
19 #include "llvm/ADT/Triple.h" | 19 #include "llvm/ADT/Triple.h" |
20 #include "llvm/ADT/DenseMap.h" | 20 #include "llvm/ADT/DenseMap.h" |
| 21 #include "llvm/ADT/PointerIntPair.h" |
21 #include "llvm/Object/ObjectFile.h" | 22 #include "llvm/Object/ObjectFile.h" |
22 #include "llvm/Support/Casting.h" | 23 #include "llvm/Support/Casting.h" |
23 #include "llvm/Support/ELF.h" | 24 #include "llvm/Support/ELF.h" |
24 #include "llvm/Support/Endian.h" | 25 #include "llvm/Support/Endian.h" |
25 #include "llvm/Support/ErrorHandling.h" | 26 #include "llvm/Support/ErrorHandling.h" |
26 #include "llvm/Support/MemoryBuffer.h" | 27 #include "llvm/Support/MemoryBuffer.h" |
27 #include "llvm/Support/raw_ostream.h" | 28 #include "llvm/Support/raw_ostream.h" |
28 #include <algorithm> | 29 #include <algorithm> |
29 #include <limits> | 30 #include <limits> |
30 #include <utility> | 31 #include <utility> |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: | 170 // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: |
170 unsigned char getBinding() const { return st_info >> 4; } | 171 unsigned char getBinding() const { return st_info >> 4; } |
171 unsigned char getType() const { return st_info & 0x0f; } | 172 unsigned char getType() const { return st_info & 0x0f; } |
172 void setBinding(unsigned char b) { setBindingAndType(b, getType()); } | 173 void setBinding(unsigned char b) { setBindingAndType(b, getType()); } |
173 void setType(unsigned char t) { setBindingAndType(getBinding(), t); } | 174 void setType(unsigned char t) { setBindingAndType(getBinding(), t); } |
174 void setBindingAndType(unsigned char b, unsigned char t) { | 175 void setBindingAndType(unsigned char b, unsigned char t) { |
175 st_info = (b << 4) + (t & 0x0f); | 176 st_info = (b << 4) + (t & 0x0f); |
176 } | 177 } |
177 }; | 178 }; |
178 | 179 |
179 // Elf_Dyn: Entry in the dynamic table | 180 /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section |
| 181 /// (.gnu.version). This structure is identical for ELF32 and ELF64. |
| 182 template<support::endianness target_endianness, bool is64Bits> |
| 183 struct Elf_Versym_Impl { |
| 184 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) |
| 185 Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) |
| 186 }; |
| 187 |
| 188 template<support::endianness target_endianness, bool is64Bits> |
| 189 struct Elf_Verdaux_Impl; |
| 190 |
| 191 /// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section |
| 192 /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. |
| 193 template<support::endianness target_endianness, bool is64Bits> |
| 194 struct Elf_Verdef_Impl { |
| 195 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) |
| 196 typedef Elf_Verdaux_Impl<target_endianness, is64Bits> Elf_Verdaux; |
| 197 Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) |
| 198 Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) |
| 199 Elf_Half vd_ndx; // Version index, used in .gnu.version entries |
| 200 Elf_Half vd_cnt; // Number of Verdaux entries |
| 201 Elf_Word vd_hash; // Hash of name |
| 202 Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) |
| 203 Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) |
| 204 |
| 205 /// Get the first Verdaux entry for this Verdef. |
| 206 const Elf_Verdaux *getAux() const { |
| 207 return reinterpret_cast<const Elf_Verdaux*>((const char*)this + vd_aux); |
| 208 } |
| 209 }; |
| 210 |
| 211 /// Elf_Verdaux: This is the structure of auxilary data in the SHT_GNU_verdef |
| 212 /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. |
| 213 template<support::endianness target_endianness, bool is64Bits> |
| 214 struct Elf_Verdaux_Impl { |
| 215 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) |
| 216 Elf_Word vda_name; // Version name (offset in string table) |
| 217 Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) |
| 218 }; |
| 219 |
| 220 /// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed |
| 221 /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. |
| 222 template<support::endianness target_endianness, bool is64Bits> |
| 223 struct Elf_Verneed_Impl { |
| 224 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) |
| 225 Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) |
| 226 Elf_Half vn_cnt; // Number of associated Vernaux entries |
| 227 Elf_Word vn_file; // Library name (string table offset) |
| 228 Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) |
| 229 Elf_Word vn_next; // Offset to next Verneed entry (in bytes) |
| 230 }; |
| 231 |
| 232 /// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed |
| 233 /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. |
| 234 template<support::endianness target_endianness, bool is64Bits> |
| 235 struct Elf_Vernaux_Impl { |
| 236 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) |
| 237 Elf_Word vna_hash; // Hash of dependency name |
| 238 Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) |
| 239 Elf_Half vna_other; // Version index, used in .gnu.version entries |
| 240 Elf_Word vna_name; // Dependency name |
| 241 Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) |
| 242 }; |
| 243 |
| 244 /// Elf_Dyn_Base: This structure matches the form of entries in the dynamic |
| 245 /// table section (.dynamic) look like. |
180 template<support::endianness target_endianness, bool is64Bits> | 246 template<support::endianness target_endianness, bool is64Bits> |
181 struct Elf_Dyn_Base; | 247 struct Elf_Dyn_Base; |
182 | 248 |
183 template<support::endianness target_endianness> | 249 template<support::endianness target_endianness> |
184 struct Elf_Dyn_Base<target_endianness, false> { | 250 struct Elf_Dyn_Base<target_endianness, false> { |
185 LLVM_ELF_IMPORT_TYPES(target_endianness, false) | 251 LLVM_ELF_IMPORT_TYPES(target_endianness, false) |
186 Elf_Sword d_tag; | 252 Elf_Sword d_tag; |
187 union { | 253 union { |
188 Elf_Word d_val; | 254 Elf_Word d_val; |
189 Elf_Addr d_ptr; | 255 Elf_Addr d_ptr; |
190 } d_un; | 256 } d_un; |
191 }; | 257 }; |
192 | 258 |
193 template<support::endianness target_endianness> | 259 template<support::endianness target_endianness> |
194 struct Elf_Dyn_Base<target_endianness, true> { | 260 struct Elf_Dyn_Base<target_endianness, true> { |
195 LLVM_ELF_IMPORT_TYPES(target_endianness, true) | 261 LLVM_ELF_IMPORT_TYPES(target_endianness, true) |
196 Elf_Sxword d_tag; | 262 Elf_Sxword d_tag; |
197 union { | 263 union { |
198 Elf_Xword d_val; | 264 Elf_Xword d_val; |
199 Elf_Addr d_ptr; | 265 Elf_Addr d_ptr; |
200 } d_un; | 266 } d_un; |
201 }; | 267 }; |
202 | 268 |
| 269 /// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. |
203 template<support::endianness target_endianness, bool is64Bits> | 270 template<support::endianness target_endianness, bool is64Bits> |
204 struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, is64Bits> { | 271 struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, is64Bits> { |
205 using Elf_Dyn_Base<target_endianness, is64Bits>::d_tag; | 272 using Elf_Dyn_Base<target_endianness, is64Bits>::d_tag; |
206 using Elf_Dyn_Base<target_endianness, is64Bits>::d_un; | 273 using Elf_Dyn_Base<target_endianness, is64Bits>::d_un; |
207 int64_t getTag() const { return d_tag; } | 274 int64_t getTag() const { return d_tag; } |
208 uint64_t getVal() const { return d_un.d_val; } | 275 uint64_t getVal() const { return d_un.d_val; } |
209 uint64_t getPtr() const { return d_un.ptr; } | 276 uint64_t getPtr() const { return d_un.ptr; } |
210 }; | 277 }; |
211 | 278 |
212 template<support::endianness target_endianness, bool is64Bits> | 279 template<support::endianness target_endianness, bool is64Bits> |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 | 383 |
317 template<support::endianness target_endianness, bool is64Bits> | 384 template<support::endianness target_endianness, bool is64Bits> |
318 class ELFObjectFile : public ObjectFile { | 385 class ELFObjectFile : public ObjectFile { |
319 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) | 386 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) |
320 | 387 |
321 typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; | 388 typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; |
322 typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; | 389 typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; |
323 typedef Elf_Dyn_Impl<target_endianness, is64Bits> Elf_Dyn; | 390 typedef Elf_Dyn_Impl<target_endianness, is64Bits> Elf_Dyn; |
324 typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; | 391 typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; |
325 typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; | 392 typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; |
| 393 typedef Elf_Verdef_Impl<target_endianness, is64Bits> Elf_Verdef; |
| 394 typedef Elf_Verdaux_Impl<target_endianness, is64Bits> Elf_Verdaux; |
| 395 typedef Elf_Verneed_Impl<target_endianness, is64Bits> Elf_Verneed; |
| 396 typedef Elf_Vernaux_Impl<target_endianness, is64Bits> Elf_Vernaux; |
| 397 typedef Elf_Versym_Impl<target_endianness, is64Bits> Elf_Versym; |
326 typedef DynRefImpl<target_endianness, is64Bits> DynRef; | 398 typedef DynRefImpl<target_endianness, is64Bits> DynRef; |
327 typedef content_iterator<DynRef> dyn_iterator; | 399 typedef content_iterator<DynRef> dyn_iterator; |
328 | 400 |
329 protected: | 401 protected: |
330 struct Elf_Ehdr { | 402 struct Elf_Ehdr { |
331 unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes | 403 unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes |
332 Elf_Half e_type; // Type of file (see ET_*) | 404 Elf_Half e_type; // Type of file (see ET_*) |
333 Elf_Half e_machine; // Required architecture for this file (see EM_*) | 405 Elf_Half e_machine; // Required architecture for this file (see EM_*) |
334 Elf_Word e_version; // Must be equal to 1 | 406 Elf_Word e_version; // Must be equal to 1 |
335 Elf_Addr e_entry; // Address to jump to in order to start program | 407 Elf_Addr e_entry; // Address to jump to in order to start program |
(...skipping 25 matching lines...) Expand all Loading... |
361 | 433 |
362 const Elf_Ehdr *Header; | 434 const Elf_Ehdr *Header; |
363 const Elf_Shdr *SectionHeaderTable; | 435 const Elf_Shdr *SectionHeaderTable; |
364 const Elf_Shdr *dot_shstrtab_sec; // Section header string table. | 436 const Elf_Shdr *dot_shstrtab_sec; // Section header string table. |
365 const Elf_Shdr *dot_strtab_sec; // Symbol header string table. | 437 const Elf_Shdr *dot_strtab_sec; // Symbol header string table. |
366 const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. | 438 const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. |
367 Sections_t SymbolTableSections; | 439 Sections_t SymbolTableSections; |
368 IndexMap_t SymbolTableSectionsIndexMap; | 440 IndexMap_t SymbolTableSectionsIndexMap; |
369 DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; | 441 DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; |
370 | 442 |
371 const Elf_Shdr *dot_dynamic_sec; // .dynamic | 443 const Elf_Shdr *dot_dynamic_sec; // .dynamic |
| 444 const Elf_Shdr *dot_gnu_version_sec; // .gnu.version |
| 445 const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r |
| 446 const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d |
| 447 |
372 // Pointer to SONAME entry in dynamic string table | 448 // Pointer to SONAME entry in dynamic string table |
373 // This is set the first time getLoadName is called. | 449 // This is set the first time getLoadName is called. |
374 mutable const char *dt_soname; | 450 mutable const char *dt_soname; |
375 | 451 |
| 452 // Records for each version index the corresponding Verdef or Vernaux entry. |
| 453 // This is filled the first time LoadVersionMap() is called. |
| 454 class VersionMapEntry : public PointerIntPair<const void*, 1> { |
| 455 public: |
| 456 // If the integer is 0, this is an Elf_Verdef*. |
| 457 // If the integer is 1, this is an Elf_Vernaux*. |
| 458 VersionMapEntry() : PointerIntPair<const void*, 1>(NULL, 0) { } |
| 459 VersionMapEntry(const Elf_Verdef *verdef) |
| 460 : PointerIntPair<const void*, 1>(verdef, 0) { } |
| 461 VersionMapEntry(const Elf_Vernaux *vernaux) |
| 462 : PointerIntPair<const void*, 1>(vernaux, 1) { } |
| 463 bool isNull() const { return getPointer() == NULL; } |
| 464 bool isVerdef() const { return !isNull() && getInt() == 0; } |
| 465 bool isVernaux() const { return !isNull() && getInt() == 1; } |
| 466 const Elf_Verdef *getVerdef() const { |
| 467 return isVerdef() ? (const Elf_Verdef*)getPointer() : NULL; |
| 468 } |
| 469 const Elf_Vernaux *getVernaux() const { |
| 470 return isVernaux() ? (const Elf_Vernaux*)getPointer() : NULL; |
| 471 } |
| 472 }; |
| 473 mutable SmallVector<VersionMapEntry, 16> VersionMap; |
| 474 void LoadVersionDefs(const Elf_Shdr *sec) const; |
| 475 void LoadVersionNeeds(const Elf_Shdr *ec) const; |
| 476 void LoadVersionMap() const; |
| 477 |
376 /// @brief Map sections to an array of relocation sections that reference | 478 /// @brief Map sections to an array of relocation sections that reference |
377 /// them sorted by section index. | 479 /// them sorted by section index. |
378 RelocMap_t SectionRelocMap; | 480 RelocMap_t SectionRelocMap; |
379 | 481 |
380 /// @brief Get the relocation section that contains \a Rel. | 482 /// @brief Get the relocation section that contains \a Rel. |
381 const Elf_Shdr *getRelSection(DataRefImpl Rel) const { | 483 const Elf_Shdr *getRelSection(DataRefImpl Rel) const { |
382 return getSection(Rel.w.b); | 484 return getSection(Rel.w.b); |
383 } | 485 } |
384 | 486 |
385 bool isRelocationHasAddend(DataRefImpl Rel) const; | 487 bool isRelocationHasAddend(DataRefImpl Rel) const; |
386 template<typename T> | 488 template<typename T> |
387 const T *getEntry(uint16_t Section, uint32_t Entry) const; | 489 const T *getEntry(uint16_t Section, uint32_t Entry) const; |
388 template<typename T> | 490 template<typename T> |
389 const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; | 491 const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; |
390 const Elf_Shdr *getSection(DataRefImpl index) const; | 492 const Elf_Shdr *getSection(DataRefImpl index) const; |
391 const Elf_Shdr *getSection(uint32_t index) const; | 493 const Elf_Shdr *getSection(uint32_t index) const; |
392 const Elf_Rel *getRel(DataRefImpl Rel) const; | 494 const Elf_Rel *getRel(DataRefImpl Rel) const; |
393 const Elf_Rela *getRela(DataRefImpl Rela) const; | 495 const Elf_Rela *getRela(DataRefImpl Rela) const; |
394 const char *getString(uint32_t section, uint32_t offset) const; | 496 const char *getString(uint32_t section, uint32_t offset) const; |
395 const char *getString(const Elf_Shdr *section, uint32_t offset) const; | 497 const char *getString(const Elf_Shdr *section, uint32_t offset) const; |
396 error_code getSymbolName(const Elf_Shdr *section, | 498 error_code getSymbolName(const Elf_Shdr *section, |
397 const Elf_Sym *Symb, | 499 const Elf_Sym *Symb, |
398 StringRef &Res) const; | 500 StringRef &Res) const; |
| 501 error_code getSymbolVersion(const Elf_Shdr *section, |
| 502 const Elf_Sym *Symb, |
| 503 StringRef &Version, |
| 504 bool &IsDefault) const; |
399 void VerifyStrTab(const Elf_Shdr *sh) const; | 505 void VerifyStrTab(const Elf_Shdr *sh) const; |
400 | 506 |
401 protected: | 507 protected: |
402 const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private
? | 508 const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private
? |
403 void validateSymbol(DataRefImpl Symb) const; | 509 void validateSymbol(DataRefImpl Symb) const; |
404 | 510 |
405 public: | 511 public: |
406 const Elf_Dyn *getDyn(DataRefImpl DynData) const; | 512 const Elf_Dyn *getDyn(DataRefImpl DynData) const; |
407 | 513 error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, |
| 514 bool &IsDefault) const; |
408 protected: | 515 protected: |
409 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; | 516 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; |
410 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; | 517 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; |
411 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; | 518 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; |
412 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; | 519 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; |
413 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; | 520 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; |
414 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; | 521 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; |
415 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; | 522 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; |
416 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const
; | 523 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const
; |
417 virtual error_code getSymbolSection(DataRefImpl Symb, | 524 virtual error_code getSymbolSection(DataRefImpl Symb, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 virtual section_iterator end_sections() const; | 573 virtual section_iterator end_sections() const; |
467 | 574 |
468 virtual library_iterator begin_libraries_needed() const; | 575 virtual library_iterator begin_libraries_needed() const; |
469 virtual library_iterator end_libraries_needed() const; | 576 virtual library_iterator end_libraries_needed() const; |
470 | 577 |
471 virtual dyn_iterator begin_dynamic_table() const; | 578 virtual dyn_iterator begin_dynamic_table() const; |
472 virtual dyn_iterator end_dynamic_table() const; | 579 virtual dyn_iterator end_dynamic_table() const; |
473 | 580 |
474 virtual uint8_t getBytesInAddress() const; | 581 virtual uint8_t getBytesInAddress() const; |
475 virtual StringRef getFileFormatName() const; | 582 virtual StringRef getFileFormatName() const; |
| 583 virtual StringRef getObjectType() const { return "ELF"; } |
476 virtual unsigned getArch() const; | 584 virtual unsigned getArch() const; |
477 virtual StringRef getLoadName() const; | 585 virtual StringRef getLoadName() const; |
478 | 586 |
479 uint64_t getNumSections() const; | 587 uint64_t getNumSections() const; |
480 uint64_t getStringTableIndex() const; | 588 uint64_t getStringTableIndex() const; |
481 ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; | 589 ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; |
482 const Elf_Shdr *getSection(const Elf_Sym *symb) const; | 590 const Elf_Shdr *getSection(const Elf_Sym *symb) const; |
483 | 591 |
484 // Methods for type inquiry through isa, cast, and dyn_cast | 592 // Methods for type inquiry through isa, cast, and dyn_cast |
485 bool isDyldType() const { return isDyldELFObject; } | 593 bool isDyldType() const { return isDyldELFObject; } |
486 static inline bool classof(const Binary *v) { | 594 static inline bool classof(const Binary *v) { |
487 return v->getType() == Binary::isELF; | 595 return v->getType() == Binary::isELF; |
488 } | 596 } |
489 static inline bool classof(const ELFObjectFile *v) { return true; } | 597 static inline bool classof(const ELFObjectFile *v) { return true; } |
490 }; | 598 }; |
491 | 599 |
| 600 // Iterate through the version definitions, and place each Elf_Verdef |
| 601 // in the VersionMap according to its index. |
| 602 template<support::endianness target_endianness, bool is64Bits> |
| 603 void ELFObjectFile<target_endianness, is64Bits>:: |
| 604 LoadVersionDefs(const Elf_Shdr *sec) const { |
| 605 unsigned vd_size = sec->sh_size; // Size of section in bytes |
| 606 unsigned vd_count = sec->sh_info; // Number of Verdef entries |
| 607 const char *sec_start = (const char*)base() + sec->sh_offset; |
| 608 const char *sec_end = sec_start + vd_size; |
| 609 // The first Verdef entry is at the start of the section. |
| 610 const char *p = sec_start; |
| 611 for (unsigned i = 0; i < vd_count; i++) { |
| 612 if (p + sizeof(Elf_Verdef) > sec_end) |
| 613 report_fatal_error("Section ended unexpectedly while scanning " |
| 614 "version definitions."); |
| 615 const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p); |
| 616 if (vd->vd_version != ELF::VER_DEF_CURRENT) |
| 617 report_fatal_error("Unexpected verdef version"); |
| 618 size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; |
| 619 if (index >= VersionMap.size()) |
| 620 VersionMap.resize(index+1); |
| 621 VersionMap[index] = VersionMapEntry(vd); |
| 622 p += vd->vd_next; |
| 623 } |
| 624 } |
| 625 |
| 626 // Iterate through the versions needed section, and place each Elf_Vernaux |
| 627 // in the VersionMap according to its index. |
| 628 template<support::endianness target_endianness, bool is64Bits> |
| 629 void ELFObjectFile<target_endianness, is64Bits>:: |
| 630 LoadVersionNeeds(const Elf_Shdr *sec) const { |
| 631 unsigned vn_size = sec->sh_size; // Size of section in bytes |
| 632 unsigned vn_count = sec->sh_info; // Number of Verneed entries |
| 633 const char *sec_start = (const char*)base() + sec->sh_offset; |
| 634 const char *sec_end = sec_start + vn_size; |
| 635 // The first Verneed entry is at the start of the section. |
| 636 const char *p = sec_start; |
| 637 for (unsigned i = 0; i < vn_count; i++) { |
| 638 if (p + sizeof(Elf_Verneed) > sec_end) |
| 639 report_fatal_error("Section ended unexpectedly while scanning " |
| 640 "version needed records."); |
| 641 const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p); |
| 642 if (vn->vn_version != ELF::VER_NEED_CURRENT) |
| 643 report_fatal_error("Unexpected verneed version"); |
| 644 // Iterate through the Vernaux entries |
| 645 const char *paux = p + vn->vn_aux; |
| 646 for (unsigned j = 0; j < vn->vn_cnt; j++) { |
| 647 if (paux + sizeof(Elf_Vernaux) > sec_end) |
| 648 report_fatal_error("Section ended unexpected while scanning auxiliary " |
| 649 "version needed records."); |
| 650 const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux); |
| 651 size_t index = vna->vna_other & ELF::VERSYM_VERSION; |
| 652 if (index >= VersionMap.size()) |
| 653 VersionMap.resize(index+1); |
| 654 VersionMap[index] = VersionMapEntry(vna); |
| 655 paux += vna->vna_next; |
| 656 } |
| 657 p += vn->vn_next; |
| 658 } |
| 659 } |
| 660 |
| 661 template<support::endianness target_endianness, bool is64Bits> |
| 662 void ELFObjectFile<target_endianness, is64Bits>::LoadVersionMap() const { |
| 663 // If there is no dynamic symtab or version table, there is nothing to do. |
| 664 if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) |
| 665 return; |
| 666 |
| 667 // Has the VersionMap already been loaded? |
| 668 if (VersionMap.size() > 0) |
| 669 return; |
| 670 |
| 671 // The first two version indexes are reserved. |
| 672 // Index 0 is LOCAL, index 1 is GLOBAL. |
| 673 VersionMap.push_back(VersionMapEntry()); |
| 674 VersionMap.push_back(VersionMapEntry()); |
| 675 |
| 676 if (dot_gnu_version_d_sec) |
| 677 LoadVersionDefs(dot_gnu_version_d_sec); |
| 678 |
| 679 if (dot_gnu_version_r_sec) |
| 680 LoadVersionNeeds(dot_gnu_version_r_sec); |
| 681 } |
| 682 |
492 template<support::endianness target_endianness, bool is64Bits> | 683 template<support::endianness target_endianness, bool is64Bits> |
493 void ELFObjectFile<target_endianness, is64Bits> | 684 void ELFObjectFile<target_endianness, is64Bits> |
494 ::validateSymbol(DataRefImpl Symb) const { | 685 ::validateSymbol(DataRefImpl Symb) const { |
495 const Elf_Sym *symb = getSymbol(Symb); | 686 const Elf_Sym *symb = getSymbol(Symb); |
496 const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; | 687 const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; |
497 // FIXME: We really need to do proper error handling in the case of an invalid | 688 // FIXME: We really need to do proper error handling in the case of an invalid |
498 // input file. Because we don't use exceptions, I think we'll just pass | 689 // input file. Because we don't use exceptions, I think we'll just pass |
499 // an error object around. | 690 // an error object around. |
500 if (!( symb | 691 if (!( symb |
501 && SymbolTableSection | 692 && SymbolTableSection |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 template<support::endianness target_endianness, bool is64Bits> | 730 template<support::endianness target_endianness, bool is64Bits> |
540 error_code ELFObjectFile<target_endianness, is64Bits> | 731 error_code ELFObjectFile<target_endianness, is64Bits> |
541 ::getSymbolName(DataRefImpl Symb, | 732 ::getSymbolName(DataRefImpl Symb, |
542 StringRef &Result) const { | 733 StringRef &Result) const { |
543 validateSymbol(Symb); | 734 validateSymbol(Symb); |
544 const Elf_Sym *symb = getSymbol(Symb); | 735 const Elf_Sym *symb = getSymbol(Symb); |
545 return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); | 736 return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); |
546 } | 737 } |
547 | 738 |
548 template<support::endianness target_endianness, bool is64Bits> | 739 template<support::endianness target_endianness, bool is64Bits> |
| 740 error_code ELFObjectFile<target_endianness, is64Bits> |
| 741 ::getSymbolVersion(SymbolRef SymRef, |
| 742 StringRef &Version, |
| 743 bool &IsDefault) const { |
| 744 DataRefImpl Symb = SymRef.getRawDataRefImpl(); |
| 745 validateSymbol(Symb); |
| 746 const Elf_Sym *symb = getSymbol(Symb); |
| 747 return getSymbolVersion(SymbolTableSections[Symb.d.b], symb, |
| 748 Version, IsDefault); |
| 749 } |
| 750 |
| 751 template<support::endianness target_endianness, bool is64Bits> |
549 ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits> | 752 ELF::Elf64_Word ELFObjectFile<target_endianness, is64Bits> |
550 ::getSymbolTableIndex(const Elf_Sym *symb) const { | 753 ::getSymbolTableIndex(const Elf_Sym *symb) const { |
551 if (symb->st_shndx == ELF::SHN_XINDEX) | 754 if (symb->st_shndx == ELF::SHN_XINDEX) |
552 return ExtendedSymbolTable.lookup(symb); | 755 return ExtendedSymbolTable.lookup(symb); |
553 return symb->st_shndx; | 756 return symb->st_shndx; |
554 } | 757 } |
555 | 758 |
556 template<support::endianness target_endianness, bool is64Bits> | 759 template<support::endianness target_endianness, bool is64Bits> |
557 const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * | 760 const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Shdr * |
558 ELFObjectFile<target_endianness, is64Bits> | 761 ELFObjectFile<target_endianness, is64Bits> |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 template<support::endianness target_endianness, bool is64Bits> | 1460 template<support::endianness target_endianness, bool is64Bits> |
1258 ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object | 1461 ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object |
1259 , error_code &ec) | 1462 , error_code &ec) |
1260 : ObjectFile(Binary::isELF, Object, ec) | 1463 : ObjectFile(Binary::isELF, Object, ec) |
1261 , isDyldELFObject(false) | 1464 , isDyldELFObject(false) |
1262 , SectionHeaderTable(0) | 1465 , SectionHeaderTable(0) |
1263 , dot_shstrtab_sec(0) | 1466 , dot_shstrtab_sec(0) |
1264 , dot_strtab_sec(0) | 1467 , dot_strtab_sec(0) |
1265 , dot_dynstr_sec(0) | 1468 , dot_dynstr_sec(0) |
1266 , dot_dynamic_sec(0) | 1469 , dot_dynamic_sec(0) |
1267 , dt_soname(0) { | 1470 , dot_gnu_version_sec(0) |
| 1471 , dot_gnu_version_r_sec(0) |
| 1472 , dot_gnu_version_d_sec(0) |
| 1473 , dt_soname(0) |
| 1474 { |
1268 | 1475 |
1269 const uint64_t FileSize = Data->getBufferSize(); | 1476 const uint64_t FileSize = Data->getBufferSize(); |
1270 | 1477 |
1271 if (sizeof(Elf_Ehdr) > FileSize) | 1478 if (sizeof(Elf_Ehdr) > FileSize) |
1272 // FIXME: Proper error handling. | 1479 // FIXME: Proper error handling. |
1273 report_fatal_error("File too short!"); | 1480 report_fatal_error("File too short!"); |
1274 | 1481 |
1275 Header = reinterpret_cast<const Elf_Ehdr *>(base()); | 1482 Header = reinterpret_cast<const Elf_Ehdr *>(base()); |
1276 | 1483 |
1277 if (Header->e_shoff == 0) | 1484 if (Header->e_shoff == 0) |
(...skipping 15 matching lines...) Expand all Loading... |
1293 report_fatal_error("Section table goes past end of file!"); | 1500 report_fatal_error("Section table goes past end of file!"); |
1294 | 1501 |
1295 // To find the symbol tables we walk the section table to find SHT_SYMTAB. | 1502 // To find the symbol tables we walk the section table to find SHT_SYMTAB. |
1296 const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; | 1503 const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; |
1297 const Elf_Shdr* sh = SectionHeaderTable; | 1504 const Elf_Shdr* sh = SectionHeaderTable; |
1298 | 1505 |
1299 // Reserve SymbolTableSections[0] for .dynsym | 1506 // Reserve SymbolTableSections[0] for .dynsym |
1300 SymbolTableSections.push_back(NULL); | 1507 SymbolTableSections.push_back(NULL); |
1301 | 1508 |
1302 for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { | 1509 for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { |
1303 if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) { | 1510 switch (sh->sh_type) { |
| 1511 case ELF::SHT_SYMTAB_SHNDX: { |
1304 if (SymbolTableSectionHeaderIndex) | 1512 if (SymbolTableSectionHeaderIndex) |
1305 // FIXME: Proper error handling. | 1513 // FIXME: Proper error handling. |
1306 report_fatal_error("More than one .symtab_shndx!"); | 1514 report_fatal_error("More than one .symtab_shndx!"); |
1307 SymbolTableSectionHeaderIndex = sh; | 1515 SymbolTableSectionHeaderIndex = sh; |
| 1516 break; |
1308 } | 1517 } |
1309 if (sh->sh_type == ELF::SHT_SYMTAB) { | 1518 case ELF::SHT_SYMTAB: { |
1310 SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); | 1519 SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); |
1311 SymbolTableSections.push_back(sh); | 1520 SymbolTableSections.push_back(sh); |
| 1521 break; |
1312 } | 1522 } |
1313 if (sh->sh_type == ELF::SHT_DYNSYM) { | 1523 case ELF::SHT_DYNSYM: { |
1314 if (SymbolTableSections[0] != NULL) | 1524 if (SymbolTableSections[0] != NULL) |
1315 // FIXME: Proper error handling. | 1525 // FIXME: Proper error handling. |
1316 report_fatal_error("More than one .dynsym!"); | 1526 report_fatal_error("More than one .dynsym!"); |
1317 SymbolTableSectionsIndexMap[i] = 0; | 1527 SymbolTableSectionsIndexMap[i] = 0; |
1318 SymbolTableSections[0] = sh; | 1528 SymbolTableSections[0] = sh; |
| 1529 break; |
1319 } | 1530 } |
1320 if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { | 1531 case ELF::SHT_REL: |
| 1532 case ELF::SHT_RELA: { |
1321 SectionRelocMap[getSection(sh->sh_info)].push_back(i); | 1533 SectionRelocMap[getSection(sh->sh_info)].push_back(i); |
| 1534 break; |
1322 } | 1535 } |
1323 if (sh->sh_type == ELF::SHT_DYNAMIC) { | 1536 case ELF::SHT_DYNAMIC: { |
1324 if (dot_dynamic_sec != NULL) | 1537 if (dot_dynamic_sec != NULL) |
1325 // FIXME: Proper error handling. | 1538 // FIXME: Proper error handling. |
1326 report_fatal_error("More than one .dynamic!"); | 1539 report_fatal_error("More than one .dynamic!"); |
1327 dot_dynamic_sec = sh; | 1540 dot_dynamic_sec = sh; |
| 1541 break; |
| 1542 } |
| 1543 case ELF::SHT_GNU_versym: { |
| 1544 if (dot_gnu_version_sec != NULL) |
| 1545 // FIXME: Proper error handling. |
| 1546 report_fatal_error("More than one .gnu.version section!"); |
| 1547 dot_gnu_version_sec = sh; |
| 1548 break; |
| 1549 } |
| 1550 case ELF::SHT_GNU_verdef: { |
| 1551 if (dot_gnu_version_d_sec != NULL) |
| 1552 // FIXME: Proper error handling. |
| 1553 report_fatal_error("More than one .gnu.version_d section!"); |
| 1554 dot_gnu_version_d_sec = sh; |
| 1555 break; |
| 1556 } |
| 1557 case ELF::SHT_GNU_verneed: { |
| 1558 if (dot_gnu_version_r_sec != NULL) |
| 1559 // FIXME: Proper error handling. |
| 1560 report_fatal_error("More than one .gnu.version_r section!"); |
| 1561 dot_gnu_version_r_sec = sh; |
| 1562 break; |
| 1563 } |
1328 } | 1564 } |
1329 ++sh; | 1565 ++sh; |
1330 } | 1566 } |
1331 | 1567 |
1332 // Sort section relocation lists by index. | 1568 // Sort section relocation lists by index. |
1333 for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), | 1569 for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), |
1334 e = SectionRelocMap.end(); i != e; ++i) { | 1570 e = SectionRelocMap.end(); i != e; ++i) { |
1335 std::sort(i->second.begin(), i->second.end()); | 1571 std::sort(i->second.begin(), i->second.end()); |
1336 } | 1572 } |
1337 | 1573 |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 // Symbol is in .dynsym, use .dynstr string table | 2003 // Symbol is in .dynsym, use .dynstr string table |
1768 Result = getString(dot_dynstr_sec, symb->st_name); | 2004 Result = getString(dot_dynstr_sec, symb->st_name); |
1769 } else { | 2005 } else { |
1770 // Use the default symbol table name section. | 2006 // Use the default symbol table name section. |
1771 Result = getString(dot_strtab_sec, symb->st_name); | 2007 Result = getString(dot_strtab_sec, symb->st_name); |
1772 } | 2008 } |
1773 return object_error::success; | 2009 return object_error::success; |
1774 } | 2010 } |
1775 | 2011 |
1776 template<support::endianness target_endianness, bool is64Bits> | 2012 template<support::endianness target_endianness, bool is64Bits> |
| 2013 error_code ELFObjectFile<target_endianness, is64Bits> |
| 2014 ::getSymbolVersion(const Elf_Shdr *section, |
| 2015 const Elf_Sym *symb, |
| 2016 StringRef &Version, |
| 2017 bool &IsDefault) const { |
| 2018 // Handle non-dynamic symbols. |
| 2019 if (section != SymbolTableSections[0]) { |
| 2020 // Non-dynamic symbols can have versions in their names |
| 2021 // A name of the form 'foo@V1' indicates version 'V1', non-default. |
| 2022 // A name of the form 'foo@@V2' indicates version 'V2', default version. |
| 2023 StringRef Name; |
| 2024 error_code ec = getSymbolName(section, symb, Name); |
| 2025 if (ec != object_error::success) |
| 2026 return ec; |
| 2027 size_t atpos = Name.find('@'); |
| 2028 if (atpos == StringRef::npos) { |
| 2029 Version = ""; |
| 2030 IsDefault = false; |
| 2031 return object_error::success; |
| 2032 } |
| 2033 ++atpos; |
| 2034 if (atpos < Name.size() && Name[atpos] == '@') { |
| 2035 IsDefault = true; |
| 2036 ++atpos; |
| 2037 } else { |
| 2038 IsDefault = false; |
| 2039 } |
| 2040 Version = Name.substr(atpos); |
| 2041 return object_error::success; |
| 2042 } |
| 2043 |
| 2044 // This is a dynamic symbol. Look in the GNU symbol version table. |
| 2045 if (dot_gnu_version_sec == NULL) { |
| 2046 // No version table. |
| 2047 Version = ""; |
| 2048 IsDefault = false; |
| 2049 return object_error::success; |
| 2050 } |
| 2051 |
| 2052 // Determine the position in the symbol table of this entry. |
| 2053 const char *sec_start = (const char*)base() + section->sh_offset; |
| 2054 size_t entry_index = ((const char*)symb - sec_start)/section->sh_entsize; |
| 2055 |
| 2056 // Get the corresponding version index entry |
| 2057 const Elf_Versym *vs = getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index); |
| 2058 size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; |
| 2059 |
| 2060 // Special markers for unversioned symbols. |
| 2061 if (version_index == ELF::VER_NDX_LOCAL || |
| 2062 version_index == ELF::VER_NDX_GLOBAL) { |
| 2063 Version = ""; |
| 2064 IsDefault = false; |
| 2065 return object_error::success; |
| 2066 } |
| 2067 |
| 2068 // Lookup this symbol in the version table |
| 2069 LoadVersionMap(); |
| 2070 if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) |
| 2071 report_fatal_error("Symbol has version index without corresponding " |
| 2072 "define or reference entry"); |
| 2073 const VersionMapEntry &entry = VersionMap[version_index]; |
| 2074 |
| 2075 // Get the version name string |
| 2076 size_t name_offset; |
| 2077 if (entry.isVerdef()) { |
| 2078 // The first Verdaux entry holds the name. |
| 2079 name_offset = entry.getVerdef()->getAux()->vda_name; |
| 2080 } else { |
| 2081 name_offset = entry.getVernaux()->vna_name; |
| 2082 } |
| 2083 Version = getString(dot_dynstr_sec, name_offset); |
| 2084 |
| 2085 // Set IsDefault |
| 2086 if (entry.isVerdef()) { |
| 2087 IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN); |
| 2088 } else { |
| 2089 IsDefault = false; |
| 2090 } |
| 2091 |
| 2092 return object_error::success; |
| 2093 } |
| 2094 |
| 2095 template<support::endianness target_endianness, bool is64Bits> |
1777 inline DynRefImpl<target_endianness, is64Bits> | 2096 inline DynRefImpl<target_endianness, is64Bits> |
1778 ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) | 2097 ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) |
1779 : DynPimpl(DynP) | 2098 : DynPimpl(DynP) |
1780 , OwningObject(Owner) {} | 2099 , OwningObject(Owner) {} |
1781 | 2100 |
1782 template<support::endianness target_endianness, bool is64Bits> | 2101 template<support::endianness target_endianness, bool is64Bits> |
1783 inline bool DynRefImpl<target_endianness, is64Bits> | 2102 inline bool DynRefImpl<target_endianness, is64Bits> |
1784 ::operator==(const DynRefImpl &Other) const { | 2103 ::operator==(const DynRefImpl &Other) const { |
1785 return DynPimpl == Other.DynPimpl; | 2104 return DynPimpl == Other.DynPimpl; |
1786 } | 2105 } |
(...skipping 27 matching lines...) Expand all Loading... |
1814 ::getPtr() const { | 2133 ::getPtr() const { |
1815 return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; | 2134 return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; |
1816 } | 2135 } |
1817 | 2136 |
1818 template<support::endianness target_endianness, bool is64Bits> | 2137 template<support::endianness target_endianness, bool is64Bits> |
1819 inline DataRefImpl DynRefImpl<target_endianness, is64Bits> | 2138 inline DataRefImpl DynRefImpl<target_endianness, is64Bits> |
1820 ::getRawDataRefImpl() const { | 2139 ::getRawDataRefImpl() const { |
1821 return DynPimpl; | 2140 return DynPimpl; |
1822 } | 2141 } |
1823 | 2142 |
| 2143 /// This is a generic interface for retrieving GNU symbol version |
| 2144 /// information from an ELFObjectFile. |
| 2145 static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, |
| 2146 const SymbolRef &Sym, |
| 2147 StringRef &Version, |
| 2148 bool &IsDefault) { |
| 2149 // Little-endian 32-bit |
| 2150 if (const ELFObjectFile<support::little, false> *ELFObj = |
| 2151 dyn_cast<ELFObjectFile<support::little, false> >(Obj)) |
| 2152 return ELFObj->getSymbolVersion(Sym, Version, IsDefault); |
| 2153 |
| 2154 // Big-endian 32-bit |
| 2155 if (const ELFObjectFile<support::big, false> *ELFObj = |
| 2156 dyn_cast<ELFObjectFile<support::big, false> >(Obj)) |
| 2157 return ELFObj->getSymbolVersion(Sym, Version, IsDefault); |
| 2158 |
| 2159 // Little-endian 64-bit |
| 2160 if (const ELFObjectFile<support::little, true> *ELFObj = |
| 2161 dyn_cast<ELFObjectFile<support::little, true> >(Obj)) |
| 2162 return ELFObj->getSymbolVersion(Sym, Version, IsDefault); |
| 2163 |
| 2164 // Big-endian 64-bit |
| 2165 if (const ELFObjectFile<support::big, true> *ELFObj = |
| 2166 dyn_cast<ELFObjectFile<support::big, true> >(Obj)) |
| 2167 return ELFObj->getSymbolVersion(Sym, Version, IsDefault); |
| 2168 |
| 2169 llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); |
| 2170 } |
| 2171 |
1824 } | 2172 } |
1825 } | 2173 } |
1826 | 2174 |
1827 #endif | 2175 #endif |
OLD | NEW |