]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
C++ reader interface for line info
authorRoland McGrath <roland@redhat.com>
Thu, 29 Jan 2009 06:14:29 +0000 (22:14 -0800)
committerRoland McGrath <roland@redhat.com>
Thu, 29 Jan 2009 06:14:29 +0000 (22:14 -0800)
libdw/ChangeLog
libdw/Makefile.am
libdw/c++/dwarf
libdw/c++/line_info.cc [new file with mode: 0644]
libdw/c++/subr.hh [new file with mode: 0644]
libdw/c++/values.cc
src/Makefile.am

index 06ff0290f17424eb8a6ac3b9c7c61b45ccf79700..7b1d37e9d060823a642ed4e3bdc90594478cb4a7 100644 (file)
@@ -1,5 +1,11 @@
 2009-01-28  Roland McGrath  <roland@redhat.com>
 
+       * c++/dwarf: Add line table support.
+       * c++/values.cc: New file.
+       * c++/line_info.cc: New file.
+       * c++/subr.hh: New file.
+       * Makefile.am (pkginclude_HEADERS): Add it.
+
        * libdwP.h (struct Dwarf_Line_s): Move out of struct Dwarf_Lines_s
        defn so C++ doesn't scope the name to not match the Dwarf_Line typedef.
 
index daeeead1e97d1e9f5e5b0963f502f483f55b7c20..3f5032dc6d99c5cbd0738cfb268e5bed97d33ef3 100644 (file)
@@ -48,6 +48,7 @@ endif
 
 include_HEADERS = dwarf.h
 pkginclude_HEADERS = libdw.h \
+                    c++/subr.hh \
                     c++/dwarf c++/dwarf_edit
 
 libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
index 8fa911553e933866769704fe2d091b7b0d487c49..e8fb2214be186d932c8ea166c4ef6e0ccf932b00 100644 (file)
@@ -52,8 +52,8 @@
 
 #include "libdw.h"
 #include "dwarf.h"
+#include "subr.hh"
 #include <stdexcept>
-#include <iterator>
 
 #include <cstring>
 #include <iostream>
@@ -375,6 +375,11 @@ namespace elfutils
     class location_attr;
     class range_list;
     class ranges;
+    class line_info_table;
+    class directory_table;
+    class file_table;
+    class line_table;
+    class line_entry;
 
     class debug_info_entry
     {
@@ -888,6 +893,23 @@ namespace elfutils
       inline compile_unit (const debug_info_entry &die)
        : debug_info_entry (die) {}
 
+      // Fetch the CU's DW_AT_stmt_list.
+      const line_info_table line_info () const;
+
+      // Convenience methods for line_info_table sub-containers.
+      inline const directory_table include_directories () const
+      {
+       return line_info ().include_directories ();
+      }
+      const file_table files () const
+      {
+       return line_info ().files ();
+      }
+      const line_table lines () const
+      {
+       return line_info ().lines ();
+      }
+
       /*
        containers/iterators:
 
@@ -931,6 +953,8 @@ namespace elfutils
     class source_file
     {
       friend class attr_value;
+      friend class file_table;
+      friend class line_entry;
     private:
       ::Dwarf_Attribute _m_attr;
       inline ::Dwarf_Attribute *thisattr () const
@@ -1029,7 +1053,8 @@ namespace elfutils
        return range_list (*this);
       }
 
-      // XXX lineptr
+      const line_info_table line_info () const;
+
       // XXX macptr
 
       template<typename value>
@@ -1050,7 +1075,9 @@ namespace elfutils
            case VS_rangelistptr:
              return ranges () == other.ranges ();
 
-           case VS_lineptr:    // XXX punt for now, treat as constant
+           case VS_lineptr:
+             return line_info () == other.line_info ();
+
            case VS_macptr:     // XXX punt for now, treat as constant
              /*FALLTHRU*/
            case VS_constant:
@@ -1244,6 +1271,310 @@ namespace elfutils
       }
     };
 
+    // This describes a CU's directory table, a simple array of strings.
+    class directory_table
+    {
+    private:
+      ::Dwarf_Files *_m_files;
+
+      template<typename string>
+      struct name_equal
+       : public std::binary_function<const char *, string, bool>
+      {
+       bool operator () (const char *me, const string &you)
+       {
+         return you == me;
+       }
+      };
+      template<typename table>
+      inline bool table_equal (const table &other) const
+      {
+       /* We ignore the first element, the compilation directory.
+          This is not encoded in the .debug_line table, but in
+          the DW_AT_comp_dir attribute of the referring CU.
+          The directory table itself matches regardless.  */
+       const_iterator i = begin ();
+       typename table::const_iterator j = other.begin ();
+       return std::equal (++i, end (), ++j,
+                          name_equal<typename table::value_type> ());
+      }
+
+    public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef const char *value_type;
+
+      inline directory_table (::Dwarf_Files *const files)
+       : _m_files (files) {}
+      inline directory_table (const directory_table &t)
+       : _m_files (t._m_files) {}
+
+      typedef const char *const *const_iterator;
+
+      inline bool empty () const
+      {
+       return size () == 0;
+      }
+
+      size_t size () const;
+      const_iterator begin () const;
+      const_iterator end () const;
+
+      template<typename table>
+      inline bool operator== (const table &other) const
+      {
+       return table_equal (other);
+      }
+      template<typename table>
+      inline bool operator!= (const table &other) const
+      {
+       return !(*this == other);
+      }
+      // Short-circuit for comparing to self.
+      inline bool operator== (const directory_table &other) const
+      {
+       return _m_files == other._m_files || table_equal (other);
+      }
+    };
+
+    /* This describes a CU's file table.  It works like a read-only
+       std::vector<source_file>, and also supports lookup by name.  */
+    class file_table
+    {
+    private:
+      ::Dwarf_Files *_m_files;
+
+    public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef source_file value_type;
+
+      inline file_table (::Dwarf_Files *const files)
+       : _m_files (files) {}
+      inline file_table (const file_table &t)
+       : _m_files (t._m_files) {}
+
+      inline file_table &operator= (const file_table &t)
+      {
+       _m_files = t._m_files;
+       return *this;
+      }
+
+      typedef subr::indexed_iterator<file_table> const_iterator;
+
+      inline bool empty () const
+      {
+       return size () == 0;
+      }
+
+      size_t size () const;
+
+      inline const_iterator begin () const
+      {
+       return const_iterator (*this, 0);
+      }
+      inline const_iterator end () const
+      {
+       return const_iterator (*this, size ());
+      }
+
+      const source_file at (size_t idx) const;
+      const source_file operator[] (size_t idx) const
+      {
+       return at (idx);
+      }
+
+      // Look up by matching file name.
+      const_iterator find (const source_file &) const;
+      const_iterator find (const char *filename) const
+      {
+       const_iterator i = begin ();
+       while (i != end () && strcmp ((*i).name (), filename) != 0)
+         ++i;
+       return i;
+      }
+      template<typename string>
+      const_iterator find (const string &filename) const
+      {
+       const_iterator i = begin ();
+       while (i != end () && filename != (*i).name ())
+         ++i;
+       return i;
+      }
+    };
+
+    class line_entry
+    {
+    private:
+      ::Dwarf_Line *_m_line;
+
+    public:
+      line_entry (::Dwarf_Line *entry) : _m_line (entry) {}
+      line_entry (const line_entry &entry) : _m_line (entry._m_line) {}
+
+      // XXX reloc, dwfl
+      ::Dwarf_Addr address () const;
+
+      bool statement () const;
+      bool basic_block () const;
+      bool end_sequence () const;
+      bool prologue_end () const;
+      bool epilogue_begin () const;
+
+      const source_file file () const;
+      unsigned int line () const;
+      unsigned int column () const;
+
+      template<typename entry>
+      bool operator< (const entry &other) const
+      {
+       return address () < other.address ();
+      }
+      template<typename entry>
+      bool operator> (const entry &other) const
+      {
+       return address () > other.address ();
+      }
+      template<typename entry>
+      bool operator<= (const entry &other) const
+      {
+       return address () <= other.address ();
+      }
+      template<typename entry>
+      bool operator>= (const entry &other) const
+      {
+       return address () >= other.address ();
+      }
+
+      template<typename entry>
+      inline bool operator== (const entry &other) const
+      {
+       return (address () == other.address ()
+               && line () == other.line ()
+               && column () == other.column ()
+               && statement () == other.statement ()
+               && basic_block () == other.basic_block ()
+               && end_sequence () == other.end_sequence ()
+               && prologue_end () == other.prologue_end ()
+               && epilogue_begin () == other.epilogue_begin ()
+               && file () == other.file ());
+      }
+      template<typename entry>
+      inline bool operator!= (const entry &other) const
+      {
+       return !(*this == other);
+      }
+      // Short-circuit for our own type.
+      bool operator== (const line_entry &other) const;
+    };
+
+    class line_table
+    {
+    private:
+      ::Dwarf_Lines *_m_lines;
+
+    public:
+      typedef size_t size_type;
+      typedef ptrdiff_t difference_type;
+      typedef line_entry value_type;
+
+      inline line_table (::Dwarf_Lines *const lines)
+       : _m_lines (lines) {}
+      inline line_table (const line_table &t)
+       : _m_lines (t._m_lines) {}
+
+      inline line_table &operator= (const line_table &t)
+      {
+       _m_lines = t._m_lines;
+       return *this;
+      }
+
+      typedef subr::indexed_iterator<line_table> const_iterator;
+
+      inline bool empty () const
+      {
+       return size () == 0;
+      }
+
+      size_t size () const;
+
+      inline const_iterator begin () const
+      {
+       return const_iterator (*this, 0);
+      }
+      inline const_iterator end () const
+      {
+       return const_iterator (*this, size ());
+      }
+
+      const line_entry at (size_t idx) const;
+      const line_entry operator[] (size_t idx) const
+      {
+       return at (idx);
+      }
+
+      template<typename table>
+      inline bool operator== (const table &other) const
+      {
+       return std::equal (begin (), end (), other.begin ());
+      }
+      template<typename table>
+      inline bool operator!= (const table &other) const
+      {
+       return !(*this == other);
+      }
+      // Short-circuit for comparing to self.
+      inline bool operator== (const line_table &other) const
+      {
+       return (_m_lines == other._m_lines
+               || std::equal (begin (), end (), other.begin ()));
+      }
+
+      // Look up by matching address.
+      const_iterator find (::Dwarf_Addr) const;
+    };
+
+    // The DW_AT_stmt_list attribute yields a line info table.
+    class line_info_table
+    {
+    private:
+      ::Dwarf_Files *_m_files;
+
+    public:
+      inline line_info_table (::Dwarf_Files *const t)
+       : _m_files (t) {}
+      inline line_info_table (const line_info_table &t)
+       : _m_files (t._m_files) {}
+
+      inline line_info_table &operator= (const line_info_table &t)
+      {
+       _m_files = t._m_files;
+       return *this;
+      }
+
+      const directory_table include_directories () const
+      {
+       return directory_table (_m_files);
+      }
+      const file_table files () const
+      {
+       return file_table (_m_files);
+      }
+      const line_table lines () const;
+
+      template<typename table>
+      inline bool operator== (const table &other) const
+      {
+       return (include_directories () == other.include_directories ()
+               && lines () == other.lines ());
+      }
+      template<typename table>
+      inline bool operator!= (const table &other) const
+      {
+       return !(*this == other);
+      }
+    };
+
     // This describes one attribute, equivalent to pair<const int, attr_value>.
     class attribute
     {
@@ -1679,6 +2010,17 @@ namespace elfutils
       }
   };
 
+  // Explicit specialization used inside dwarf::directory_table::operator==.
+  template<>
+  struct dwarf::directory_table::name_equal<const char *>
+    : public std::binary_function<const char *, const char *, bool>
+  {
+    bool operator () (const char *me, const char *you)
+    {
+      return !strcmp (me, you);
+    }
+  };
+
   inline class dwarf::debug_info_entry::raw_children
   dwarf::debug_info_entry::raw_children () const
   {
diff --git a/libdw/c++/line_info.cc b/libdw/c++/line_info.cc
new file mode 100644 (file)
index 0000000..d86b724
--- /dev/null
@@ -0,0 +1,338 @@
+#include <config.h>
+#include <cassert>
+#include "dwarf"
+
+extern "C"
+{
+#include "libdwP.h"
+}
+
+using namespace elfutils;
+using namespace std;
+
+
+// dwarf::line_info_table
+
+const dwarf::line_info_table
+dwarf::attr_value::line_info () const
+{
+  assert (dwarf_whatattr (thisattr ()) == DW_AT_stmt_list);
+
+  CUDIE (cudie, _m_attr.cu);
+  Dwarf_Lines *lines;
+  size_t n;
+  xif (dwarf_getsrclines (&cudie, &lines, &n) < 0);
+
+  return line_info_table (_m_attr.cu->files);
+}
+
+const dwarf::line_table
+dwarf::line_info_table::lines () const
+{
+  return line_table (_m_files->cu->lines);
+}
+\f
+// dwarf::source_file
+
+const class dwarf::source_file
+dwarf::attr_value::source_file () const
+{
+  switch (what_space ())
+    {
+    case VS_string:
+    case VS_source_file:
+      break;
+    default:
+      throw std::runtime_error ("XXX not a file name");
+    }
+  return source_file::source_file (_m_attr);
+}
+
+static bool
+stringform (Dwarf_Attribute *attr)
+{
+  if (attr->valp != NULL)
+    switch (dwarf_whatform (attr))
+      {
+      case DW_FORM_string:
+      case DW_FORM_strp:
+       return true;
+      }
+  return false;
+}
+
+/* Mock up a dummy attribute with a special kludge that get_files groks.
+   We use these for source_file objects consed directly from an index
+   rather than from a real attribute.  */
+static inline const Dwarf_Attribute
+dummy_source_file (Dwarf_CU *cu, unsigned int idx)
+{
+  const Dwarf_Attribute dummy = { idx, DW_FORM_indirect, NULL, cu };
+  return dummy;
+}
+
+static bool
+get_files (const Dwarf_Attribute *attr, Dwarf_Files **files, Dwarf_Word *idx)
+{
+  if (attr->valp == NULL)
+    {
+      // Dummy hack created by dummy_source_file, above.
+      assert (attr->form == DW_FORM_indirect);
+      *files = attr->cu->files;
+      *idx = attr->code;
+      return false;
+    }
+
+  CUDIE (cudie, attr->cu);
+  return (dwarf_formudata (const_cast<Dwarf_Attribute *> (attr), idx) < 0
+         || dwarf_getsrcfiles (&cudie, files, NULL) < 0);
+}
+
+Dwarf_Word
+dwarf::source_file::mtime () const
+{
+  if (stringform (thisattr ()))
+    return 0;
+
+  Dwarf_Files *files;
+  Dwarf_Word idx;
+  xif (get_files (thisattr (), &files, &idx));
+
+  Dwarf_Word result;
+  xif (dwarf_filesrc (files, idx, &result, NULL) == NULL);
+  return result;
+}
+
+Dwarf_Word
+dwarf::source_file::size () const
+{
+  if (stringform (thisattr ()))
+    return 0;
+
+  Dwarf_Files *files;
+  Dwarf_Word idx;
+  xif (get_files (thisattr (), &files, &idx));
+
+  Dwarf_Word result;
+  xif (dwarf_filesrc (files, idx, NULL, &result) == NULL);
+  return result;
+}
+
+const char *
+dwarf::source_file::name () const
+{
+  if (stringform (thisattr ()))
+    return dwarf_formstring (thisattr ());
+
+  Dwarf_Files *files;
+  size_t idx;
+  xif (get_files (thisattr (), &files, &idx));
+
+  const char *result = dwarf_filesrc (files, idx, NULL, NULL);
+  xif (result == NULL);
+  return result;
+}
+
+static inline string
+plain_string (const char *filename)
+{
+  return string ("\"") + filename + "\"";
+}
+
+string
+dwarf::source_file::to_string () const
+{
+  if (stringform (thisattr ()))
+    return plain_string (dwarf_formstring (thisattr ()));
+
+  Dwarf_Files *files;
+  size_t idx;
+  xif (get_files (thisattr (), &files, &idx));
+
+  Dwarf_Word file_mtime;
+  Dwarf_Word file_size;
+  const char *result = dwarf_filesrc (files, idx, &file_mtime, &file_size);
+  xif (result == NULL);
+
+  if (likely (file_mtime == 0) && likely (file_size == 0))
+    return plain_string (result);
+
+  std::ostringstream os;
+  os << "{\"" << result << "," << file_mtime << "," << file_size << "}";
+  return os.str ();
+}
+\f
+// dwarf::directory_table
+
+size_t
+dwarf::directory_table::size () const
+{
+  return _m_files->ndirs;
+}
+
+static inline dwarf::directory_table::const_iterator
+directory_table_array (Dwarf_Files *files)
+{
+  // See dwarf_getsrcdirs.
+  return reinterpret_cast<const char *const *> (&files->info[files->nfiles]);
+}
+
+dwarf::directory_table::const_iterator
+dwarf::directory_table::begin () const
+{
+  return directory_table_array (_m_files);
+}
+
+dwarf::directory_table::const_iterator
+dwarf::directory_table::end () const
+{
+  return directory_table_array (_m_files) + _m_files->ndirs;
+}
+\f
+// dwarf::file_table
+
+size_t
+dwarf::file_table::size () const
+{
+  return _m_files->nfiles;
+}
+
+const dwarf::source_file
+dwarf::file_table::at (size_t idx) const
+{
+  if (unlikely (idx >= _m_files->nfiles))
+    throw std::out_of_range ("XXX fileidx");
+
+  return dwarf::source_file (dummy_source_file (_m_files->cu, idx));
+}
+
+dwarf::file_table::const_iterator
+dwarf::file_table::find (const source_file &src) const
+{
+  if (src._m_attr.cu->files == _m_files)
+    {
+      // Same table, just cons an iterator using its index.
+      Dwarf_Files *files;
+      Dwarf_Word idx;
+      xif (get_files (&src._m_attr, &files, &idx));
+      return const_iterator (*this, idx);
+    }
+
+  // Not from this table, just match on file name.
+  return find (src.name ());
+}
+\f
+// dwarf::line_table
+
+size_t
+dwarf::line_table::size () const
+{
+  return _m_lines->nlines;
+}
+
+const dwarf::line_entry
+dwarf::line_table::at (size_t idx) const
+{
+  if (unlikely (idx >= _m_lines->nlines))
+    throw std::out_of_range ("XXX line table index");
+
+  return line_entry (reinterpret_cast<Dwarf_Line *> (&_m_lines->info[idx]));
+}
+
+dwarf::line_table::const_iterator
+dwarf::line_table::find (Dwarf_Addr address) const
+{
+  size_t idx = _m_lines->nlines; // end ()
+  if (likely (idx > 0))
+    {
+      CUDIE (cudie, _m_lines->info[0].files->cu);
+      Dwarf_Line *line = dwarf_getsrc_die (&cudie, address);
+      if (line != NULL)
+       idx = line - &_m_lines->info[0];
+    }
+  return const_iterator (*this, idx);
+}
+\f
+// dwarf::line_entry
+
+const dwarf::source_file
+dwarf::line_entry::file () const
+{
+  return dwarf::source_file (dummy_source_file (_m_line->files->cu,
+                                               _m_line->file));
+}
+
+#define LINEFIELD(type, method, field)         \
+  type                                         \
+  dwarf::line_entry::method () const           \
+  {                                            \
+    return _m_line->field;                     \
+  }
+
+LINEFIELD (Dwarf_Addr, address, addr) // XXX dwfl?
+LINEFIELD (unsigned int, line, line)
+LINEFIELD (unsigned int, column, column)
+LINEFIELD (bool, statement, is_stmt)
+LINEFIELD (bool, basic_block, basic_block)
+LINEFIELD (bool, end_sequence, end_sequence)
+LINEFIELD (bool, prologue_end, prologue_end)
+LINEFIELD (bool, epilogue_begin, epilogue_begin)
+
+#undef LINEFIELD
+
+bool
+dwarf::line_entry::operator== (const dwarf::line_entry &other) const
+{
+  Dwarf_Line *const a = _m_line;
+  Dwarf_Line *const b = other._m_line;
+
+  if (a == b)
+    return true;
+
+  if (a->addr != b->addr
+      || a->line != b->line
+      || a->column != b->column
+      || a->is_stmt != b->is_stmt
+      || a->basic_block != b->basic_block
+      || a->end_sequence != b->end_sequence
+      || a->prologue_end != b->prologue_end
+      || a->epilogue_begin != b->epilogue_begin)
+    return false;
+
+  // Everything else matches, now have to try the file.
+  if (a->files == b->files)
+    // Same table, just compare indices.
+    return a->file == b->file;
+
+  Dwarf_Word atime;
+  Dwarf_Word asize;
+  const char *aname = dwarf_linesrc (a, &atime, &asize);
+  xif (aname == NULL);
+  Dwarf_Word btime;
+  Dwarf_Word bsize;
+  const char *bname = dwarf_linesrc (b, &btime, &bsize);
+  xif (bname == NULL);
+
+  /* The mtime and size only count when encoded as nonzero.
+     If either side is zero, we don't consider the field.  */
+
+  if (atime != btime && atime != 0 && btime != 0)
+    return false;
+
+  if (asize != bsize && asize != 0 && bsize != 0)
+    return false;
+
+  return !strcmp (aname, bname);
+}
+\f
+// dwarf::compile_unit convenience functions.
+
+const dwarf::line_info_table
+dwarf::compile_unit::line_info () const
+{
+  Dwarf_Lines *l;
+  size_t n;
+  xif (dwarf_getsrclines (thisdie (), &l, &n) < 0);
+
+  return line_info_table (thisdie ()->cu->files);
+}
diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh
new file mode 100644 (file)
index 0000000..070b3cd
--- /dev/null
@@ -0,0 +1,125 @@
+/* Private helper classes for elfutils -*- C++ -*- interfaces.
+
+ */
+
+#ifndef _ELFUTILS_SUBR_HH
+#define _ELFUTILS_SUBR_HH      1
+
+#include <iterator>
+
+namespace elfutils
+{
+  namespace subr
+  {
+
+    template<typename array, typename element = typename array::value_type>
+    class indexed_iterator
+      : public std::iterator<std::random_access_iterator_tag,
+                            typename array::value_type,
+                            typename array::difference_type>
+    {
+    private:
+      typedef typename array::size_type index_type;
+
+      array _m_contents;
+      index_type _m_idx;
+
+    public:
+      indexed_iterator (array contents, index_type idx)
+       : _m_contents (contents), _m_idx (idx) {}
+      indexed_iterator (const indexed_iterator &i)
+       : _m_contents (i._m_contents), _m_idx (i._m_idx) {}
+
+      inline element operator* () const
+      {
+       return _m_contents[_m_idx];
+      }
+      template<typename elt>
+      inline elt operator* () const
+      {
+       return _m_contents[_m_idx];
+      }
+      template<typename elt>
+      inline elt *operator-> () const
+      {
+       return &_m_contents[_m_idx];
+      }
+      template<typename elt>
+      inline elt operator[] (const index_type &n) const
+      {
+       return _m_contents[_m_idx + n];
+      }
+
+      inline indexed_iterator operator+ (const indexed_iterator &i)
+      {
+       return indexed_iterator (_m_contents, _m_idx + i._m_idx);
+      }
+      inline indexed_iterator operator- (const indexed_iterator &i)
+      {
+       return indexed_iterator (_m_contents, _m_idx - i._m_idx);
+      }
+
+      inline bool operator== (const indexed_iterator &i)
+      {
+       return _m_idx == i._m_idx;
+      }
+      inline bool operator!= (const indexed_iterator &i)
+      {
+       return _m_idx != i._m_idx;
+      }
+      inline bool operator< (const indexed_iterator &i)
+      {
+       return _m_idx < i._m_idx;
+      }
+      inline bool operator> (const indexed_iterator &i)
+      {
+       return _m_idx > i._m_idx;
+      }
+      inline bool operator<= (const indexed_iterator &i)
+      {
+       return _m_idx <= i._m_idx;
+      }
+      inline bool operator>= (const indexed_iterator &i)
+      {
+       return _m_idx >= i._m_idx;
+      }
+
+      inline indexed_iterator &operator= (const indexed_iterator &i)
+      {
+       _m_idx = i._m_idx;
+       return *this;
+      }
+      inline indexed_iterator &operator+= (const index_type &n)
+      {
+       _m_idx += n;
+       return *this;
+      }
+      inline indexed_iterator &operator-= (const index_type &n)
+      {
+       _m_idx -= n;
+       return *this;
+      }
+
+      inline indexed_iterator &operator++ () // prefix
+      {
+       ++_m_idx;
+       return *this;
+      }
+      inline indexed_iterator operator++ (int) // postfix
+      {
+       return indexed_iterator (_m_contents, _m_idx++);
+      }
+      inline indexed_iterator &operator-- () // prefix
+      {
+       --_m_idx;
+       return *this;
+      }
+      inline indexed_iterator operator-- (int) // postfix
+      {
+       return indexed_iterator (_m_contents, _m_idx--);
+      }
+    };
+  };
+};
+
+#endif // <elfutils/subr.hh>
index 3f858cf35e15a4fc6f31f780b997bcbcb28e2691..45f2ce30c9d37400c0f4a3198cc6b043b2464e03 100644 (file)
@@ -48,6 +48,7 @@
    <http://www.openinventionnetwork.com>.  */
 
 #include <config.h>
+#include <cassert>
 #include "dwarf"
 
 extern "C"
@@ -296,110 +297,6 @@ dwarf::attr_value::constant_block () const
   return const_vector<uint8_t> (begin, end);
 }
 \f
-// dwarf::source_file
-
-const class dwarf::source_file
-dwarf::attr_value::source_file () const
-{
-  switch (what_space ())
-    {
-    case VS_string:
-    case VS_source_file:
-      break;
-    default:
-      throw std::runtime_error ("XXX not a file name");
-    }
-  return source_file::source_file (_m_attr);
-}
-
-static bool
-stringform (Dwarf_Attribute *attr)
-{
-  switch (dwarf_whatform (attr))
-    {
-    case DW_FORM_string:
-    case DW_FORM_strp:
-      return true;
-    }
-  return false;
-}
-
-static bool
-get_files (Dwarf_Attribute *attr, Dwarf_Files **files, Dwarf_Word *idx)
-{
-  CUDIE (cudie, attr->cu);
-  return (dwarf_formudata (attr, idx) < 0
-         || dwarf_getsrcfiles (&cudie, files, NULL) < 0);
-}
-
-Dwarf_Word
-dwarf::source_file::mtime () const
-{
-  if (stringform (thisattr ()))
-    return 0;
-
-  Dwarf_Files *files;
-  Dwarf_Word idx;
-  xif (get_files (thisattr (), &files, &idx));
-
-  Dwarf_Word result;
-  xif (dwarf_filesrc (files, idx, &result, NULL) == NULL);
-  return result;
-}
-
-Dwarf_Word
-dwarf::source_file::size () const
-{
-  if (stringform (thisattr ()))
-    return 0;
-
-  Dwarf_Files *files;
-  Dwarf_Word idx;
-  xif (get_files (thisattr (), &files, &idx));
-
-  Dwarf_Word result;
-  xif (dwarf_filesrc (files, idx, NULL, &result) == NULL);
-  return result;
-}
-
-const char *
-dwarf::source_file::name () const
-{
-  if (stringform (thisattr ()))
-    return dwarf_formstring (thisattr ());
-
-  Dwarf_Files *files;
-  size_t idx;
-  xif (get_files (thisattr (), &files, &idx));
-
-  const char *result = dwarf_filesrc (files, idx, NULL, NULL);
-  xif (result == NULL);
-  return result;
-}
-
-string
-dwarf::source_file::to_string () const
-{
-  if (stringform (thisattr ()))
-    return plain_string (dwarf_formstring (thisattr ()));
-
-  Dwarf_Files *files;
-  size_t idx;
-  xif (get_files (thisattr (), &files, &idx));
-
-  Dwarf_Word file_mtime;
-  Dwarf_Word file_size;
-  const char *result = dwarf_filesrc (files, idx, &file_mtime, &file_size);
-  xif (result == NULL);
-
-  if (likely (file_mtime == 0) && likely (file_size == 0))
-    return plain_string (result);
-
-  std::ostringstream os;
-  os << "{\"" << result << "," << file_mtime << "," << file_size << "}";
-  return os.str ();
-}
-\f
 // dwarf::location_attr
 
 const dwarf::location_attr
index be8989e368c3cee10a5fbee68b62477fd8496352..ffb58cb87f91bcff0ff2a94c446a474d4e85b2a6 100644 (file)
@@ -81,9 +81,12 @@ ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \
 
 libar_a_SOURCES = arlib.c arlib2.c
 
-dwarfcmp_SOURCES = dwarfcmp.cc
 # XXX need to figure out C++ dso crapola
-dwarfcmp_SOURCES += ../libdw/c++/values.cc ../libdw/c++/known.cc
+libdwplusplus_SOURCES = ../libdw/c++/values.cc ../libdw/c++/known.cc \
+                       ../libdw/c++/line_info.cc
+
+dwarfcmp_SOURCES = dwarfcmp.cc
+dwarfcmp_SOURCES += $(libdwplusplus_SOURCES)
 
 noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \
                 ldscript.h xelf.h unaligned.h