[llvm-readobj] Add ELF .dynamic table dumping.

llvm-svn: 175592
This commit is contained in:
Michael J. Spencer 2013-02-20 02:37:12 +00:00
parent fa42b5d77d
commit 6270bca74a
6 changed files with 281 additions and 9 deletions

View File

@ -471,9 +471,9 @@ public:
template<class EntT>
class ELFEntityIterator {
public:
typedef void difference_type;
typedef ptrdiff_t difference_type;
typedef EntT value_type;
typedef std::forward_iterator_tag iterator_category;
typedef std::random_access_iterator_tag iterator_category;
typedef value_type &reference;
typedef value_type *pointer;
@ -513,10 +513,22 @@ public:
return Tmp;
}
ELFEntityIterator &operator =(const ELFEntityIterator &Other) {
EntitySize = Other.EntitySize;
Current = Other.Current;
return *this;
}
difference_type operator -(const ELFEntityIterator &Other) const {
assert(EntitySize == Other.EntitySize &&
"Subtracting iterators of different EntitiySize!");
return (Current - Other.Current) / EntitySize;
}
const char *get() const { return Current; }
private:
const uint64_t EntitySize;
uint64_t EntitySize;
const char *Current;
};
@ -605,6 +617,7 @@ private:
return getSection(Rel.w.b);
}
public:
bool isRelocationHasAddend(DataRefImpl Rel) const;
template<typename T>
const T *getEntry(uint16_t Section, uint32_t Entry) const;
@ -706,8 +719,14 @@ public:
return SymbolTableSections[0];
}
const Elf_Shdr *getDynamicStringTableSectionHeader() const {
return dot_dynstr_sec;
}
Elf_Dyn_iterator begin_dynamic_table() const;
Elf_Dyn_iterator end_dynamic_table() const;
/// \param NULLEnd use one past the first DT_NULL entry as the end instead of
/// the section size.
Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const;
Elf_Sym_iterator begin_elf_dynamic_symbols() const {
const Elf_Shdr *DynSymtab = SymbolTableSections[0];
@ -2276,11 +2295,23 @@ ELFObjectFile<ELFT>::begin_dynamic_table() const {
template<class ELFT>
typename ELFObjectFile<ELFT>::Elf_Dyn_iterator
ELFObjectFile<ELFT>::end_dynamic_table() const {
if (dot_dynamic_sec)
return Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize,
(const char *)base() + dot_dynamic_sec->sh_offset +
dot_dynamic_sec->sh_size);
ELFObjectFile<ELFT>::end_dynamic_table(bool NULLEnd) const {
if (dot_dynamic_sec) {
Elf_Dyn_iterator Ret(dot_dynamic_sec->sh_entsize,
(const char *)base() + dot_dynamic_sec->sh_offset +
dot_dynamic_sec->sh_size);
if (NULLEnd) {
Elf_Dyn_iterator Start = begin_dynamic_table();
for (; Start != Ret && Start->getTag() != ELF::DT_NULL; ++Start)
;
// Include the DT_NULL.
if (Start != Ret)
++Start;
Ret = Start;
}
return Ret;
}
return Elf_Dyn_iterator(0, 0);
}

View File

@ -71,6 +71,19 @@ ELF: .symtab {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} r
ELF: .strtab {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} rodata
ELF: Total: 14
ELF:Dynamic section contains 9 entries
ELF: Tag Type Name/Value
ELF: 00000001 (NEEDED) Shared library: [libc.so.6]
ELF: 00000001 (NEEDED) Shared library: [libm.so.6]
ELF: 0000000e (SONAME) Library soname: [libfoo.so]
ELF: 00000004 (HASH) {{[0-9a-f]+}}
ELF: 00000005 (STRTAB) {{[0-9a-f]+}}
ELF: 00000006 (SYMTAB) {{[0-9a-f]+}}
ELF: 0000000a (STRSZ) {{[0-9]+}} (bytes)
ELF: 0000000b (SYMENT) {{[0-9]+}} (bytes)
ELF: 00000000 (NULL) 0x0
ELF: Total: 9
ELF:Libraries needed:
ELF: libc.so.6
ELF: libm.so.6

View File

@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS archive bitreader object)
add_llvm_tool(llvm-readobj
ELF.cpp
llvm-readobj.cpp
)

196
tools/llvm-readobj/ELF.cpp Normal file
View File

@ -0,0 +1,196 @@
//===- llvm-readobj/ELF.cpp - ELF Specific Dumper -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm-readobj.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Format.h"
namespace llvm {
using namespace object;
using namespace ELF;
const char *getTypeString(uint64_t Type) {
switch (Type) {
case DT_BIND_NOW:
return "(BIND_NOW)";
case DT_DEBUG:
return "(DEBUG)";
case DT_FINI:
return "(FINI)";
case DT_FINI_ARRAY:
return "(FINI_ARRAY)";
case DT_FINI_ARRAYSZ:
return "(FINI_ARRAYSZ)";
case DT_FLAGS:
return "(FLAGS)";
case DT_HASH:
return "(HASH)";
case DT_INIT:
return "(INIT)";
case DT_INIT_ARRAY:
return "(INIT_ARRAY)";
case DT_INIT_ARRAYSZ:
return "(INIT_ARRAYSZ)";
case DT_PREINIT_ARRAY:
return "(PREINIT_ARRAY)";
case DT_PREINIT_ARRAYSZ:
return "(PREINIT_ARRAYSZ)";
case DT_JMPREL:
return "(JMPREL)";
case DT_NEEDED:
return "(NEEDED)";
case DT_NULL:
return "(NULL)";
case DT_PLTGOT:
return "(PLTGOT)";
case DT_PLTREL:
return "(PLTREL)";
case DT_PLTRELSZ:
return "(PLTRELSZ)";
case DT_REL:
return "(REL)";
case DT_RELA:
return "(RELA)";
case DT_RELENT:
return "(RELENT)";
case DT_RELSZ:
return "(RELSZ)";
case DT_RELAENT:
return "(RELAENT)";
case DT_RELASZ:
return "(RELASZ)";
case DT_RPATH:
return "(RPATH)";
case DT_RUNPATH:
return "(RUNPATH)";
case DT_SONAME:
return "(SONAME)";
case DT_STRSZ:
return "(STRSZ)";
case DT_STRTAB:
return "(STRTAB)";
case DT_SYMBOLIC:
return "(SYMBOLIC)";
case DT_SYMENT:
return "(SYMENT)";
case DT_SYMTAB:
return "(SYMTAB)";
case DT_TEXTREL:
return "(TEXTREL)";
default:
return "unknown";
}
}
template <class ELFT>
void printValue(const ELFObjectFile<ELFT> *O, uint64_t Type, uint64_t Value,
bool Is64, raw_ostream &OS) {
switch (Type) {
case DT_PLTREL:
if (Value == DT_REL) {
OS << "REL";
break;
} else if (Value == DT_RELA) {
OS << "RELA";
break;
}
// Fallthrough.
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
case DT_DEBUG:
case DT_NULL:
OS << format("0x%" PRIx64, Value);
break;
case DT_PLTRELSZ:
case DT_RELASZ:
case DT_RELAENT:
case DT_STRSZ:
case DT_SYMENT:
case DT_RELSZ:
case DT_RELENT:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_PREINIT_ARRAYSZ:
OS << Value << " (bytes)";
break;
case DT_NEEDED:
OS << "Shared library: ["
<< O->getString(O->getDynamicStringTableSectionHeader(), Value) << "]";
break;
case DT_SONAME:
OS << "Library soname: ["
<< O->getString(O->getDynamicStringTableSectionHeader(), Value) << "]";
break;
}
}
template <class ELFT>
ErrorOr<void> dumpDynamicTable(const ELFObjectFile<ELFT> *O, raw_ostream &OS) {
typedef ELFObjectFile<ELFT> ELFO;
typedef typename ELFO::Elf_Dyn_iterator EDI;
EDI Start = O->begin_dynamic_table(),
End = O->end_dynamic_table(true);
if (Start == End)
return error_code::success();
ptrdiff_t Total = std::distance(Start, End);
OS << "Dynamic section contains " << Total << " entries\n";
bool Is64 = O->getBytesInAddress() == 8;
OS << " Tag" << (Is64 ? " " : " ") << "Type"
<< " " << "Name/Value\n";
for (; Start != End; ++Start) {
OS << " "
<< format(Is64 ? "0x%016" PRIx64 : "0x%08" PRIx64, Start->getTag())
<< " " << format("%-21s", getTypeString(Start->getTag()));
printValue(O, Start->getTag(), Start->getVal(), Is64, OS);
OS << "\n";
}
OS << " Total: " << Total << "\n\n";
return error_code::success();
}
ErrorOr<void> dumpELFDynamicTable(ObjectFile *O, raw_ostream &OS) {
// Little-endian 32-bit
if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj =
dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(O))
return dumpDynamicTable(ELFObj, OS);
// Big-endian 32-bit
if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj =
dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(O))
return dumpDynamicTable(ELFObj, OS);
// Little-endian 64-bit
if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj =
dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(O))
return dumpDynamicTable(ELFObj, OS);
// Big-endian 64-bit
if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj =
dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(O))
return dumpDynamicTable(ELFObj, OS);
return error_code(object_error::invalid_file_type);
}
} // end namespace llvm

View File

@ -19,6 +19,8 @@
//
//===----------------------------------------------------------------------===//
#include "llvm-readobj.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Object/ELF.h"
@ -263,6 +265,13 @@ int main(int argc, char** argv) {
dump(obj, &dumpSection, obj->begin_sections(), obj->end_sections(),
"Section iteration failed");
if (obj->isELF()) {
if (ErrorOr<void> e = dumpELFDynamicTable(obj, outs()))
;
else
errs() << "InputFilename" << ": " << error_code(e).message() << "\n";
}
outs() << "Libraries needed:\n";
dump(obj, &dumpLibrary, obj->begin_libraries_needed(),
obj->end_libraries_needed(), "Needed libraries iteration failed");

View File

@ -0,0 +1,22 @@
//===- llvm-readobj.h - Dump contents of an Object File -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_READ_OBJ_H
#define LLVM_TOOLS_READ_OBJ_H
#include "llvm/Support/ErrorOr.h"
namespace llvm {
namespace object { class ObjectFile; }
class raw_ostream;
ErrorOr<void> dumpELFDynamicTable(object::ObjectFile *O, raw_ostream &OS);
} // end namespace llvm
#endif