[PATCH] Fix bug using dwarf_next_unit to iterate over .debug_types

Tom Tromey tromey at redhat.com
Mon Mar 19 17:46:45 UTC 2012


	* libdw_findcu.c (findcu_cb): Move earlier.
	(__libdw_intern_next_unit): Add new CU to search tree here...
	(__libdw_findcu): ... not here.

If you call dwarf_next_unit to iterate over .debug_types, then call
dwarf_offdie_types, you can see a failure if some earlier call
happened to call __libdw_intern_next_unit via dwarf_formref_die.

What happens is that __libdw_intern_next_unit updates the Dwarf's
next_tu_offset, but does not add the TU to the TU search tree.  So,
the call to dwarf_offdie_types does not find the TU in the tree, and
will not search any more, causing a failure.

This fix changes __libdw_intern_next_unit to add the TU to the search
tree, rather than relying on __libdw_findcu to do it.
---
 libdw/ChangeLog      |    6 ++++
 libdw/libdw_findcu.c |   68 ++++++++++++++++++++++++-------------------------
 2 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 98b67f4..f96c0d1 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2012-03-19  Tom Tromey  <tromey at redhat.com>
+
+	* libdw_findcu.c (findcu_cb): Move earlier.
+	(__libdw_intern_next_unit): Add new CU to search tree here...
+	(__libdw_findcu): ... not here.
+
 2012-01-31  Mark Wielaard  <mjw at redhat.com>
 
 	* dwarf_formudata.c (dwarf_formudata): Handle DW_FORM_sec_offset.
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 8e5f9e9..83c96ba 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -56,6 +56,31 @@
 #include <search.h>
 #include "libdwP.h"
 
+static int
+findcu_cb (const void *arg1, const void *arg2)
+{
+  struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
+  struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
+
+  /* Find out which of the two arguments is the search value.  It has
+     end offset 0.  */
+  if (cu1->end == 0)
+    {
+      if (cu1->start < cu2->start)
+	return -1;
+      if (cu1->start >= cu2->end)
+	return 1;
+    }
+  else
+    {
+      if (cu2->start < cu1->start)
+	return 1;
+      if (cu2->start >= cu1->end)
+	return -1;
+    }
+
+  return 0;
+}
 
 struct Dwarf_CU *
 internal_function
@@ -65,6 +90,7 @@ __libdw_intern_next_unit (dbg, debug_types)
 {
   Dwarf_Off *const offsetp
     = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
+  void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree;
 
   Dwarf_Off oldoff = *offsetp;
   uint16_t version;
@@ -105,34 +131,16 @@ __libdw_intern_next_unit (dbg, debug_types)
   newp->lines = NULL;
   newp->locs = NULL;
 
-  return newp;
-}
-
-
-static int
-findcu_cb (const void *arg1, const void *arg2)
-{
-  struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
-  struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
-
-  /* Find out which of the two arguments is the search value.  It has
-     end offset 0.  */
-  if (cu1->end == 0)
+  /* Add the new entry to the search tree.  */
+  if (tsearch (newp, tree, findcu_cb) == NULL)
     {
-      if (cu1->start < cu2->start)
-	return -1;
-      if (cu1->start >= cu2->end)
-	return 1;
-    }
-  else
-    {
-      if (cu2->start < cu1->start)
-	return 1;
-      if (cu2->start >= cu1->end)
-	return -1;
+      /* Something went wrong.  Undo the operation.  */
+      *offsetp = oldoff;
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
     }
 
-  return 0;
+  return newp;
 }
 
 struct Dwarf_CU *
@@ -160,20 +168,10 @@ __libdw_findcu (dbg, start, debug_types)
   /* No.  Then read more CUs.  */
   while (1)
     {
-      Dwarf_Off oldoff = *next_offset;
       struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, debug_types);
       if (newp == NULL)
 	return NULL;
 
-      /* Add the new entry to the search tree.  */
-      if (tsearch (newp, tree, findcu_cb) == NULL)
-	{
-	  /* Something went wrong.  Undo the operation.  */
-	  *next_offset = oldoff;
-	  __libdw_seterrno (DWARF_E_NOMEM);
-	  return NULL;
-	}
-
       /* Is this the one we are looking for?  */
       if (start < *next_offset)
 	// XXX Match exact offset.
-- 
1.7.7.6



More information about the elfutils-devel mailing list