Skip to content

Commit

Permalink
[Object]
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
David Meyer committed Mar 1, 2012
1 parent 741981a commit 5c2b4ea
Show file tree
Hide file tree
Showing 16 changed files with 654 additions and 4 deletions.
7 changes: 7 additions & 0 deletions include/llvm/Object/COFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,19 @@ class COFFObjectFile : public ObjectFile {
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;

Expand Down
265 changes: 264 additions & 1 deletion include/llvm/Object/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -300,6 +368,8 @@ class ELFObjectFile : public ObjectFile {
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;
Expand Down Expand Up @@ -329,6 +399,9 @@ class ELFObjectFile : public ObjectFile {
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;
Expand All @@ -341,6 +414,12 @@ class ELFObjectFile : public ObjectFile {
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;
Expand Down Expand Up @@ -376,11 +455,19 @@ class ELFObjectFile : public ObjectFile {
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;
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -1352,6 +1446,121 @@ section_iterator ELFObjectFile<target_endianness, is64Bits>
return section_iterator(SectionRef(ret, this));
}

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;
Expand Down Expand Up @@ -1449,6 +1658,12 @@ ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a);
}

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 {
Expand Down Expand Up @@ -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;
}

}
}

Expand Down
5 changes: 5 additions & 0 deletions include/llvm/Object/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class MachOObjectFile : public ObjectFile {
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;

Expand Down Expand Up @@ -92,6 +94,9 @@ class MachOObjectFile : public ObjectFile {
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;
Expand Down
Loading

0 comments on commit 5c2b4ea

Please sign in to comment.