From: Roland McGrath Date: Tue, 16 Jun 2009 13:03:42 +0000 (-0700) Subject: unfinished X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29503677ad61e35ee45e0a30b7dde45a46e4ab22;p=thirdparty%2Felfutils.git unfinished --- diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output index d4d2ee611..ac015c74e 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -65,8 +65,29 @@ namespace elfutils { + class dwarf_output_collector; + class dwarf_output { + public: + class compile_units; + class debug_info_entry; + typedef debug_info_entry compile_unit; + + private: + template + static inline const input & + collect (dwarf_output_collector *c, + const subr::auto_ref &p) + { + return static_cast (p); + } + + template + static inline const debug_info_entry & + collect (dwarf_output_collector *, + const typename input::debug_info_entry &); + public: class compile_units; @@ -79,52 +100,32 @@ namespace elfutils class debug_info_entry { - public: - - class children : public std::vector - { - friend class debug_info_entry; - private: - children () {} - - template - children (const childrens &other) - : std::vector (other.begin (), other.end ()) {} - }; - - class attributes : public std::map - { - friend class debug_info_entry; - private: - attributes () {} - - template - attributes (const attrs &other) - : std::map (other.begin (), other.end ()) {} - - public: - template - inline operator attrs () const - { - return attrs (begin (), end ()); - } - }; + friend class dwarf_output; private: + typedef subr::hashed_unordered_map _attributes; + typedef subr::hashed_vector _children; + const int _m_tag; - const attributes _m_attributes; - const children _m_children; + const _attributes _m_attributes; + const _children _m_children; + size_t _m_hash; - public: /* The template constructor lets us copy in from any class that has compatibly iterable containers for attributes and children. */ - template - debug_info_entry (const die &die) + template + debug_info_entry (const die_type &die) : _m_tag (die.tag ()), _m_attributes (die.attributes ()), - _m_children (die.children ()) - {} + _m_children (die.children ()), + _m_hash (0) + { + subr::hash_combine (_m_hash, _m_tag); + subr::hash_combine (_m_hash, _m_attributes); + subr::hash_combine (_m_hash, _m_children); + } + public: inline int tag () const { return _m_tag; @@ -135,20 +136,12 @@ namespace elfutils return !_m_children.empty (); } - inline class children &children () - { - return _m_children; - } - inline const class children &children () const + inline const _children &children () const { return _m_children; } - inline class attributes &attributes () - { - return _m_attributes; - } - inline const class attributes &attributes () const + inline const _attributes &attributes () const { return _m_attributes; } @@ -162,27 +155,63 @@ namespace elfutils template bool operator!= (const die &other) const { - return !(*this == other);; + return !(*this == other); } }; - typedef debug_info_entry::attributes::value_type attribute; + typedef debug_info_entry::_attributes::value_type attribute; - class compile_unit : public debug_info_entry - { - }; - - // Main container anchoring all the output. - class compile_units : public std::vector + public: + /* Main container anchoring all the output. + + This is the only container that actually lives in the dwarf_output + object. All others live in the dwarf_output_collector's sets, and + we return const references to those copies. + + This vector is actually mutable as a std::vector. But note that you + should never remove a compile_unit, though you can reorder the + vector. Nothing is ever removed from the collector, so your final + output file can wind up with unreferenced data being encoded. If + you do remove any elements, then you should start a fresh collector + and construct a new dwarf_output object by copying using that + collector (or, equivalently, call o.compile_units ().recollect (C) + on the new collector C). */ + class compile_units + : public std::vector > { friend class dwarf_output; private: - // Constructor copying CUs from input container. + typedef std::vector > _base; + template - compile_units(const input &units) - : std::vector (units.begin (), units.end ()) + struct make + : public std::binary_function + { + _base::value_type operator () (const typename input::value_type &cu, + dwarf_output_collector *c) const + { + return _base::value_type (collect (c, cu)); + } + }; + + // Construct empty container. + compile_units () + : _base () {} + // Constructor copying CUs from input container. + template + compile_units (const input &units, dwarf_output_collector *c) + : _base () + { + for (typename input::const_iterator it = units.begin (); + it != units.end (); + ++it) + push_back (make () (*it, c)); + } + public: template bool operator== (const other_children &other) const @@ -194,6 +223,12 @@ namespace elfutils { return !(*this == other); } + + void recollect (dwarf_output_collector *c) + { + std::transform (begin (), end (), begin (), + std::bind2nd (make (), c)); + } }; private: @@ -206,9 +241,17 @@ namespace elfutils } public: - // Constructor copying CUs from an input file (dwarf or dwarf_output). + // Constructor for an empty file, can add to its compile_units (). + dwarf_output () + : _m_units () + {} + + // Constructor copying CUs from an input file (can be any of dwarf, + // dwarf_edit, or dwarf_output). template - dwarf_output (const input &dw) : _m_units (dw.compile_units ()) {} + dwarf_output (const input &dw, dwarf_output_collector *c) + : _m_units (dw.compile_units (), c) + {} template inline bool operator== (const file &other) const @@ -221,4 +264,24 @@ namespace elfutils return !(*this == other); } }; -} + + class dwarf_output_collector + { + friend class dwarf_output; + + private: + subr::value_set _m_die; + + }; + + template + inline const dwarf_output::debug_info_entry & + dwarf_output::collect (dwarf_output_collector *c, + const typename input::debug_info_entry &die) + { + return c->_m_die.add (die); + } + +}; + +#endif // diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh index e11846279..527f0c073 100644 --- a/libdw/c++/subr.hh +++ b/libdw/c++/subr.hh @@ -10,11 +10,25 @@ #include #include #include +#include +#include +#include +#include namespace elfutils { namespace subr { + // XXX + template + struct hash { }; + + template + inline void hash_combine (size_t &seed, const T &v) + { + seed ^= hash (v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } + template struct name_equal : public std::binary_function { @@ -262,6 +276,174 @@ namespace elfutils return indexed_iterator (_m_contents, _m_idx--); } }; + + // Pair of some value and its precomputed hash. + template + class hashed_value + : public std::pair + { + private: + typedef std::pair _base; + + public: + hashed_value (const value_type &v) + : _base (subr::hash (v), v) {} + hashed_value (const hashed_value &v) + : _base (v.first, v.second) {} + + bool operator== (const hashed_value &other) + const + { + return other.first == this->first && other.second == this->second; + } + + struct hasher + : public std::unary_function, size_t> + { + size_t operator () (const hashed_value &v) + { + return v.first; + } + }; + }; + + // Set of hashed_value's. + template + class value_set + : public std::tr1::unordered_set, + struct hashed_value::hasher> + { + public: + typedef hashed_value hashed_value_type; + + private: + typedef std::tr1::unordered_set _base; + + public: + const value_type &add (const value_type &v) + { + std::pair p + = _base::insert (hashed_value_type (v)); + if (p.second) + { + // XXX hook for collection: abbrev building, etc. + } + return *p.first; + }; + }; + + // A vector of hashed_value's that itself acts like a hashed_value. + template + class hashed_vector + : public std::vector > + { + private: + typedef hashed_value elt_type; + typedef std::vector _base; + + size_t _m_hash; + + public: + template + hashed_vector (iterator first, iterator last) + : _base (first, last), _m_hash (0) + { + struct hashit + { + size_t &_m_hash; + hashit (size_t &h) : _m_hash (h) {} + inline void operator () (const elt_type &p) + { + subr::hash_combine (_m_hash, p.first); + } + }; + std::for_each (_base::begin (), _base::end (), hashit (_m_hash)); + } + + template + hashed_vector (const container &other) + : hashed_vector (other.begin (), other.end ()) + {} + + bool operator== (const hashed_vector &other) const + { + return (other._m_hash == _m_hash && + other.size () == _base::size () + && std::equal (_base::begin (), _base::end (), other.begin ())); + } + + struct hasher + : public std::unary_function, size_t> + { + size_t operator () (const hashed_vector &v) + { + return v._m_hash; + } + }; + }; + + // An unordered_map of hashed_value's that itself acts like a hashed_value. + template + class hashed_unordered_map + : public std::tr1::unordered_map, + class hashed_value::hasher> + { + private: + typedef std::tr1::unordered_map, + class hashed_value::hasher> + _base; + + size_t _m_hash; + + public: + template + hashed_unordered_map (iterator first, iterator last) + : _base (first, last), _m_hash (0) + { + class hashit + { + size_t &_m_hash; + hashit (size_t &h) : _m_hash (h) {} + + void operator () (const typename _base::value_type &p) + { + subr::hash_combine (_m_hash, subr::hash (p.first)); + subr::hash_combine (_m_hash, p.second.first); + } + }; + std::for_each (_base::begin (), _base::end (), hashit (_m_hash)); + } + + template + hashed_unordered_map (const container &other) + : hashed_unordered_map (other.begin (), other.end ()) + {} + }; + + template + class auto_ref + { + private: + T *_m_ptr; + + public: + auto_ref (const T &other) + : _m_ptr (&other) + {} + + inline operator T& () const + { + return *_m_ptr; + } + + auto_ref (const auto_ref &other) + : _m_ptr (other._m_ptr) + {} + }; + }; }; diff --git a/src/dwarfcmp.cc b/src/dwarfcmp.cc index ecadfd52b..370f1ad06 100644 --- a/src/dwarfcmp.cc +++ b/src/dwarfcmp.cc @@ -47,6 +47,7 @@ #include "c++/dwarf_edit" #include "c++/dwarf_comparator" #include "c++/dwarf_tracker" +#include "c++/dwarf_output" using namespace elfutils; using namespace std; @@ -313,9 +314,26 @@ main (int argc, char *argv[]) if (test_writer) { - dwarf_edit out1 (file1); - dwarf_edit out2 (file2); - test_classes (file1, file2, out1, out2, same); + dwarf_edit edit1 (file1); + dwarf_edit edit2 (file2); + test_classes (file1, file2, edit1, edit2, same); + + { + dwarf_output_collector c1; + dwarf_output_collector c2; + dwarf_output out1 (file1, &c1); + dwarf_output out2 (file2, &c2); + test_classes (file1, file2, out1, out2, same); + test_classes (edit1, edit2, out1, out2, same); + } + { + dwarf_output_collector c1; + dwarf_output_collector c2; + dwarf_output out1 (edit1, &c1); + dwarf_output out2 (edit2, &c2); + test_classes (file1, file2, out1, out2, same); + test_classes (edit1, edit2, out1, out2, same); + } } result = !same;