]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Emit .debug_loc
authorPetr Machata <pmachata@redhat.com>
Wed, 23 Sep 2009 20:27:54 +0000 (22:27 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 23 Sep 2009 20:27:54 +0000 (22:27 +0200)
libdw/c++/dwarf_output
libdw/c++/output-shape.cc
src/writer.cc

index 906bdf293930e2a2d7928814456ad343d3bb12ee..9269060c8c5a88e7ddf3e93397568dd629fb30b9 100644 (file)
@@ -933,6 +933,10 @@ namespace elfutils
                                  range_list const *>> range_backpatch_vec;
     typedef std::map<range_list const *, ::Dwarf_Off> range_offsets_map;
 
+    typedef std::vector<std::pair<gap,
+                                 location_attr const *>> loc_backpatch_vec;
+    typedef std::map<location_attr const *, ::Dwarf_Off> loc_offsets_map;
+
     dwarf_output_collector &_m_col;
     dwarf_output &_m_dw;
 
@@ -945,6 +949,9 @@ namespace elfutils
     range_backpatch_vec _m_range_backpatch;
     range_offsets_map _m_range_offsets;
 
+    loc_backpatch_vec _m_loc_backpatch;
+    loc_offsets_map _m_loc_offsets;
+
     // Set of shapes.
     typedef std::tr1::unordered_map<dwarf_output::shape_type,
       dwarf_output::shape_info,
@@ -999,6 +1006,7 @@ namespace elfutils
     void output_debug_info (section_appender &appender);
     void output_debug_line (section_appender &appender);
     void output_debug_ranges (section_appender &appender);
+    void output_debug_loc (section_appender &appender);
     void apply_patches ();
   };
 
index 1574622d297f054798f62de80d7b0b7fca2f189a..0d1a6560570fab1daa6124e86d6d092c54afd50e 100644 (file)
@@ -277,8 +277,12 @@ namespace
        return const_forms;
 
       case dwarf::VS_location:
+       /* xxx we spit out everything in .debug_loc.  Make similar
+          heuristic of !is_list location as is done for strings.
+
        if (!value.location ().is_list ())
          return block_forms;
+       */
        /* Fall through.  */
 
       case dwarf::VS_lineptr:
@@ -319,7 +323,6 @@ namespace
       {
       case dwarf::VS_flag:
       case dwarf::VS_macptr:
-      case dwarf::VS_location:
       case dwarf::VS_constant:
       case dwarf::VS_dwarf_constant:
       case dwarf::VS_source_line:
@@ -341,6 +344,7 @@ namespace
       case dwarf::VS_lineptr:  // xxx but wait, if we emit lines
                                // first, we can optimize it.
       case dwarf::VS_rangelistptr: // xxx same here
+      case dwarf::VS_location: // xxx and here
        return false;
       }
 
@@ -359,7 +363,6 @@ namespace
        return !!value.flag ();
 
       case dwarf::VS_macptr:
-      case dwarf::VS_location:
        return 0; /* xxx */
 
       case dwarf::VS_constant:
@@ -393,6 +396,7 @@ namespace
       case dwarf::VS_reference:
       case dwarf::VS_discr_list:
       case dwarf::VS_lineptr:
+      case dwarf::VS_location:
        abort ();
       }
 
@@ -1263,11 +1267,9 @@ public:
            break;
 
          case dwarf::VS_location:
-           // XXX leave out for now
-           if (form == DW_FORM_block)
-             ::dw_write_uleb128 (inserter, 0);
-           else
-             _m_parent.write_form (inserter, form, 0 /*xxx*/);
+           _m_parent._m_loc_backpatch.push_back
+             (std::make_pair (gap (_m_parent, appender, form),
+                              &value.location ()));
            break;
 
          case dwarf::VS_discr_list:
@@ -1784,7 +1786,7 @@ dwarf_output::writer::output_debug_line (section_appender &appender)
 void
 dwarf_output::writer::output_debug_ranges (section_appender &appender)
 {
-  __unused std::back_insert_iterator <section_appender> inserter
+  std::back_insert_iterator <section_appender> inserter
     = std::back_inserter (appender);
 
   for (subr::value_set<dwarf_output::value::value_rangelistptr>::const_iterator
@@ -1808,6 +1810,57 @@ dwarf_output::writer::output_debug_ranges (section_appender &appender)
     }
 }
 
+void
+dwarf_output::writer::output_debug_loc (section_appender &appender)
+{
+  typedef std::set <dwarf_output::location_attr const *> loc_set;
+  loc_set locations;
+
+  for (dwarf_output_collector::die_map::const_iterator it
+        = _m_col._m_unique.begin ();
+       it != _m_col._m_unique.end (); ++it)
+    {
+      debug_info_entry const &die = it->first;
+      for (debug_info_entry::attributes_type::const_iterator
+            at = die.attributes ().begin ();
+          at != die.attributes ().end (); ++at)
+       {
+         attr_value const &value = at->second;
+         dwarf::value_space vs = value.what_space ();
+
+         if (vs == dwarf::VS_location)
+           {
+             dwarf_output::location_attr const &loc = value.location ();
+             locations.insert (&loc);
+           }
+       }
+    }
+
+  std::back_insert_iterator <section_appender> inserter
+    = std::back_inserter (appender);
+  for (loc_set::const_iterator it = locations.begin ();
+       it != locations.end (); ++it)
+    {
+      dwarf_output::location_attr const &loc = **it;
+      if (!_m_loc_offsets.insert (std::make_pair (&loc, appender.size ()))
+         .second)
+       throw std::runtime_error ("duplicate loc table address");
+
+      for (dwarf_output::location_attr::const_iterator jt = loc.begin ();
+          jt != loc.end (); ++jt)
+       {
+         write_form (inserter, DW_FORM_addr, jt->first.first);
+         write_form (inserter, DW_FORM_addr, jt->first.second);
+         write_form (inserter, DW_FORM_data2, jt->second.size ());
+         std::copy (jt->second.begin (), jt->second.end (), inserter);
+       }
+
+      // end of list entry
+      write_form (inserter, DW_FORM_addr, 0);
+      write_form (inserter, DW_FORM_addr, 0);
+    }
+}
+
 void
 dwarf_output::writer::apply_patches ()
 {
@@ -1836,4 +1889,15 @@ dwarf_output::writer::apply_patches ()
        throw std::runtime_error (".debug_ranges ref not found");
       it->first.patch (ot->second);
     }
+
+  for (loc_backpatch_vec::const_iterator it = _m_loc_backpatch.begin ();
+       it != _m_loc_backpatch.end (); ++it)
+    {
+      loc_offsets_map::const_iterator ot = _m_loc_offsets.find (it->second);
+      if (ot == _m_loc_offsets.end ())
+       // no point mentioning the key, since it's just a memory
+       // address...
+       throw std::runtime_error (".debug_loc ref not found");
+      it->first.patch (ot->second);
+    }
 }
index e57c09b877a63475ccedb2d37987701a76fa292a..b91357629a0b9ee4c3b7e92d7ae321af19795d2b 100644 (file)
@@ -586,6 +586,11 @@ handle_elf (Elf *elf, size_t alloc_unit,
   writer.output_debug_ranges (sec_debug_ranges);
   sec_debug_ranges.done (shdr_info);
 
+  new_debug_section sec_debug_loc
+    (".debug_loc", shst, SHT_PROGBITS, ++idx, newelf, alloc_unit);
+  writer.output_debug_loc (sec_debug_loc);
+  sec_debug_loc.done (shdr_info);
+
   new_str_section sec_debug_str
     (".debug_str", shst, SHT_STRTAB, ++idx, newelf, shdr_info, debug_strtab);