From: Michael J. Spencer Date: Thu, 25 Jun 2015 21:47:32 +0000 (+0000) Subject: [Object][ELF] Add support for dumping dynamic relocations when sections are stripped. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=4cbb2db3ab7c598a0ab1f0a955639384d7ad7b97 [Object][ELF] Add support for dumping dynamic relocations when sections are stripped. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240703 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index a9d742d230d..8b28567f72c 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -265,6 +265,7 @@ private: 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. @@ -363,6 +364,21 @@ public: 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)); @@ -762,6 +778,38 @@ ELFFile::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(); } diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 2eda0c179f1..70f6d8b930b 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -293,7 +293,7 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base { using Elf_Dyn_Base::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 diff --git a/test/Object/relocation-executable.test b/test/Object/relocation-executable.test index 1236035d9f6..38ad5968af8 100644 --- a/test/Object/relocation-executable.test +++ b/test/Object/relocation-executable.test @@ -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 { @@ -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: } diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index d8c089a63e3..3df8ed9f710 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -47,6 +47,7 @@ public: void printFileHeaders() override; void printSections() override; void printRelocations() override; + void printDynamicRelocations() override; void printSymbols() override; void printDynamicSymbols() override; void printUnwindInfo() override; @@ -676,6 +677,39 @@ void ELFDumper::printRelocations() { } } +template +void ELFDumper::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 void ELFDumper::printRelocations(const Elf_Shdr *Sec) { switch (Sec->sh_type) { @@ -986,6 +1020,9 @@ static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, case DT_FLAGS_1: printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS); break; + default: + OS << format("0x%" PRIX64, Value); + break; } } diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index 323f5e319cf..cfca850150f 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -33,6 +33,7 @@ public: virtual void printUnwindInfo() = 0; // Only implemented for ELF at this time. + virtual void printDynamicRelocations() { } virtual void printDynamicTable() { } virtual void printNeededLibraries() { } virtual void printProgramHeaders() { } diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index d40cc05d0f4..3a6483a1386 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -40,7 +40,6 @@ #include #include - using namespace llvm; using namespace llvm::object; @@ -91,6 +90,10 @@ namespace opts { cl::desc("Alias for --relocations"), cl::aliasopt(Relocations)); + // -dyn-relocations + cl::opt DynRelocs("dyn-relocations", + cl::desc("Display the dynamic relocation entries in the file")); + // -symbols, -t cl::opt Symbols("symbols", cl::desc("Display the symbol table")); @@ -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) @@ -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(), @@ -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);