Index: test/tools/llvm-readobj/elf-no-dtnull.s =================================================================== --- /dev/null +++ test/tools/llvm-readobj/elf-no-dtnull.s @@ -0,0 +1,78 @@ +# Check we are able to dump the dynamic section without a DT_NULL entry correctly. + +# RUN: yaml2obj -docnum=1 %s -o %t.o +# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s + +# CHECK: DynamicSection [ (1 entries) +# CHECK-NEXT: Tag Type Name/Value +# CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 +# CHECK-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Address: 0x0000000000001010 + AddressAlign: 0x0000000000000010 + EntSize: 0x0000000000000010 + Entries: + - Tag: DT_DEBUG + Value: 0x0000000000000000 +ProgramHeaders: + - Type: PT_LOAD + VAddr: 0x1000 + Sections: + - Section: .dynstr + - Section: .dynamic + - Type: PT_DYNAMIC + VAddr: 0x1010 + Sections: + - Section: .dynamic + +# Sometimes .dynamic section content length can be greater than the +# length of its entries. In this case, we should not try to dump anything +# past the DT_NULL entry, which works as a terminator. + +# RUN: yaml2obj -docnum=2 %s -o %t.o +# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s --check-prefix=LONG + +# LONG: DynamicSection [ (2 entries) +# LONG-NEXT: Tag Type Name/Value +# LONG-NEXT: 0x0000000000000015 DEBUG 0x0 +# LONG-NEXT: 0x0000000000000000 NULL 0x0 +# LONG-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Address: 0x0000000000001010 + AddressAlign: 0x0000000000000010 + EntSize: 0x0000000000000010 + Entries: + - Tag: DT_DEBUG + Value: 0x0000000000000000 + - Tag: DT_NULL + Value: 0x0000000000000000 + - Tag: DT_NULL + Value: 0x0000000000000000 +ProgramHeaders: + - Type: PT_LOAD + VAddr: 0x1000 + Sections: + - Section: .dynstr + - Section: .dynamic + - Type: PT_DYNAMIC + VAddr: 0x1010 + Sections: + - Section: .dynamic Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -1914,35 +1914,29 @@ template void ELFDumper::printDynamicTable() { - auto I = dynamic_table().begin(); - auto E = dynamic_table().end(); - - if (I == E) - return; - - --E; - while (I != E && E->getTag() == ELF::DT_NULL) - --E; - if (E->getTag() != ELF::DT_NULL) - ++E; - ++E; + // A valid .dynamic section contains an array of entries terminated with an + // DT_NULL entry. But sometimes section content might overpass that barrier + // and so to dump this section correctly we should find the end of entries at + // first. Here we iterate over all of them to do that. + size_t Size = 0; + Elf_Dyn_Range DynTableEntries = dynamic_table(); + for (; Size < DynTableEntries.size();) + if (DynTableEntries[Size++].getTag() == DT_NULL) + break; - ptrdiff_t Total = std::distance(I, E); - if (Total == 0) + if (!Size) return; raw_ostream &OS = W.getOStream(); - W.startLine() << "DynamicSection [ (" << Total << " entries)\n"; + W.startLine() << "DynamicSection [ (" << Size << " entries)\n"; bool Is64 = ELFT::Is64Bits; - W.startLine() << " Tag" << (Is64 ? " " : " ") << "Type" << " " << "Name/Value\n"; - while (I != E) { - const Elf_Dyn &Entry = *I; + for (size_t I = 0; I < Size; ++I) { + const Elf_Dyn &Entry = DynTableEntries[I]; uintX_t Tag = Entry.getTag(); - ++I; W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, opts::Output != opts::GNU) << " " << format("%-21s", getTypeString(ObjF->getELFFile()->getHeader()->e_machine, Tag)); printValue(Tag, Entry.getVal());