]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Works again
authorPetr Machata <pmachata@redhat.com>
Fri, 21 Aug 2009 20:22:21 +0000 (22:22 +0200)
committerPetr Machata <pmachata@redhat.com>
Fri, 21 Aug 2009 20:22:21 +0000 (22:22 +0200)
libdw/c++/dwarf_output
libdw/c++/output-shape.cc

index ca8c6bce22272f3b39e1e83fee6b6915a8d325e8..32881f090e2f8f06a97ba99bd41fc3709edca352 100644 (file)
@@ -269,7 +269,6 @@ namespace elfutils
 
       private:
        typedef dwarf_data::attributes_type<dwarf_output, value> _base;
-
        size_t _m_hash;
 
        inline attributes_type ()
@@ -327,7 +326,6 @@ namespace elfutils
 
       protected:
        typedef std::vector<die_info_pair *> _base;
-
        size_t _m_hash;
 
        inline void set_hash ()
@@ -346,11 +344,6 @@ namespace elfutils
          set_hash ();
        }
 
-       inline const _base &info () const
-       {
-         return *this;
-       }
-
        struct deref
          : public std::unary_function<die_info_pair *,
                                       const debug_info_entry &>
@@ -362,6 +355,11 @@ namespace elfutils
        inline void reify_children () const;
 
       public:
+       inline const _base &info () const
+       {
+         return *this;
+       }
+
        friend class subr::hashed_hasher<children_type>;
        typedef subr::hashed_hasher<children_type> hasher;
 
@@ -628,8 +626,6 @@ namespace elfutils
       };
     };
 
-    typedef std::vector<debug_info_entry::pointer> die_ref_vect;
-
     struct shape_type
     {
       struct form_constraint_t
@@ -695,7 +691,7 @@ namespace elfutils
       friend class subr::hashed_hasher<shape_type>;
       typedef subr::hashed_hasher<shape_type> hasher;
 
-      shape_type (const debug_info_entry::pointer &ref,
+      shape_type (const debug_info_entry &die,
                  const dwarf_output::die_info &info);
 
       inline bool operator== (const shape_type &other) const
@@ -713,42 +709,46 @@ namespace elfutils
 
     struct shape_info
     {
+      typedef std::vector<std::reference_wrapper<const debug_info_entry>>
+         die_ref_vect;
+
       // We keep list of users of this shape.  That will make it
       // simpler to evaluate the space trade-offs when we generate
       // actual abbrevs from this shape.
       die_ref_vect _m_users;
 
-      // Instances.  Instance is a sequence of concrete forms in the
-      // order matching that of shape_type::_m_attrs.  Each shape can
-      // produce several instances to ideally cover its users.  The
-      // second element of the pair is unique code assigned to that
-      // instance, or 0 if no code was assigned yet.
-      // XXX is size_t enough?  Use uintptr_t?
-      typedef std::pair<std::vector<int>, size_t> instance_type;
-      typedef std::vector<instance_type> instances_type;
-      instances_type _m_instances;
+      // Instances.  Each shape can produce several instances to
+      // ideally cover its users.  The second element of the pair is
+      // unique code assigned to that instance, or 0 if no code was
+      // assigned yet.  XXX is size_t enough?  Use uintptr_t?
+      struct instance_type
+      {
+       typedef std::map<int, int> forms_type;
+       forms_type forms; // attribute->form
+       size_t code; // or 0 if not assigned yet
+       instance_type () : code (0) {}
+      };
+      typedef std::vector<instance_type> instance_vec;
+      instance_vec _m_instances;
 
-      shape_info (debug_info_entry::pointer ref)
+      shape_info (debug_info_entry const &die)
       {
-       add_user (ref);
+       add_user (die);
       }
 
-      void add_user (debug_info_entry::pointer ref)
+      void add_user (debug_info_entry const &die)
       {
-       _m_users.push_back (ref);
+       _m_users.push_back (std::ref (die));
       }
 
       void instantiate (shape_type const &shape,
+                       dwarf_output_collector &col,
                        bool addr_64, bool dwarf_64);
       void build_data (shape_type const &shape,
                       instance_type const &inst,
                       section_appender &appender);
     };
 
-    typedef std::tr1::unordered_map<shape_type, shape_info,
-                                   shape_type::hasher> shape_map;
-    shape_map _m_shapes;
-
     typedef debug_info_entry::attributes_type::value_type attribute;
 
     typedef dwarf_data::compile_unit<dwarf_output> compile_unit;
@@ -901,9 +901,7 @@ namespace elfutils
 
   public:
     // Constructor for an empty file, can add to its compile_units ().
-    inline dwarf_output ()
-      : _m_output_built (false)
-    {}
+    inline dwarf_output () {}
 
     // Constructor copying CUs from an input file (can be any of dwarf,
     // dwarf_edit, or dwarf_output).
@@ -912,7 +910,6 @@ namespace elfutils
     inline dwarf_output (const input &dw, dwarf_output_collector &c,
                         copier<input> maker = copier<input> ())
       : _m_units (dw.compile_units (), maker (c))
-      , _m_output_built (false)
     {}
 
     template<typename file>
@@ -937,9 +934,6 @@ namespace elfutils
                            bool addr_64, bool big_endian);
 
     void add_shape (debug_info_entry &die, bool last_sibling);
-
-    bool _m_output_built;
-    void build_output (bool addr_64, bool dwarf_64);
   };
 
   // Explicit specializations.
@@ -1085,12 +1079,11 @@ namespace elfutils
     std::queue<value::value_reference *> _m_refs;
     std::bitset<2> _m_with_sibling;
     unsigned int _m_uses;
-    size_t abbrev_code; // Or 0 if unassigned.
-    dwarf_output::shape_info::instance_type *instance;
+
+    dwarf_output::shape_info::instance_vec::iterator abbrev_ptr;
 
     inline die_info ()
       : _m_refs (), _m_with_sibling (), _m_uses (0)
-      , abbrev_code (0)
     {}
 
     inline ~die_info ()
@@ -1122,34 +1115,7 @@ namespace elfutils
     }
 
     inline void placed (const debug_info_entry::pointer &ref,
-                       bool have_sibling)
-    {
-      ++_m_uses;
-      _m_with_sibling[have_sibling] = true;
-
-      if (_m_refs.empty ())
-       {
-         subr::nothing dummy;
-         self (new value::value_reference (ref, dummy));
-       }
-      else
-       for (size_t n = _m_refs.size (); n > 0; --n)
-         {
-           value::value_reference *self_ref = _m_refs.front ();
-           self_ref->ref = ref;
-           _m_refs.pop ();
-           _m_refs.push (self_ref);
-         }
-
-      /* xxx yyy create shapes afterwards
-      shape_type shape (ref, *this);
-      shape_map::iterator st = _m_shapes.find (shape);
-      if (st != _m_shapes.end ())
-       st->second.add_user (&x.first);
-      else
-       _m_shapes.insert (std::make_pair (shape, shape_info (x)));
-      */
-    }
+                       bool have_sibling);
   };
 
   /* This is the wrapper in the guts of a children_type iterator.
@@ -1165,7 +1131,7 @@ namespace elfutils
   /* This is called when a children_type is installed freshly in the collector.
      Fill in its back pointers.  */
   inline void
-  dwarf_output::debug_info_entry::children_type::reify_children () const
+  dwarf_output::debug_info_entry::children_type::reify_children() const
   {
     _base::const_iterator i = _base::begin ();
     bool have_sibling = i != _base::end ();
@@ -1241,6 +1207,13 @@ namespace elfutils
     typedef subr::identity_map<die_type, die_info> die_map;
     die_map _m_unique;
 
+    // Set of shapes.
+    typedef std::tr1::unordered_map<dwarf_output::shape_type,
+                                   dwarf_output::shape_info,
+                                   dwarf_output::shape_type::hasher>
+       shape_map;
+    shape_map _m_shapes;
+
     inline die_info_pair *add_entry (int tag,
                                     const children_type *children,
                                     const attrs_type *attrs)
@@ -1289,6 +1262,7 @@ namespace elfutils
   public:
     inline dwarf_output_collector ()
       : _m_total (0)
+      , _m_output_built (false)
     {}
 
     static void die_stats (const die_map::value_type &elt)
@@ -1304,8 +1278,33 @@ namespace elfutils
                << " unique of " << _m_total << " total DIEs\n";
       std::for_each (_m_unique.begin (), _m_unique.end (), die_stats);
     }
+
+    bool _m_output_built;
+    void build_output (bool addr_64, bool dwarf_64);
   };
 
+  inline void
+  dwarf_output::die_info::placed (const debug_info_entry::pointer &ref,
+                                 bool have_sibling)
+  {
+    ++_m_uses;
+    _m_with_sibling[have_sibling] = true;
+
+    if (_m_refs.empty ())
+      {
+       subr::nothing dummy;
+       self (new value::value_reference (ref, dummy));
+      }
+    else
+      for (size_t n = _m_refs.size (); n > 0; --n)
+       {
+         value::value_reference *self_ref = _m_refs.front ();
+         self_ref->ref = ref;
+         _m_refs.pop ();
+         _m_refs.push (self_ref);
+       }
+  }
+
   struct dwarf_output::value::circular_reference
     : public dwarf_output::value::value_reference
   {
@@ -2274,7 +2273,6 @@ namespace elfutils
               const compile_units::iterator &out)
     {
       typename tracker::walk into (_m_tracker, in, out);
-
       *out = unit_copier (this, *in).final ()->first;
     }
 
index f3edd345070c80d6e730c84294f0ad8e76a059be..7c47d44d9148ba65931ff87b6df5829e3d8da819 100644 (file)
@@ -388,18 +388,18 @@ namespace
 }
 
 dwarf_output::shape_type::shape_type
-    (const debug_info_entry::pointer &ref,
+    (const debug_info_entry &die,
      const dwarf_output::die_info &info)
-  : _m_tag (ref->tag ())
-  , _m_has_children (ref->has_children ())
+  : _m_tag (die.tag ())
+  , _m_has_children (die.has_children ())
   , _m_hash (8675309 << _m_has_children)
 {
-  if (info._m_with_sibling[true] && ref->has_children ())
+  if (info._m_with_sibling[true] && die.has_children ())
     _m_attrs.push_back (DW_AT_sibling);
 
   for (debug_info_entry::attributes_type::const_iterator it
-        = ref->attributes ().begin ();
-       it != ref->attributes ().end (); ++it)
+        = die.attributes ().begin ();
+       it != die.attributes ().end (); ++it)
     _m_attrs.push_back (it->first);
 
   // Sort it, but leave sibling attribute at the beginning.
@@ -413,19 +413,6 @@ dwarf_output::shape_type::shape_type
     subr::hash_combine (_m_hash, *it);
 }
 
-namespace
-{
-  struct abbreviation
-  {
-    dwarf_output::die_ref_vect _m_users;
-    std::vector <int> _m_forms;
-
-    abbreviation (std::vector <int> forms)
-      : _m_forms (forms)
-    {}
-  };
-}
-
 namespace
 {
   template <class Iterator>
@@ -775,13 +762,17 @@ namespace
 void
 dwarf_output::shape_info::instantiate
   (dwarf_output::shape_type const &shape,
+   dwarf_output_collector &col,
    bool addr_64, bool dwarf_64)
 {
+  // Prevent instance pointers from invalidation upon push_back.
+  _m_instances.reserve (_m_users.size ());
+
   for (die_ref_vect::const_iterator it = _m_users.begin ();
        it != _m_users.end (); ++it)
     {
       instance_type inst;
-      debug_info_entry const &die = **it;
+      debug_info_entry const &die = *it;
       debug_info_entry::attributes_type const &attribs = die.attributes ();
       for (shape_type::attrs_vec::const_iterator at = shape._m_attrs.begin ();
           at != shape._m_attrs.end (); ++at)
@@ -844,9 +835,11 @@ dwarf_output::shape_info::instantiate
                  assert (form != -1);
                }
            }
-         inst.first.push_back (form);
+         inst.forms.insert (std::make_pair (name, form));
        }
-      std::cout << "Need to add to instance map." << std::endl;
+
+      die_info &i = col._m_unique.find (die)->second;
+      i.abbrev_ptr = _m_instances.end ();
       _m_instances.push_back (inst);
     }
 
@@ -865,23 +858,17 @@ dwarf_output::shape_info::build_data
 {
   std::back_insert_iterator<section_appender> inserter
     = std::back_inserter (appender);
-  ::dw_write_uleb128 (inserter, inst.second);
+  ::dw_write_uleb128 (inserter, inst.code);
   ::dw_write_uleb128 (inserter, shape._m_tag);
   *inserter++ = shape._m_has_children ? DW_CHILDREN_yes : DW_CHILDREN_no;
 
-  // We iterate shape attribute map in parallel with instance
-  // attribute forms.  They are stored in the same order.  We get
-  // attribute name from attribute map, and concrete form from
-  // instance.
-  assert (shape._m_attrs.size () == inst.first.size ());
-  dwarf_output::shape_type::attrs_vec::const_iterator at
-    = shape._m_attrs.begin ();
-  for (instance_type::first_type::const_iterator it = inst.first.begin ();
-       it != inst.first.end (); ++it)
+  assert (shape._m_attrs.size () == inst.forms.size ());
+  for (instance_type::forms_type::const_iterator it = inst.forms.begin ();
+       it != inst.forms.end (); ++it)
     {
       // ULEB128 name & form
-      ::dw_write_uleb128 (inserter, *at++);
-      ::dw_write_uleb128 (inserter, *it);
+      ::dw_write_uleb128 (inserter, it->first);
+      ::dw_write_uleb128 (inserter, it->second);
     }
 
   // 0 for name & form to terminate the abbreviation
@@ -890,17 +877,32 @@ dwarf_output::shape_info::build_data
 }
 
 void
-dwarf_output::build_output (bool addr_64, bool dwarf_64)
+dwarf_output_collector::build_output (bool addr_64, bool dwarf_64)
 {
   size_t code = 0;
-  for (dwarf_output::shape_map::iterator it = _m_shapes.begin ();
+  for (die_map::const_iterator it = _m_unique.begin ();
+       it != _m_unique.end (); ++it)
+    {
+      dwarf_output::shape_type shape (it->first, it->second);
+      dwarf_output_collector::shape_map::iterator st
+       = _m_shapes.find (shape);
+      if (st != _m_shapes.end ())
+       st->second.add_user (it->first);
+      else
+       {
+         dwarf_output::shape_info i (it->first);
+         _m_shapes.insert (std::make_pair (shape, i));
+       }
+    }
+
+  for (shape_map::iterator it = _m_shapes.begin ();
        it != _m_shapes.end (); ++it)
     {
-      it->second.instantiate (it->first, addr_64, dwarf_64);
-      for (dwarf_output::shape_info::instances_type::iterator jt
+      it->second.instantiate (it->first, *this, addr_64, dwarf_64);
+      for (dwarf_output::shape_info::instance_vec::iterator jt
             = it->second._m_instances.begin ();
           jt != it->second._m_instances.end (); ++jt)
-       jt->second = ++code;
+       jt->code = ++code;
     }
 
   _m_output_built = true;
@@ -908,19 +910,19 @@ dwarf_output::build_output (bool addr_64, bool dwarf_64)
 
 void
 dwarf_output::output_debug_abbrev (section_appender &appender,
-                                  __unused dwarf_output_collector &c,
+                                  dwarf_output_collector &c,
                                   bool addr_64)
 {
-  if (!_m_output_built)
+  if (!c._m_output_built)
     /* xxx we need to decide on dwarf_64 as soon as here.  That's not
        good.  We will probably have to build debug_info and
        abbreviations in parallel, and dump abbreviations after
        debug_info is done and we know how big the data were.  */
-    build_output (addr_64, false /* xxx dwarf_64 */);
+    c.build_output (addr_64, false /* xxx dwarf_64 */);
 
-  for (dwarf_output::shape_map::iterator it = _m_shapes.begin ();
-       it != _m_shapes.end (); ++it)
-    for (dwarf_output::shape_info::instances_type::const_iterator jt
+  for (dwarf_output_collector::shape_map::iterator it = c._m_shapes.begin ();
+       it != c._m_shapes.end (); ++it)
+    for (dwarf_output::shape_info::instance_vec::const_iterator jt
           = it->second._m_instances.begin ();
         jt != it->second._m_instances.end (); ++jt)
       it->second.build_data (it->first, *jt, appender);
@@ -984,7 +986,7 @@ public:
       cu_local_recomputer (new local_ref_recomputer (cu_start))
   {}
 
-  void dump (dwarf_output::debug_info_entry const &die,
+  void dump (dwarf_output::die_info_pair const &info_pair,
             gap &sibling_gap,
             unsigned level)
   {
@@ -994,61 +996,39 @@ public:
       "                                                            ";
     static char const *tail = spaces + strlen (spaces);
     __attribute__ ((unused)) char const *pad = tail - level * 2;
-    //std::cout << pad << "CHILD " << dwarf_tag_string (die.tag ()) << " ";
-
-    std::back_insert_iterator <section_appender> inserter
-      = std::back_inserter (appender);
-
-    /* Find shape instance.  XXX We currently have to iterate
-       through all the shapes.  Fix later.  */
-    dwarf_output::shape_type const *shape = NULL;
-    dwarf_output::shape_info const *info = NULL;
-    size_t instance_id = (size_t)-1;
 
+    dwarf_output::debug_info_entry const &die = info_pair.first;
+    dwarf_output::die_info const &info = info_pair.second;
     /*
-    for (dwarf_output::shape_map::iterator st = c._m_shapes.begin ();
-        st != c._m_shapes.end (); ++st)
-      {
-       dwarf_output::shape_info::instance_map::const_iterator
-         instance_it = st->second._m_instance_map.find (ref);
-       if (instance_it != st->second._m_instance_map.end ())
-         {
-           assert (shape == NULL && info == NULL);
-
-           shape = &st->first;
-           info = &st->second;
-           instance_id = instance_it->second;
-         }
-      }
+    std::cout << pad << "CHILD " << dwarf_tag_string (die.tag ())
+             << " " << std::flush;
     */
-    assert (shape != NULL && info != NULL);
+
+    std::back_insert_iterator <section_appender> inserter
+      = std::back_inserter (appender);
 
     /* Record where the DIE begins.  */
     die_off [die.offset ()] = appender.size ();
-    // xxx handle non-CU-local
 
     /* Our instance.  */
-    dwarf_output::shape_info::instance_type const &instance
-      = info->_m_instances[instance_id];
-    size_t code = instance.second;
-    ::dw_write_uleb128 (inserter, code);
+    dwarf_output::shape_info::instance_type const &instance = *info.abbrev_ptr;
+    ::dw_write_uleb128 (inserter, instance.code);
 
     //std::cout << " " << code << std::endl;
 
     /* Dump attribute values.  */
     debug_info_entry::attributes_type const &attribs = die.attributes ();
-    std::vector<int>::const_iterator form_it = instance.first.begin ();
-    for (dwarf_output::shape_type::attrs_vec::const_iterator
-          at = shape->_m_attrs.begin ();
-        at != shape->_m_attrs.end (); ++at)
+    for (dwarf_output::shape_info::instance_type::forms_type::const_iterator
+          at = instance.forms.begin (); at != instance.forms.end (); ++at)
       {
-       int name = *at;
-       int form = *form_it++;
+       int name = at->first;
+       int form = at->second;
        if (name == DW_AT_sibling)
          {
            // XXX in fact we want to handle this case just like any
            // other CU-local reference.  So also use this below (or
-           // better reuse single piece of code).
+           // better reuse single piece of code for reference
+           // handling).
            size_t gap_size
              = ::form_width (form, addr_64, false /* xxx dwarf_64 */);
            sibling_gap = gap (appender, gap_size,
@@ -1071,8 +1051,8 @@ public:
        dwarf::value_space vs = value.what_space ();
 
        /*
-       std::cout << pad << "  " << dwarf_attr_string (name)
-                 << ": " << dwarf_form_string (form) << " ";
+         std::cout << pad << "  " << dwarf_attr_string (name)
+         << ": " << dwarf_form_string (form) << " ";
        */
        switch (vs)
          {
@@ -1187,76 +1167,77 @@ public:
          };
        //std::cout << std::endl;
       }
-    assert (form_it == instance.first.end ());
 
     if (!die.children ().empty ())
       {
        gap my_sibling_gap;
-       for (compile_unit::children_type::const_iterator jt
-              = die.children ().begin (); jt != die.children ().end (); ++jt)
+       for (std::vector<dwarf_output::die_info_pair *>::const_iterator jt
+              = die.children ().info ().begin ();
+            jt != die.children ().info ().end (); ++jt)
          {
            if (my_sibling_gap.valid ())
              {
-               die_backpatch.push_back (std::make_pair (my_sibling_gap,
-                                                        jt->offset ()));
+               die_backpatch.push_back
+                 (std::make_pair (my_sibling_gap,
+                                  (*jt)->first.offset ()));
                my_sibling_gap = gap ();
              }
-           dump (*jt, my_sibling_gap, level + 1);
+           dump (**jt, my_sibling_gap, level + 1);
          }
        *inserter++ = 0;
       }
   }
 };
 
-void
-dwarf_output::output_debug_info (section_appender &appender,
-                                __unused dwarf_output_collector &c,
-                                strtab &debug_str,
-                                str_backpatch_vec &str_backpatch,
-                                bool addr_64, bool big_endian)
-{
-  /* We request appender directly, because we depend on .alloc method
-     being implemented, which is not the case for std containers.
-     Alternative approach would use purely random access
-     iterator-based solution, which would be considerable amount of
-     work (and bugs) and would involve memory overhead for holding all
-     these otherwise useless Elf_Data pointers that we've allocated in
-     the past.  So just ditch it and KISS.  */
-
-  if (!_m_output_built)
-    build_output (addr_64, false /* dwarf_64 */);
-
-  std::back_insert_iterator <section_appender> inserter
-    = std::back_inserter (appender);
-
-  for (compile_units::const_iterator it = _m_units.begin ();
-       it != _m_units.end (); ++it)
-    {
-      // Remember where the unit started for back-patching of size.
-      size_t cu_start = appender.size ();
-
-      // Unit length.
-      gap length_gap (appender, 4 /*XXX dwarf64*/, big_endian);
-
-      // Version.
-      ::dw_write<2> (appender.alloc (2), 3, big_endian);
-
-      // Debug abbrev offset.  Use the single abbrev table that we
-      // emit at offset 0.
-      ::dw_write<4> (appender.alloc (4), 0, big_endian);
-
-      // Size in bytes of an address on the target architecture.
-      *inserter++ = addr_64 ? 8 : 4;
-
-      die_off_map die_off;
-      die_backpatch_vec die_backpatch;
-
-      //std::cout << "UNIT " << it->_m_cu_die << std::endl;
-      gap fake_gap;
-      recursive_dumper (*this, appender, debug_str, addr_64,
-                       die_off, die_backpatch, str_backpatch,
-                       big_endian, cu_start)
-       .dump (*it, fake_gap, 0);
+ void
+ dwarf_output::output_debug_info (section_appender &appender,
+                                 dwarf_output_collector &c,
+                                 strtab &debug_str,
+                                 str_backpatch_vec &str_backpatch,
+                                 bool addr_64, bool big_endian)
+ {
+   /* We request appender directly, because we depend on .alloc method
+      being implemented, which is not the case for std containers.
+      Alternative approach would use purely random access
+      iterator-based solution, which would be considerable amount of
+      work (and bugs) and would involve memory overhead for holding all
+      these otherwise useless Elf_Data pointers that we've allocated in
+      the past.  So just ditch it and KISS.  */
+
+   if (!c._m_output_built)
+     c.build_output (addr_64, false /* dwarf_64 */);
+
+   std::back_insert_iterator <section_appender> inserter
+     = std::back_inserter (appender);
+
+   for (compile_units::const_iterator it = _m_units.begin ();
+       it != _m_units.end (); ++it)
+     {
+       // Remember where the unit started for back-patching of size.
+       size_t cu_start = appender.size ();
+
+       // Unit length.
+       gap length_gap (appender, 4 /*XXX dwarf64*/, big_endian);
+
+       // Version.
+       ::dw_write<2> (appender.alloc (2), 3, big_endian);
+
+       // Debug abbrev offset.  Use the single abbrev table that we
+       // emit at offset 0.
+       ::dw_write<4> (appender.alloc (4), 0, big_endian);
+
+       // Size in bytes of an address on the target architecture.
+       *inserter++ = addr_64 ? 8 : 4;
+
+       die_off_map die_off;
+       die_backpatch_vec die_backpatch;
+
+       //std::cout << "UNIT " << it->_m_cu_die << std::endl;
+       gap fake_gap;
+       recursive_dumper (*this, appender, debug_str, addr_64,
+                        die_off, die_backpatch, str_backpatch,
+                        big_endian, cu_start)
+        .dump (*c._m_unique.find (*it), fake_gap, 0);
       assert (!fake_gap.valid ());
 
       std::for_each (die_backpatch.begin (), die_backpatch.end (),