]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Fix bug using dwarf_next_unit to iterate over .debug_types
authorTom Tromey <tromey@redhat.com>
Wed, 21 Mar 2012 14:54:32 +0000 (08:54 -0600)
committerMark Wielaard <mjw@redhat.com>
Wed, 21 Mar 2012 15:32:47 +0000 (16:32 +0100)
* libdw_findcu.c (findcu_cb): Move earlier.
(__libdw_intern_next_unit): Add new CU to search tree here...
(__libdw_findcu): ... not here.

* typeiter.c: New file.
* run-typeiter.sh: New file.
* testfile59.bz2: New file.
* Makefile.am (noinst_PROGRAMS): Add typeiter.
(TESTS): Add run-typeiter.sh.
(EXTRA_DIST): Add run-typeiter.sh, testfile59.bz2.
(typeiter_LDADD): New variable.

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
libdw/libdw_findcu.c
tests/ChangeLog
tests/Makefile.am
tests/run-typeiter.sh [new file with mode: 0755]
tests/testfile59.bz2 [new file with mode: 0755]
tests/typeiter.c [new file with mode: 0644]

index 98b67f4a7ea1e7e06c924b781f17a75311c9fb07..f96c0d1ba13604d37b60c5633f23145dc3f2fa63 100644 (file)
@@ -1,3 +1,9 @@
+2012-03-19  Tom Tromey  <tromey@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@redhat.com>
 
        * dwarf_formudata.c (dwarf_formudata): Handle DW_FORM_sec_offset.
index 8e5f9e9b1285ad6293cb44d91076549af501e20a..83c96bafdab4b57a23413168f00438b7aeda5ccf 100644 (file)
 #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.
index a7825911e2f8b23c37e198dbb6c24bc78128c8de..8d2b83f18623740b691244383bc3dcaf115f136e 100644 (file)
@@ -1,3 +1,13 @@
+2012-03-21  Tom Tromey  <tromey@redhat.com>
+
+       * typeiter.c: New file.
+       * run-typeiter.sh: New file.
+       * testfile59.bz2: New file.
+       * Makefile.am (noinst_PROGRAMS): Add typeiter.
+       (TESTS): Add run-typeiter.sh.
+       (EXTRA_DIST): Add run-typeiter.sh, testfile59.bz2.
+       (typeiter_LDADD): New variable.
+
 2012-02-21  Kurt Roeckx  <kurt@roeckx.be>
 
        * run-alldts.sh: testrun ./alldts.
index 3074c893496b8f3bb9bab2dcc1de3070271153f2..f2c211b563a24bc8ce8ae677332e434c0fbcc31a 100644 (file)
@@ -58,7 +58,7 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
                  dwfl-addr-sect dwfl-bug-report early-offscn \
                  dwfl-bug-getmodules dwarf-getmacros addrcfi \
                  test-flag-nobits dwarf-getstring rerequest_tag \
-                 alldts md5-sha1-test
+                 alldts md5-sha1-test typeiter
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
            asm-tst6 asm-tst7 asm-tst8 asm-tst9
 
@@ -86,7 +86,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
        run-disasm-x86.sh run-disasm-x86-64.sh \
        run-early-offscn.sh run-dwarf-getmacros.sh \
        run-test-flag-nobits.sh run-prelink-addr-test.sh \
-       run-dwarf-getstring.sh run-rerequest_tag.sh
+       run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh
 # run-show-ciefde.sh
 
 if !STANDALONE
@@ -161,7 +161,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
             testfile55-32.bz2 testfile55-32.debug.bz2 \
             testfile55-32.prelink.bz2 testfile55-64.bz2 \
             testfile55-64.debug.bz2 testfile55-64.prelink.bz2 \
-            testfile56.bz2 testfile57.bz2 testfile58.bz2
+            testfile56.bz2 testfile57.bz2 testfile58.bz2 \
+            run-typeiter.sh testfile59.bz2
 
 installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \
                              bindir=$(DESTDIR)$(bindir) \
@@ -258,6 +259,7 @@ test_flag_nobits_LDADD = $(libelf) $(libmudflap)
 rerequest_tag_LDADD = $(libdw) $(libmudflap)
 alldts_LDADD = $(libebl) $(libelf) $(libmudflap)
 md5_sha1_test_LDADD = $(libeu)
+typeiter_LDADD = $(libdw) $(libelf) $(libmudflap)
 
 if GCOV
 check: check-am coverage
diff --git a/tests/run-typeiter.sh b/tests/run-typeiter.sh
new file mode 100755 (executable)
index 0000000..4f650ca
--- /dev/null
@@ -0,0 +1,58 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of Red Hat elfutils.
+#
+# Red Hat elfutils is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# Red Hat elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with Red Hat elfutils; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+#
+# Red Hat elfutils is an included package of the Open Invention Network.
+# An included package of the Open Invention Network is a package for which
+# Open Invention Network licensees cross-license their patents.  No patent
+# license is granted, either expressly or impliedly, by designation as an
+# included package.  Should you wish to participate in the Open Invention
+# Network licensing program, please visit www.openinventionnetwork.com
+# <http://www.openinventionnetwork.com>.
+
+. $srcdir/test-subr.sh
+
+# struct s1
+# {
+#   char c;
+#   short s;
+#   int i;
+#   long l;
+#   float f;
+#   double d;
+# };
+# 
+# s1 S1;
+# 
+# int func (s1 *p)
+# {
+#   return p->i;
+# }
+# 
+# int main()
+# {
+#   return func (&S1);
+# }
+#
+# g++ -gdwarf-4 -g -fdebug-types-section
+
+testfiles testfile59
+
+testrun_compare ./typeiter testfile59 <<\EOF
+ok
+EOF
+
+exit 0
diff --git a/tests/testfile59.bz2 b/tests/testfile59.bz2
new file mode 100755 (executable)
index 0000000..bcee648
Binary files /dev/null and b/tests/testfile59.bz2 differ
diff --git a/tests/typeiter.c b/tests/typeiter.c
new file mode 100644 (file)
index 0000000..184b00b
--- /dev/null
@@ -0,0 +1,98 @@
+/* Copyright (C) 2012 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+#include <dwarf.h>
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; ++i)
+    {
+      int fd = open (argv[i], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg != NULL)
+       {
+         Dwarf_Off off = 0;
+         size_t cuhl;
+         Dwarf_Off noff;
+
+         while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+           {
+             Dwarf_Die die_mem;
+             Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem);
+
+             Dwarf_Die iter_mem;
+             Dwarf_Die *iter = &iter_mem;
+             dwarf_child (die, &iter_mem);
+
+             while (1)
+               {
+                 if (dwarf_tag (iter) == DW_TAG_variable)
+                   {
+                     Dwarf_Attribute attr_mem;
+                     Dwarf_Die form_mem;
+                     dwarf_formref_die (dwarf_attr (iter, DW_AT_type,
+                                                    &attr_mem),
+                                        &form_mem);
+                   }
+
+                 if (dwarf_siblingof (iter, &iter_mem) != 0)
+                   break;
+               }
+
+             off = noff;
+           }
+
+         off = 0;
+         uint64_t type_sig;
+
+         while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL,
+                                 NULL, &type_sig, NULL) == 0)
+           {
+             Dwarf_Die die_mem;
+             Dwarf_Die *die = dwarf_offdie_types (dbg, off + cuhl, &die_mem);
+
+             if (die == NULL)
+               printf ("fail\n");
+             else
+               printf ("ok\n");
+
+             off = noff;
+           }
+
+         dwarf_end (dbg);
+       }
+
+      close (fd);
+    }
+}