diff options
author | Tom Tromey <tromey@redhat.com> | 2012-03-21 08:54:32 -0600 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2012-03-21 16:32:47 +0100 |
commit | 581c3f60e2b1fc7ddaf4260bb5a9cb59f8e3f0d0 (patch) | |
tree | b56cf7ffba1cf97c14e7546029a1fb07e2b53ab7 /tests/typeiter.c | |
parent | 30bb714e7446d35d15cd53b3c794dd8ac08d0a29 (diff) | |
download | elfutils-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.c | 98 |
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); + } +} |