]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Extract some stuff to `writer' class
authorPetr Machata <pmachata@redhat.com>
Wed, 26 Aug 2009 15:28:30 +0000 (17:28 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 26 Aug 2009 15:28:30 +0000 (17:28 +0200)
* stuff related directly to writing is gathered here

libdw/c++/dwarf_output
libdw/c++/output-shape.cc
src/writer.cc

index 32881f090e2f8f06a97ba99bd41fc3709edca352..e4f3e3426a871a757058d1dab27858911d060ace 100644 (file)
@@ -869,14 +869,6 @@ namespace elfutils
     // [(gap, string entry)]
     typedef std::vector<std::pair<gap, ::Ebl_Strent *> > str_backpatch_vec;
 
-    struct backpatch_strp
-    {
-      void operator () (std::pair<gap, ::Ebl_Strent *> const &v)
-      {
-       v.first.patch (ebl_strtaboffset (v.second));
-      }
-    };
-
   private:
     // die offset -> file address
     typedef std::map< ::Dwarf_Off, ::Dwarf_Off> die_off_map;
@@ -897,8 +889,6 @@ namespace elfutils
       }
     };
 
-    class recursive_dumper;
-
   public:
     // Constructor for an empty file, can add to its compile_units ().
     inline dwarf_output () {}
@@ -923,19 +913,41 @@ namespace elfutils
       return !(*this == other);
     }
 
-    void output_debug_abbrev (section_appender &appender,
-                             dwarf_output_collector &dw,
-                             bool addr_64);
+    class writer
+    {
+      dwarf_output_collector &_m_col;
+      dwarf_output &_m_dw;
+
+      bool _m_addr_64;
+      bool _m_dwarf_64;
+      bool _m_big_endian;
 
-    void output_debug_info (section_appender &appender,
-                           dwarf_output_collector &dw,
-                           strtab &debug_str,
-                           str_backpatch_vec &str_backpatch,
-                           bool addr_64, bool big_endian);
+      strtab &_m_debug_str;
+      str_backpatch_vec _m_str_backpatch;
 
-    void add_shape (debug_info_entry &die, bool last_sibling);
+      // 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;
+
+      void add_shape (debug_info_entry &die, bool last_sibling);
+      class recursive_dumper;
+
+    public:
+      writer (dwarf_output_collector &col,
+             dwarf_output &dw,
+             bool big_endian, bool addr_64, bool dwarf_64,
+             strtab &debug_str);
+
+      void output_debug_abbrev (section_appender &appender);
+      void output_debug_info (section_appender &appender);
+      void apply_patches ();
+    };
   };
 
+
   // Explicit specializations.
   template<>
   std::string to_string<dwarf_output::debug_info_entry>
@@ -1146,6 +1158,7 @@ namespace elfutils
   class dwarf_output_collector
   {
     friend class dwarf_output;
+    friend class dwarf_output::writer;
 
   private:
     dwarf_path_finder<dwarf_output> _m_tracker;
@@ -1207,13 +1220,6 @@ 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)
@@ -1262,7 +1268,6 @@ namespace elfutils
   public:
     inline dwarf_output_collector ()
       : _m_total (0)
-      , _m_output_built (false)
     {}
 
     static void die_stats (const die_map::value_type &elt)
@@ -1279,7 +1284,6 @@ namespace elfutils
       std::for_each (_m_unique.begin (), _m_unique.end (), die_stats);
     }
 
-    bool _m_output_built;
     void build_output (bool addr_64, bool dwarf_64);
   };
 
index 0cda2921377483188833a3e5f5fd7c278607f49e..e6602b638b07e1f85890a486684a240f4887aa68 100644 (file)
@@ -927,16 +927,24 @@ dwarf_output::shape_info::build_data
   *inserter++ = 0;
 }
 
-void
-dwarf_output_collector::build_output (bool addr_64, bool dwarf_64)
+dwarf_output::writer::writer (dwarf_output_collector &col,
+                             dwarf_output &dw,
+                             bool big_endian, bool addr_64, bool dwarf_64,
+                             strtab &debug_str)
+  : _m_col (col)
+  , _m_dw (dw)
+  , _m_addr_64 (addr_64)
+  , _m_dwarf_64 (dwarf_64)
+  , _m_big_endian (big_endian)
+  , _m_debug_str (debug_str)
 {
   size_t code = 0;
-  for (die_map::const_iterator it = _m_unique.begin ();
-       it != _m_unique.end (); ++it)
+  for (dwarf_output_collector::die_map::const_iterator it
+        = col._m_unique.begin ();
+       it != col._m_unique.end (); ++it)
     {
       dwarf_output::shape_type shape (it->first, it->second);
-      dwarf_output_collector::shape_map::iterator st
-       = _m_shapes.find (shape);
+      shape_map::iterator st = _m_shapes.find (shape);
       if (st != _m_shapes.end ())
        st->second.add_user (it->first);
       else
@@ -949,26 +957,19 @@ dwarf_output_collector::build_output (bool addr_64, bool dwarf_64)
   for (shape_map::iterator it = _m_shapes.begin ();
        it != _m_shapes.end (); ++it)
     {
-      it->second.instantiate (it->first, *this, addr_64, dwarf_64);
+      it->second.instantiate (it->first, col, 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->code = ++code;
     }
-
-  _m_output_built = true;
 }
 
 void
-dwarf_output::output_debug_abbrev (section_appender &appender,
-                                  dwarf_output_collector &c,
-                                  bool addr_64)
+dwarf_output::writer::output_debug_abbrev (section_appender &appender)
 {
-  if (!c._m_output_built)
-    c.build_output (addr_64, false /* xxx dwarf_64 */);
-
-  for (dwarf_output_collector::shape_map::iterator it = c._m_shapes.begin ();
-       it != c._m_shapes.end (); ++it)
+  for (shape_map::iterator it = _m_shapes.begin ();
+       it != _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)
@@ -998,38 +999,26 @@ struct local_ref_recomputer
   }
 };
 
-class dwarf_output::recursive_dumper
+class dwarf_output::writer::recursive_dumper
 {
-  dwarf_output &c;
+  dwarf_output::writer &_m_parent;
   section_appender &appender;
-  strtab &debug_str;
-  bool addr_64;
   die_off_map &die_off;
   die_backpatch_vec &die_backpatch;
-  str_backpatch_vec &str_backpatch;
-  bool big_endian;
   gap::recomputer::ptr cu_local_recomputer;
 
   recursive_dumper (recursive_dumper const &copy); // nocopy
 
 public:
-  recursive_dumper (dwarf_output &a_c,
+  recursive_dumper (dwarf_output::writer &writer,
                    section_appender &a_appender,
-                   strtab &a_debug_str,
-                   bool a_addr_64,
                    die_off_map &a_die_off,
                    die_backpatch_vec &a_die_backpatch,
-                   str_backpatch_vec &a_str_backpatch,
-                   bool a_big_endian,
                    uint64_t cu_start)
-    : c (a_c),
+    : _m_parent (writer),
       appender (a_appender),
-      debug_str (a_debug_str),
-      addr_64 (a_addr_64),
       die_off (a_die_off),
       die_backpatch (a_die_backpatch),
-      str_backpatch (a_str_backpatch),
-      big_endian (a_big_endian),
       cu_local_recomputer (new local_ref_recomputer (cu_start))
   {}
 
@@ -1077,10 +1066,11 @@ public:
            // other CU-local reference.  So also use this below (or
            // better reuse single piece of code for reference
            // handling).
-           size_t gap_size
-             = ::form_width (form, addr_64, false /* xxx dwarf_64 */);
+           size_t gap_size = ::form_width (form,
+                                           _m_parent._m_addr_64,
+                                           _m_parent._m_dwarf_64);
            sibling_gap = gap (appender, gap_size,
-                              big_endian, cu_local_recomputer);
+                              _m_parent._m_big_endian, cu_local_recomputer);
            continue;
          }
 
@@ -1114,46 +1104,62 @@ public:
          case dwarf::VS_rangelistptr:
          case dwarf::VS_lineptr:
          case dwarf::VS_macptr:
-           ::dw_write_form (appender, form, 0 /*xxx*/, big_endian,
-                            addr_64, false /* dwarf_64 */);
+           ::dw_write_form (appender, form, 0 /*xxx*/,
+                            _m_parent._m_big_endian,
+                            _m_parent._m_addr_64,
+                            _m_parent._m_dwarf_64);
            break;
 
          case dwarf::VS_constant:
            if (value.constant_is_integer ())
-             ::dw_write_form (appender, form, value.constant (), big_endian,
-                              addr_64, false /* dwarf_64 */);
+             ::dw_write_form (appender, form, value.constant (),
+                              _m_parent._m_big_endian,
+                              _m_parent._m_addr_64,
+                              _m_parent._m_dwarf_64);
            else
              {
                const std::vector<uint8_t> &block = value.constant_block ();
-               ::dw_write_form (appender, form, block.size (), big_endian,
-                                addr_64, false /* dwarf_64 */);
+               ::dw_write_form (appender, form, block.size (),
+                                _m_parent._m_big_endian,
+                                _m_parent._m_addr_64,
+                                _m_parent._m_dwarf_64);
                std::copy (block.begin (), block.end (), inserter);
              }
            break;
 
          case dwarf::VS_dwarf_constant:
            ::dw_write_form (appender, form, value.dwarf_constant (),
-                            big_endian, addr_64, false /* dwarf_64 */);
+                            _m_parent._m_big_endian,
+                            _m_parent._m_addr_64,
+                            _m_parent._m_dwarf_64);
            break;
 
          case dwarf::VS_source_line:
            ::dw_write_form (appender, form, value.source_line (),
-                            big_endian, addr_64, false /* dwarf_64 */);
+                            _m_parent._m_big_endian,
+                            _m_parent._m_addr_64,
+                            _m_parent._m_dwarf_64);
            break;
 
          case dwarf::VS_source_column:
            ::dw_write_form (appender, form, value.source_column (),
-                            big_endian, addr_64, false /* dwarf_64 */);
+                            _m_parent._m_big_endian,
+                            _m_parent._m_addr_64,
+                            _m_parent._m_dwarf_64);
            break;
 
          case dwarf::VS_string:
            ::dw_write_string (value.string (), form, appender,
-                              debug_str, str_backpatch, big_endian);
+                              _m_parent._m_debug_str,
+                              _m_parent._m_str_backpatch,
+                              _m_parent._m_big_endian);
            break;
 
          case dwarf::VS_identifier:
            ::dw_write_string (value.identifier (), form, appender,
-                              debug_str, str_backpatch, big_endian);
+                              _m_parent._m_debug_str,
+                              _m_parent._m_str_backpatch,
+                              _m_parent._m_big_endian);
            break;
 
          case dwarf::VS_source_file:
@@ -1161,20 +1167,25 @@ public:
              {
                ::dw_write_string (value.source_file ().name (),
                                   form, appender,
-                                  debug_str, str_backpatch, big_endian);
+                                  _m_parent._m_debug_str,
+                                  _m_parent._m_str_backpatch,
+                                  _m_parent._m_big_endian);
                break;
              }
            else
-             ::dw_write_form (appender, form, 0 /*xxx*/, big_endian,
-                              addr_64, false /* dwarf_64 */);
+             ::dw_write_form (appender, form, 0 /*xxx*/,
+                              _m_parent._m_big_endian,
+                              _m_parent._m_addr_64,
+                              _m_parent._m_dwarf_64);
            break;
 
          case dwarf::VS_address:
            {
              assert (form == DW_FORM_addr);
-             size_t w = addr_64 ? 8 : 4;
+             size_t w = _m_parent._m_addr_64 ? 8 : 4;
              ::dw_write_var (appender.alloc (w), w,
-                             value.address (), big_endian);
+                             value.address (),
+                             _m_parent._m_big_endian);
            }
            break;
 
@@ -1183,7 +1194,7 @@ public:
              assert (form == DW_FORM_ref_addr);
              // XXX dwarf64
              die_backpatch.push_back
-               (std::make_pair (gap (appender, 4, big_endian),
+               (std::make_pair (gap (appender, 4, _m_parent._m_big_endian),
                                 value.reference ()->offset ()));
            }
            break;
@@ -1193,8 +1204,10 @@ public:
            if (form == DW_FORM_block)
              ::dw_write_uleb128 (inserter, 0);
            else
-             ::dw_write_form (appender, form, 0 /*xxx*/, big_endian,
-                              addr_64, false /* dwarf_64 */);
+             ::dw_write_form (appender, form, 0 /*xxx*/,
+                              _m_parent._m_big_endian,
+                              _m_parent._m_addr_64,
+                              _m_parent._m_dwarf_64);
            break;
 
          case dwarf::VS_discr_list:
@@ -1224,52 +1237,39 @@ public:
   }
 };
 
- 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: we need continuous chunks of memory for
-      back-patching.  While it would be possible to implement this
-      purely on iterators, it's not really useful.  */
-
-   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);
+void
+dwarf_output::writer::output_debug_info (section_appender &appender)
+{
+  std::back_insert_iterator <section_appender> inserter
+    = std::back_inserter (appender);
+
+  for (compile_units::const_iterator it = _m_dw._m_units.begin ();
+       it != _m_dw._m_units.end (); ++it)
+    {
+      // Remember where the unit started for back-patching of size.
+      size_t cu_start = appender.size ();
+
+      // Unit length.
+      dwarf_output::gap length_gap (appender,
+                                   _m_dwarf_64 ? 8 : 4,
+                                   _m_big_endian);
+
+      // Version.
+      ::dw_write<2> (appender.alloc (2), 3, _m_big_endian);
+
+      // Debug abbrev offset.  Use the single abbrev table that we
+      // emit at offset 0.
+      ::dw_write<4> (appender.alloc (4), 0, _m_big_endian);
+
+      // Size in bytes of an address on the target architecture.
+      *inserter++ = _m_addr_64 ? 8 : 4;
+
+      die_off_map die_off;
+      die_backpatch_vec die_backpatch;
+
+      gap fake_gap;
+      recursive_dumper (*this, appender, die_off, die_backpatch, cu_start)
+       .dump (*_m_col._m_unique.find (*it), fake_gap, 0);
       assert (!fake_gap.valid ());
 
       std::for_each (die_backpatch.begin (), die_backpatch.end (),
@@ -1281,3 +1281,12 @@ public:
       length_gap.patch (length);
     }
 }
+
+void
+dwarf_output::writer::apply_patches ()
+{
+  for (dwarf_output::str_backpatch_vec::const_iterator it
+        = _m_str_backpatch.begin ();
+       it != _m_str_backpatch.end (); ++it)
+    it->first.patch (ebl_strtaboffset (it->second));
+}
index 08da3026b95fc1f2230d0c1d8505aea6c859cd35..27f975d1c7d6ef3b910f03f1b1e826097a90078b 100644 (file)
@@ -485,6 +485,9 @@ handle_elf (Elf *elf, size_t alloc_unit,
   bool big_endian = ehdr->e_ident[EI_DATA] == ELFDATA2MSB;
   elfutils::strtab debug_strtab (false);
   elfutils::dwarf_output::str_backpatch_vec str_backpatch;
+  elfutils::dwarf_output::writer writer (collector, dwout,
+                                        big_endian, addr_64, false,
+                                        debug_strtab);
 
 #define ADD_SECTION(NAME, TYPE, COMMAND)                               \
   {                                                                    \
@@ -498,30 +501,25 @@ handle_elf (Elf *elf, size_t alloc_unit,
   }
 
   ADD_SECTION (".debug_abbrev", SHT_PROGBITS,
-              (dwout.output_debug_abbrev (appender, collector, addr_64),
+              (writer.output_debug_abbrev (appender),
                appender.size ()));
 
   ADD_SECTION (".debug_info", SHT_PROGBITS,
-              (dwout.output_debug_info (appender, collector,
-                                        debug_strtab, str_backpatch,
-                                        addr_64, big_endian),
+              (writer.output_debug_info (appender),
                appender.size ()));
 
   ADD_SECTION (".debug_str", SHT_STRTAB,
-              ({
-                GElf_Word __size
-                  = debug_strtab.finalize (data_info.newscn)->d_size;
-                std::for_each
-                  (str_backpatch.begin (), str_backpatch.end (),
-                   elfutils::dwarf_output::backpatch_strp ());
-                __size;
-              }));
+              (debug_strtab.finalize (data_info.newscn)->d_size));
 
   ADD_SECTION (".shstrtab", SHT_STRTAB,
               shst.finalize (data_info.newscn)->d_size);
 
 #undef ADD_SECTION
 
+  // XXX This assumes that the data created by appenders of each
+  // section survive the death of appender itself.
+  writer.apply_patches ();
+
   /* Update the section information.  */
   GElf_Off lastoffset = 0;
   for (size_t cnt = 1; cnt < shdr_info.size (); ++cnt)