diff options
| author | Roland McGrath <[email protected]> | 2009-07-01 16:18:28 -0700 |
|---|---|---|
| committer | Roland McGrath <[email protected]> | 2009-07-01 16:18:28 -0700 |
| commit | 0dc95300ccad0554456be0186a7740181b5dd9b4 (patch) | |
| tree | de545f5c85799b1a309c020257e0ee244a764bb5 | |
| parent | 609af3f5dd3064e2f0f0434a413ed0bae9908470 (diff) | |
more fiddling
| -rw-r--r-- | libdw/c++/dwarf_comparator | 142 | ||||
| -rw-r--r-- | libdw/c++/dwarf_tracker | 170 | ||||
| -rwxr-xr-x | tests/run-dwarfcmp-self.sh | 9 |
3 files changed, 162 insertions, 159 deletions
diff --git a/libdw/c++/dwarf_comparator b/libdw/c++/dwarf_comparator index 4f0f470c..d0c18f24 100644 --- a/libdw/c++/dwarf_comparator +++ b/libdw/c++/dwarf_comparator @@ -68,18 +68,27 @@ namespace elfutils typedef typename dwarf1_die::attributes_type::const_iterator attr1; typedef typename dwarf2_die::attributes_type::const_iterator attr2; - inline void start_walk (const cu1 &a, const cu2 &b) - { - } - inline void finish_walk (const cu1 &a, const cu2 &b) - { - } - inline void pre_order (const die1 &a, const die2 &b) + // This object is created to start a walk and destroyed to finish one. + struct walk { - } - inline void post_order (const die1 &a, const die2 &b) + inline walk (dwarf_tracker_base *, const cu1 &a, const cu2 &b) + { + } + inline ~walk () + { + } + }; + + // This object is created in pre-order and destroyed in post-order. + struct step { - } + inline step (dwarf_tracker_base *, const die1 &a, const die2 &b) + { + } + inline ~step () + { + } + }; inline void visit (const typename dwarf1::debug_info_entry &a, const typename dwarf2::debug_info_entry &b) @@ -169,55 +178,6 @@ namespace elfutils }; - struct dwarf_tracker_utils - { - /* A walk object does start_walk when constructed and finish_walk - when destroyed, so finish_walk always runs even for exceptions. */ - template<typename tracker> - struct walk - { - typedef typename tracker::cu1 cu1; - typedef typename tracker::cu2 cu2; - - tracker *_m_walker; - const cu1 &_m_a; - const cu2 &_m_b; - - inline walk (tracker *w, const cu1 &a, const cu2 &b) - : _m_walker (w), _m_a (a), _m_b (b) - { - _m_walker->start_walk (_m_a, _m_b); - } - inline ~walk () - { - _m_walker->finish_walk (_m_a, _m_b); - } - }; - - /* A step object does pre_order when constructed and post_order - when destroyed, so post_order always runs even for exceptions. */ - template<typename tracker> - struct step - { - typedef typename tracker::die1 die1; - typedef typename tracker::die2 die2; - - tracker *_m_walker; - const die1 &_m_a; - const die2 &_m_b; - - inline step (tracker *w, const die1 &a, const die2 &b) - : _m_walker (w), _m_a (a), _m_b (b) - { - _m_walker->pre_order (_m_a, _m_b); - } - inline ~step () - { - _m_walker->post_order (_m_a, _m_b); - } - }; - }; - template<class dwarf1, class dwarf2, bool ignore_refs = false, class tracker = dwarf_tracker_base<dwarf1, dwarf2> @@ -242,7 +202,8 @@ namespace elfutils } }; #define MATCHER(item) \ - matcher<typename dwarf1::item, typename dwarf2::item> + matcher<typename dwarf1::item::const_iterator, \ + typename dwarf2::item::const_iterator> (*this) inline bool match (const dwarf1 &a, const dwarf2 &b) { @@ -260,8 +221,7 @@ namespace elfutils const cu1_it end1 = a.end (); const cu2_it end2 = b.end (); if (subr::container_equal - (it1, end1, it2, end2, - MATCHER (compile_units::const_iterator) (*this))) + (it1, end1, it2, end2, MATCHER (compile_units))) return true; _m_tracker.mismatch (it1, end1, it2, end2); return false; @@ -271,7 +231,7 @@ namespace elfutils typedef typename dwarf2::debug_info_entry die2; inline bool match (const cu1_it &a, const cu2_it &b) { - dwarf_tracker_utils::walk<tracker> in (&_m_tracker, a, b); + typename tracker::walk in (&_m_tracker, a, b); return match (static_cast<die1> (*a), static_cast<die2> (*b)); } @@ -390,47 +350,49 @@ namespace elfutils typedef typename dwarf2::debug_info_entry::children_type children2; typedef typename children1::const_iterator cit1; typedef typename children2::const_iterator cit2; - struct die_matcher - : public std::binary_function<cit1, cit2, bool> + + inline bool match_child (const cit1 &a, const cit2 &b) { - dwarf_comparator &_m_cmp; - die_matcher (dwarf_comparator &cmp) - : _m_cmp (cmp) - {} + typename tracker::step into (&_m_tracker, a, b); + return match (*a, *b); + } - inline bool operator () (const cit1 &a, const cit2 &b) - { + inline bool match (const cit1 &a, const cit2 &b) + { #if 0 // XXX - // Maybe the tracker has already cached a correspondence of DIEs. - typename tracker::reference_match matched; - if (_m_cmp._m_tracker.reference_matched - (matched, - _m_cmp._m_tracker.left_context (), a, - _m_cmp._m_tracker.right_context (), b)) + // Maybe the tracker has already cached a correspondence of DIEs. + typename tracker::reference_match matched; + if (_m_tracker.reference_matched (matched, + _m_tracker.left_context (), a, + _m_tracker.right_context (), b)) + { + std::cout << "short-circuit DIE match " << std::hex << a->offset () + << std::endl; return true; + } - if (matched.cannot_match ()) - return false; + if (matched.cannot_match ()) + return false; #endif - dwarf_tracker_utils::step<tracker> into (&_m_cmp._m_tracker, a, b); - bool result = _m_cmp.match (*a, *b); + bool result = match_child (a, b); #if 0 // XXX - // Let the tracker cache a result for its reference_matched. - matched.notice_match (b, result); + // Let the tracker cache a result for its reference_matched. + matched.notice_match (b, result); #endif - return result; - } - }; + return result; + } + inline bool match (const children1 &a, const children2 &b) { cit1 it1 = a.begin (); cit2 it2 = b.begin (); const cit1 end1 = a.end (); const cit2 end2 = b.end (); - if (subr::container_equal (it1, end1, it2, end2, die_matcher (*this))) + if (subr::container_equal (it1, end1, it2, end2, + MATCHER (debug_info_entry::children_type))) return true; _m_tracker.mismatch (it1, end1, it2, end2); return false; @@ -537,7 +499,11 @@ namespace elfutils // Maybe the tracker has already cached a correspondence of references. typename tracker::reference_match matched; if (_m_tracker.reference_matched (matched, lhs, ref1, rhs, ref2)) - return true; + { + std::cout << "short-circuit ref match " << std::hex << a.offset () + << std::endl; + return true; + } if (matched.cannot_match ()) return false; diff --git a/libdw/c++/dwarf_tracker b/libdw/c++/dwarf_tracker index bc68a1fb..104a689d 100644 --- a/libdw/c++/dwarf_tracker +++ b/libdw/c++/dwarf_tracker @@ -87,6 +87,7 @@ namespace elfutils cu _m_root; die_path _m_path; + const die_path *_m_context; // We use a singleton list of a default-constructed iterator as a marker. static inline const die_path bad_die_path () @@ -104,15 +105,17 @@ namespace elfutils // Default constructor: an original tracker. inline tracker () - : _m_seen (new die_map), _m_delete_seen (true) + : _m_seen (new die_map), _m_delete_seen (true), _m_context (NULL) {} // Construct a derived tracker: does its own walk, but sharing caches. inline tracker (const tracker &proto, const die_path &context, const die &there) : _m_seen (proto._m_seen), _m_delete_seen (false), - _m_root (proto._m_root), _m_path (context) + _m_root (proto._m_root), _m_path (context), _m_context (&context) { + printf("derived tracker context %p from %p\n", + _m_context, proto._m_context); _m_path.push_back (there); } @@ -123,55 +126,90 @@ namespace elfutils delete _m_seen; // We should never be left with a partial walk on the books. assert (_m_path.empty ()); + assert (_m_context == NULL); } } // Main hooks for a normal walk. - inline void start_walk (const cu &a) + /* A walk object does set-up work when constructed and tear-down + work when destroyed, so tear-down is done even for exceptions. */ + struct walk { - assert (_m_path.empty ()); - _m_root = a; - } + tracker *_m_tracker; + inline walk (tracker *w, const cu &root) + : _m_tracker (w) + { + assert (_m_tracker->_m_path.empty ()); + _m_tracker->_m_root = root; + //??? _m_tracker->_m_context = &(*_m_tracker->_m_seen)[(*root).identity ()]; + printf("walk CU %#x context %p\n", (*root).offset (), _m_tracker->_m_context); + } + inline ~walk () + { + assert (_m_tracker->_m_path.empty ()); + _m_tracker->_m_root = cu (); + //??? _m_tracker->_m_context = NULL; + } + }; - inline void finish_walk (const cu &a) + /* A step object does pre-order work when constructed and post-order + work when destroyed, so post-order is done even for exceptions. + While this object lives, HERE is on the _m_path stack. */ + struct step { - assert (_m_path.empty ()); - _m_root = cu (); - } + tracker *_m_walker; + const die_path *_m_old_context; + inline step (tracker *w, const die &here) + : _m_walker (w), _m_old_context (w->_m_context) + { + _m_walker->print_path (_m_walker->_m_path, true, false, "pre_order", here); + + printf ("ctx{%p} %d vs path %u\n", + _m_walker->_m_context, + _m_walker->_m_context? + _m_walker->_m_context->size():-1,_m_walker->_m_path.size()); + + // Record the path down from the CU to see this DIE. + _m_walker->_m_context = &(_m_walker->_m_seen->insert + (std::make_pair (here->identity (), + _m_walker->_m_path)) + .first->second); - bool print_path (bool before, bool result, - const char *what, const die &there) + printf("pre_order context %p from %p", + _m_walker->_m_context, _m_old_context); + _m_walker->print_path (*_m_walker->_m_context, true, false, ":", here); + + // Append this DIE to the path we'll record for its children. + _m_walker->_m_path.push_back (here); + } + inline ~step () + { + printf("post_order context %p from %p\n", + _m_walker->_m_context, _m_old_context); + _m_walker->_m_context = _m_old_context; + _m_walker->_m_path.pop_back (); + } + }; + + static bool print_path (const die_path &path, + bool before, bool result, + const char *what, const die &there) { - return result; if (before) std::cout << what << std::hex << "(" << there->offset () << ")"; else std::cout << "after " << what << std::hex << "(" << there->offset () << (result ? "=>T)" : "=>F)"); - for (typename die_path::const_iterator it = _m_path.begin (); - it != _m_path.end (); + for (typename die_path::const_iterator it = path.begin (); + it != path.end (); ++it) std::cout << "->" << (*it)->offset (); std::cout << std::endl; return result; } -#define W(w,r) (print_path(true,false,#w,a),print_path(false,w r,#w,a)) - - inline void pre_order (const die &a) - { - print_path(true,false, "pre_order", a); - // Record the path down from the CU to see this DIE. - _m_seen->insert (std::make_pair (a->identity (), _m_path)); - // Append this DIE to the path we'll record for its children. - _m_path.push_back (a); - } - - inline void post_order (const die &a) - { - _m_path.pop_back (); - } +#define W(w,r) (print_path(_m_path,true,false,#w,a),print_path(_m_path,false,w r,#w,a)) // Random access to a DIE, find the path of the walk that gets there. inline const die_path &path_to (const die &a) @@ -205,24 +243,6 @@ namespace elfutils there, cache); } - /* A step object does pre_order when constructed and post_order - when destroyed, so post_order always runs even for exceptions. - While this object lives, HERE is on the _m_path stack. */ - struct step - { - tracker *_m_walker; - const die &_m_here; - inline step (tracker *w, const die &here) - : _m_walker (w), _m_here (here) - { - _m_walker->pre_order (_m_here); - } - inline ~step () - { - _m_walker->post_order (_m_here); - } - }; - bool walk_to (die it, const die &end, const die &there, typename die_map::iterator &cache) { @@ -232,7 +252,7 @@ namespace elfutils { // XXX is this iterator really still valid for erase/insert? // XXX note there may have been other insertions since - print_path(false,true, "walk_to", there); + print_path(_m_path,false,true, "walk_to", there); typename die_map::iterator x = _m_seen->find (there->identity ()); @@ -241,6 +261,9 @@ namespace elfutils cache = _m_seen->insert (x, std::make_pair (there->identity (), _m_path)); + printf("walk_to %#x insert %p\n", + there->offset(), &cache->second); + return true; } else @@ -386,34 +409,30 @@ namespace elfutils _m_right._m_seen->clear (); } - inline void start_walk (const cu1 &a, const cu2 &b) + struct walk { - _m_left.start_walk (a); - _m_right.start_walk (b); - } + typename tracker1::walk _m_left; + typename tracker2::walk _m_right; - inline void finish_walk (const cu1 &a, const cu2 &b) - { - _m_left.finish_walk (a); - _m_right.finish_walk (b); - } + inline walk (dwarf_ref_tracker *w, const cu1 &a, const cu2 &b) + : _m_left (&w->_m_left, a), _m_right (&w->_m_right, b) + {} + }; - inline void pre_order (const die1 &a, const die2 &b) + struct step { - _m_left.pre_order (a); - _m_right.pre_order (b); - } + typename tracker1::step _m_left; + typename tracker2::step _m_right; - inline void post_order (const die1 &a, const die2 &b) - { - _m_left.post_order (a); - _m_right.post_order (b); - } + inline step (dwarf_ref_tracker *w, const die1 &a, const die2 &b) + : _m_left (&w->_m_left, a), _m_right (&w->_m_right, b) + {} + }; typedef std::list<die1> left_context_type; inline const left_context_type &left_context () { - return _m_left._m_path; + return *_m_left._m_context; } inline const left_context_type &left_context (const die1 &die) @@ -424,7 +443,7 @@ namespace elfutils typedef std::list<die2> right_context_type; inline const right_context_type &right_context () { - return _m_right._m_path; + return *_m_right._m_context; } inline const right_context_type &right_context (const die2 &die) @@ -482,9 +501,17 @@ namespace elfutils const left_context_type &lhs, const die1 &a, const right_context_type &rhs, const die2 &b) { + if (&lhs) _m_left.print_path (lhs, true, false, "r_m lhs", a); + else puts("r_m lhs NULL!"); + if (&rhs) _m_right.print_path (rhs, true, false, "r_m rhs", b); + else puts("r_m rhs NULL!"); typename equiv_map::mapped_type *elt = &(*_m_equiv)[a->identity ()]; if (elt->first == NULL) { + printf("r_m {%p, %#x} vs {%p, %#x}\n", + &lhs, a->offset (), + &rhs, b->offset ()); + /* Record that we have a walk in progress crossing A. When MATCHED goes out of scope in our caller, its destructor will reset ELT->first to clear this record. */ @@ -495,6 +522,11 @@ namespace elfutils return elt->second.find (b->identity ()) != elt->second.end (); } + printf("r_m circ %p {%p, %#x} vs {%p, %#x}\n", + elt->first, + &lhs, a->offset (), + &rhs, b->offset ()); + /* We have a circularity. We can tell because ELT->first remains set from an outer recursion still in progress. diff --git a/tests/run-dwarfcmp-self.sh b/tests/run-dwarfcmp-self.sh index 927083ed..6f511444 100755 --- a/tests/run-dwarfcmp-self.sh +++ b/tests/run-dwarfcmp-self.sh @@ -30,9 +30,13 @@ runtest() { for file; do if [ -f $file ]; then - { testrun ../src/dwarfcmp -q -i $file $file && + { +(set -x + testrun ../src/dwarfcmp -q -i $file $file && testrun ../src/dwarfcmp -i $file $file && - testrun ../src/dwarfcmp -T -q -i $file $file +: +# testrun ../src/dwarfcmp -T -q -i $file $file +) > dwarfcmp-${file//\//_}.out 2>&1 } || { echo "*** failure in $file"; status=1; } fi @@ -41,6 +45,7 @@ runtest() runtest ../src/addr2line runtest ../src/dwarfcmp +runtest ../src/dwarflint runtest ../src/elfcmp runtest ../src/elflint runtest ../src/findtextrel |
