[llvm] r258001 - [llvm-readobj][ELF] Teach llvm-readobj to show dynamic relocation in REL format

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 16 14:40:09 PST 2016


Author: atanasyan
Date: Sat Jan 16 16:40:09 2016
New Revision: 258001

URL: http://llvm.org/viewvc/llvm-project?rev=258001&view=rev
Log:
[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

Added:
    llvm/trunk/test/Object/Inputs/dyn-rel.so.elf-mips   (with props)
    llvm/trunk/test/Object/dyn-rel-relocation.test
Modified:
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp

Added: llvm/trunk/test/Object/Inputs/dyn-rel.so.elf-mips
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/dyn-rel.so.elf-mips?rev=258001&view=auto
==============================================================================
Binary files llvm/trunk/test/Object/Inputs/dyn-rel.so.elf-mips (added) and llvm/trunk/test/Object/Inputs/dyn-rel.so.elf-mips Sat Jan 16 16:40:09 2016 differ

Propchange: llvm/trunk/test/Object/Inputs/dyn-rel.so.elf-mips
------------------------------------------------------------------------------
    svn:executable = *

Added: llvm/trunk/test/Object/dyn-rel-relocation.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/dyn-rel-relocation.test?rev=258001&view=auto
==============================================================================
--- llvm/trunk/test/Object/dyn-rel-relocation.test (added)
+++ llvm/trunk/test/Object/dyn-rel-relocation.test Sat Jan 16 16:40:09 2016
@@ -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, at object
+//   .size  v1,4
+// v1:
+//   .word 0
+// 
+//   .globl v2
+//   .type  v2, at 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: }

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=258001&r1=258000&r2=258001&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Sat Jan 16 16:40:09 2016
@@ -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
       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
 }
 
 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";
 }
@@ -1242,6 +1255,28 @@ void ELFDumper<ELFT>::printRelocation(El
        << W.hex(Rel.r_addend) << "\n";
   }
 }
+
+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) {




More information about the llvm-commits mailing list