diff options
author | David Meyer <pdox@google.com> | 2012-03-01 01:36:50 +0000 |
---|---|---|
committer | David Meyer <pdox@google.com> | 2012-03-01 01:36:50 +0000 |
commit | 5c2b4ea73c8f48bb5f96c86fe437385b8fb3dcda (patch) | |
tree | e62d2d345c810a0aaf0a561192a31079c5acb5b6 /include | |
parent | 741981adf3a2bc0c6652c9c4ec846250950f3e68 (diff) | |
download | external_llvm-5c2b4ea73c8f48bb5f96c86fe437385b8fb3dcda.zip external_llvm-5c2b4ea73c8f48bb5f96c86fe437385b8fb3dcda.tar.gz external_llvm-5c2b4ea73c8f48bb5f96c86fe437385b8fb3dcda.tar.bz2 |
[Object]
* Add begin_dynamic_table() / end_dynamic_table() private interface to ELFObjectFile.
* Add begin_libraries_needed() / end_libraries_needed() interface to ObjectFile, for grabbing the list of needed libraries for a shared object or dynamic executable.
* Implement this new interface completely for ELF, leave stubs for COFF and MachO.
* Add 'llvm-readobj' tool for dumping ObjectFile information.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/Object/COFF.h | 7 | ||||
-rw-r--r-- | include/llvm/Object/ELF.h | 265 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 5 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 54 |
4 files changed, 330 insertions, 1 deletions
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 7321412..6212785 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -145,12 +145,19 @@ protected: virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; + virtual error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const; + virtual error_code getLibraryPath(DataRefImpl LibData, + StringRef &Result) const; + public: COFFObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual symbol_iterator begin_dynamic_symbols() const; virtual symbol_iterator end_dynamic_symbols() const; + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 6e3fa01..ce002f2 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -176,6 +176,71 @@ struct Elf_Sym_Impl : Elf_Sym_Base<target_endianness, is64Bits> { } }; +// Elf_Dyn: Entry in the dynamic table +template<support::endianness target_endianness, bool is64Bits> +struct Elf_Dyn_Base; + +template<support::endianness target_endianness> +struct Elf_Dyn_Base<target_endianness, false> { + LLVM_ELF_IMPORT_TYPES(target_endianness, false) + Elf_Sword d_tag; + union { + Elf_Word d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template<support::endianness target_endianness> +struct Elf_Dyn_Base<target_endianness, true> { + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + Elf_Sxword d_tag; + union { + Elf_Xword d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template<support::endianness target_endianness, bool is64Bits> +struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, is64Bits> { + using Elf_Dyn_Base<target_endianness, is64Bits>::d_tag; + using Elf_Dyn_Base<target_endianness, is64Bits>::d_un; + int64_t getTag() const { return d_tag; } + uint64_t getVal() const { return d_un.d_val; } + uint64_t getPtr() const { return d_un.ptr; } +}; + +template<support::endianness target_endianness, bool is64Bits> +class ELFObjectFile; + +// DynRefImpl: Reference to an entry in the dynamic table +// This is an ELF-specific interface. +template<support::endianness target_endianness, bool is64Bits> +class DynRefImpl { + typedef Elf_Dyn_Impl<target_endianness, is64Bits> Elf_Dyn; + typedef ELFObjectFile<target_endianness, is64Bits> OwningType; + + DataRefImpl DynPimpl; + const OwningType *OwningObject; + +public: + DynRefImpl() : OwningObject(NULL) { + std::memset(&DynPimpl, 0, sizeof(DynPimpl)); + } + + DynRefImpl(DataRefImpl DynP, const OwningType *Owner); + + bool operator==(const DynRefImpl &Other) const; + bool operator <(const DynRefImpl &Other) const; + + error_code getNext(DynRefImpl &Result) const; + int64_t getTag() const; + uint64_t getVal() const; + uint64_t getPtr() const; + + DataRefImpl getRawDataRefImpl() const; +}; + +// Elf_Rel: Elf Relocation template<support::endianness target_endianness, bool is64Bits, bool isRela> struct Elf_Rel_Base; @@ -255,8 +320,11 @@ class ELFObjectFile : public ObjectFile { typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr; typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym; + typedef Elf_Dyn_Impl<target_endianness, is64Bits> Elf_Dyn; typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel; typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela; + typedef DynRefImpl<target_endianness, is64Bits> DynRef; + typedef content_iterator<DynRef> dyn_iterator; protected: struct Elf_Ehdr { @@ -300,6 +368,8 @@ private: IndexMap_t SymbolTableSectionsIndexMap; DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; + const Elf_Shdr *dot_dynamic_sec; // .dynamic + /// @brief Map sections to an array of relocation sections that reference /// them sorted by section index. RelocMap_t SectionRelocMap; @@ -329,6 +399,9 @@ protected: const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? void validateSymbol(DataRefImpl Symb) const; +public: + const Elf_Dyn *getDyn(DataRefImpl DynData) const; + protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; @@ -341,6 +414,12 @@ protected: virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; + friend class DynRefImpl<target_endianness, is64Bits>; + virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const; + + virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; + virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; @@ -376,11 +455,19 @@ public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; + virtual symbol_iterator begin_dynamic_symbols() const; virtual symbol_iterator end_dynamic_symbols() const; + virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + virtual dyn_iterator begin_dynamic_table() const; + virtual dyn_iterator end_dynamic_table() const; + virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual unsigned getArch() const; @@ -1171,7 +1258,8 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object , SectionHeaderTable(0) , dot_shstrtab_sec(0) , dot_strtab_sec(0) - , dot_dynstr_sec(0) { + , dot_dynstr_sec(0) + , dot_dynamic_sec(0) { const uint64_t FileSize = Data->getBufferSize(); @@ -1227,6 +1315,12 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { SectionRelocMap[getSection(sh->sh_info)].push_back(i); } + if (sh->sh_type == ELF::SHT_DYNAMIC) { + if (dot_dynamic_sec != NULL) + // FIXME: Proper error handling. + report_fatal_error("More than one .dynamic!"); + dot_dynamic_sec = sh; + } ++sh; } @@ -1353,6 +1447,121 @@ section_iterator ELFObjectFile<target_endianness, is64Bits> } template<support::endianness target_endianness, bool is64Bits> +typename ELFObjectFile<target_endianness, is64Bits>::dyn_iterator +ELFObjectFile<target_endianness, is64Bits>::begin_dynamic_table() const { + DataRefImpl DynData; + memset(&DynData, 0, sizeof(DynData)); + if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) { + DynData.d.a = std::numeric_limits<uint32_t>::max(); + } else { + DynData.d.a = 0; + } + return dyn_iterator(DynRef(DynData, this)); +} + +template<support::endianness target_endianness, bool is64Bits> +typename ELFObjectFile<target_endianness, is64Bits>::dyn_iterator +ELFObjectFile<target_endianness, is64Bits> + ::end_dynamic_table() const { + DataRefImpl DynData; + memset(&DynData, 0, sizeof(DynData)); + DynData.d.a = std::numeric_limits<uint32_t>::max(); + return dyn_iterator(DynRef(DynData, this)); +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getDynNext(DataRefImpl DynData, + DynRef &Result) const { + ++DynData.d.a; + + // Check to see if we are at the end of .dynamic + if (DynData.d.a >= dot_dynamic_sec->getEntityCount()) { + // We are at the end. Return the terminator. + DynData.d.a = std::numeric_limits<uint32_t>::max(); + } + + Result = DynRef(DynData, this); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +library_iterator ELFObjectFile<target_endianness, is64Bits> + ::begin_libraries_needed() const { + // Find the first DT_NEEDED entry + dyn_iterator i = begin_dynamic_table(); + dyn_iterator e = end_dynamic_table(); + error_code ec; + while (i != e) { + if (i->getTag() == ELF::DT_NEEDED) + break; + i.increment(ec); + if (ec) + report_fatal_error("dynamic table iteration failed"); + } + // Use the same DataRefImpl format as DynRef. + return library_iterator(LibraryRef(i->getRawDataRefImpl(), this)); +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { + // Use the same DataRefImpl format as DynRef. + dyn_iterator i = dyn_iterator(DynRef(Data, this)); + dyn_iterator e = end_dynamic_table(); + + // Skip the current dynamic table entry. + error_code ec; + if (i != e) { + i.increment(ec); + // TODO: proper error handling + if (ec) + report_fatal_error("dynamic table iteration failed"); + } + + // Find the next DT_NEEDED entry. + while (i != e) { + if (i->getTag() == ELF::DT_NEEDED) + break; + i.increment(ec); + if (ec) + report_fatal_error("dynamic table iteration failed"); + } + Result = LibraryRef(i->getRawDataRefImpl(), this); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> + ::getLibraryPath(DataRefImpl Data, StringRef &Res) const { + dyn_iterator i = dyn_iterator(DynRef(Data, this)); + if (i == end_dynamic_table()) + report_fatal_error("getLibraryPath() called on iterator end"); + + if (i->getTag() != ELF::DT_NEEDED) + report_fatal_error("Invalid library_iterator"); + + // This uses .dynstr to lookup the name of the DT_NEEDED entry. + // THis works as long as DT_STRTAB == .dynstr. This is true most of + // the time, but the specification allows exceptions. + // TODO: This should really use DT_STRTAB instead. Doing this requires + // reading the program headers. + if (dot_dynstr_sec == NULL) + report_fatal_error("Dynamic string table is missing"); + Res = getString(dot_dynstr_sec, i->getVal()); + return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +library_iterator ELFObjectFile<target_endianness, is64Bits> + ::end_libraries_needed() const { + dyn_iterator e = end_dynamic_table(); + // Use the same DataRefImpl format as DynRef. + return library_iterator(LibraryRef(e->getRawDataRefImpl(), this)); +} + +template<support::endianness target_endianness, bool is64Bits> uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const { return is64Bits ? 8 : 4; } @@ -1450,6 +1659,12 @@ ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const { } template<support::endianness target_endianness, bool is64Bits> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Dyn * +ELFObjectFile<target_endianness, is64Bits>::getDyn(DataRefImpl DynData) const { + return getEntry<Elf_Dyn>(dot_dynamic_sec, DynData.d.a); +} + +template<support::endianness target_endianness, bool is64Bits> const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel * ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const { return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); @@ -1527,6 +1742,54 @@ error_code ELFObjectFile<target_endianness, is64Bits> return object_error::success; } +template<support::endianness target_endianness, bool is64Bits> +inline DynRefImpl<target_endianness, is64Bits> + ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) + : DynPimpl(DynP) + , OwningObject(Owner) {} + +template<support::endianness target_endianness, bool is64Bits> +inline bool DynRefImpl<target_endianness, is64Bits> + ::operator==(const DynRefImpl &Other) const { + return DynPimpl == Other.DynPimpl; +} + +template<support::endianness target_endianness, bool is64Bits> +inline bool DynRefImpl<target_endianness, is64Bits> + ::operator <(const DynRefImpl &Other) const { + return DynPimpl < Other.DynPimpl; +} + +template<support::endianness target_endianness, bool is64Bits> +inline error_code DynRefImpl<target_endianness, is64Bits> + ::getNext(DynRefImpl &Result) const { + return OwningObject->getDynNext(DynPimpl, Result); +} + +template<support::endianness target_endianness, bool is64Bits> +inline int64_t DynRefImpl<target_endianness, is64Bits> + ::getTag() const { + return OwningObject->getDyn(DynPimpl)->d_tag; +} + +template<support::endianness target_endianness, bool is64Bits> +inline uint64_t DynRefImpl<target_endianness, is64Bits> + ::getVal() const { + return OwningObject->getDyn(DynPimpl)->d_un.d_val; +} + +template<support::endianness target_endianness, bool is64Bits> +inline uint64_t DynRefImpl<target_endianness, is64Bits> + ::getPtr() const { + return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; +} + +template<support::endianness target_endianness, bool is64Bits> +inline DataRefImpl DynRefImpl<target_endianness, is64Bits> + ::getRawDataRefImpl() const { + return DynPimpl; +} + } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 3edbe08..185df06 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -34,6 +34,8 @@ public: virtual symbol_iterator end_symbols() const; virtual symbol_iterator begin_dynamic_symbols() const; virtual symbol_iterator end_dynamic_symbols() const; + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; @@ -92,6 +94,9 @@ protected: SmallVectorImpl<char> &Result) const; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; + virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; + virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; + private: MachOObject *MachOObj; mutable uint32_t RegisteredStringTable; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 56d8c24..dd47ceb 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -228,6 +228,32 @@ public: }; typedef content_iterator<SymbolRef> symbol_iterator; +/// LibraryRef - This is a value type class that represents a single library in +/// the list of libraries needed by a shared or dynamic object. +class LibraryRef { + friend class SectionRef; + DataRefImpl LibraryPimpl; + const ObjectFile *OwningObject; + +public: + LibraryRef() : OwningObject(NULL) { + std::memset(&LibraryPimpl, 0, sizeof(LibraryPimpl)); + } + + LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner); + + bool operator==(const LibraryRef &Other) const; + bool operator <(const LibraryRef &Other) const; + + error_code getNext(LibraryRef &Result) const; + + // Get the path to this library, as stored in the object file. + error_code getPath(StringRef &Result) const; + + DataRefImpl getRawDataRefImpl() const; +}; +typedef content_iterator<LibraryRef> library_iterator; + const uint64_t UnknownAddressOrSize = ~0ULL; /// ObjectFile - This class is the base class for all object file types. @@ -307,6 +333,11 @@ protected: return object_error::success; } + // Same for LibraryRef + friend class LibraryRef; + virtual error_code getLibraryNext(DataRefImpl Lib, LibraryRef &Res) const = 0; + virtual error_code getLibraryPath(DataRefImpl Lib, StringRef &Res) const = 0; + public: virtual symbol_iterator begin_symbols() const = 0; @@ -318,6 +349,9 @@ public: virtual section_iterator begin_sections() const = 0; virtual section_iterator end_sections() const = 0; + virtual library_iterator begin_libraries_needed() const = 0; + virtual library_iterator end_libraries_needed() const = 0; + /// @brief The number of bytes used to represent an address in this object /// file format. virtual uint8_t getBytesInAddress() const = 0; @@ -509,6 +543,26 @@ inline error_code RelocationRef::getValueString(SmallVectorImpl<char> &Result) inline error_code RelocationRef::getHidden(bool &Result) const { return OwningObject->getRelocationHidden(RelocationPimpl, Result); } +// Inline function definitions. +inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) + : LibraryPimpl(LibraryP) + , OwningObject(Owner) {} + +inline bool LibraryRef::operator==(const LibraryRef &Other) const { + return LibraryPimpl == Other.LibraryPimpl; +} + +inline bool LibraryRef::operator <(const LibraryRef &Other) const { + return LibraryPimpl < Other.LibraryPimpl; +} + +inline error_code LibraryRef::getNext(LibraryRef &Result) const { + return OwningObject->getLibraryNext(LibraryPimpl, Result); +} + +inline error_code LibraryRef::getPath(StringRef &Result) const { + return OwningObject->getLibraryPath(LibraryPimpl, Result); +} } // end namespace object } // end namespace llvm |