From: Roland McGrath Date: Fri, 3 Jul 2009 07:29:59 +0000 (-0700) Subject: Working dwarf_edit copy-construction with ref-maker. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d12f6e2e1310438f455016809dfb0f4f3c30d91a;p=thirdparty%2Felfutils.git Working dwarf_edit copy-construction with ref-maker. --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 3c1b98d59..68c292c66 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,11 @@ +2009-07-03 Roland McGrath + + * c++/dwarf_edit: Fix copy construction using a ref-maker. + * c++/dwarf_data: Updates. + * c++/subr.hh: Updates. + * c++/dwarf_ref_maker: New file. + * Makefile.am (pkginclude_HEADERS): Add it. + 2009-07-02 Roland McGrath * c++/dwarf: Get rid of VS::unit_reference. diff --git a/libdw/Makefile.am b/libdw/Makefile.am index f358840c4..7fb3171c8 100644 --- a/libdw/Makefile.am +++ b/libdw/Makefile.am @@ -50,7 +50,8 @@ include_HEADERS = dwarf.h pkginclude_HEADERS = libdw.h \ c++/subr.hh c++/dwarf_data \ c++/dwarf c++/dwarf_edit c++/dwarf_output \ - c++/dwarf_tracker c++/dwarf_comparator + c++/dwarf_tracker c++/dwarf_ref_maker \ + c++/dwarf_comparator libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \ dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \ diff --git a/libdw/c++/dwarf b/libdw/c++/dwarf index 3958cd1f6..212bcb39a 100644 --- a/libdw/c++/dwarf +++ b/libdw/c++/dwarf @@ -449,6 +449,8 @@ namespace elfutils class attributes_type; attributes_type attributes () const; + class const_pointer; + inline int tag () const { int t = ::dwarf_tag (thisdie ()); @@ -857,6 +859,9 @@ namespace elfutils } }; + // Actually always const. + typedef const_iterator iterator; + const_iterator begin () const { return const_iterator (raw_children_type::begin ()); @@ -878,6 +883,10 @@ namespace elfutils } }; + class debug_info_entry::const_pointer + : public debug_info_entry::children_type::const_iterator + {}; + private: static inline bool skip_sibling (const attribute &attr) { @@ -1112,7 +1121,7 @@ namespace elfutils inline std::string to_string () const; // Return an iterator on which * will yield the referent debug_info_entry. - inline debug_info_entry::raw_children_type::const_iterator + inline debug_info_entry::children_type::const_iterator reference () const { return (debug_info_entry::raw_children_type::const_iterator diff --git a/libdw/c++/dwarf_comparator b/libdw/c++/dwarf_comparator index 4373f6309..62556596b 100644 --- a/libdw/c++/dwarf_comparator +++ b/libdw/c++/dwarf_comparator @@ -67,6 +67,7 @@ namespace elfutils typedef typename dwarf2_die::children_type::const_iterator die2; typedef typename dwarf1_die::attributes_type::const_iterator attr1; typedef typename dwarf2_die::attributes_type::const_iterator attr2; + typedef typename dwarf1_die::children_type::iterator dwarf1_ref; // This object is created to start a walk and destroyed to finish one. struct walk @@ -162,7 +163,6 @@ namespace elfutils const left_context_type &, const die1 &, const right_context_type &, const die2 &) {} - }; template (*a), static_cast (*b)); + return match (*a, *b); } inline bool match (const die1 &a, const die2 &b) diff --git a/libdw/c++/dwarf_data b/libdw/c++/dwarf_data index dff1bd3ec..9ee162544 100644 --- a/libdw/c++/dwarf_data +++ b/libdw/c++/dwarf_data @@ -683,7 +683,7 @@ namespace elfutils template static inline value_dispatch * - make (flavor *&result, const input &x, const arg_type &arg) + make (flavor *&result, const input &x, arg_type &arg) { return result = new flavor (x, arg); } @@ -693,7 +693,7 @@ namespace elfutils inline value_string () {} template - inline value_string (const string &s, const arg_type &arg) + inline value_string (const string &s, arg_type &arg) : std::string (s) {} @@ -709,7 +709,7 @@ namespace elfutils struct value_identifier : public value_string { template - inline value_identifier (const id &s, const arg_type &arg) + inline value_identifier (const id &s, arg_type &arg) : value_string (s, arg) {} }; @@ -733,9 +733,11 @@ namespace elfutils {} template - inline value_reference (const iter &i, tracker *t) - : ref () - {} + inline value_reference (const iter &i, tracker &t) + : ref () // Invalid until t.finish (). + { + t.refer (&ref, i); + } }; struct value_flag : public value_dispatch @@ -747,7 +749,7 @@ namespace elfutils {} template - inline value_flag (bool t, const arg_type &arg) + inline value_flag (bool t, arg_type &arg) : flag (t) {} }; @@ -762,7 +764,7 @@ namespace elfutils {} template - inline value_address (::Dwarf_Addr x, const arg_type &arg) + inline value_address (::Dwarf_Addr x, arg_type &arg) : addr (x) {} }; @@ -772,7 +774,7 @@ namespace elfutils inline value_rangelistptr () {} template - inline value_rangelistptr (const list &other, const arg_type &arg) + inline value_rangelistptr (const list &other, arg_type &arg) : range_list (other) {} }; @@ -782,7 +784,7 @@ namespace elfutils inline value_lineptr () {} template - inline value_lineptr (const table &other, const arg_type &arg) + inline value_lineptr (const table &other, arg_type &arg) : impl::line_info_table (other) {} }; @@ -800,7 +802,7 @@ namespace elfutils {} template - inline value_constant (::Dwarf_Word x, const arg_type &arg) + inline value_constant (::Dwarf_Word x, arg_type &arg) : word (x) {} }; @@ -811,7 +813,7 @@ namespace elfutils inline value_constant_block () {} template - inline value_constant_block (const block &b, const arg_type &arg) + inline value_constant_block (const block &b, arg_type &arg) : std::vector (b.begin (), b.end ()) {} }; @@ -821,7 +823,7 @@ namespace elfutils inline value_dwarf_constant () {} template - inline value_dwarf_constant (const constant &other, const arg_type &arg) + inline value_dwarf_constant (const constant &other, arg_type &arg) : dwarf_enum (other) {} }; @@ -831,7 +833,7 @@ namespace elfutils inline value_source_file () {} template - inline value_source_file (const file &other, const arg_type &arg) + inline value_source_file (const file &other, arg_type &arg) : source_file (other) {} }; @@ -845,7 +847,7 @@ namespace elfutils {} template - inline value_source_line (unsigned int m, const arg_type &arg) + inline value_source_line (unsigned int m, arg_type &arg) : n (m) {} }; @@ -858,23 +860,29 @@ namespace elfutils inline value_location () {} template - inline value_location (const loc &other, const arg_type &arg) + inline value_location (const loc &other, arg_type &arg) : location_attr (other) {} }; }; + // Forward decl. + template > class attributes_type; + template > class attr_value { + friend class attributes_type; + private: typename vw::value_dispatch *_m_value; + typedef typename impl::debug_info_entry::pointer die_ptr; - template + template struct init { inline init (attr_value *av, - const value &other, const arg_type &arg = arg_type ()) + const value &other, arg_type &arg = arg_type ()) { switch (other.what_space ()) { @@ -921,6 +929,14 @@ namespace elfutils } }; + // This kosher only when freshly default-constructed. + template + inline void set (const value &other, arg_type &arg) + { + assert (_m_value == NULL); + init me (this, other, arg); + } + template inline flavor &const_variant () const { @@ -954,10 +970,10 @@ namespace elfutils } template - attr_value (const value &other, const arg_type &arg) + attr_value (const value &other, arg_type &arg) : _m_value (NULL) { - init me (this, other, arg); + set (this, other, arg); } inline attr_value () @@ -1017,12 +1033,12 @@ namespace elfutils return variant ().addr; } - inline typename impl::debug_info_entry::pointer &reference () const + inline die_ptr &reference () const { return variant ().ref; } - inline typename impl::debug_info_entry::pointer &reference () + inline die_ptr &reference () { return variant ().ref; } @@ -1220,7 +1236,7 @@ namespace elfutils } }; - template > + template class attributes_type : public std::map > { @@ -1232,13 +1248,34 @@ namespace elfutils inline attributes_type () {} public: // XXX should be protected + + /* We don't use the base_type (begin, end) iterator constructor here + for good reason. The ref-maker needs to collect back-pointers + into our mapped_value (attr_value) objects. It would not fly to + have that done in a temporary attr_value object that gets copied + into the map cell by assignment. We must make sure that when a + value_reference is constructed, it is really the one sitting in + our map that the ref-maker will want to update later. */ template - inline attributes_type (const input &other, const arg_type &c) - : base_type (subr::argify2nd + inline attributes_type (const input &other, arg_type &c) + : base_type () + { + for (typename input::const_iterator attr = other.begin (); + attr != other.end (); + ++attr) + (*this)[(*attr).first].set ((*attr).second, c); + } + +#if 0 + // dwarf_output probably will do it this way (?) + template + inline attributes_type (const input &other, arg_type &c) + : base_type (subr::argify2nd (other.begin (), c), - subr::argify2nd + subr::argify2nd (other.end (), c)) {} +#endif public: typedef typename base_type::key_type key_type; diff --git a/libdw/c++/dwarf_edit b/libdw/c++/dwarf_edit index 3139aa604..321565c87 100644 --- a/libdw/c++/dwarf_edit +++ b/libdw/c++/dwarf_edit @@ -52,7 +52,7 @@ #include "dwarf" #include "dwarf_data" -#include "dwarf_tracker" +#include "dwarf_ref_maker" /* Read the comments for elfutils::dwarf first. @@ -108,14 +108,23 @@ namespace elfutils { friend class debug_info_entry; private: - children_type () {} + inline children_type () {} template - children_type (const input &other, tracker *t) - : std::list - (subr::argify (other.begin (), t), - subr::argify (other.end (), t)) - {} + inline children_type (const input &other, tracker &t) + { + for (typename input::const_iterator in = other.begin (); + in != other.end (); + ++in) + { + /* Don't copy-construct the entry from *in here because that + copies it again into the list and destroys the first copy. */ + push_back (debug_info_entry ()); + iterator out = --end (); + out->set (*in, t); + t.equivalence (out, in); + } + } public: typedef debug_info_entry value_type; @@ -144,18 +153,35 @@ namespace elfutils inline attributes_type () {} template - inline attributes_type (const attrs &other, tracker *t) + inline attributes_type (const attrs &other, tracker &t) : base_type (other, t) {} }; - private: - const int _m_tag; + protected: + int _m_tag; attributes_type _m_attributes; children_type _m_children; + // This is can only be used by the children_type constructor, + // which immediately calls set. + inline debug_info_entry () + : _m_tag (-1), _m_attributes (), _m_children () + {} + + template + inline void set (const die_type &die, arg_type &arg) + { + _m_attributes.clear (); + _m_children.clear (); + _m_tag = die.tag (); + _m_attributes.swap (attributes_type (die.attributes (), arg)); + _m_children.swap (children_type (die.children (), arg)); + } + public: - debug_info_entry (int t) : _m_tag (t) + inline debug_info_entry (int t) + : _m_tag (t), _m_attributes (), _m_children () { if (unlikely (t <= 0)) throw std::invalid_argument ("invalid tag"); @@ -164,7 +190,7 @@ namespace elfutils /* 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_type &die, tracker *t) + debug_info_entry (const die_type &die, tracker &t) : _m_tag (die.tag ()), _m_attributes (die.attributes (), t), _m_children (die.children (), t) @@ -239,7 +265,7 @@ namespace elfutils // XXX should be private public: template - inline compile_unit (const die_type &die, tracker *t) + inline compile_unit (const die_type &die, tracker &t) : debug_info_entry (die, t) { if (die.tag () != ::DW_TAG_compile_unit) @@ -260,17 +286,32 @@ namespace elfutils typedef std::list _base; // Default constructor: an empty container, no CUs. - inline compile_units () - {} + inline compile_units () {} // Constructor copying CUs from input container. template - inline compile_units (const input &units, tracker *t) - : _base (subr::argify + inline compile_units (const input &other, tracker &t) + { + for (typename input::const_iterator in = other.begin (); + in != other.end (); + ++in) + { + /* Don't copy-construct the entry from *in here because that + copies it again into the list and destroys the first copy. */ + push_back (compile_unit ()); + iterator out = --end (); + out->set (*in, t); + } + } +#if 0 // dwarf_output might use this (?) + template + inline compile_units (const input &units, tracker &t) + : _base (subr::argify (units.begin (), t), - subr::argify + subr::argify (units.end (), t)) {} +#endif public: typedef compile_unit value_type; @@ -316,13 +357,30 @@ namespace elfutils public: // Default constructor: an empty container, no CUs. - inline dwarf_edit () {} + inline dwarf_edit () + : _m_units () + {} // Constructor copying CUs from an input file (dwarf or dwarf_edit). template - dwarf_edit (const input &dw, tracker *t) - : _m_units (dw.compile_units (), t) - {} + inline dwarf_edit (const input &dw, tracker &t, + subr::guard guard = subr::guard ()) + : _m_units (dw.compile_units (), guard (t)) + { + guard.clear (); + } + + // Copying constructor with default ref-maker. + template + inline dwarf_edit (const input &dw, + dwarf_ref_maker t + = dwarf_ref_maker (), + subr::guard > guard + = subr::guard > ()) + : _m_units (dw.compile_units (), guard (t)) + { + guard.clear (); + } template inline bool operator== (const file &other) const diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output index c224d3623..c9f1bf809 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -79,7 +79,7 @@ namespace elfutils private: template static inline const input & - collect (dwarf_output_collector *c, + collect (dwarf_output_collector &c, const subr::auto_ref &p) { return static_cast (p); @@ -87,7 +87,7 @@ namespace elfutils template static inline const debug_info_entry & - collect (dwarf_output_collector *, + collect (dwarf_output_collector &, const typename input::debug_info_entry &); public: @@ -116,7 +116,7 @@ namespace elfutils /* 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_type &die, dwarf_output_collector *c) + debug_info_entry (const die_type &die, dwarf_output_collector &c) : _m_tag (die.tag ()), _m_attributes (die.attributes ()), _m_children (die.children ()), @@ -188,11 +188,11 @@ namespace elfutils template struct make : public std::binary_function { _base::value_type operator () (const typename input::value_type &cu, - dwarf_output_collector *c) const + dwarf_output_collector &c) const { return _base::value_type (collect (c, cu)); } @@ -205,7 +205,7 @@ namespace elfutils // Constructor copying CUs from input container. template - compile_units (const input &units, dwarf_output_collector *c) + compile_units (const input &units, dwarf_output_collector &c) : _base () { for (typename input::const_iterator it = units.begin (); @@ -226,7 +226,7 @@ namespace elfutils return !(*this == other); } - void recollect (dwarf_output_collector *c) + void recollect (dwarf_output_collector &c) { std::transform (begin (), end (), begin (), std::bind2nd (make (), c)); @@ -251,7 +251,7 @@ namespace elfutils // Constructor copying CUs from an input file (can be any of dwarf, // dwarf_edit, or dwarf_output). template - dwarf_output (const input &dw, dwarf_output_collector *c) + dwarf_output (const input &dw, dwarf_output_collector &c) : _m_units (dw.compile_units (), c) {} @@ -289,18 +289,18 @@ namespace elfutils template static inline const std::string & - collect_string (dwarf_output_collector *, const input &); + collect_string (dwarf_output_collector &c, const input &); /* An iterator adapter for use in iterator-based constructors. collectify (iterator) yields an iterator on input where *i constructs output::value_type (input::value_type v, collector). */ template static inline typename subr::argifier::result_type + dwarf_output_collector &>::result_type collectify (const typename input::const_iterator &in, - dwarf_output_collector *c) + dwarf_output_collector &c) { - return subr::argifier (c) (in); + return subr::argifier (c) (in); } struct value_wrapper @@ -311,7 +311,7 @@ namespace elfutils const std::string &_m_str; template - inline value_string (const string &s, dwarf_output_collector *c) + inline value_string (const string &s, dwarf_output_collector &c) : _m_str (collect_string (c, s)) {} @@ -345,7 +345,7 @@ namespace elfutils template static inline value_dispatch * - make (value_string *&result, const input &x, dwarf_output_collector *c) + make (value_string *&result, const input &x, dwarf_output_collector &c) { return result = new value_string (x, c); } @@ -369,7 +369,7 @@ namespace elfutils children_type () {} template - inline children_type (const input &other, dwarf_output_collector *c) + inline children_type (const input &other, dwarf_output_collector &c) : std::list (collectify (other.begin (), c), collectify (other.end (), c)) @@ -383,18 +383,15 @@ namespace elfutils typedef children_type::const_iterator pointer; class attributes_type - : public dwarf_data::attributes_type + : public dwarf_data::attributes_type { friend class debug_info_entry; private: typedef dwarf_data::attributes_type base_type; template - inline attributes_type (const input &other, dwarf_output_collector *c) + inline attributes_type (const input &other, dwarf_output_collector &c) : base_type (other, c) {} }; @@ -406,7 +403,7 @@ namespace elfutils public: template - debug_info_entry (const die_type &die, dwarf_output_collector *c) + debug_info_entry (const die_type &die, dwarf_output_collector &c) : _m_tag (die.tag ()), _m_attributes (die.attributes (), c), _m_children (die.children (), c) @@ -473,7 +470,7 @@ namespace elfutils // XXX should be private public: template - compile_unit (const die_type &die, dwarf_output_collector *c) + compile_unit (const die_type &die, dwarf_output_collector &c) : debug_info_entry (die, c) { if (die.tag () != ::DW_TAG_compile_unit) @@ -501,7 +498,7 @@ namespace elfutils // Constructor copying CUs from input container. template - compile_units (const input &units, dwarf_output_collector *c) + compile_units (const input &units, dwarf_output_collector &c) : _base (collectify (units.begin (), c), collectify (units.end (), c)) { @@ -546,7 +543,7 @@ namespace elfutils // Constructor copying CUs from an input file (can be any of dwarf, // dwarf_edit, or dwarf_output). template - dwarf_output (const input &dw, dwarf_output_collector *c) + dwarf_output (const input &dw, dwarf_output_collector &c) : _m_units (dw.compile_units (), c) {} @@ -578,13 +575,20 @@ namespace elfutils subr::value_set _m_strings; subr::value_set _m_ranges; + public: + + template // XXX + inline void equivalence (const die1 &a, const die2 &b) {} + + template // XXX + inline void refer (die1 *ref, const die2 &b) {} }; template inline const std::string & - dwarf_output::collect_string (dwarf_output_collector *c, const input &s) + dwarf_output::collect_string (dwarf_output_collector &c, const input &s) { - return c->_m_strings.add (s); + return c._m_strings.add (s); } }; diff --git a/libdw/c++/dwarf_ref_maker b/libdw/c++/dwarf_ref_maker new file mode 100644 index 000000000..1bceeca74 --- /dev/null +++ b/libdw/c++/dwarf_ref_maker @@ -0,0 +1,178 @@ +/* elfutils::dwarf_ref_maker -- -*- C++ -*- template type specification + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifndef _ELFUTILS_DWARF_REF_MAKER +#define _ELFUTILS_DWARF_REF_MAKER 1 + +#include "dwarf" +#include +#include + +namespace elfutils +{ + // Prototypical stub for reference maker object. + // This keeps no state and can't really be used. + template + struct dwarf_ref_maker_base + { + typedef typename input::debug_info_entry input_entry; + typedef typename input_entry::children_type::const_iterator input_ref; + typedef typename output::debug_info_entry::pointer output_ref; + + // These are called around a whole-file construction. + inline void start () {} + + // If called, all pointers passed in since start () before are bogus. + inline void abort () {} + + // Construction is complete: now snap in all recorded references. + inline void finish (output &file) {} + + // The referenced output DIE has been constructed to match the input DIE. + inline void equivalence (const output_ref &to, const input_ref &from) + { + } + + // *REF is an uninitialized attr_value.reference (). + // It's meant to refer to the output DIE equivalent to the given input DIE. + inline void refer (output_ref *ref, const input_ref &target) + { + throw std::logic_error ("dwarf_ref_maker_base cannot make references"); + } + }; + + // Simple maker used for a single copy-construction. + template + class dwarf_ref_maker : public dwarf_ref_maker_base + { + public: + typedef typename input::debug_info_entry input_entry; + typedef typename output::debug_info_entry output_entry; + typedef typename input_entry::children_type::const_iterator input_ref; + typedef typename output_entry::children_type::iterator output_ref; + + private: + + struct seen + { + bool _m_known; + output_ref _m_out; + std::vector _m_refs; + + inline seen () + : _m_known (false), _m_out (), _m_refs () + {} + + inline void resolve () + { + for (; !_m_refs.empty (); _m_refs.pop_back ()) + *_m_refs.back () = _m_out; + } + + inline void resolve (const output_ref &to) + { + _m_out = to; + _m_known = true; + resolve (); + } + + inline void refer (output_ref *out) + { + _m_refs.push_back (out); + if (_m_known) + resolve (); + } + }; + + std::tr1::unordered_map< ::Dwarf_Off, seen> _m_map; + + public: + inline dwarf_ref_maker () + : _m_map () + {} + + inline dwarf_ref_maker (const dwarf_ref_maker &other) + : _m_map () + { + if (unlikely (!other._m_map.empty ())) + throw std::logic_error + ("dwarf_ref_maker copy constructs only from default-constructed"); + } + + inline ~dwarf_ref_maker () + {} + + inline void abort () + { + _m_map.clear (); + } + + inline void equivalence (const output_ref &out, const input_ref &in) + { + _m_map[in->identity ()].resolve (out); + } + + inline void refer (output_ref *out, const input_ref &in) + { + _m_map[in->identity ()].refer (out); + } + + inline void finish (output &file) + { + while (_m_map.begin () != _m_map.end ()) + if (_m_map.begin ()->second._m_known) + _m_map.erase (_m_map.begin ()); + else + throw std::logic_error ("construction finished with unresolved refs"); + } + }; + +}; + +#endif // diff --git a/libdw/c++/dwarf_tracker b/libdw/c++/dwarf_tracker index c27a737f8..67c1ae733 100644 --- a/libdw/c++/dwarf_tracker +++ b/libdw/c++/dwarf_tracker @@ -69,6 +69,7 @@ namespace elfutils typedef typename _base::cu2 cu2; typedef typename _base::die1 die1; typedef typename _base::die2 die2; + typedef typename _base::dwarf1_ref dwarf1_ref; private: template diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh index d1b4c7062..b768abe70 100644 --- a/libdw/c++/subr.hh +++ b/libdw/c++/subr.hh @@ -578,20 +578,21 @@ namespace elfutils /* A wrapped_input_iterator is like an input::const_iterator, but *i returns wrapper (*i) instead; wrapper returns element (or const element & or something). */ - template class wrapped_input_iterator : public input::const_iterator { private: typedef typename input::const_iterator _base; - wrapper *_m_wrapper; + wrapper _m_wrapper; public: typedef element value_type; - inline wrapped_input_iterator (const _base &i, wrapper &w) - : _base (static_cast<_base> (i)), _m_wrapper (&w) + template + inline wrapped_input_iterator (const _base &i, const arg_type &arg) + : _base (static_cast<_base> (i)), _m_wrapper (arg) {} inline wrapped_input_iterator (const wrapped_input_iterator &i) @@ -600,7 +601,7 @@ namespace elfutils inline typename wrapper::result_type operator* () const { - return (*_m_wrapper) (_base::operator* ()); + return _m_wrapper (_base::operator* ()); } }; @@ -622,8 +623,15 @@ namespace elfutils struct maker : public std::unary_function { - arg_type _m_arg; - explicit inline maker (const arg_type &c) : _m_arg (c) {} + const arg_type _m_arg; + + inline maker (const arg_type &c) + : _m_arg (c) + {} + + inline maker (const maker &m) + : _m_arg (m._m_arg) + {} inline outlet operator () (const inlet &x) const { @@ -635,7 +643,7 @@ namespace elfutils : _m_maker (c) {} - typedef subr::wrapped_input_iterator result_type; + typedef wrapped_input_iterator result_type; inline result_type operator () (const inny &i) { @@ -662,17 +670,19 @@ namespace elfutils /* Wrapper worker passed to wrapped_input_iterator. This object holds the collector pointer. */ - struct maker - : public std::unary_function + struct pair_maker + : public argifier::maker { - arg_type _m_arg; - explicit inline maker (const arg_type &c) : _m_arg (c) {} + typedef typename argifier::maker maker; + + inline pair_maker (const arg_type &c) : maker (c) {} + inline pair_maker (const pair_maker &m) : maker (m) {} inline outlet operator () (const inlet &x) const { return std::make_pair (x.first, typename outlet::second_type (x.second, - _m_arg)); + this->_m_arg)); } } _m_maker; @@ -680,7 +690,7 @@ namespace elfutils : _m_maker (c) {} - typedef subr::wrapped_input_iterator const_iterator; + typedef subr::wrapped_input_iterator const_iterator; inline const_iterator operator () (const inny &i) { @@ -695,6 +705,85 @@ namespace elfutils return argifier2nd (arg) (in); } + /* A guard object is intended to be ephemeral, existing solely to be + destroyed in exception paths where it was not cleared explicitly. + In that case, it calls tracker::soiled (). + + For convenience, it can be constructed from a tracker reference or + pointer, or default-constructed and then filled. It's fillable by + calling the guard object as a function, passing it the tracker + reference or pointer, which it passes through on return: + + guard g; + use (g (t)); + g.clear (); + + This first calls T.start (). When G goes out of scope, + it calls T.abort () iff G.clear () was never called. */ + + template + class guard + { + private: + tracker *_m_tracker; + + inline void start () + { + _m_tracker->start (); + } + + public: + inline guard (tracker *t) + : _m_tracker (t) + { + start (); + } + + inline guard (tracker &t) + : _m_tracker (&t) + { + start (); + } + + inline guard () + : _m_tracker (NULL) + {} + + inline tracker *operator () (tracker *t) + { + _m_tracker = t; + start (); + return t; + } + + inline tracker &operator () (tracker &t) + { + _m_tracker = &t; + start (); + return t; + } + + inline operator tracker * () const + { + return _m_tracker; + } + + inline operator tracker & () const + { + return *_m_tracker; + } + + inline void clear () + { + _m_tracker = NULL; + } + + inline ~guard () + { + if (unlikely (_m_tracker != NULL)) + _m_tracker->abort (); + } + }; }; }; diff --git a/src/dwarfcmp.cc b/src/dwarfcmp.cc index 677a5beba..71e06292e 100644 --- a/src/dwarfcmp.cc +++ b/src/dwarfcmp.cc @@ -325,28 +325,28 @@ main (int argc, char *argv[]) if (test_writer) { - dwarf_ref_tracker t1; - dwarf_ref_tracker t2; - dwarf_edit edit1 (file1, &t1); - dwarf_edit edit2 (file2, &t2); + 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); + 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); + 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;