summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2016-01-16 22:40:09 +0000
committerSimon Atanasyan <simon@atanasyan.com>2016-01-16 22:40:09 +0000
commit72155c33b10e5ec20fef065a05abc7a7e0311fbf (patch)
tree66c3b1c9068ba243b4852c476a9eaceed930b77b
parent20f31fa31a119640dfda40528a25f3b03ae1d818 (diff)
downloadbcm5719-llvm-72155c33b10e5ec20fef065a05abc7a7e0311fbf.tar.gz
bcm5719-llvm-72155c33b10e5ec20fef065a05abc7a7e0311fbf.zip
[llvm-readobj][ELF] Teach llvm-readobj to show dynamic relocation in REL format
MIPS 32-bit ABI uses REL relocation record format to save dynamic relocations. The patch teaches llvm-readobj to show dynamic relocations in this format. Differential Revision: http://reviews.llvm.org/D16114 llvm-svn: 258001
-rwxr-xr-xllvm/test/Object/Inputs/dyn-rel.so.elf-mipsbin0 -> 1946 bytes
-rw-r--r--llvm/test/Object/dyn-rel-relocation.test71
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp103
3 files changed, 140 insertions, 34 deletions
diff --git a/llvm/test/Object/Inputs/dyn-rel.so.elf-mips b/llvm/test/Object/Inputs/dyn-rel.so.elf-mips
new file mode 100755
index 00000000000..08fe70eae30
--- /dev/null
+++ b/llvm/test/Object/Inputs/dyn-rel.so.elf-mips
Binary files differ
diff --git a/llvm/test/Object/dyn-rel-relocation.test b/llvm/test/Object/dyn-rel-relocation.test
new file mode 100644
index 00000000000..4b528a7ef91
--- /dev/null
+++ b/llvm/test/Object/dyn-rel-relocation.test
@@ -0,0 +1,71 @@
+// Check that 'llvm-readobj -dyn-relocations' shows dynamic relocations
+// if they have REL record format.
+
+// dyn-rel.so.elf-mips
+// % cat test.s
+// .globl __start
+// __start:
+// nop
+//
+// .data
+// .type v1,@object
+// .size v1,4
+// v1:
+// .word 0
+//
+// .globl v2
+// .type v2,@object
+// .size v2,8
+// v2:
+// .word v2+4 # R_MIPS_32 target v2 addend 4
+// .word v1 # R_MIPS_32 target v1 addend 0
+//
+// % llvm-mc -filetype=obj -triple=mips-unknown-linux -o test.o test.s
+// % ld -m elf32btsmip -shared -o dyn-rel.so.elf-mips test.o
+
+RUN: llvm-readobj -relocations -dyn-relocations -expand-relocs \
+RUN: %p/Inputs/dyn-rel.so.elf-mips | FileCheck %s
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (6) .rel.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: Type: R_MIPS_NONE (0)
+// CHECK-NEXT: Symbol: - (0)
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x102F8
+// CHECK-NEXT: Type: R_MIPS_REL32 (3)
+// CHECK-NEXT: Symbol: - (0)
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x102F4
+// CHECK-NEXT: Type: R_MIPS_REL32 (3)
+// CHECK-NEXT: Symbol: v2 (9)
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// CHECK: Dynamic Relocations {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: Type: R_MIPS_NONE (0)
+// CHECK-NEXT: Symbol: -
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x102F8
+// CHECK-NEXT: Type: R_MIPS_REL32 (3)
+// CHECK-NEXT: Symbol: -
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x102F4
+// CHECK-NEXT: Type: R_MIPS_REL32 (3)
+// CHECK-NEXT: Symbol: v2
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 64059ed74b3..4eac7e4b8bf 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -75,6 +75,7 @@ private:
typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
typedef typename ELFO::Elf_Rel Elf_Rel;
typedef typename ELFO::Elf_Rela Elf_Rela;
+ typedef typename ELFO::Elf_Rel_Range Elf_Rel_Range;
typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range;
typedef typename ELFO::Elf_Phdr Elf_Phdr;
typedef typename ELFO::Elf_Half Elf_Half;
@@ -104,12 +105,16 @@ private:
void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
StringRef StrTable, bool IsDynamic);
+ void printDynamicRelocation(Elf_Rela Rel);
void printRelocations(const Elf_Shdr *Sec);
void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab);
void printValue(uint64_t Type, uint64_t Value);
- const Elf_Rela *dyn_rela_begin() const;
- const Elf_Rela *dyn_rela_end() const;
+ template <typename RELA>
+ static const RELA *dyn_rela_begin(const DynRegionInfo &region);
+ template <typename RELA>
+ static const RELA *dyn_rela_end(const DynRegionInfo &region);
+ Elf_Rel_Range dyn_rels() const;
Elf_Rela_Range dyn_relas() const;
StringRef getDynamicString(uint64_t Offset) const;
const Elf_Dyn *dynamic_table_begin() const {
@@ -129,6 +134,7 @@ private:
void LoadVersionDefs(const Elf_Shdr *sec) const;
const ELFO *Obj;
+ DynRegionInfo DynRelRegion;
DynRegionInfo DynRelaRegion;
const Elf_Phdr *DynamicProgHeader = nullptr;
StringRef DynamicStringTable;
@@ -944,6 +950,15 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
GnuHashTable =
reinterpret_cast<const Elf_GnuHash *>(toMappedAddr(Dyn.getPtr()));
break;
+ case ELF::DT_REL:
+ DynRelRegion.Addr = toMappedAddr(Dyn.getPtr());
+ break;
+ case ELF::DT_RELSZ:
+ DynRelRegion.Size = Dyn.getVal();
+ break;
+ case ELF::DT_RELENT:
+ DynRelRegion.EntSize = Dyn.getVal();
+ break;
case ELF::DT_RELA:
DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
break;
@@ -1011,25 +1026,32 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
}
template <typename ELFT>
-const typename ELFDumper<ELFT>::Elf_Rela *
-ELFDumper<ELFT>::dyn_rela_begin() const {
- if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela))
+template <typename RELA>
+const RELA *ELFDumper<ELFT>::dyn_rela_begin(const DynRegionInfo &Region) {
+ if (Region.Size && Region.EntSize != sizeof(RELA))
report_fatal_error("Invalid relocation entry size");
- return reinterpret_cast<const Elf_Rela *>(DynRelaRegion.Addr);
+ return reinterpret_cast<const RELA *>(Region.Addr);
}
template <typename ELFT>
-const typename ELFDumper<ELFT>::Elf_Rela *
-ELFDumper<ELFT>::dyn_rela_end() const {
- uint64_t Size = DynRelaRegion.Size;
- if (Size % sizeof(Elf_Rela))
+template <typename RELA>
+const RELA *ELFDumper<ELFT>::dyn_rela_end(const DynRegionInfo &Region) {
+ uint64_t Size = Region.Size;
+ if (Size % sizeof(RELA))
report_fatal_error("Invalid relocation table size");
- return dyn_rela_begin() + Size / sizeof(Elf_Rela);
+ return dyn_rela_begin<RELA>(Region) + Size / sizeof(RELA);
+}
+
+template <typename ELFT>
+typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const {
+ return make_range(dyn_rela_begin<Elf_Rel>(DynRelRegion),
+ dyn_rela_end<Elf_Rel>(DynRelRegion));
}
template <typename ELFT>
typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
- return make_range(dyn_rela_begin(), dyn_rela_end());
+ return make_range(dyn_rela_begin<Elf_Rela>(DynRelaRegion),
+ dyn_rela_end<Elf_Rela>(DynRelaRegion));
}
template<class ELFT>
@@ -1158,31 +1180,22 @@ void ELFDumper<ELFT>::printRelocations() {
}
}
-template<class ELFT>
-void ELFDumper<ELFT>::printDynamicRelocations() {
+template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() {
+ if (DynRelRegion.Size && DynRelaRegion.Size)
+ report_fatal_error("There are both REL and RELA dynamic relocations");
W.startLine() << "Dynamic Relocations {\n";
W.indent();
- for (const Elf_Rela &Rel : dyn_relas()) {
- SmallString<32> RelocName;
- Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
- StringRef SymbolName;
- uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
- const Elf_Sym *Sym = DynSymStart + SymIndex;
- SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
- if (opts::ExpandRelocs) {
- DictScope Group(W, "Relocation");
- W.printHex("Offset", Rel.r_offset);
- W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
- W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
- W.printHex("Addend", Rel.r_addend);
- }
- else {
- raw_ostream& OS = W.startLine();
- OS << W.hex(Rel.r_offset) << " " << RelocName << " "
- << (SymbolName.size() > 0 ? SymbolName : "-") << " "
- << W.hex(Rel.r_addend) << "\n";
+ if (DynRelaRegion.Size > 0)
+ for (const Elf_Rela &Rela : dyn_relas())
+ printDynamicRelocation(Rela);
+ else
+ for (const Elf_Rel &Rel : dyn_rels()) {
+ Elf_Rela Rela;
+ Rela.r_offset = Rel.r_offset;
+ Rela.r_info = Rel.r_info;
+ Rela.r_addend = 0;
+ printDynamicRelocation(Rela);
}
- }
W.unindent();
W.startLine() << "}\n";
}
@@ -1243,6 +1256,28 @@ void ELFDumper<ELFT>::printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab) {
}
}
+template <class ELFT>
+void ELFDumper<ELFT>::printDynamicRelocation(Elf_Rela Rel) {
+ SmallString<32> RelocName;
+ Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
+ StringRef SymbolName;
+ uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
+ const Elf_Sym *Sym = DynSymStart + SymIndex;
+ SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
+ if (opts::ExpandRelocs) {
+ DictScope Group(W, "Relocation");
+ W.printHex("Offset", Rel.r_offset);
+ W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
+ W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
+ W.printHex("Addend", Rel.r_addend);
+ } else {
+ raw_ostream &OS = W.startLine();
+ OS << W.hex(Rel.r_offset) << " " << RelocName << " "
+ << (SymbolName.size() > 0 ? SymbolName : "-") << " "
+ << W.hex(Rel.r_addend) << "\n";
+ }
+}
+
template<class ELFT>
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) {
const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec;
OpenPOWER on IntegriCloud