summaryrefslogtreecommitdiff
path: root/tests/typeiter.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2012-03-21 08:54:32 -0600
committerMark Wielaard <mjw@redhat.com>2012-03-21 16:32:47 +0100
commit581c3f60e2b1fc7ddaf4260bb5a9cb59f8e3f0d0 (patch)
treeb56cf7ffba1cf97c14e7546029a1fb07e2b53ab7 /tests/typeiter.c
parent30bb714e7446d35d15cd53b3c794dd8ac08d0a29 (diff)
downloadelfutils-581c3f60e2b1fc7ddaf4260bb5a9cb59f8e3f0d0.tar.gz
Fix bug using dwarf_next_unit to iterate over .debug_types
* 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.
Diffstat (limited to 'tests/typeiter.c')
-rw-r--r--tests/typeiter.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/tests/typeiter.c b/tests/typeiter.c
new file mode 100644
index 00000000..184b00be
--- /dev/null
+++ b/tests/typeiter.c
@@ -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);
+ }
+}