diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2016-01-16 22:40:09 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2016-01-16 22:40:09 +0000 |
commit | 72155c33b10e5ec20fef065a05abc7a7e0311fbf (patch) | |
tree | 66c3b1c9068ba243b4852c476a9eaceed930b77b | |
parent | 20f31fa31a119640dfda40528a25f3b03ae1d818 (diff) | |
download | bcm5719-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-x | llvm/test/Object/Inputs/dyn-rel.so.elf-mips | bin | 0 -> 1946 bytes | |||
-rw-r--r-- | llvm/test/Object/dyn-rel-relocation.test | 71 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 103 |
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 Binary files differnew file mode 100755 index 00000000000..08fe70eae30 --- /dev/null +++ b/llvm/test/Object/Inputs/dyn-rel.so.elf-mips 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 ®ion); + template <typename RELA> + static const RELA *dyn_rela_end(const DynRegionInfo ®ion); + 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; |