llvm.org GIT mirror llvm / 945bc5b
[Object][ELF] Devirtualize and simplify dynamic table iteration. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174566 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 7 years ago
1 changed file(s) with 81 addition(s) and 193 deletion(s). Raw diff Collapse all Expand all
316316 int64_t getTag() const { return d_tag; }
317317 uint64_t getVal() const { return d_un.d_val; }
318318 uint64_t getPtr() const { return d_un.ptr; }
319 };
320
321 template
322 class ELFObjectFile;
323
324 // DynRefImpl: Reference to an entry in the dynamic table
325 // This is an ELF-specific interface.
326 template
327 class DynRefImpl {
328 typedef Elf_Dyn_Impl Elf_Dyn;
329 typedef ELFObjectFile OwningType;
330
331 DataRefImpl DynPimpl;
332 const OwningType *OwningObject;
333
334 public:
335 DynRefImpl() : OwningObject(NULL) { }
336
337 DynRefImpl(DataRefImpl DynP, const OwningType *Owner);
338
339 bool operator==(const DynRefImpl &Other) const;
340 bool operator <(const DynRefImpl &Other) const;
341
342 error_code getNext(DynRefImpl &Result) const;
343 int64_t getTag() const;
344 uint64_t getVal() const;
345 uint64_t getPtr() const;
346
347 DataRefImpl getRawDataRefImpl() const;
348319 };
349320
350321 // Elf_Rel: Elf Relocation
494465 class ELFObjectFile : public ObjectFile {
495466 LLVM_ELF_IMPORT_TYPES(ELFT)
496467
468 public:
469 /// \brief Iterate over constant sized entities.
470 template
471 class ELFEntityIterator {
472 public:
473 typedef void difference_type;
474 typedef EntT value_type;
475 typedef std::forward_iterator_tag iterator_category;
476 typedef value_type &reference;
477 typedef value_type *pointer;
478
479 /// \brief Default construct iterator.
480 ELFEntityIterator() : EntitySize(0), Current(0) {}
481 ELFEntityIterator(uint64_t EntSize, const char *Start)
482 : EntitySize(EntSize)
483 , Current(Start) {}
484
485 reference operator *() {
486 assert(Current && "Attempted to dereference an invalid iterator!");
487 return *reinterpret_cast(Current);
488 }
489
490 pointer operator ->() {
491 assert(Current && "Attempted to dereference an invalid iterator!");
492 return reinterpret_cast(Current);
493 }
494
495 bool operator ==(const ELFEntityIterator &Other) {
496 return Current == Other.Current;
497 }
498
499 bool operator !=(const ELFEntityIterator &Other) {
500 return !(*this == Other);
501 }
502
503 ELFEntityIterator &operator ++() {
504 assert(Current && "Attempted to increment an invalid iterator!");
505 Current += EntitySize;
506 return *this;
507 }
508
509 ELFEntityIterator operator ++(int) {
510 ELFEntityIterator Tmp = *this;
511 ++*this;
512 return Tmp;
513 }
514
515 private:
516 const uint64_t EntitySize;
517 const char *Current;
518 };
519
520 private:
497521 typedef Elf_Ehdr_Impl Elf_Ehdr;
498522 typedef Elf_Shdr_Impl Elf_Shdr;
499523 typedef Elf_Sym_Impl Elf_Sym;
506530 typedef Elf_Verneed_Impl Elf_Verneed;
507531 typedef Elf_Vernaux_Impl Elf_Vernaux;
508532 typedef Elf_Versym_Impl Elf_Versym;
509 typedef DynRefImpl DynRef;
510 typedef content_iterator> dyn_iterator;
533 typedef ELFEntityIterator> dyn_iterator;
511534
512535 protected:
513536 // This flag is used for classof, to distinguish ELFObjectFile from
540563 // Pointer to SONAME entry in dynamic string table
541564 // This is set the first time getLoadName is called.
542565 mutable const char *dt_soname;
543
544 public:
545 /// \brief Iterate over constant sized entities.
546 template
547 class ELFEntityIterator {
548 public:
549 typedef void difference_type;
550 typedef EntT value_type;
551 typedef std::forward_iterator_tag iterator_category;
552 typedef value_type &reference;
553 typedef value_type *pointer;
554
555 /// \brief Default construct iterator.
556 ELFEntityIterator() : EntitySize(0), Current(0) {}
557 ELFEntityIterator(uint64_t EntSize, const char *Start)
558 : EntitySize(EntSize)
559 , Current(Start) {}
560
561 reference operator *() {
562 assert(Current && "Attempted to dereference an invalid iterator!");
563 return *reinterpret_cast(Current);
564 }
565
566 pointer operator ->() {
567 assert(Current && "Attempted to dereference an invalid iterator!");
568 return reinterpret_cast(Current);
569 }
570
571 bool operator ==(const ELFEntityIterator &Other) {
572 return Current == Other.Current;
573 }
574
575 bool operator !=(const ELFEntityIterator &Other) {
576 return !(*this == Other);
577 }
578
579 ELFEntityIterator &operator ++() {
580 assert(Current && "Attempted to increment an invalid iterator!");
581 Current += EntitySize;
582 return *this;
583 }
584
585 ELFEntityIterator operator ++(int) {
586 ELFEntityIterator Tmp = *this;
587 ++*this;
588 return Tmp;
589 }
590
591 private:
592 const uint64_t EntitySize;
593 const char *Current;
594 };
595566
596567 private:
597568 // Records for each version index the corresponding Verdef or Vernaux entry.
672643 virtual error_code getSymbolSection(DataRefImpl Symb,
673644 section_iterator &Res) const;
674645 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
675
676 friend class DynRefImpl;
677 virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const;
678646
679647 virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const;
680648 virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const;
22762244 template
22772245 typename ELFObjectFile::dyn_iterator
22782246 ELFObjectFile::begin_dynamic_table() const {
2279 DataRefImpl DynData;
2280 if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) {
2281 DynData.d.a = std::numeric_limits::max();
2282 } else {
2283 DynData.d.a = 0;
2284 }
2285 return dyn_iterator(DynRef(DynData, this));
2247 if (dot_dynamic_sec)
2248 return dyn_iterator(dot_dynamic_sec->sh_entsize, (const char *)base() + dot_dynamic_sec->sh_offset);
2249 return dyn_iterator(0, 0);
22862250 }
22872251
22882252 template
22892253 typename ELFObjectFile::dyn_iterator
22902254 ELFObjectFile::end_dynamic_table() const {
2291 DataRefImpl DynData;
2292 DynData.d.a = std::numeric_limits::max();
2293 return dyn_iterator(DynRef(DynData, this));
2294 }
2295
2296 template
2297 error_code ELFObjectFile::getDynNext(DataRefImpl DynData,
2298 DynRef &Result) const {
2299 ++DynData.d.a;
2300
2301 // Check to see if we are at the end of .dynamic
2302 if (DynData.d.a >= dot_dynamic_sec->getEntityCount()) {
2303 // We are at the end. Return the terminator.
2304 DynData.d.a = std::numeric_limits::max();
2305 }
2306
2307 Result = DynRef(DynData, this);
2308 return object_error::success;
2309 }
2310
2311 template
2312 StringRef
2313 ELFObjectFile::getLoadName() const {
2255 if (dot_dynamic_sec)
2256 return dyn_iterator(dot_dynamic_sec->sh_entsize, (const char *)base() + dot_dynamic_sec->sh_offset + dot_dynamic_sec->sh_size);
2257 return dyn_iterator(0, 0);
2258 }
2259
2260 template
2261 StringRef ELFObjectFile::getLoadName() const {
23142262 if (!dt_soname) {
23152263 // Find the DT_SONAME entry
23162264 dyn_iterator it = begin_dynamic_table();
23172265 dyn_iterator ie = end_dynamic_table();
2318 error_code ec;
2319 while (it != ie) {
2266 for (; it != ie; ++it) {
23202267 if (it->getTag() == ELF::DT_SONAME)
23212268 break;
2322 it.increment(ec);
2323 if (ec)
2324 report_fatal_error("dynamic table iteration failed");
23252269 }
23262270 if (it != ie) {
23272271 if (dot_dynstr_sec == NULL)
23392283 // Find the first DT_NEEDED entry
23402284 dyn_iterator i = begin_dynamic_table();
23412285 dyn_iterator e = end_dynamic_table();
2342 error_code ec;
23432286 while (i != e) {
23442287 if (i->getTag() == ELF::DT_NEEDED)
23452288 break;
2346 i.increment(ec);
2347 if (ec)
2348 report_fatal_error("dynamic table iteration failed");
2349 }
2350 // Use the same DataRefImpl format as DynRef.
2351 return library_iterator(LibraryRef(i->getRawDataRefImpl(), this));
2289 }
2290
2291 DataRefImpl DRI;
2292 DRI.p = reinterpret_cast(&*i);
2293 return library_iterator(LibraryRef(DRI, this));
23522294 }
23532295
23542296 template
23552297 error_code ELFObjectFile::getLibraryNext(DataRefImpl Data,
23562298 LibraryRef &Result) const {
23572299 // Use the same DataRefImpl format as DynRef.
2358 dyn_iterator i = dyn_iterator(DynRef(Data, this));
2300 dyn_iterator i = dyn_iterator(dot_dynamic_sec->sh_entsize, reinterpret_cast(Data.p));
23592301 dyn_iterator e = end_dynamic_table();
23602302
23612303 // Skip the current dynamic table entry.
2362 error_code ec;
2363 if (i != e) {
2364 i.increment(ec);
2365 // TODO: proper error handling
2366 if (ec)
2367 report_fatal_error("dynamic table iteration failed");
2368 }
2304 ++i;
23692305
23702306 // Find the next DT_NEEDED entry.
2371 while (i != e) {
2372 if (i->getTag() == ELF::DT_NEEDED)
2373 break;
2374 i.increment(ec);
2375 if (ec)
2376 report_fatal_error("dynamic table iteration failed");
2377 }
2378 Result = LibraryRef(i->getRawDataRefImpl(), this);
2307 for (; i != e && i->getTag() != ELF::DT_NEEDED; ++i);
2308
2309 DataRefImpl DRI;
2310 DRI.p = reinterpret_cast(&*i);
2311 Result = LibraryRef(DRI, this);
23792312 return object_error::success;
23802313 }
23812314
23822315 template
23832316 error_code ELFObjectFile::getLibraryPath(DataRefImpl Data,
23842317 StringRef &Res) const {
2385 dyn_iterator i = dyn_iterator(DynRef(Data, this));
2318 dyn_iterator i = dyn_iterator(dot_dynamic_sec->sh_entsize, reinterpret_cast(Data.p));
23862319 if (i == end_dynamic_table())
23872320 report_fatal_error("getLibraryPath() called on iterator end");
23882321
24032336 template
24042337 library_iterator ELFObjectFile::end_libraries_needed() const {
24052338 dyn_iterator e = end_dynamic_table();
2406 // Use the same DataRefImpl format as DynRef.
2407 return library_iterator(LibraryRef(e->getRawDataRefImpl(), this));
2339 DataRefImpl DRI;
2340 DRI.p = reinterpret_cast(&*e);
2341 return library_iterator(LibraryRef(DRI, this));
24082342 }
24092343
24102344 template
25182452 }
25192453
25202454 template
2521 const typename ELFObjectFile::Elf_Dyn *
2522 ELFObjectFile::getDyn(DataRefImpl DynData) const {
2523 return getEntry(dot_dynamic_sec, DynData.d.a);
2524 }
2525
2526 template
25272455 const typename ELFObjectFile::Elf_Rel *
25282456 ELFObjectFile::getRel(DataRefImpl Rel) const {
25292457 return getEntry(Rel.w.b, Rel.w.c);
26872615 return object_error::success;
26882616 }
26892617
2690 template
2691 inline DynRefImpl::DynRefImpl(DataRefImpl DynP, const OwningType *Owner)
2692 : DynPimpl(DynP)
2693 , OwningObject(Owner) {}
2694
2695 template
2696 inline bool DynRefImpl::operator==(const DynRefImpl &Other) const {
2697 return DynPimpl == Other.DynPimpl;
2698 }
2699
2700 template
2701 inline bool DynRefImpl::operator <(const DynRefImpl &Other) const {
2702 return DynPimpl < Other.DynPimpl;
2703 }
2704
2705 template
2706 inline error_code DynRefImpl::getNext(DynRefImpl &Result) const {
2707 return OwningObject->getDynNext(DynPimpl, Result);
2708 }
2709
2710 template
2711 inline int64_t DynRefImpl::getTag() const {
2712 return OwningObject->getDyn(DynPimpl)->d_tag;
2713 }
2714
2715 template
2716 inline uint64_t DynRefImpl::getVal() const {
2717 return OwningObject->getDyn(DynPimpl)->d_un.d_val;
2718 }
2719
2720 template
2721 inline uint64_t DynRefImpl::getPtr() const {
2722 return OwningObject->getDyn(DynPimpl)->d_un.d_ptr;
2723 }
2724
2725 template
2726 inline DataRefImpl DynRefImpl::getRawDataRefImpl() const {
2727 return DynPimpl;
2728 }
2729
27302618 /// This is a generic interface for retrieving GNU symbol version
27312619 /// information from an ELFObjectFile.
27322620 static inline error_code GetELFSymbolVersion(const ObjectFile *Obj,