summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2011-02-21 15:21:51 +0100
committerMark Wielaard <[email protected]>2011-02-21 15:21:51 +0100
commitca079340174bcc33a001198747062a31576b6772 (patch)
treea821d5d7c17670a13776a8245f6f459b9a9ceafc
parentbb6c7a364ee0fcd7b473335498746517e2cf507f (diff)
Add reference chain cycle detection.
-rw-r--r--libdw/c++/dwarf_output35
1 files changed, 28 insertions, 7 deletions
diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output
index 7b948310..d2cc7f6d 100644
--- a/libdw/c++/dwarf_output
+++ b/libdw/c++/dwarf_output
@@ -1382,7 +1382,7 @@ namespace elfutils
typedef typename final_children_getter::
template copy<debug_info_entry::children_type> get_final_children;
- inline size_t get_reference_hash () const
+ inline size_t get_reference_hash (std::vector<const entry *> &stack) const
{
assert (_m_info != NULL);
@@ -1401,7 +1401,7 @@ namespace elfutils
const entry *ref
= dynamic_cast<const entry *> (it->second._m_value);
if (ref != NULL)
- attr_rhashes ^= ref->get_reference_hash ();
+ attr_rhashes ^= ref->get_reference_hash (stack);
}
subr::hash_combine (rhash, attr_rhashes);
@@ -1720,7 +1720,9 @@ namespace elfutils
already. At this point all entries are still pending. */
inline void setup_reference_hash () const
{
- _m_pending->_m_info->_m_reference_hash = get_reference_hash ();
+ std::vector<const entry *> stack;
+ _m_pending->_m_info->_m_reference_hash = get_reference_hash (stack);
+ assert (stack.empty ());
for (typename std::vector<entry *>::const_iterator it
= _m_pending->_m_children.begin ();
@@ -1729,11 +1731,30 @@ namespace elfutils
(*it)->setup_reference_hash ();
}
- inline size_t get_reference_hash () const
+ inline size_t get_reference_hash (std::vector<const entry *> &stack) const
{
- // XXX Need some recursion detection to assert we aren't
- // running in circles. Probably just pass in stack of entries.
- return _m_pending->get_reference_hash ();
+ if (std::find (stack.begin (), stack.end (), this) != stack.end ())
+ {
+ std::cout << "Reference chain cycle detected\n"
+ << "offset=[0x" << std::hex << _m_offset << std::dec
+ << "] already on the reference chain stack\n";
+ typename std::vector<const entry *>::iterator it;
+ for (it = stack.begin ();
+ it != stack.end ();
+ it++)
+ {
+ std::cout << "offset=[0x" << std::hex << (*it)->_m_offset
+ << std::dec << "] "
+ << dwarf::tags::name ((*it)->_m_pending->_m_tag)
+ << "\n";
+ }
+ abort ();
+ }
+
+ stack.push_back (this);
+ size_t res = _m_pending->get_reference_hash (stack);
+ stack.pop_back ();
+ return res;
}
// Attempt to turn the pending entry into a final entry.