mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-11 21:45:16 +00:00
[llvm-readobj] Add ELF .dynamic table dumping.
llvm-svn: 175592
This commit is contained in:
parent
fa42b5d77d
commit
6270bca74a
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
196
tools/llvm-readobj/ELF.cpp
Normal 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
|
@ -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");
|
||||
|
22
tools/llvm-readobj/llvm-readobj.h
Normal file
22
tools/llvm-readobj/llvm-readobj.h
Normal 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
|
Loading…
Reference in New Issue
Block a user