* 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.

llvm-svn: 151785
This commit is contained in:
David Meyer 2012-03-01 01:36:50 +00:00
parent ec9c4e487c
commit 2fc34c5f84
16 changed files with 654 additions and 4 deletions

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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

View File

@ -515,6 +515,16 @@ symbol_iterator COFFObjectFile::end_dynamic_symbols() const {
report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
}
library_iterator COFFObjectFile::begin_libraries_needed() const {
// TODO: implement
report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
}
library_iterator COFFObjectFile::end_libraries_needed() const {
// TODO: implement
report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
}
section_iterator COFFObjectFile::begin_sections() const {
DataRefImpl ret;
std::memset(&ret, 0, sizeof(DataRefImpl));
@ -726,6 +736,16 @@ error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
return object_error::success;
}
error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData,
LibraryRef &Result) const {
report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
}
error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData,
StringRef &Result) const {
report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
}
namespace llvm {
ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {

View File

@ -377,6 +377,16 @@ symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
}
library_iterator MachOObjectFile::begin_libraries_needed() const {
// TODO: implement
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
library_iterator MachOObjectFile::end_libraries_needed() const {
// TODO: implement
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
/*===-- Sections ----------------------------------------------------------===*/
void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
@ -1175,6 +1185,17 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
return object_error::success;
}
error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
LibraryRef &Res) const {
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
StringRef &Res) const {
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
/*===-- Miscellaneous -----------------------------------------------------===*/
uint8_t MachOObjectFile::getBytesInAddress() const {

View File

@ -1,12 +1,14 @@
; How to make the shared objects from this file:
;
; LDARGS="--unresolved-symbols=ignore-all -soname=libfoo.so --no-as-needed -lc -lm"
;
; X86-32 ELF:
; llc -mtriple=i386-linux-gnu shared.ll -filetype=obj -o tmp32.o -relocation-model=pic
; ld -melf_i386 -shared tmp32.o -o shared-object-test.elf-i386 --unresolved-symbols=ignore-all
; ld -melf_i386 -shared tmp32.o -o shared-object-test.elf-i386 $LDARGS
;
; X86-64 ELF:
; llc -mtriple=x86_64-linux-gnu shared.ll -filetype=obj -o tmp64.o -relocation-model=pic
; ld -melf_x86_64 -shared tmp64.o -o shared-object-test.elf-x86-64 --unresolved-symbols=ignore-all
; ld -melf_x86_64 -shared tmp64.o -o shared-object-test.elf-x86-64 $LDARGS
@defined_sym = global i32 1, align 4

View File

@ -0,0 +1,44 @@
RUN: llvm-readobj %p/Inputs/shared-object-test.elf-i386 \
RUN: | FileCheck %s -check-prefix ELF
RUN: llvm-readobj %p/Inputs/shared-object-test.elf-x86-64 \
RUN: | FileCheck %s -check-prefix ELF
ELF:Symbols:
ELF: .dynsym DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .dynstr DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .text DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .eh_frame DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .tdata DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .dynamic DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .got.plt DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .data DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: .bss DBG {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} formatspecific
ELF: shared.ll FILE {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} absolute,formatspecific
ELF: local_func FUNC {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}}
ELF: _GLOBAL_OFFSET_TABLE_ DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} absolute
ELF: _DYNAMIC DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} absolute
ELF: common_sym DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global
ELF: tls_sym DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,threadlocal
ELF: defined_sym DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global
ELF: __bss_start ? {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,absolute
ELF: _end ? {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,absolute
ELF: global_func FUNC {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global
ELF: _edata ? {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,absolute
ELF: Total: 21
ELF:Dynamic Symbols:
ELF: common_sym DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global
ELF: tls_sym DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,threadlocal
ELF: defined_sym DATA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global
ELF: __bss_start ? {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,absolute
ELF: _end ? {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,absolute
ELF: global_func FUNC {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global
ELF: _edata ? {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} global,absolute
ELF: Total: {{[0-9a-f]+}}
ELF:Libraries needed:
ELF: libc.so.6
ELF: libm.so.6
ELF: Total: 2

View File

@ -37,6 +37,7 @@ add_subdirectory(llvm-extract)
add_subdirectory(llvm-diff)
add_subdirectory(macho-dump)
add_subdirectory(llvm-objdump)
add_subdirectory(llvm-readobj)
add_subdirectory(llvm-rtdyld)
add_subdirectory(llvm-dwarfdump)

View File

@ -32,7 +32,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \
llvm-ld llvm-prof llvm-link \
lli llvm-extract llvm-mc \
bugpoint llvm-bcanalyzer llvm-stub \
llvm-diff macho-dump llvm-objdump \
llvm-diff macho-dump llvm-objdump llvm-readobj \
llvm-rtdyld llvm-dwarfdump llvm-cov \
llvm-size llvm-stress

View File

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

View File

@ -0,0 +1,22 @@
;===- ./tools/llvm-readobj/LLVMBuild.txt ---------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Tool
name = llvm-readobj
parent = Tools
required_libraries = Archive BitReader Object

View File

@ -0,0 +1,18 @@
##===- tools/llvm-readobj/Makefile -----------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL := ../..
TOOLNAME := llvm-readobj
LINK_COMPONENTS := archive bitreader object
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
include $(LEVEL)/Makefile.common

View File

@ -0,0 +1,188 @@
/*===- pso-stub.c - Stub executable to run llvm bitcode files -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "llvm/Object/ObjectFile.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
using namespace llvm::object;
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input object>"), cl::init(""));
void DumpSymbolHeader() {
outs() << format(" %-32s", (const char*)"Name")
<< format(" %-4s", (const char*)"Type")
<< format(" %-16s", (const char*)"Address")
<< format(" %-16s", (const char*)"Size")
<< format(" %-16s", (const char*)"FileOffset")
<< format(" %-26s", (const char*)"Flags")
<< "\n";
}
const char *GetTypeStr(SymbolRef::Type Type) {
switch (Type) {
case SymbolRef::ST_Unknown: return "?";
case SymbolRef::ST_Data: return "DATA";
case SymbolRef::ST_Debug: return "DBG";
case SymbolRef::ST_File: return "FILE";
case SymbolRef::ST_Function: return "FUNC";
case SymbolRef::ST_Other: return "-";
}
return "INV";
}
std::string GetFlagStr(uint32_t Flags) {
std::string result;
if (Flags & SymbolRef::SF_Undefined)
result += "undef,";
if (Flags & SymbolRef::SF_Global)
result += "global,";
if (Flags & SymbolRef::SF_Weak)
result += "weak,";
if (Flags & SymbolRef::SF_Absolute)
result += "absolute,";
if (Flags & SymbolRef::SF_ThreadLocal)
result += "threadlocal,";
if (Flags & SymbolRef::SF_Common)
result += "common,";
if (Flags & SymbolRef::SF_FormatSpecific)
result += "formatspecific,";
// Remove trailing comma
if (result.size() > 0) {
result.erase(result.size() - 1);
}
return result;
}
void DumpSymbol(const SymbolRef &sym) {
StringRef Name;
SymbolRef::Type Type;
uint32_t Flags;
uint64_t Address;
uint64_t Size;
uint64_t FileOffset;
sym.getName(Name);
sym.getAddress(Address);
sym.getSize(Size);
sym.getFileOffset(FileOffset);
sym.getType(Type);
sym.getFlags(Flags);
// format() can't handle StringRefs
outs() << format(" %-32s", Name.str().c_str())
<< format(" %-4s", GetTypeStr(Type))
<< format(" %16"PRIx64, Address)
<< format(" %16"PRIx64, Size)
<< format(" %16"PRIx64, FileOffset)
<< " " << GetFlagStr(Flags)
<< "\n";
}
// Iterate through the normal symbols in the ObjectFile
void DumpSymbols(const ObjectFile *obj) {
error_code ec;
uint32_t count = 0;
outs() << "Symbols:\n";
symbol_iterator it = obj->begin_symbols();
symbol_iterator ie = obj->end_symbols();
while (it != ie) {
DumpSymbol(*it);
it.increment(ec);
if (ec)
report_fatal_error("Symbol iteration failed");
++count;
}
outs() << " Total: " << count << "\n\n";
}
// Iterate through the dynamic symbols in the ObjectFile.
void DumpDynamicSymbols(const ObjectFile *obj) {
error_code ec;
uint32_t count = 0;
outs() << "Dynamic Symbols:\n";
symbol_iterator it = obj->begin_dynamic_symbols();
symbol_iterator ie = obj->end_dynamic_symbols();
while (it != ie) {
DumpSymbol(*it);
it.increment(ec);
if (ec)
report_fatal_error("Symbol iteration failed");
++count;
}
outs() << " Total: " << count << "\n\n";
}
void DumpLibrary(const LibraryRef &lib) {
StringRef path;
lib.getPath(path);
outs() << " " << path << "\n";
}
// Iterate through needed libraries
void DumpLibrariesNeeded(const ObjectFile *obj) {
error_code ec;
uint32_t count = 0;
library_iterator it = obj->begin_libraries_needed();
library_iterator ie = obj->end_libraries_needed();
outs() << "Libraries needed:\n";
while (it != ie) {
DumpLibrary(*it);
it.increment(ec);
if (ec)
report_fatal_error("Needed libraries iteration failed");
++count;
}
outs() << " Total: " << count << "\n\n";
}
int main(int argc, char** argv) {
error_code ec;
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv,
"LLVM Object Reader\n");
if (InputFilename.empty()) {
errs() << "Please specify an input filename\n";
return 1;
}
// Open the object file
OwningPtr<MemoryBuffer> File;
if (MemoryBuffer::getFile(InputFilename, File)) {
errs() << InputFilename << ": Open failed\n";
return 1;
}
ObjectFile *obj = ObjectFile::createObjectFile(File.take());
if (!obj) {
errs() << InputFilename << ": Object type not recognized\n";
}
DumpSymbols(obj);
DumpDynamicSymbols(obj);
DumpLibrariesNeeded(obj);
return 0;
}