From: George Rimar Date: Thu, 28 Feb 2019 08:15:59 +0000 (+0000) Subject: [llvm-readobj] - Fix the invalid dumping of the dynamic sections without terminating... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f14213bb4cd958aeeb0222c5e28e9b4538846232;p=llvm [llvm-readobj] - Fix the invalid dumping of the dynamic sections without terminating DT_NULL entry. This is https://bugs.llvm.org/show_bug.cgi?id=40861, Previously llvm-readobj would print the DT_NULL sometimes for the dynamic section that has no terminator entry. The logic of printDynamicTable was a bit overcomplicated. I rewrote it slightly to fix the issue and commented. Differential revision: https://reviews.llvm.org/D58716 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355073 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/tools/llvm-readobj/elf-dynamic-table-dtnull.s b/test/tools/llvm-readobj/elf-dynamic-table-dtnull.s new file mode 100644 index 00000000000..8bb8d055bfb --- /dev/null +++ b/test/tools/llvm-readobj/elf-dynamic-table-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-prefix=NONULL +# RUN: llvm-readelf --dynamic-table %t.o | FileCheck %s --check-prefix=NONULL + +# NONULL: DynamicSection [ (1 entries) +# NONULL-NEXT: Tag Type Name/Value +# NONULL-NEXT: 0x0000000000000015 DEBUG 0x0 +# NONULL-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: .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 +# RUN: llvm-readelf --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: .dynamic + - Type: PT_DYNAMIC + VAddr: 0x1010 + Sections: + - Section: .dynamic diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 3597acfe061..410ab3f87ca 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -1914,35 +1914,29 @@ template <> void ELFDumper::printUnwindInfo() { 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 + // a DT_NULL entry. However, sometimes the section content may continue + // past the DT_NULL entry, so to dump the section correctly, we first find + // the end of the entries by iterating over them. + 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());