diff options
| author | Tom Tromey <[email protected]> | 2012-03-21 08:54:32 -0600 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2012-03-21 16:32:47 +0100 |
| commit | 581c3f60e2b1fc7ddaf4260bb5a9cb59f8e3f0d0 (patch) | |
| tree | b56cf7ffba1cf97c14e7546029a1fb07e2b53ab7 /libdw/libdw_findcu.c | |
| parent | 30bb714e7446d35d15cd53b3c794dd8ac08d0a29 (diff) | |
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 'libdw/libdw_findcu.c')
| -rw-r--r-- | libdw/libdw_findcu.c | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 8e5f9e9b..83c96baf 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. |
