mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-10 02:25:47 +00:00
[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
This commit is contained in:
@@ -265,6 +265,7 @@ private:
|
|||||||
DynRegionInfo DynHashRegion;
|
DynRegionInfo DynHashRegion;
|
||||||
DynRegionInfo DynStrRegion;
|
DynRegionInfo DynStrRegion;
|
||||||
DynRegionInfo DynSymRegion;
|
DynRegionInfo DynSymRegion;
|
||||||
|
DynRegionInfo DynRelaRegion;
|
||||||
|
|
||||||
// Pointer to SONAME entry in dynamic string table
|
// Pointer to SONAME entry in dynamic string table
|
||||||
// This is set the first time getLoadName is called.
|
// This is set the first time getLoadName is called.
|
||||||
@@ -363,6 +364,21 @@ public:
|
|||||||
return Elf_Sym_Iter(0, nullptr, true);
|
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 {
|
Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const {
|
||||||
return Elf_Rela_Iter(sec->sh_entsize,
|
return Elf_Rela_Iter(sec->sh_entsize,
|
||||||
(const char *)(base() + sec->sh_offset));
|
(const char *)(base() + sec->sh_offset));
|
||||||
@@ -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();
|
EC = std::error_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -293,7 +293,7 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
|
|||||||
using Elf_Dyn_Base<ELFT>::d_un;
|
using Elf_Dyn_Base<ELFT>::d_un;
|
||||||
int64_t getTag() const { return d_tag; }
|
int64_t getTag() const { return d_tag; }
|
||||||
uint64_t getVal() const { return d_un.d_val; }
|
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
|
// Elf_Rel: Elf Relocation
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
RUN: llvm-readobj -r -expand-relocs %p/Inputs/hello-world.elf-x86-64 \
|
RUN: llvm-readobj -r -expand-relocs %p/Inputs/hello-world.elf-x86-64 \
|
||||||
RUN: | FileCheck %s
|
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: Relocations [
|
||||||
// CHECK-NEXT: Section (8) .rela.dyn {
|
// CHECK-NEXT: Section (8) .rela.dyn {
|
||||||
@@ -24,3 +26,12 @@ RUN: | FileCheck %s
|
|||||||
// CHECK-NEXT: Addend: 0x0
|
// CHECK-NEXT: Addend: 0x0
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
// 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: }
|
||||||
|
@@ -47,6 +47,7 @@ public:
|
|||||||
void printFileHeaders() override;
|
void printFileHeaders() override;
|
||||||
void printSections() override;
|
void printSections() override;
|
||||||
void printRelocations() override;
|
void printRelocations() override;
|
||||||
|
void printDynamicRelocations() override;
|
||||||
void printSymbols() override;
|
void printSymbols() override;
|
||||||
void printDynamicSymbols() override;
|
void printDynamicSymbols() override;
|
||||||
void printUnwindInfo() override;
|
void printUnwindInfo() override;
|
||||||
@@ -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>
|
template <class ELFT>
|
||||||
void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) {
|
void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) {
|
||||||
switch (Sec->sh_type) {
|
switch (Sec->sh_type) {
|
||||||
@@ -986,6 +1020,9 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
|
|||||||
case DT_FLAGS_1:
|
case DT_FLAGS_1:
|
||||||
printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
|
printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
OS << format("0x%" PRIX64, Value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,6 +33,7 @@ public:
|
|||||||
virtual void printUnwindInfo() = 0;
|
virtual void printUnwindInfo() = 0;
|
||||||
|
|
||||||
// Only implemented for ELF at this time.
|
// Only implemented for ELF at this time.
|
||||||
|
virtual void printDynamicRelocations() { }
|
||||||
virtual void printDynamicTable() { }
|
virtual void printDynamicTable() { }
|
||||||
virtual void printNeededLibraries() { }
|
virtual void printNeededLibraries() { }
|
||||||
virtual void printProgramHeaders() { }
|
virtual void printProgramHeaders() { }
|
||||||
|
@@ -40,7 +40,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
|
|
||||||
@@ -91,6 +90,10 @@ namespace opts {
|
|||||||
cl::desc("Alias for --relocations"),
|
cl::desc("Alias for --relocations"),
|
||||||
cl::aliasopt(Relocations));
|
cl::aliasopt(Relocations));
|
||||||
|
|
||||||
|
// -dyn-relocations
|
||||||
|
cl::opt<bool> DynRelocs("dyn-relocations",
|
||||||
|
cl::desc("Display the dynamic relocation entries in the file"));
|
||||||
|
|
||||||
// -symbols, -t
|
// -symbols, -t
|
||||||
cl::opt<bool> Symbols("symbols",
|
cl::opt<bool> Symbols("symbols",
|
||||||
cl::desc("Display the symbol table"));
|
cl::desc("Display the symbol table"));
|
||||||
@@ -280,6 +283,8 @@ static void dumpObject(const ObjectFile *Obj) {
|
|||||||
Dumper->printSections();
|
Dumper->printSections();
|
||||||
if (opts::Relocations)
|
if (opts::Relocations)
|
||||||
Dumper->printRelocations();
|
Dumper->printRelocations();
|
||||||
|
if (opts::DynRelocs)
|
||||||
|
Dumper->printDynamicRelocations();
|
||||||
if (opts::Symbols)
|
if (opts::Symbols)
|
||||||
Dumper->printSymbols();
|
Dumper->printSymbols();
|
||||||
if (opts::DynamicSymbols)
|
if (opts::DynamicSymbols)
|
||||||
@@ -313,7 +318,6 @@ static void dumpObject(const ObjectFile *Obj) {
|
|||||||
Dumper->printCOFFBaseReloc();
|
Dumper->printCOFFBaseReloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Dumps each object file in \a Arc;
|
/// @brief Dumps each object file in \a Arc;
|
||||||
static void dumpArchive(const Archive *Arc) {
|
static void dumpArchive(const Archive *Arc) {
|
||||||
for (Archive::child_iterator ArcI = Arc->child_begin(),
|
for (Archive::child_iterator ArcI = Arc->child_begin(),
|
||||||
@@ -374,7 +378,6 @@ static void dumpInput(StringRef File) {
|
|||||||
reportError(File, readobj_error::unrecognized_file_format);
|
reportError(File, readobj_error::unrecognized_file_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
sys::PrintStackTraceOnErrorSignal();
|
sys::PrintStackTraceOnErrorSignal();
|
||||||
PrettyStackTraceProgram X(argc, argv);
|
PrettyStackTraceProgram X(argc, argv);
|
||||||
|
Reference in New Issue
Block a user