The scenario goes like this.
* end iterator has an offset of 1
* begin iterator has an offset of 0
* operator ++ does essentially the following:
_m_offset = ::dwarf_getattrs (&_m_die._m_die, &getattrs_callback,
(void *) this, _m_offset);
* operator == takes into account "parental" DIE and _m_offsetgetattrs_callback is done such that it answers CB_OK when called the first time (then it also initializes _m_attr.value), and CB_ABORT when called the second time. This way dwarf_getattrs returns the position of _next_ attribute in sequence. But that means that when the last argument is loaded in _m_attr, _m_offset already has a value of 1, and evaluates as equal to the end iterator.
As a fix for that, I propose to consider also NULL-ness of _m_attr.value when doing the iterator comparison. On empty sequences, the callback is never called, thus leaving _m_attr.value NULL. On sequence of one element, _m_offset will end up being 1, but _m_attr.value will be non-NULL. Only after the call to ++ will _m_attr.value become NULL, and dwarf_getattrs, seeing offset of 1, will immediately return 1 again without calling the callback. Etc.
Patch attached. PM
From 3e9c7e605e666ef32d1dddd93f9d303ebd801e67 Mon Sep 17 00:00:00 2001 From: Petr Machata <[email protected]> Date: Tue, 24 Mar 2009 15:04:53 +0100 Subject: [PATCH] <dwarf>: Don't swallow last attribute --- libdw/ChangeLog | 5 +++++ libdw/c++/dwarf | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index fc08176..d68075d 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,8 @@ +2009-03-24 Petr Machata <[email protected]> + + * c++/dwarf (dwarf::debug_info_entry::raw_attributes): + Fix iteration over attributes. + 2009-02-26 Roland McGrath <[email protected]> * c++/dwarf (dwarf::attr_value): Add _m_tag private member. diff --git a/libdw/c++/dwarf b/libdw/c++/dwarf index 862b9a1..33e7250 100644 --- a/libdw/c++/dwarf +++ b/libdw/c++/dwarf @@ -626,7 +626,10 @@ namespace elfutils } inline const_iterator (const debug_info_entry &die, ptrdiff_t offset) - : _m_die (die), _m_offset (offset) {} + : _m_die (die), _m_offset (offset) + { + _m_attr.valp = NULL; + } public: inline const_iterator (const const_iterator &i) @@ -643,7 +646,8 @@ namespace elfutils inline bool operator== (const const_iterator &other) const { return (_m_die._m_die.addr == other._m_die._m_die.addr - && _m_offset == other._m_offset); + && _m_offset == other._m_offset + && !_m_attr.valp == !other._m_attr.valp); } inline bool operator!= (const const_iterator &other) const { @@ -659,6 +663,7 @@ namespace elfutils _m_offset = result; return *this; } + inline const_iterator operator++ (int) // postfix { const_iterator prev = *this; @@ -668,7 +673,7 @@ namespace elfutils inline attribute operator* () const { - if (unlikely (_m_offset == 1)) + if (unlikely (_m_offset == 1 && _m_attr.valp == NULL)) throw std::runtime_error ("dereferencing end iterator"); return attribute (_m_die, _m_attr); } -- 1.6.0.6
signature.asc
Description: OpenPGP digital signature
_______________________________________________ elfutils-devel mailing list [email protected] https://fedorahosted.org/mailman/listinfo/elfutils-devel
