Skip to content

Commit

Permalink
[Object][ELF] Add support for dumping dynamic relocations when sectio…
Browse files Browse the repository at this point in the history
…ns are stripped.

llvm-svn: 240703
  • Loading branch information
Bigcheese committed Jun 25, 2015
1 parent 358cf1e commit 594c028
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 4 deletions.
48 changes: 48 additions & 0 deletions llvm/include/llvm/Object/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ class ELFFile {
DynRegionInfo DynHashRegion;
DynRegionInfo DynStrRegion;
DynRegionInfo DynSymRegion;
DynRegionInfo DynRelaRegion;

// Pointer to SONAME entry in dynamic string table
// This is set the first time getLoadName is called.
Expand Down Expand Up @@ -363,6 +364,21 @@ class ELFFile {
return Elf_Sym_Iter(0, nullptr, true);
}

Elf_Rela_Iter begin_dyn_rela() const {
if (DynRelaRegion.Addr)
return Elf_Rela_Iter(DynRelaRegion.EntSize,
(const char *)DynRelaRegion.Addr);
return Elf_Rela_Iter(0, nullptr);
}

Elf_Rela_Iter end_dyn_rela() const {
if (DynRelaRegion.Addr)
return Elf_Rela_Iter(
DynRelaRegion.EntSize,
(const char *)DynRelaRegion.Addr + DynRelaRegion.Size);
return Elf_Rela_Iter(0, nullptr);
}

Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const {
return Elf_Rela_Iter(sec->sh_entsize,
(const char *)(base() + sec->sh_offset));
Expand Down Expand Up @@ -762,6 +778,38 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
}
}

// Scan dynamic table.
for (Elf_Dyn_Iter DynI = begin_dynamic_table(), DynE = end_dynamic_table();
DynI != DynE; ++DynI) {
switch (DynI->d_tag) {
case ELF::DT_RELA: {
uint64_t VBase = 0;
const uint8_t *FBase = nullptr;
for (Elf_Phdr_Iter PhdrI = begin_program_headers(),
PhdrE = end_program_headers();
PhdrI != PhdrE; ++PhdrI) {
if (PhdrI->p_type != ELF::PT_LOAD)
continue;
if (DynI->getPtr() >= PhdrI->p_vaddr &&
DynI->getPtr() < PhdrI->p_vaddr + PhdrI->p_memsz) {
VBase = PhdrI->p_vaddr;
FBase = base() + PhdrI->p_offset;
break;
}
}
if (!VBase)
return;
DynRelaRegion.Addr = FBase + DynI->getPtr() - VBase;
break;
}
case ELF::DT_RELASZ:
DynRelaRegion.Size = DynI->getVal();
break;
case ELF::DT_RELAENT:
DynRelaRegion.EntSize = DynI->getVal();
}
}

EC = std::error_code();
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Object/ELFTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
using Elf_Dyn_Base<ELFT>::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; }
uint64_t getPtr() const { return d_un.d_ptr; }
};

// Elf_Rel: Elf Relocation
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/Object/relocation-executable.test
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
RUN: llvm-readobj -r -expand-relocs %p/Inputs/hello-world.elf-x86-64 \
RUN: | FileCheck %s
RUN: llvm-readobj -dyn-relocations -expand-relocs \
RUN: %p/Inputs/hello-world.elf-x86-64 | FileCheck %s --check-prefix=DYN

// CHECK: Relocations [
// CHECK-NEXT: Section (8) .rela.dyn {
Expand All @@ -24,3 +26,12 @@ RUN: | FileCheck %s
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: }

// DYN: Dynamic Relocations {
// DYN-NEXT: Relocation {
// DYN-NEXT: Offset: 0x4018D8
// DYN-NEXT: Type: R_X86_64_GLOB_DAT (6)
// DYN-NEXT: Symbol: __gmon_start__
// DYN-NEXT: Addend: 0x0
// DYN-NEXT: }
// DYN-NEXT: }
37 changes: 37 additions & 0 deletions llvm/tools/llvm-readobj/ELFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class ELFDumper : public ObjDumper {
void printFileHeaders() override;
void printSections() override;
void printRelocations() override;
void printDynamicRelocations() override;
void printSymbols() override;
void printDynamicSymbols() override;
void printUnwindInfo() override;
Expand Down Expand Up @@ -676,6 +677,39 @@ void ELFDumper<ELFT>::printRelocations() {
}
}

template<class ELFT>
void ELFDumper<ELFT>::printDynamicRelocations() {
W.startLine() << "Dynamic Relocations {\n";
W.indent();
for (typename ELFO::Elf_Rela_Iter RelI = Obj->begin_dyn_rela(),
RelE = Obj->end_dyn_rela();
RelI != RelE; ++RelI) {
SmallString<32> RelocName;
Obj->getRelocationTypeName(RelI->getType(Obj->isMips64EL()), RelocName);
StringRef SymbolName;
uint32_t SymIndex = RelI->getSymbol(Obj->isMips64EL());
typename ELFO::Elf_Sym_Iter Sym = Obj->begin_dynamic_symbols() + SymIndex;
SymbolName = errorOrDefault(Obj->getSymbolName(Sym));
if (opts::ExpandRelocs) {
DictScope Group(W, "Relocation");
W.printHex("Offset", RelI->r_offset);
W.printNumber("Type", RelocName, (int)RelI->getType(Obj->isMips64EL()));
W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
W.printHex("Addend", RelI->r_addend);
}
else {
raw_ostream& OS = W.startLine();
OS << W.hex(RelI->r_offset)
<< " " << RelocName
<< " " << (SymbolName.size() > 0 ? SymbolName : "-")
<< " " << W.hex(RelI->r_addend)
<< "\n";
}
}
W.unindent();
W.startLine() << "}\n";
}

template <class ELFT>
void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) {
switch (Sec->sh_type) {
Expand Down Expand Up @@ -986,6 +1020,9 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_FLAGS_1:
printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
break;
default:
OS << format("0x%" PRIX64, Value);
break;
}
}

Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-readobj/ObjDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ObjDumper {
virtual void printUnwindInfo() = 0;

// Only implemented for ELF at this time.
virtual void printDynamicRelocations() { }
virtual void printDynamicTable() { }
virtual void printNeededLibraries() { }
virtual void printProgramHeaders() { }
Expand Down
9 changes: 6 additions & 3 deletions llvm/tools/llvm-readobj/llvm-readobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
#include <string>
#include <system_error>


using namespace llvm;
using namespace llvm::object;

Expand Down Expand Up @@ -91,6 +90,10 @@ namespace opts {
cl::desc("Alias for --relocations"),
cl::aliasopt(Relocations));

// -dyn-relocations
cl::opt<bool> DynRelocs("dyn-relocations",
cl::desc("Display the dynamic relocation entries in the file"));

// -symbols, -t
cl::opt<bool> Symbols("symbols",
cl::desc("Display the symbol table"));
Expand Down Expand Up @@ -280,6 +283,8 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printSections();
if (opts::Relocations)
Dumper->printRelocations();
if (opts::DynRelocs)
Dumper->printDynamicRelocations();
if (opts::Symbols)
Dumper->printSymbols();
if (opts::DynamicSymbols)
Expand Down Expand Up @@ -313,7 +318,6 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printCOFFBaseReloc();
}


/// @brief Dumps each object file in \a Arc;
static void dumpArchive(const Archive *Arc) {
for (Archive::child_iterator ArcI = Arc->child_begin(),
Expand Down Expand Up @@ -374,7 +378,6 @@ static void dumpInput(StringRef File) {
reportError(File, readobj_error::unrecognized_file_format);
}


int main(int argc, const char *argv[]) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
Expand Down

0 comments on commit 594c028

Please sign in to comment.