Index: test/Object/dyn-rel-relocation.test =================================================================== --- /dev/null +++ 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: } Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -75,6 +75,7 @@ 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 @@ 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 + static const RELA *dyn_rela_begin(const DynRegionInfo ®ion); + template + 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 @@ 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 @@ GnuHashTable = reinterpret_cast(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 @@ } template -const typename ELFDumper::Elf_Rela * -ELFDumper::dyn_rela_begin() const { - if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela)) +template +const RELA *ELFDumper::dyn_rela_begin(const DynRegionInfo &Region) { + if (Region.Size && Region.EntSize != sizeof(RELA)) report_fatal_error("Invalid relocation entry size"); - return reinterpret_cast(DynRelaRegion.Addr); + return reinterpret_cast(Region.Addr); } template -const typename ELFDumper::Elf_Rela * -ELFDumper::dyn_rela_end() const { - uint64_t Size = DynRelaRegion.Size; - if (Size % sizeof(Elf_Rela)) +template +const RELA *ELFDumper::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(Region) + Size / sizeof(RELA); +} + +template +typename ELFDumper::Elf_Rel_Range ELFDumper::dyn_rels() const { + return make_range(dyn_rela_begin(DynRelRegion), + dyn_rela_end(DynRelRegion)); } template typename ELFDumper::Elf_Rela_Range ELFDumper::dyn_relas() const { - return make_range(dyn_rela_begin(), dyn_rela_end()); + return make_range(dyn_rela_begin(DynRelaRegion), + dyn_rela_end(DynRelaRegion)); } template @@ -1158,31 +1180,22 @@ } } -template -void ELFDumper::printDynamicRelocations() { +template void ELFDumper::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 @@ } } +template +void ELFDumper::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 void ELFDumper::printSymbolsHelper(bool IsDynamic) { const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec;