[llvm] r333635 - DWARFAcceleratorTable: fix equal_range iterators

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Thu May 31 01:47:00 PDT 2018


Author: labath
Date: Thu May 31 01:47:00 2018
New Revision: 333635

URL: http://llvm.org/viewvc/llvm-project?rev=333635&view=rev
Log:
DWARFAcceleratorTable: fix equal_range iterators

Summary:
Both (Apple and DWARF5) implementations of the iterators had bugs which
resulted in crashes if one attempted to iterate through the accelerator
tables all the way.

For the Apple tables, the issue was that we did not clear the DataOffset
field when we reached the end, which made our iterator compare unequal
to the "end" iterator. For the Dwarf5 tables, the problem was that we
incremented the CurrentIndex pointer and then used the incremented
(possibly invalid) pointer to check whether we have reached the end of
the index list.

The reason these bugs went undetected is because their only user
(dwarfdump) only ever searched for the first match. Besides allowing us
to test this fix, changing llvm-dwarfdump --find to display all matches
seems like a good improvement (it makes the behavior consistent with the
--name option), so I change llvm-dwarfdump to do that.

The existing tests would be sufficient to test this fix with the new
llvm-dwarfdump behavior, but I add a special test that demonstrates that
the tool indeed displays multiple results. The find.test test needed to
be tweaked a bit as the tool now does not print the ".debug_info
contents" header (also consistent with how --name works).

Reviewers: JDevlieghere, aprantl, dblaikie

Subscribers: mgrang, llvm-commits

Differential Revision: https://reviews.llvm.org/D47543

Added:
    llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s
Modified:
    llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/trunk/test/tools/llvm-dwarfdump/X86/find.test
    llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp?rev=333635&r1=333634&r2=333635&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp Thu May 31 01:47:00 2018
@@ -312,6 +312,7 @@ void AppleAcceleratorTable::ValueIterato
   if (Data >= NumData ||
       !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
     NumData = 0;
+    DataOffset = 0;
     return;
   }
   Current.extract(*AccelTable, &DataOffset);
@@ -849,8 +850,8 @@ void DWARFDebugNames::ValueIterator::nex
   if (getEntryAtCurrentOffset())
     return;
 
-  // If we're a local iterator, we're done.
-  if (IsLocal) {
+  // If we're a local iterator or we have reached the last Index, we're done.
+  if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
     setEnd();
     return;
   }

Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s?rev=333635&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s (added)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s Thu May 31 01:47:00 2018
@@ -0,0 +1,92 @@
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj -o %t
+# RUN: llvm-dwarfdump -find=foo - <%t | FileCheck %s
+
+# CHECK: 12: DW_TAG_subprogram
+# CHECK-NEXT: DW_AT_name ("foo")
+# CHECK-NEXT: DW_AT_external
+# CHECK: 17: DW_TAG_subprogram
+# CHECK-NEXT: DW_AT_name ("foo")
+# CHECK-NEXT: DW_AT_external
+
+	.section	.debug_str,"MS", at progbits,1
+.Lstring_foo:
+	.asciz	"foo"
+.Lstring_producer:
+	.asciz	"Hand-written dwarf"
+
+	.section	.debug_abbrev,"", at progbits
+.Lsection_abbrev:
+	.byte	1                       # Abbreviation Code
+	.byte	17                      # DW_TAG_compile_unit
+	.byte	1                       # DW_CHILDREN_yes
+	.byte	37                      # DW_AT_producer
+	.byte	14                      # DW_FORM_strp
+	.byte	19                      # DW_AT_language
+	.byte	5                       # DW_FORM_data2
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	2                       # Abbreviation Code
+	.byte	46                      # DW_TAG_subprogram
+	.byte	0                       # DW_CHILDREN_no
+	.byte	3                       # DW_AT_name
+	.byte	14                      # DW_FORM_strp
+	.byte	63                      # DW_AT_external
+	.byte	25                      # DW_FORM_flag_present
+	.byte	0                       # EOM(1)
+	.byte	0                       # EOM(2)
+	.byte	0                       # EOM(3)
+
+	.section	.debug_info,"", at progbits
+.Lcu_begin0:
+	.long	.Lcu_end0-.Lcu_start0   # Length of Unit
+.Lcu_start0:
+	.short	4                       # DWARF version number
+	.long	.Lsection_abbrev        # Offset Into Abbrev. Section
+	.byte	8                       # Address Size (in bytes)
+	.byte	1                       # Abbrev [1] DW_TAG_compile_unit
+	.long	.Lstring_producer       # DW_AT_producer
+	.short	12                      # DW_AT_language
+.Ldie_foo:
+	.byte	2                       # Abbrev [2] DW_TAG_subprogram
+	.long	.Lstring_foo            # DW_AT_name
+                                        # DW_AT_external
+.Ldie_foo2:
+	.byte	2                       # Abbrev [2] DW_TAG_subprogram
+	.long	.Lstring_foo            # DW_AT_name
+                                        # DW_AT_external
+	.byte	0                       # End Of Children Mark
+.Lcu_end0:
+
+	.section	.debug_names,"", at progbits
+	.long	.Lnames_end0-.Lnames_start0 # Header: contribution length
+.Lnames_start0:
+	.short	5                       # Header: version
+	.short	0                       # Header: padding
+	.long	1                       # Header: compilation unit count
+	.long	0                       # Header: local type unit count
+	.long	0                       # Header: foreign type unit count
+	.long	0                       # Header: bucket count
+	.long	1                       # Header: name count
+	.long	.Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+	.long	0                       # Header: augmentation length
+	.long	.Lcu_begin0             # Compilation unit 0
+	.long	.Lstring_foo            # String in Bucket 0: foo
+	.long	.Lnames0-.Lnames_entries0 # Offset in Bucket 0
+.Lnames_abbrev_start0:
+	.byte	46                      # Abbrev code
+	.byte	46                      # DW_TAG_subprogram
+	.byte	3                       # DW_IDX_die_offset
+	.byte	19                      # DW_FORM_ref4
+	.byte	0                       # End of abbrev
+	.byte	0                       # End of abbrev
+	.byte	0                       # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+	.byte	46                      # Abbrev code
+	.long	.Ldie_foo-.Lcu_begin0   # DW_IDX_die_offset
+	.byte	46                      # Abbrev code
+	.long	.Ldie_foo2-.Lcu_begin0  # DW_IDX_die_offset
+	.long	0                       # End of list: foo
+	.p2align	2
+.Lnames_end0:

Modified: llvm/trunk/test/tools/llvm-dwarfdump/X86/find.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/find.test?rev=333635&r1=333634&r2=333635&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/find.test (original)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/find.test Thu May 31 01:47:00 2018
@@ -5,8 +5,6 @@ EMPTY: {{^$}}
 
 RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
 RUN:   | llvm-dwarfdump -find=main - | FileCheck %s
-CHECK: .debug_info contents:
-CHECK-NOT: {{:}}
 CHECK: : DW_TAG_subprogram
 CHECK-NOT: {{:}}
 CHECK:     DW_AT_name ("main")
@@ -15,13 +13,13 @@ CHECK-NOT: {{:}}
 RUN: llvm-dwarfdump %S/../../dsymutil/Inputs/libfat-test.a \
 RUN:   -find=x86_64h_var -find=i386_var \
 RUN:   | FileCheck %s --check-prefix=MULTI
-MULTI: .debug_info contents:
+MULTI: libfat-test.a(i386)
 MULTI-NOT: {{: DW}}
 MULTI: : DW_TAG_variable
 MULTI-NOT: {{: DW}}
 MULTI:    DW_AT_name ("i386_var")
+MULTI: libfat-test.a(x86_64h)
 MULTI-NOT: {{: DW}}
-MULTI: .debug_info contents:
 MULTI: : DW_TAG_variable
 MULTI-NOT: {{: DW}}
 MULTI:    DW_AT_name ("x86_64h_var")
@@ -29,8 +27,6 @@ MULTI-NOT: {{: DW}}
 
 RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \
 RUN:   | llvm-dwarfdump -find=int - | FileCheck %s --check-prefix=TYPES
-TYPES: .debug_info contents:
-TYPES-NOT: {{:}}
 TYPES: : DW_TAG_base_type
 TYPES-NOT: {{:}}
 TYPES:     DW_AT_name ("int")

Modified: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp?rev=333635&r1=333634&r2=333635&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp (original)
+++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp Thu May 31 01:47:00 2018
@@ -309,6 +309,33 @@ static void filterByName(const StringSet
 
 }
 
+template <typename AccelTable>
+static void getDIEOffset(const AccelTable &Accel, StringRef Name,
+                         SmallVectorImpl<uint64_t> &Offsets) {
+  for (const auto &Entry : Accel.equal_range(Name))
+    if (llvm::Optional<uint64_t> Off = Entry.getDIESectionOffset())
+      Offsets.push_back(*Off);
+}
+
+/// Print only DIEs that have a certain name.
+static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
+                              raw_ostream &OS) {
+  SmallVector<uint64_t, 4> Offsets;
+  for (const auto &Name : Names) {
+    getDIEOffset(DICtx.getAppleNames(), Name, Offsets);
+    getDIEOffset(DICtx.getAppleTypes(), Name, Offsets);
+    getDIEOffset(DICtx.getAppleNamespaces(), Name, Offsets);
+    getDIEOffset(DICtx.getDebugNames(), Name, Offsets);
+  }
+  llvm::sort(Offsets.begin(), Offsets.end());
+  Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
+
+  for (uint64_t Off: Offsets) {
+    DWARFDie Die = DICtx.getDIEForOffset(Off);
+    Die.dump(OS, 0, getDumpOpts());
+  }
+}
+
 /// Handle the --lookup option and dump the DIEs and line info for the given
 /// address.
 static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) {
@@ -335,15 +362,6 @@ static bool lookup(DWARFContext &DICtx,
 bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
                                Twine Filename, raw_ostream &OS);
 
-template <typename AccelTable>
-static llvm::Optional<uint64_t> getDIEOffset(const AccelTable &Accel,
-                                       StringRef Name) {
-  for (const auto &Entry : Accel.equal_range(Name))
-    if (llvm::Optional<uint64_t> Off = Entry.getDIESectionOffset())
-      return *Off;
-  return None;
-}
-
 static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename,
                            raw_ostream &OS) {
   logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(),
@@ -369,22 +387,8 @@ static bool dumpObjectFile(ObjectFile &O
 
   // Handle the --find option and lower it to --debug-info=<offset>.
   if (!Find.empty()) {
-    DumpOffsets[DIDT_ID_DebugInfo] = [&]() -> llvm::Optional<uint64_t> {
-      for (auto Name : Find) {
-        if (auto Offset = getDIEOffset(DICtx.getAppleNames(), Name))
-          return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-        if (auto Offset = getDIEOffset(DICtx.getAppleTypes(), Name))
-          return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-        if (auto Offset = getDIEOffset(DICtx.getAppleNamespaces(), Name))
-          return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-        if (auto Offset = getDIEOffset(DICtx.getDebugNames(), Name))
-          return DumpOffsets[DIDT_ID_DebugInfo] = *Offset;
-      }
-      return None;
-    }();
-    // Early exit if --find was specified but the current file doesn't have it.
-    if (!DumpOffsets[DIDT_ID_DebugInfo])
-      return true;
+    filterByAccelName(Find, DICtx, OS);
+    return true;
   }
 
   // Dump the complete DWARF structure.




More information about the llvm-commits mailing list