Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: include/llvm/Object/ELF.h

Issue 9546035: Support reading GNU symbol versions in ELFObjectFile (Closed) Base URL: https://llvm.org/svn/llvm-project/llvm/trunk/
Patch Set: fixed #defines Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | include/llvm/Support/ELF.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | include/llvm/Support/ELF.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698