]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Back-patch DIE references
authorPetr Machata <pmachata@redhat.com>
Wed, 5 Aug 2009 14:17:59 +0000 (16:17 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 5 Aug 2009 14:17:59 +0000 (16:17 +0200)
libdw/c++/dwarf_output
libdw/c++/output-shape.cc

index 41ebe96c4262a670696400d32b550c92571d0554..7726126c35daccfbedec95aa3403c7900973c4e2 100644 (file)
@@ -652,6 +652,20 @@ namespace elfutils
       throw std::logic_error ("copying dwarf_output requires a collector");
     }
 
+    // die offset -> file address
+    typedef std::map< ::Dwarf_Off, ::Dwarf_Off> die_off_map;
+
+    // [((pointer, length), die offset)]
+    typedef std::vector<std::pair<std::pair<unsigned char *, size_t>,
+                                 ::Dwarf_Off> > backpatch_vec;
+    static void recursively_dump (section_appender &appender,
+                                 dwarf_output_collector &c,
+                                 debug_info_entry const &die,
+                                 unsigned level,
+                                 bool a_addr_64,
+                                 die_off_map &die_off,
+                                 backpatch_vec &backpatch);
+
   public:
     // Constructor for an empty file, can add to its compile_units ().
     inline dwarf_output () {}
index 52f79aed4a81f7a99de18ed47eccfac1b548df6b..4b6fed70d50bdf3edaa6c16be2d731b439f0cfa1 100644 (file)
@@ -338,6 +338,191 @@ dwarf_output::output_debug_abbrev (section_appender &appender,
   appender.push_back (0); // terminate table
 }
 
+void
+dwarf_output::recursively_dump (section_appender &appender,
+                               dwarf_output_collector &c,
+                               debug_info_entry const &die,
+                               unsigned level,
+                               bool  addr_64,
+                               dwarf_output::die_off_map &die_off,
+                               dwarf_output::backpatch_vec &backpatch)
+{
+  static char const spaces[] =
+    "                                                            "
+    "                                                            "
+    "                                                            ";
+  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_collector::shape_type const *shape = NULL;
+  dwarf_output_collector::shape_info const *info = NULL;
+  size_t instance_id = (size_t)-1;
+
+  for (dwarf_output_collector::shape_map::iterator st = c._m_shapes.begin ();
+       st != c._m_shapes.end (); ++st)
+    {
+      dwarf_output_collector::shape_info::instance_map::const_iterator
+       instance_it = st->second._m_instance_map.find (&die);
+      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 - st->second._m_instances.begin ();
+       }
+    }
+  assert (shape != NULL && info != NULL);
+
+  /* Record where the DIE begins.  */
+  die_off [die.offset ()] = appender.size ();
+  // xxx handle non-CU-local
+
+  /* Our instance.  */
+  dwarf_output_collector::shape_info::instance_type const &instance
+    = info->_m_instances[instance_id];
+  size_t code = instance.second;
+  ::dw_write_uleb128 (inserter, 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_collector::shape_type::attrs_type::const_iterator
+        at = shape->_m_attrs.begin ();
+       at != shape->_m_attrs.end (); ++at)
+    {
+      int name = at->first;
+      int form = *form_it++;
+      debug_info_entry::attributes_type::const_iterator
+       vt = attribs.find (name);
+      assert (vt != attribs.end ());
+
+      attr_value const &value = vt->second;
+      /*
+       std::cout << pad
+       << "    " << dwarf_attr_string (name)
+       << ":" << dwarf_form_string (form)
+       << ":" << dwarf_form_string (at->second)
+       << ":" << value.to_string () << std::endl;
+      */
+      dwarf::value_space vs = value.what_space ();
+
+      switch (vs)
+       {
+       case dwarf::VS_flag:
+         assert (form == DW_FORM_flag);
+         ::dw_write<1> (appender.alloc (1), !!value.flag ());
+         break;
+
+       case dwarf::VS_rangelistptr:
+       case dwarf::VS_lineptr:
+       case dwarf::VS_macptr:
+         assert (form == DW_FORM_data4); // XXX temporary
+         // XXX leave out for now
+         ::dw_write<4> (appender.alloc (4), 0);
+         break;
+
+       case dwarf::VS_constant:
+         assert (form == DW_FORM_udata);
+         ::dw_write_uleb128 (inserter, value.constant ());
+         break;
+
+       case dwarf::VS_dwarf_constant:
+         assert (form == DW_FORM_udata);
+         ::dw_write_uleb128 (inserter, value.dwarf_constant ());
+         break;
+
+       case dwarf::VS_source_line:
+         assert (form == DW_FORM_udata);
+         ::dw_write_uleb128 (inserter, value.source_line ());
+         break;
+
+       case dwarf::VS_source_column:
+         assert (form == DW_FORM_udata);
+         ::dw_write_uleb128 (inserter, value.source_column ());
+         break;
+
+       case dwarf::VS_string:
+       case dwarf::VS_identifier:
+       case dwarf::VS_source_file:
+         if (vs != dwarf::VS_source_file
+             || form == DW_FORM_string
+             || form == DW_FORM_strp)
+           {
+             assert (form == DW_FORM_string); // XXX temporary
+             std::string const &str =
+               vs == dwarf::VS_string
+               ? value.string ()
+               : (vs == dwarf::VS_source_file
+                  ? value.source_file ().name ()
+                  : value.identifier ());
+
+             std::copy (str.begin (), str.end (), inserter);
+             *inserter++ = 0;
+           }
+         else if (vs == dwarf::VS_source_file
+                  && form == DW_FORM_udata)
+           // XXX leave out for now
+           ::dw_write_uleb128 (inserter, 0);
+         break;
+
+       case dwarf::VS_address:
+         {
+           assert (form == DW_FORM_addr);
+           size_t w = addr_64 ? 8 : 4;
+           ::dw_write_var (appender.alloc (w), w, value.address ());
+         }
+         break;
+
+       case dwarf::VS_reference:
+         {
+           assert (form == DW_FORM_ref_addr);
+           // Emit zero, patch later.
+           // XXX dwarf64
+           unsigned char *ptr = appender.alloc (4);
+           ::dw_write<4> (ptr, 0);
+           backpatch.push_back
+             (std::make_pair (std::make_pair (ptr, 4),
+                              value.reference ()->offset ()));
+         }
+         break;
+
+       case dwarf::VS_location:
+         // XXX leave out for now
+         if (form == DW_FORM_block)
+           ::dw_write_uleb128 (inserter, 0);
+         else
+           {
+             assert (form == DW_FORM_data4); // XXX temporary
+             ::dw_write<4> (appender.alloc (4), 0);
+           }
+         break;
+
+       case dwarf::VS_discr_list:
+         throw std::runtime_error ("Can't handle VS_discr_list.");
+       };
+    }
+  assert (form_it == instance.first.end ());
+
+  if (!die.children ().empty ())
+    {
+      for (compile_unit::children_type::const_iterator jt
+            = die.children ().begin (); jt != die.children ().end (); ++jt)
+       recursively_dump (appender, c, *jt, level + 1, addr_64,
+                         die_off, backpatch);
+      *inserter++ = 0;
+    }
+}
+
 void
 dwarf_output::output_debug_info (section_appender &appender,
                                 dwarf_output_collector &c,
@@ -377,190 +562,25 @@ dwarf_output::output_debug_info (section_appender &appender,
       // XXX size in bytes of an address on the target architecture.
       *inserter++ = addr_64 ? 8 : 4;
 
-      struct recursively_dump
-      {
-       section_appender &appender;
-       dwarf_output_collector &c;
-       bool addr_64;
-       std::back_insert_iterator <section_appender> inserter;
-
-       recursively_dump (section_appender &an_appender,
-                         dwarf_output_collector &a_c,
-                         debug_info_entry const &die,
-                         unsigned level,
-                         bool a_addr_64)
-         : appender (an_appender), c (a_c), addr_64 (a_addr_64)
-         , inserter (std::back_inserter (appender))
-       {
-         static char const spaces[] =
-           "                                                            "
-           "                                                            "
-           "                                                            ";
-         static char const *tail = spaces + strlen (spaces);
-         __attribute__ ((unused)) char const *pad = tail - level * 2;
-         //std::cout << pad << "CHILD " << dwarf_tag_string (die.tag ());
-
-         /* Find shape instance.  XXX We currently have to iterate
-            through all the shapes.  Fix later.  */
-         dwarf_output_collector::shape_type const *shape = NULL;
-         dwarf_output_collector::shape_info const *info = NULL;
-         size_t instance_id = (size_t)-1;
-
-         for (dwarf_output_collector::shape_map::iterator st = c._m_shapes.begin ();
-              st != c._m_shapes.end (); ++st)
-           {
-             dwarf_output_collector::shape_info::instance_map::const_iterator
-               instance_it = st->second._m_instance_map.find (&die);
-             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 - st->second._m_instances.begin ();
-               }
-           }
-         assert (shape != NULL && info != NULL);
-
-         /* Our instance.  */
-         dwarf_output_collector::shape_info::instance_type const &instance
-           = info->_m_instances[instance_id];
-         size_t code = instance.second;
-         ::dw_write_uleb128 (inserter, 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_collector::shape_type::attrs_type::const_iterator
-                at = shape->_m_attrs.begin ();
-              at != shape->_m_attrs.end (); ++at)
-           {
-             int name = at->first;
-             int form = *form_it++;
-             debug_info_entry::attributes_type::const_iterator
-               vt = attribs.find (name);
-             assert (vt != attribs.end ());
-
-             attr_value const &value = vt->second;
-             /*
-             std::cout << pad
-                       << "    " << dwarf_attr_string (name)
-                       << ":" << dwarf_form_string (form)
-                       << ":" << dwarf_form_string (at->second)
-                       << ":" << value.to_string () << std::endl;
-             */
-             dwarf::value_space vs = value.what_space ();
-
-             switch (vs)
-               {
-               case dwarf::VS_flag:
-                 assert (form == DW_FORM_flag);
-                 ::dw_write<1> (appender.alloc (1), !!value.flag ());
-                 break;
-
-               case dwarf::VS_rangelistptr:
-               case dwarf::VS_lineptr:
-               case dwarf::VS_macptr:
-                 assert (form == DW_FORM_data4); // XXX temporary
-                 // XXX leave out for now
-                 ::dw_write<4> (appender.alloc (4), 0);
-                 break;
-
-               case dwarf::VS_constant:
-                 assert (form == DW_FORM_udata);
-                 ::dw_write_uleb128 (inserter, value.constant ());
-                 break;
-
-               case dwarf::VS_dwarf_constant:
-                 assert (form == DW_FORM_udata);
-                 ::dw_write_uleb128 (inserter, value.dwarf_constant ());
-                 break;
-
-               case dwarf::VS_source_line:
-                 assert (form == DW_FORM_udata);
-                 ::dw_write_uleb128 (inserter, value.source_line ());
-                 break;
-
-               case dwarf::VS_source_column:
-                 assert (form == DW_FORM_udata);
-                 ::dw_write_uleb128 (inserter, value.source_column ());
-                 break;
-
-               case dwarf::VS_string:
-               case dwarf::VS_identifier:
-               case dwarf::VS_source_file:
-                 if (vs != dwarf::VS_source_file
-                     || form == DW_FORM_string
-                     || form == DW_FORM_strp)
-                   {
-                     assert (form == DW_FORM_string); // XXX temporary
-                     std::string const &str =
-                       vs == dwarf::VS_string
-                       ? value.string ()
-                       : (vs == dwarf::VS_source_file
-                          ? value.source_file ().name ()
-                          : value.identifier ());
-
-                     std::copy (str.begin (), str.end (), inserter);
-                     *inserter++ = 0;
-                   }
-                 else if (vs == dwarf::VS_source_file
-                          && form == DW_FORM_udata)
-                   // XXX leave out for now
-                   ::dw_write_uleb128 (inserter, 0);
-                 break;
-
-               case dwarf::VS_address:
-                 {
-                   assert (form == DW_FORM_addr);
-                   size_t w = addr_64 ? 8 : 4;
-                   ::dw_write_var (appender.alloc (w), w, value.address ());
-                 }
-                 break;
-
-               case dwarf::VS_reference:
-                 assert (form == DW_FORM_ref_addr);
-                 // XXX dwarf64
-                 ::dw_write<4> (appender.alloc (4),
-                                value.reference ()->offset ());
-                 break;
-
-               case dwarf::VS_location:
-                 // XXX leave out for now
-                 if (form == DW_FORM_block)
-                   ::dw_write_uleb128 (inserter, 0);
-                 else
-                   {
-                     assert (form == DW_FORM_data4); // XXX temporary
-                     ::dw_write<4> (appender.alloc (4), 0);
-                   }
-                 break;
-
-               case dwarf::VS_discr_list:
-                 std::cout << dwarf_form_string (form)
-                           << " " << dwarf_attr_string (name) << std::endl;
-                 break;
-               };
-           }
-         assert (form_it == instance.first.end ());
+      die_off_map die_off;
+      backpatch_vec backpatch;
 
-         if (!die.children ().empty ())
-           {
-             for (compile_unit::children_type::const_iterator jt
-                    = die.children ().begin (); jt != die.children ().end (); ++jt)
-               recursively_dump (appender, c, *jt, level + 1, addr_64);
-             *inserter++ = 0;
-           }
+      //std::cout << "UNIT " << it->_m_cu_die << std::endl;
+      recursively_dump (appender, c, *it->_m_cu_die, 0, addr_64,
+                       die_off, backpatch);
+
+      /* Do the back-patching.  */
+      for (backpatch_vec::const_iterator bt = backpatch.begin ();
+          bt != backpatch.end (); ++bt)
+       {
+         die_off_map::const_iterator ot = die_off.find (bt->second);
+         assert (ot != die_off.end ());
+         ::dw_write_var (bt->first.first, bt->first.second, ot->second);
        }
-      };
 
-      //std::cout << "UNIT " << it->_m_cu_die << std::endl;
-      recursively_dump (appender, c, *it->_m_cu_die, 0, addr_64);
+      /* Back-patch length.  */
       size_t length = appender.size () - cu_start - 4; // -4 for length info. XXX dwarf64
       assert (length < (uint32_t)-1); // XXX temporary XXX dwarf64
-      ::dw_write<4> (length_data, length);
+      ::dw_write<4> (length_data, length); // XXX dwarf64
     }
 }