summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2009-07-01 16:18:28 -0700
committerRoland McGrath <[email protected]>2009-07-01 16:18:28 -0700
commit0dc95300ccad0554456be0186a7740181b5dd9b4 (patch)
treede545f5c85799b1a309c020257e0ee244a764bb5
parent609af3f5dd3064e2f0f0434a413ed0bae9908470 (diff)
more fiddling
-rw-r--r--libdw/c++/dwarf_comparator142
-rw-r--r--libdw/c++/dwarf_tracker170
-rwxr-xr-xtests/run-dwarfcmp-self.sh9
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