]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
new tack, still unfinished
authorRoland McGrath <roland@redhat.com>
Sat, 27 Jun 2009 00:13:20 +0000 (17:13 -0700)
committerRoland McGrath <roland@redhat.com>
Sat, 27 Jun 2009 00:13:20 +0000 (17:13 -0700)
12 files changed:
libdw/Makefile.am
libdw/c++/data-values.hh [new file with mode: 0644]
libdw/c++/dwarf
libdw/c++/dwarf_data [new file with mode: 0644]
libdw/c++/dwarf_edit
libdw/c++/dwarf_output
libdw/c++/edit-values.cc
libdw/c++/known.cc
libdw/c++/output-values.cc [new file with mode: 0644]
libdw/c++/subr.hh
libdw/c++/values.cc
src/dwarfcmp.cc

index b957c168d907f59aa2ce2af1979e8372e8535312..9f3a910d5ae1fc36ba9add3bf1e33d6225ad5d78 100644 (file)
@@ -48,8 +48,8 @@ endif
 
 include_HEADERS = dwarf.h
 pkginclude_HEADERS = libdw.h \
-                    c++/subr.hh \
-                    c++/dwarf c++/dwarf_edit \
+                    c++/subr.hh c++/dwarf_data \
+                    c++/dwarf c++/dwarf_edit c++/dwarf_output \
                     c++/dwarf_tracker c++/dwarf_comparator
 
 libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
@@ -94,7 +94,8 @@ libdwpp_a_SOURCES = c++/values.cc \
                    c++/exception.cc \
                    c++/known.cc \
                    c++/line_info.cc \
-                   c++/edit-values.cc
+                   c++/edit-values.cc \
+                   c++/output-values.cc
 noinst_HEADERS    = c++/dwarf-knowledge.cc
 
 if MAINTAINER_MODE
diff --git a/libdw/c++/data-values.hh b/libdw/c++/data-values.hh
new file mode 100644 (file)
index 0000000..e20cc25
--- /dev/null
@@ -0,0 +1,97 @@
+/* elfutils::dwarf_data common internal templates.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   In addition, as a special exception, Red Hat, Inc. gives You the
+   additional right to link the code of Red Hat elfutils with code licensed
+   under any Open Source Initiative certified open source license
+   (http://www.opensource.org/licenses/index.php) which requires the
+   distribution of source code with any binary distribution and to
+   distribute linked combinations of the two.  Non-GPL Code permitted under
+   this exception must only link to the code of Red Hat elfutils through
+   those well defined interfaces identified in the file named EXCEPTION
+   found in the source code files (the "Approved Interfaces").  The files
+   of Non-GPL Code may instantiate templates or use macros or inline
+   functions from the Approved Interfaces without causing the resulting
+   work to be covered by the GNU General Public License.  Only Red Hat,
+   Inc. may make changes or additions to the list of Approved Interfaces.
+   Red Hat's grant of this exception is conditioned upon your not adding
+   any new exceptions.  If you wish to add a new Approved Interface or
+   exception, please contact Red Hat.  You must obey the GNU General Public
+   License in all respects for all of the Red Hat elfutils code and other
+   code used in conjunction with Red Hat elfutils except the Non-GPL Code
+   covered by this exception.  If you modify this file, you may extend this
+   exception to your version of the file, but you are not obligated to do
+   so.  If you do not wish to provide this exception without modification,
+   you must delete this exception statement from your version and license
+   this file solely under the GPL without exception.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#include "dwarf_data"
+
+#include <typeinfo>
+
+namespace elfutils
+{
+
+  template<class impl>
+  dwarf::value_space
+  dwarf_data::attr_value<impl>::what_space () const
+  {
+    if (typeid (*_m_value) == typeid (value_flag))
+      return dwarf::VS_flag;
+    if (typeid (*_m_value) == typeid (value_dwarf_constant))
+      return dwarf::VS_dwarf_constant;
+    if (typeid (*_m_value) == typeid (value_reference<impl>))
+      return dwarf::VS_reference;
+    if (typeid (*_m_value) == typeid (value_unit_reference<impl>))
+      return dwarf::VS_unit_reference;
+    if (typeid (*_m_value) == typeid (value_lineptr<impl>))
+      return dwarf::VS_lineptr;
+    if (typeid (*_m_value) == typeid (value_macptr))
+      return dwarf::VS_macptr;
+    if (typeid (*_m_value) == typeid (value_rangelistptr))
+      return dwarf::VS_rangelistptr;
+    if (typeid (*_m_value) == typeid (value_identifier))
+      return dwarf::VS_identifier;
+    if (typeid (*_m_value) == typeid (value_string))
+      return dwarf::VS_string;
+    if (typeid (*_m_value) == typeid (value_source_file))
+      return dwarf::VS_source_file;
+    if (typeid (*_m_value) == typeid (value_source_line))
+      return dwarf::VS_source_line;
+    if (typeid (*_m_value) == typeid (value_source_column))
+      return dwarf::VS_source_column;
+    if (typeid (*_m_value) == typeid (value_address))
+      return dwarf::VS_address;
+    if (typeid (*_m_value) == typeid (value_constant)
+       || typeid (*_m_value) == typeid (value_constant_block))
+      return dwarf::VS_constant;
+    if (typeid (*_m_value) == typeid (value_location))
+      return dwarf::VS_location;
+
+    throw std::runtime_error ("XXX impossible");
+  }
+
+
+};
index cf24cc209ce2e29dee473c249cb65cbf83360dc1..a3bee5dd10c03c45f2ef31036d0eafd5cfc28099 100644 (file)
@@ -1899,13 +1899,7 @@ namespace elfutils
        return !(*this == other);
       }
 
-      inline std::string to_string () const
-      {
-       std::string result = attributes::name (::dwarf_whatattr (thisattr ()));
-       result += "=";
-       result += second.to_string ();
-       return result;
-      }
+      inline std::string to_string () const;
     };
 
     /* This works like range_list, but is based on a debug_info_entry using
@@ -2363,15 +2357,19 @@ namespace elfutils
     return const_iterator (*this, 1);
   }
 
-  // Explicit specialization.
+  // Explicit specializations.
+  template<>
+  std::string to_string<dwarf::attribute> (const dwarf::attribute &);
+  inline std::string dwarf::attribute::to_string () const
+  {
+    return elfutils::to_string (*this); // Use that.
+  }
   template<>
   std::string to_string<dwarf::attr_value> (const dwarf::attr_value &);
   inline std::string dwarf::attr_value::to_string () const
   {
     return elfutils::to_string (*this); // Use that.
   }
-
-  // Explicit specialization.
   template<>
   std::string to_string<dwarf::dwarf_enum> (const dwarf::dwarf_enum &);
   inline std::string dwarf::dwarf_enum::to_string () const
diff --git a/libdw/c++/dwarf_data b/libdw/c++/dwarf_data
new file mode 100644 (file)
index 0000000..ba324f0
--- /dev/null
@@ -0,0 +1,1059 @@
+/* elfutils::dwarf_data -- internal DWARF data representations in -*- C++ -*-
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   In addition, as a special exception, Red Hat, Inc. gives You the
+   additional right to link the code of Red Hat elfutils with code licensed
+   under any Open Source Initiative certified open source license
+   (http://www.opensource.org/licenses/index.php) which requires the
+   distribution of source code with any binary distribution and to
+   distribute linked combinations of the two.  Non-GPL Code permitted under
+   this exception must only link to the code of Red Hat elfutils through
+   those well defined interfaces identified in the file named EXCEPTION
+   found in the source code files (the "Approved Interfaces").  The files
+   of Non-GPL Code may instantiate templates or use macros or inline
+   functions from the Approved Interfaces without causing the resulting
+   work to be covered by the GNU General Public License.  Only Red Hat,
+   Inc. may make changes or additions to the list of Approved Interfaces.
+   Red Hat's grant of this exception is conditioned upon your not adding
+   any new exceptions.  If you wish to add a new Approved Interface or
+   exception, please contact Red Hat.  You must obey the GNU General Public
+   License in all respects for all of the Red Hat elfutils code and other
+   code used in conjunction with Red Hat elfutils except the Non-GPL Code
+   covered by this exception.  If you modify this file, you may extend this
+   exception to your version of the file, but you are not obligated to do
+   so.  If you do not wish to provide this exception without modification,
+   you must delete this exception statement from your version and license
+   this file solely under the GPL without exception.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef _ELFUTILS_DWARF_DATA
+#define _ELFUTILS_DWARF_DATA   1
+
+#include "dwarf"
+#include <bitset>
+
+/* This contains common classes/templates used by dwarf_output and dwarf_edit.
+
+   These are implementations of the "boring" components of the dwarf
+   object interface.
+*/
+
+namespace elfutils
+{
+  // This is a class only for scoping purposes.
+  // It contains no members, only inner classes.
+  class dwarf_data
+  {
+  public:
+
+    class source_file
+    {
+    private:
+      std::string _m_name;
+      ::Dwarf_Word _m_mtime;
+      ::Dwarf_Word _m_size;
+
+    public:
+
+      struct hasher
+       : public std::unary_function<source_file, size_t>
+      {
+       size_t operator () (const source_file &v) const
+       {
+         size_t hash = 0;
+         subr::hash_combine (hash, v._m_name);
+         subr::hash_combine (hash, v._m_mtime);
+         subr::hash_combine (hash, v._m_size);
+         return hash;
+       }
+      };
+
+      source_file () : _m_name (), _m_mtime (0), _m_size (0) {}
+      source_file (const std::string &n, ::Dwarf_Word m = 0, ::Dwarf_Word s = 0)
+       : _m_name (n), _m_mtime (m), _m_size (s) {}
+
+      template<typename file>
+      source_file (const file &other)
+       : _m_name (other.name ()),
+         _m_mtime (other.mtime ()), _m_size (other.size ()) {}
+
+      template<typename file>
+      inline source_file &operator= (const file &other)
+      {
+       _m_name = other.name ();
+       _m_mtime = other.mtime ();
+       _m_size = other.size ();
+       return *this;
+      }
+      inline source_file &operator= (const std::string &n)
+      {
+       _m_name = n;
+       _m_mtime = 0;
+       _m_size = 0;
+       return *this;
+      }
+      inline source_file &operator= (const char *n)
+      {
+       _m_name = n;
+       _m_mtime = 0;
+       _m_size = 0;
+       return *this;
+      }
+
+      std::string to_string () const;
+
+      inline std::string &name ()
+      {
+       return _m_name;
+      }
+      inline const std::string &name () const
+      {
+       return _m_name;
+      }
+      inline ::Dwarf_Word &mtime ()
+      {
+       return _m_mtime;
+      }
+      inline ::Dwarf_Word mtime () const
+      {
+       return _m_mtime;
+      }
+      inline ::Dwarf_Word &size ()
+      {
+       return _m_size;
+      }
+      inline ::Dwarf_Word size () const
+      {
+       return _m_size;
+      }
+
+      template<typename other_file>
+      bool operator== (const other_file &other) const
+      {
+       if (mtime () != 0)
+         {
+           ::Dwarf_Word other_mtime = other.mtime ();
+           if (other_mtime != 0 && other_mtime != mtime ())
+             return false;
+         }
+       if (size () != 0)
+         {
+           ::Dwarf_Word other_size = other.size ();
+           if (other_size != 0 && other_size != size ())
+             return false;
+         }
+       return name () == other.name ();
+      }
+      template<typename other_file>
+      inline bool operator!= (const other_file &other) const
+      {
+       return !(*this == other);
+      }
+    };
+
+    // This describes a CU's directory table, a simple array of strings.
+    class directory_table : public std::vector<std::string>
+    {
+    private:
+      typedef std::vector<std::string> _base;
+
+    public:
+      struct hasher : public subr::container_hasher<directory_table> {};
+
+      directory_table () {}
+
+      template<typename table>
+      directory_table (const table &other)
+       : _base (other.begin (), other.end ()) {}
+
+      template<typename table>
+      inline bool operator== (const table &other) const
+      {
+       return size () == other.size () && subr::container_equal (*this, other);
+      }
+      template<typename table>
+      inline bool operator!= (const table &other) const
+      {
+       return !(*this == other);
+      }
+    };
+
+  private:
+
+    /* This is the common base class for all line_entry<T> instantiations.
+       For some reason beyond my ken, std::bitset<flag_count>::reference
+       as a return type is rejected by the compiler when used in a template
+       class, but not a non-template class.  Go figure.  */
+    class line_entry_common
+    {
+    protected:
+      unsigned int _m_line;
+      unsigned int _m_column;
+
+      enum flag_bit
+       {
+         flag_statement,
+         flag_basic_block,
+         flag_end_sequence,
+         flag_prologue_end,
+         flag_epilogue_begin,
+         flag_count
+       };
+      std::bitset<flag_count> _m_flags;
+
+    public:
+      line_entry_common ()
+       : _m_line (0), _m_column (0) {}
+
+      inline unsigned int &line ()
+      {
+       return _m_line;
+      }
+      inline unsigned int line () const
+      {
+       return _m_line;
+      }
+      inline unsigned int &column ()
+      {
+       return _m_column;
+      }
+      inline unsigned int column () const
+      {
+       return _m_column;
+      }
+
+#define _DWARF_EDIT_LE_FLAG(what)                      \
+      bool what () const                               \
+      {                                                        \
+       return _m_flags[flag_##what];                   \
+      }                                                        \
+      std::bitset<flag_count>::reference what ()       \
+      {                                                        \
+       return _m_flags[flag_##what];                   \
+      }
+      _DWARF_EDIT_LE_FLAG (statement)
+      _DWARF_EDIT_LE_FLAG (basic_block)
+      _DWARF_EDIT_LE_FLAG (end_sequence)
+      _DWARF_EDIT_LE_FLAG (prologue_end)
+      _DWARF_EDIT_LE_FLAG (epilogue_begin)
+#undef _DWARF_EDIT_LE_FLAG
+    };
+
+  public:
+    /* This holds a line table entry.
+       It's parameterized by the source_file representation.  */
+    template<typename source_file>
+    class line_entry : public line_entry_common
+    {
+    private:
+      ::Dwarf_Addr _m_addr;    // XXX dwfl, reloc
+      source_file _m_file;
+
+    public:
+
+      struct hasher
+       : public std::unary_function<line_entry, size_t>
+      {
+       size_t operator () (const line_entry &v) const
+       {
+         size_t hash = 0;
+         subr::hash_combine (hash, v._m_addr);
+         subr::hash_combine (hash, v._m_file);
+         subr::hash_combine (hash, v._m_line);
+         subr::hash_combine (hash, v._m_column);
+         return hash;
+       }
+      };
+
+      line_entry (::Dwarf_Addr addr)
+       : line_entry_common (), _m_addr (addr), _m_file ()
+      {}
+
+      template<typename entry>
+      line_entry (const entry &other)
+       : line_entry_common (), _m_addr (0), _m_file ()
+      {
+       *this = other;
+      }
+
+      template<typename entry>
+      line_entry &operator= (const entry &other)
+      {
+       _m_addr = other.address ();
+       _m_file = other.file ();
+       _m_line = other.line ();
+       _m_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 ();
+       return *this;
+      }
+
+      inline ::Dwarf_Addr &address ()
+      {
+       return _m_addr;
+      }
+      inline ::Dwarf_Addr address () const
+      {
+       return _m_addr;
+      }
+      inline source_file &file ()
+      {
+       return _m_file;
+      }
+      inline const source_file &file () const
+      {
+       return _m_file;
+      }
+
+      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);
+      }
+    };
+
+    /* This holds a line table.
+       It's parameterized by the line_entry representation.  */
+    template<typename line_entry>
+    class line_table : public std::vector<line_entry>
+    {
+    private:
+      typedef std::vector<line_entry> _base;
+
+    public:
+      typedef typename _base::size_type size_type;
+      typedef typename _base::difference_type difference_type;
+      typedef typename _base::value_type value_type;
+      typedef typename _base::iterator iterator;
+      typedef typename _base::const_iterator const_iterator;
+
+      struct hasher : public subr::container_hasher<line_table> {};
+
+      line_table () {}
+
+      template<typename table>
+      line_table (const table &other) : _base (other.begin (), other.end ()) {}
+
+      template<typename table>
+      inline bool operator== (const table &other) const
+      {
+       return (_base::size () == other.size ()
+               && subr::container_equal (*this, other));
+      }
+      template<typename table>
+      inline bool operator!= (const table &other) const
+      {
+       return !(*this == other);
+      }
+
+      // Look up by matching address.
+      iterator find (::Dwarf_Addr);
+      const_iterator find (::Dwarf_Addr) const;
+    };
+
+    /* This holds the entirety of line information.  It's parameterized
+       by the directory_table and line_table representations.  */
+    template<typename directory_table, typename line_table>
+    class line_info_table
+      : private std::pair<directory_table, line_table>
+    {
+    private:
+      typedef std::pair<directory_table, line_table> _base;
+
+    public:
+      inline line_info_table () : _base () {}
+
+      template<typename table>
+      inline line_info_table (const table &other)
+       : _base (other.include_directories (), other.lines ())
+      {}
+
+      template<typename table>
+      inline line_info_table &operator= (const table &other)
+      {
+       this->first = directory_table (other.include_directories ());
+       this->second = line_table (other.lines ());
+       return *this;
+      }
+
+      inline directory_table &include_directories ()
+      {
+       return this->first;
+      }
+      inline const directory_table &include_directories () const
+      {
+       return this->first;
+      }
+      inline line_table &lines ()
+      {
+       return this->second;
+      }
+      inline const line_table &lines () const
+      {
+       return this->second;
+      }
+
+      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);
+      }
+    };
+
+    class dwarf_enum
+      : private std::pair< ::Dwarf_Word, unsigned int>
+    {
+    private:
+      typedef std::pair< ::Dwarf_Word, unsigned int> _base;
+
+    public:
+      inline dwarf_enum (unsigned int attr, unsigned int value)
+       : _base (value, attr)
+      {}
+
+      template<typename constant>
+      inline dwarf_enum (const constant &other)
+       : _base (static_cast<unsigned int> (other), other.which ())
+      {}
+
+      // Return the DW_AT_* indicating which enum this value belongs to.
+      inline unsigned int which () const
+      {
+       return this->second;
+      }
+
+      inline operator unsigned int () const
+      {
+       return this->first;
+      }
+
+      inline dwarf_enum &operator= (const dwarf_enum& other)
+      {
+       this->first = other.first;
+       this->second = other.second;
+       return *this;
+      }
+
+      template<typename constant>
+      inline dwarf_enum &operator= (const constant& other)
+      {
+       return *this = dwarf_enum (other.which (), other);
+      }
+
+      std::string to_string () const;
+
+      const char *identifier () const;
+      const char *name () const;
+
+      template<typename constant>
+      inline bool operator== (const constant &other) const
+      {
+       return (static_cast<unsigned int> (*this)
+               == static_cast<unsigned int> (other));
+      }
+      template<typename constant>
+      inline bool operator!= (const constant &other) const
+      {
+       return !(*this == other);
+      }
+    };
+
+    // Same as set<pair<Dwarf_Addr, Dwarf_Addr>>.
+    class range_list : public dwarf::arange_list
+    {
+    public:
+      struct hasher : public subr::container_hasher<range_list> {};
+
+      template<typename list>
+      range_list (const list &other)
+       : dwarf::arange_list (other.begin (), other.end ()) {}
+    };
+
+    class location_attr
+      : public std::map<dwarf::location_attr::key_type, std::vector<uint8_t> >
+    {
+    private:
+      typedef std::map<dwarf::location_attr::key_type,
+                      std::vector<uint8_t> > _base;
+
+      template<typename pair>
+      struct nonempty : public std::unary_function<pair, bool>
+      {
+       inline bool operator () (const pair &x)
+       {
+         return !x.second.empty ();
+       }
+      };
+
+    public:
+      typedef _base::size_type size_type;
+      typedef _base::difference_type difference_type;
+      typedef _base::key_type key_type;
+      typedef _base::mapped_type mapped_type;
+      typedef _base::value_type value_type;
+      typedef _base::iterator iterator;
+      typedef _base::const_iterator const_iterator;
+
+      struct hasher : public subr::container_hasher<location_attr> {};
+
+      inline location_attr () : _base () {}
+      inline location_attr (const location_attr &other)
+       : _base (static_cast<const _base &> (other)) {}
+      template<typename loc>
+      inline location_attr (const loc &other) : _base ()
+      {
+       *this = other;
+      }
+
+      template<typename loc>
+      inline location_attr &operator= (const loc &other)
+      {
+       clear ();
+       if (other.empty ())
+         ;
+       else if (other.is_list ())
+         for (typename loc::const_iterator i = other.begin ();
+              i != other.end ();
+              ++i)
+           {
+             const typename loc::mapped_type &x = (*i).second;
+             (*this)[(*i).first] = mapped_type (x.begin (), x.end ());
+           }
+       else
+         {
+           mapped_type v = other.location ();
+           (*this)[key_type (0, -1)] = v;
+         }
+       return *this;
+      }
+
+      inline bool is_list () const
+      {
+       if (empty ())
+         return false;
+       if (size () > 1)
+         return true;
+
+       const key_type &elt = begin ()->first;
+       return !(elt.first == 0 && elt.second == (Dwarf_Addr) -1);
+      }
+
+      inline mapped_type &location ()
+      {
+       if (empty ())
+         return (*this)[key_type (0, -1)];
+
+       value_type &v = *begin ();
+       if (v.first.first != 0 || v.first.second != (Dwarf_Addr) -1
+           || size () > 1)
+         throw std::runtime_error ("location is list, not single location");
+
+       return v.second;
+      }
+      inline const mapped_type &location () const
+      {
+       if (size () == 1)
+         {
+           const value_type &v = *begin ();
+           if (v.first.first == 0 && v.first.second == (Dwarf_Addr) -1)
+             return v.second;
+         }
+       throw std::runtime_error ("location is list, not single location");
+      }
+
+      template<typename other_attr>
+      bool operator== (const other_attr &other) const
+      {
+       if (empty ())
+         return (other.empty ()
+                 || std::find_if (other.begin (), other.end (),
+                                  nonempty<typename other_attr::value_type> ()
+                                  ) == other.end ());
+       if (!is_list ())
+         return (!other.is_list () && !other.empty ()
+                 && subr::container_equal (location (), other.location ()));
+
+       return other.is_list () && subr::container_equal (*this, other);
+      }
+      template<typename other_attr>
+      inline bool operator!= (const other_attr &other) const
+      {
+       return !(*this == other);
+      }
+
+      std::string to_string () const;
+    };
+
+  private:
+    class value_dispatch
+    {
+    public:
+      virtual ~value_dispatch () {}
+    };
+
+    struct value_string : public value_dispatch, public std::string
+    {
+      template<typename string>
+      value_string (const string &s) : std::string (s) {}
+
+      std::string to_string () const
+      {
+       std::string result ("\"");
+       result += *this;
+       result += "\"";
+       return result;
+      }
+    };
+
+    struct value_identifier : public value_string
+    {
+      template<typename id>
+      value_identifier (const id &s) : value_string (s) {}
+    };
+
+    template<class impl>
+    struct value_reference : public value_dispatch
+    {
+      typename impl::debug_info_entry::children_type::iterator ref;
+      value_reference (const typename
+                      impl::debug_info_entry::children_type::iterator &i)
+       : ref (i) {}
+
+      template<typename iter>  // XXX dummy
+      value_reference (const iter &i) : ref () {}
+    };
+
+    template<class impl>
+    struct value_unit_reference : public value_dispatch
+    {
+      typename impl::compile_units::iterator ref;
+      value_unit_reference (const typename impl::compile_units::iterator &i)
+       : ref (i)
+      {}
+
+      template<typename iter>  // XXX dummy
+      value_unit_reference (const iter &i) : ref () {}
+    };
+
+    struct value_flag : public value_dispatch
+    {
+      bool flag;
+      value_flag (bool t) : flag (t) {}
+    };
+
+    struct value_address : public value_dispatch
+    {
+      // XXX dwfl, reloc
+      ::Dwarf_Addr addr;
+      value_address (::Dwarf_Addr a) : addr (a) {}
+    };
+
+    struct value_rangelistptr : public value_dispatch, public range_list
+    {
+      template<typename list>
+      value_rangelistptr (const list &other) : range_list (other) {}
+    };
+
+    template<class impl>
+    struct value_lineptr : public value_dispatch, public impl::line_info_table
+    {
+      template<typename table>
+      value_lineptr (const table &other) : impl::line_info_table (other) {}
+    };
+
+    struct value_constant : public value_dispatch
+    {
+      union
+      {
+       ::Dwarf_Word word;
+       ::Dwarf_Sword sword;
+      };
+      value_constant (::Dwarf_Word x) : word (x) {}
+    };
+
+    struct value_constant_block : public value_dispatch,
+                                 public std::vector<uint8_t>
+    {
+      template<typename block>
+      value_constant_block (const block &b)
+       : std::vector<uint8_t> (b.begin (), b.end ()) {}
+    };
+
+    struct value_dwarf_constant : public value_dispatch, public dwarf_enum
+    {
+      template<typename constant>
+      value_dwarf_constant (const constant &other) : dwarf_enum (other) {}
+    };
+
+    struct value_source_file : public value_dispatch, public source_file
+    {
+      template<typename file>
+      value_source_file (const file &other) : source_file (other) {}
+    };
+
+    struct value_source_line : public value_dispatch
+    {
+      unsigned int n;
+      value_source_line (unsigned int m) : n (m) {}
+    };
+    typedef value_source_line value_source_column;
+
+    struct value_macptr : public value_dispatch {};
+
+    struct value_location : public value_dispatch, public location_attr
+    {
+      template<typename loc>
+      value_location (const loc &other) : location_attr (other) {}
+    };
+
+  public:
+    template<class impl>
+    class attr_value
+    {
+    private:
+      value_dispatch *_m_value;
+
+      template<typename value>
+      inline void init (const value &other)
+      {
+       switch (other.what_space ())
+         {
+         case dwarf::VS_identifier:
+           _m_value = new value_identifier (other.identifier ());
+           break;
+         case dwarf::VS_string:
+           _m_value = new value_string (other.string ());
+           break;
+         case dwarf::VS_flag:
+           _m_value = new value_flag (other.flag ());
+           break;
+         case dwarf::VS_rangelistptr:
+           _m_value = new value_rangelistptr (other.ranges ());
+           break;
+         case dwarf::VS_lineptr:
+           _m_value = new value_lineptr<impl> (other.line_info ());
+           break;
+         case dwarf::VS_address:
+           _m_value = new value_address (other.address ());
+           break;
+         case dwarf::VS_constant:
+           if (other.constant_is_integer ())
+             _m_value = new value_constant (other.constant ());
+           else
+             _m_value = new value_constant_block (other.constant_block ());
+           break;
+         case dwarf::VS_source_line:
+           _m_value = new value_source_line (other.source_line ());
+           break;
+         case dwarf::VS_source_column:
+           _m_value = new value_source_column (other.source_column ());
+           break;
+         case dwarf::VS_source_file:
+           _m_value = new value_source_file (other.source_file ());
+           break;
+         case dwarf::VS_dwarf_constant:
+           _m_value = new value_dwarf_constant (other.dwarf_constant ());
+           break;
+         case dwarf::VS_reference:
+           _m_value = new value_reference<impl> (other.reference ());
+           break;
+         case dwarf::VS_unit_reference:
+           _m_value = new value_unit_reference<impl> (other.unit_reference ());
+           break;
+         case dwarf::VS_location:
+           _m_value = new value_location (other.location ());
+           break;
+#if 0
+         case dwarf::VS_macptr:
+           _m_value = new value_macptr (other.macptr ());
+           break;
+#endif
+         default:
+         case dwarf::VS_discr_list:
+           throw std::runtime_error ("XXX unimplemented");
+         }
+      }
+
+      template<typename flavor>
+      inline flavor &variant () const
+      {
+       flavor *p = dynamic_cast<flavor *> (_m_value);
+       if (p == NULL)
+         throw std::runtime_error ("wrong value type");
+       return *p;
+      }
+
+    public:
+      attr_value (const attr_value &other) : _m_value (NULL)
+      {
+       init (other);
+      }
+      template<typename value>
+      attr_value (const value &other) : _m_value (NULL)
+      {
+       init (other);
+      }
+
+      attr_value () : _m_value (NULL) {}
+
+      ~attr_value ()
+      {
+       if (_m_value != NULL)
+         delete _m_value;
+      }
+
+      inline attr_value &operator= (const attr_value &other)
+      {
+       if (_m_value != NULL)
+         {
+           delete _m_value;
+           _m_value = NULL;
+         }
+       init (other);
+       return *this;
+      }
+      template<typename value>
+      inline attr_value &operator= (const value &other)
+      {
+       if (_m_value != NULL)
+         {
+           delete _m_value;
+           _m_value = NULL;
+         }
+       init (other);
+       return *this;
+      }
+
+      dwarf::value_space what_space () const;
+      inline std::string to_string () const;
+
+      inline bool &flag () const
+      {
+       return variant<value_flag> ().flag;
+      }
+
+      // XXX dwfl, reloc
+      inline ::Dwarf_Addr &address () const
+      {
+       return variant<value_address> ().addr;
+      }
+
+      inline typename impl::debug_info_entry::children_type::iterator
+      reference () const
+      {
+       return variant<value_reference<impl> > ().ref;
+      }
+      inline typename impl::compile_units::iterator
+      unit_reference () const
+      {
+       return variant<value_unit_reference<impl> > ().ref;
+      }
+
+      inline location_attr &location () const
+      {
+       return static_cast<location_attr &> (variant<value_location> ());
+      }
+
+      inline std::string &string () const
+      {
+       return static_cast<std::string &> (variant<value_string> ());
+      }
+      inline std::string &identifier () const
+      {
+       return string ();
+      }
+
+      inline typename impl::source_file &source_file () const
+      {
+       return static_cast<typename impl::source_file &>
+         (variant<value_source_file> ());
+      }
+
+      inline unsigned int &source_line () const
+      {
+       return variant<value_source_line> ().n;
+      }
+
+      inline unsigned int &source_column () const
+      {
+       return variant<value_source_column> ().n;
+      }
+
+      inline ::Dwarf_Word &constant () const
+      {
+       return variant<value_constant> ().word;
+      }
+
+      inline ::Dwarf_Sword &signed_constant () const
+      {
+       return variant<value_constant> ().sword;
+      }
+
+      inline std::vector<uint8_t> &constant_block () const
+      {
+       return static_cast<std::vector<uint8_t> &>
+         (variant<value_constant_block> ());
+      }
+
+      inline typename impl::dwarf_enum &dwarf_constant () const
+      {
+       return variant<value_dwarf_constant> ();
+      }
+
+      inline bool constant_is_integer () const
+      {
+       return dynamic_cast<value_constant *> (_m_value) != NULL;
+      }
+
+      inline typename impl::range_list &ranges () const
+      {
+       return static_cast<range_list &> (variant<value_rangelistptr> ());
+      }
+
+      inline typename impl::line_info_table &line_info () const
+      {
+       return static_cast<typename impl::line_info_table &>
+         (variant<value_lineptr<impl> > ());
+      }
+
+      // macptr
+
+      template<typename value>
+      inline bool operator== (const value &other) const
+      {
+       const dwarf::value_space what = what_space ();
+       if (likely (other.what_space () == what))
+         switch (what)
+           {
+           case dwarf::VS_identifier:
+             return identifier () == other.identifier ();
+           case dwarf::VS_string:
+             return string () == other.string ();
+           case dwarf::VS_reference:
+             return reference () == other.reference ();
+           case dwarf::VS_unit_reference:
+             return unit_reference () == other.unit_reference ();
+           case dwarf::VS_flag:
+             return flag () == other.flag ();
+           case dwarf::VS_rangelistptr:
+             return ranges () == other.ranges ();
+           case dwarf::VS_lineptr:
+             return line_info () == other.line_info ();
+           case dwarf::VS_constant:
+             if (constant_is_integer ())
+               return (other.constant_is_integer ()
+                       && constant () == other.constant ());
+             return (!other.constant_is_integer ()
+                     && constant_block () == other.constant_block ());
+           case dwarf::VS_source_file:
+             return source_file () == other.source_file ();
+           case dwarf::VS_source_line:
+             return source_line () == other.source_line ();
+           case dwarf::VS_source_column:
+             return source_column () == other.source_column ();
+           case dwarf::VS_address:
+             return address () == other.address ();
+           case dwarf::VS_location:
+             return location () == other.location ();
+           case dwarf::VS_dwarf_constant:
+             return dwarf_constant () == other.dwarf_constant ();
+#if 0
+           case dwarf::VS_macptr:
+             return macptr () == other.macptr ();
+#endif
+           default:
+           case dwarf::VS_discr_list:
+             throw std::runtime_error ("XXX unimplemented");
+           }
+       return false;
+      }
+      template<typename value>
+      inline bool operator!= (const value &other) const
+      {
+       return !(*this == other);
+      }
+    };
+
+  };
+
+  // Explicit specializations.
+  template<>
+  std::string to_string<dwarf_data::dwarf_enum> (const dwarf_data::dwarf_enum&);
+  inline std::string dwarf_data::dwarf_enum::to_string () const
+  {
+    return elfutils::to_string (*this); // Use that.
+  }
+
+  template<class impl>
+  inline std::string dwarf_data::attr_value<impl>::to_string () const
+  {
+    return elfutils::to_string (*this); // Use that.
+  }
+
+};
+
+#endif
index 00698b540bc1b76c99294f1addd3c4955746b5e8..50714de25d915a45d66fbdb2b333c2665aa15e70 100644 (file)
@@ -51,7 +51,7 @@
 #define _ELFUTILS_DWARF_EDIT   1
 
 #include "dwarf"
-#include <bitset>
+#include "dwarf_data"
 
 /* Read the comments for elfutils::dwarf first.
 
@@ -86,8 +86,18 @@ namespace elfutils
   class dwarf_edit
   {
   public:
+    typedef dwarf_data::source_file source_file;
+    typedef dwarf_data::directory_table directory_table;
+    typedef dwarf_data::line_entry<source_file> line_entry;
+    typedef dwarf_data::line_table<line_entry> line_table;
+    typedef dwarf_data::line_info_table<directory_table,
+                                       line_table> line_info_table;
+    typedef dwarf_data::dwarf_enum dwarf_enum;
+    typedef dwarf_data::range_list range_list;
+    typedef dwarf_data::location_attr location_attr;
+    typedef dwarf_data::attr_value<dwarf_edit> attr_value;
+
     class compile_units;
-    class attr_value;
 
     class debug_info_entry
     {
@@ -268,901 +278,6 @@ namespace elfutils
       }
     };
 
-    // Same as set<pair<Dwarf_Addr, Dwarf_Addr>>.
-    class range_list : public dwarf::arange_list
-    {
-    public:
-      template<typename list>
-      range_list (const list &other)
-       : dwarf::arange_list (other.begin (), other.end ()) {}
-    };
-
-    class source_file
-    {
-    private:
-      std::string _m_name;
-      ::Dwarf_Word _m_mtime;
-      ::Dwarf_Word _m_size;
-
-    public:
-      source_file () : _m_name (), _m_mtime (0), _m_size (0) {}
-      source_file (const std::string &n, ::Dwarf_Word m = 0, ::Dwarf_Word s = 0)
-       : _m_name (n), _m_mtime (m), _m_size (s) {}
-
-      template<typename file>
-      source_file (const file &other)
-       : _m_name (other.name ()),
-         _m_mtime (other.mtime ()), _m_size (other.size ()) {}
-
-      template<typename file>
-      inline source_file &operator= (const file &other)
-      {
-       _m_name = other.name ();
-       _m_mtime = other.mtime ();
-       _m_size = other.size ();
-       return *this;
-      }
-      inline source_file &operator= (const std::string &n)
-      {
-       _m_name = n;
-       _m_mtime = 0;
-       _m_size = 0;
-       return *this;
-      }
-      inline source_file &operator= (const char *n)
-      {
-       _m_name = n;
-       _m_mtime = 0;
-       _m_size = 0;
-       return *this;
-      }
-
-      std::string to_string () const;
-
-      inline std::string &name ()
-      {
-       return _m_name;
-      }
-      inline const std::string &name () const
-      {
-       return _m_name;
-      }
-      inline ::Dwarf_Word &mtime ()
-      {
-       return _m_mtime;
-      }
-      inline ::Dwarf_Word mtime () const
-      {
-       return _m_mtime;
-      }
-      inline ::Dwarf_Word &size ()
-      {
-       return _m_size;
-      }
-      inline ::Dwarf_Word size () const
-      {
-       return _m_size;
-      }
-
-      template<typename other_file>
-      bool operator== (const other_file &other) const
-      {
-       if (mtime () != 0)
-         {
-           ::Dwarf_Word other_mtime = other.mtime ();
-           if (other_mtime != 0 && other_mtime != mtime ())
-             return false;
-         }
-       if (size () != 0)
-         {
-           ::Dwarf_Word other_size = other.size ();
-           if (other_size != 0 && other_size != size ())
-             return false;
-         }
-       return name () == other.name ();
-      }
-      template<typename other_file>
-      inline bool operator!= (const other_file &other) const
-      {
-       return !(*this == other);
-      }
-    };
-
-    // This describes a CU's directory table, a simple array of strings.
-    class directory_table : public std::vector<std::string>
-    {
-    private:
-      typedef std::vector<std::string> _base;
-
-    public:
-      directory_table () {}
-
-      template<typename table>
-      directory_table (const table &other)
-       : _base (other.begin (), other.end ()) {}
-
-      template<typename table>
-      inline bool operator== (const table &other) const
-      {
-       return size () == other.size () && subr::container_equal (*this, other);
-      }
-      template<typename table>
-      inline bool operator!= (const table &other) const
-      {
-       return !(*this == other);
-      }
-    };
-
-    class line_entry
-    {
-    private:
-      ::Dwarf_Addr _m_addr;    // XXX dwfl, reloc
-      source_file _m_file;
-      unsigned int _m_line;
-      unsigned int _m_column;
-
-      enum flag_bit
-       {
-         flag_statement,
-         flag_basic_block,
-         flag_end_sequence,
-         flag_prologue_end,
-         flag_epilogue_begin,
-         flag_count
-       };
-      std::bitset<flag_count> _m_flags;
-
-    public:
-      line_entry (::Dwarf_Addr addr)
-       : _m_addr (addr), _m_file (), _m_line (0), _m_column (0) {}
-
-      template<typename entry>
-      line_entry (const entry &other)
-       : _m_addr (0), _m_file (), _m_line (0), _m_column (0)
-      {
-       *this = other;
-      }
-
-      template<typename entry>
-      line_entry &operator= (const entry &other)
-      {
-       _m_addr = other.address ();
-       _m_file = other.file ();
-       _m_line = other.line ();
-       _m_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 ();
-       return *this;
-      }
-
-      inline ::Dwarf_Addr &address ()
-      {
-       return _m_addr;
-      }
-      inline ::Dwarf_Addr address () const
-      {
-       return _m_addr;
-      }
-      inline source_file &file ()
-      {
-       return _m_file;
-      }
-      inline const source_file &file () const
-      {
-       return _m_file;
-      }
-      inline unsigned int &line ()
-      {
-       return _m_line;
-      }
-      inline unsigned int line () const
-      {
-       return _m_line;
-      }
-      inline unsigned int &column ()
-      {
-       return _m_column;
-      }
-      inline unsigned int column () const
-      {
-       return _m_column;
-      }
-
-#define _DWARF_EDIT_LE_FLAG(what)                      \
-      bool what () const                               \
-      {                                                        \
-       return _m_flags[flag_##what];                   \
-      }                                                        \
-      std::bitset<flag_count>::reference what ()       \
-      {                                                        \
-       return _m_flags[flag_##what];                   \
-      }
-      _DWARF_EDIT_LE_FLAG (statement)
-      _DWARF_EDIT_LE_FLAG (basic_block)
-      _DWARF_EDIT_LE_FLAG (end_sequence)
-      _DWARF_EDIT_LE_FLAG (prologue_end)
-      _DWARF_EDIT_LE_FLAG (epilogue_begin)
-#undef _DWARF_EDIT_LE_FLAG
-
-      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);
-      }
-    };
-
-    class line_table : public std::vector<line_entry>
-    {
-    private:
-      typedef std::vector<line_entry> _base;
-
-    public:
-      typedef _base::size_type size_type;
-      typedef _base::difference_type difference_type;
-      typedef _base::value_type value_type;
-      typedef _base::iterator iterator;
-      typedef _base::const_iterator const_iterator;
-
-      line_table () {}
-
-      template<typename table>
-      line_table (const table &other) : _base (other.begin (), other.end ()) {}
-
-      template<typename table>
-      inline bool operator== (const table &other) const
-      {
-       return size () == other.size () && subr::container_equal (*this, other);
-      }
-      template<typename table>
-      inline bool operator!= (const table &other) const
-      {
-       return !(*this == other);
-      }
-
-      // Look up by matching address.
-      iterator find (::Dwarf_Addr);
-      const_iterator find (::Dwarf_Addr) const;
-    };
-
-    class line_info_table
-    {
-    private:
-      directory_table _m_dirs;
-      line_table _m_lines;
-
-    public:
-      line_info_table () : _m_dirs (), _m_lines () {}
-
-      template<typename table>
-      line_info_table (const table &other)
-       : _m_dirs (other.include_directories ()), _m_lines (other.lines ()) {}
-
-      template<typename table>
-      inline line_info_table &operator= (const table &other)
-      {
-       _m_dirs = directory_table (other.include_directories ());
-       _m_lines = line_table (other.lines ());
-       return *this;
-      }
-
-      inline directory_table &include_directories ()
-      {
-       return _m_dirs;
-      }
-      inline const directory_table &include_directories () const
-      {
-       return _m_dirs;
-      }
-      inline line_table &lines ()
-      {
-       return _m_lines;
-      }
-      inline const line_table &lines () const
-      {
-       return _m_lines;
-      }
-
-      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);
-      }
-    };
-
-    class location_attr : public std::map<dwarf::location_attr::key_type,
-                                         std::vector<uint8_t> >
-    {
-    private:
-      typedef std::map<dwarf::location_attr::key_type,
-                      std::vector<uint8_t> > _base;
-
-      template<typename pair>
-      struct nonempty : public std::unary_function<pair, bool>
-      {
-       inline bool operator () (const pair &x)
-       {
-         return !x.second.empty ();
-       }
-      };
-
-    public:
-      typedef _base::size_type size_type;
-      typedef _base::difference_type difference_type;
-      typedef _base::key_type key_type;
-      typedef _base::mapped_type mapped_type;
-      typedef _base::value_type value_type;
-      typedef _base::iterator iterator;
-      typedef _base::const_iterator const_iterator;
-
-      inline location_attr () : _base () {}
-      inline location_attr (const location_attr &other)
-       : _base (static_cast<const _base &> (other)) {}
-      template<typename loc>
-      inline location_attr (const loc &other) : _base ()
-      {
-       *this = other;
-      }
-
-      template<typename loc>
-      inline location_attr &operator= (const loc &other)
-      {
-       clear ();
-       if (other.empty ())
-         ;
-       else if (other.is_list ())
-         for (typename loc::const_iterator i = other.begin ();
-              i != other.end ();
-              ++i)
-           {
-             const typename loc::mapped_type &x = (*i).second;
-             (*this)[(*i).first] = mapped_type (x.begin (), x.end ());
-           }
-       else
-         {
-           mapped_type v = other.location ();
-           (*this)[key_type (0, -1)] = v;
-         }
-       return *this;
-      }
-
-      inline bool is_list () const
-      {
-       if (empty ())
-         return false;
-       if (size () > 1)
-         return true;
-
-       const key_type &elt = begin ()->first;
-       return !(elt.first == 0 && elt.second == (Dwarf_Addr) -1);
-      }
-
-      inline mapped_type &location ()
-      {
-       if (empty ())
-         return (*this)[key_type (0, -1)];
-
-       value_type &v = *begin ();
-       if (v.first.first != 0 || v.first.second != (Dwarf_Addr) -1
-           || size () > 1)
-         throw std::runtime_error ("location is list, not single location");
-
-       return v.second;
-      }
-      inline const mapped_type &location () const
-      {
-       if (size () == 1)
-         {
-           const value_type &v = *begin ();
-           if (v.first.first == 0 && v.first.second == (Dwarf_Addr) -1)
-             return v.second;
-         }
-       throw std::runtime_error ("location is list, not single location");
-      }
-
-      template<typename other_attr>
-      bool operator== (const other_attr &other) const
-      {
-       if (empty ())
-         return (other.empty ()
-                 || std::find_if (other.begin (), other.end (),
-                                  nonempty<typename other_attr::value_type> ()
-                                  ) == other.end ());
-       if (!is_list ())
-         return (!other.is_list () && !other.empty ()
-                 && subr::container_equal (location (), other.location ()));
-
-       return other.is_list () && subr::container_equal (*this, other);
-      }
-      template<typename other_attr>
-      inline bool operator!= (const other_attr &other) const
-      {
-       return !(*this == other);
-      }
-
-      std::string to_string () const;
-    };
-
-    class dwarf_enum
-    {
-    private:
-      ::Dwarf_Word _m_value;
-      unsigned int _m_which;
-
-    public:
-      inline dwarf_enum (unsigned int attr, unsigned int value)
-       : _m_value (value), _m_which (attr)
-      {}
-
-      template<typename constant>
-      inline dwarf_enum (const constant &other)
-       : _m_value (static_cast<unsigned int> (other)),
-         _m_which (other.which ())
-      {}
-
-      // Return the DW_AT_* indicating which enum this value belongs to.
-      inline unsigned int which () const
-      {
-       return _m_which;
-      }
-
-      inline operator unsigned int () const
-      {
-       return _m_value;
-      }
-
-      inline dwarf_enum &operator= (const dwarf_enum& other)
-      {
-       _m_value = other._m_value;
-       _m_which = other._m_which;
-       return *this;
-      }
-
-      template<typename constant>
-      inline dwarf_enum &operator= (const constant& other)
-      {
-       return *this = dwarf_enum (other.which (), other);
-      }
-
-      std::string to_string () const;
-
-      const char *identifier () const;
-      const char *name () const;
-
-      template<typename constant>
-      inline bool operator== (const constant &other) const
-      {
-       return (static_cast<unsigned int> (*this)
-               == static_cast<unsigned int> (other));
-      }
-      template<typename constant>
-      inline bool operator!= (const constant &other) const
-      {
-       return !(*this == other);
-      }
-    };
-
-  private:
-    class value_dispatch
-    {
-    public:
-      virtual ~value_dispatch () {}
-    };
-
-    struct value_string : public value_dispatch, public std::string
-    {
-      template<typename string>
-      value_string (const string &s) : std::string (s) {}
-
-      std::string to_string () const
-      {
-       std::string result ("\"");
-       result += *this;
-       result += "\"";
-       return result;
-      }
-    };
-
-    struct value_identifier : public value_string
-    {
-      template<typename id>
-      value_identifier (const id &s) : value_string (s) {}
-    };
-
-    struct value_reference : public value_dispatch
-    {
-      debug_info_entry::children_type::iterator ref;
-      value_reference (const debug_info_entry::children_type::iterator &i)
-       : ref (i) {}
-
-      template<typename iter>  // XXX dummy
-      value_reference (const iter &i) : ref () {}
-    };
-    struct value_unit_reference : public value_dispatch
-    {
-      compile_units::iterator ref;
-      value_unit_reference (const compile_units::iterator &i) : ref (i) {}
-
-      template<typename iter>  // XXX dummy
-      value_unit_reference (const iter &i) : ref () {}
-    };
-
-    struct value_flag : public value_dispatch
-    {
-      bool flag;
-      value_flag (bool t) : flag (t) {}
-    };
-
-    struct value_address : public value_dispatch
-    {
-      // XXX dwfl, reloc
-      ::Dwarf_Addr addr;
-      value_address (::Dwarf_Addr a) : addr (a) {}
-    };
-
-    struct value_rangelistptr : public value_dispatch, public range_list
-    {
-      template<typename list>
-      value_rangelistptr (const list &other) : range_list (other) {}
-    };
-
-    struct value_lineptr : public value_dispatch, public line_info_table
-    {
-      template<typename table>
-      value_lineptr (const table &other) : line_info_table (other) {}
-    };
-
-    struct value_constant : public value_dispatch
-    {
-      union
-      {
-       ::Dwarf_Word word;
-       ::Dwarf_Sword sword;
-      };
-      value_constant (::Dwarf_Word x) : word (x) {}
-    };
-
-    struct value_constant_block : public value_dispatch,
-                                 public std::vector<uint8_t>
-    {
-      template<typename block>
-      value_constant_block (const block &b)
-       : std::vector<uint8_t> (b.begin (), b.end ()) {}
-    };
-
-    struct value_dwarf_constant : public value_dispatch, public dwarf_enum
-    {
-      template<typename constant>
-      value_dwarf_constant (const constant &other) : dwarf_enum (other) {}
-    };
-
-    struct value_source_file : public value_dispatch, public source_file
-    {
-      template<typename file>
-      value_source_file (const file &other) : source_file (other) {}
-    };
-
-    struct value_source_line : public value_dispatch
-    {
-      unsigned int n;
-      value_source_line (unsigned int m) : n (m) {}
-    };
-    typedef value_source_line value_source_column;
-
-    struct value_macptr : public value_dispatch {};
-
-    struct value_location : public value_dispatch, public location_attr
-    {
-      template<typename loc>
-      value_location (const loc &other) : location_attr (other) {}
-    };
-
-  public:
-    class attr_value
-    {
-    private:
-      value_dispatch *_m_value;
-
-      template<typename value>
-      inline void init (const value &other)
-      {
-       switch (other.what_space ())
-         {
-         case dwarf::VS_identifier:
-           _m_value = new value_identifier (other.identifier ());
-           break;
-         case dwarf::VS_string:
-           _m_value = new value_string (other.string ());
-           break;
-         case dwarf::VS_flag:
-           _m_value = new value_flag (other.flag ());
-           break;
-         case dwarf::VS_rangelistptr:
-           _m_value = new value_rangelistptr (other.ranges ());
-           break;
-         case dwarf::VS_lineptr:
-           _m_value = new value_lineptr (other.line_info ());
-           break;
-         case dwarf::VS_address:
-           _m_value = new value_address (other.address ());
-           break;
-         case dwarf::VS_constant:
-           if (other.constant_is_integer ())
-             _m_value = new value_constant (other.constant ());
-           else
-             _m_value = new value_constant_block (other.constant_block ());
-           break;
-         case dwarf::VS_source_line:
-           _m_value = new value_source_line (other.source_line ());
-           break;
-         case dwarf::VS_source_column:
-           _m_value = new value_source_column (other.source_column ());
-           break;
-         case dwarf::VS_source_file:
-           _m_value = new value_source_file (other.source_file ());
-           break;
-         case dwarf::VS_dwarf_constant:
-           _m_value = new value_dwarf_constant (other.dwarf_constant ());
-           break;
-         case dwarf::VS_reference:
-           _m_value = new value_reference (other.reference ());
-           break;
-         case dwarf::VS_unit_reference:
-           _m_value = new value_unit_reference (other.unit_reference ());
-           break;
-         case dwarf::VS_location:
-           _m_value = new value_location (other.location ());
-           break;
-#if 0
-         case dwarf::VS_macptr:
-           _m_value = new value_macptr (other.macptr ());
-           break;
-#endif
-         default:
-         case dwarf::VS_discr_list:
-           throw std::runtime_error ("XXX unimplemented");
-         }
-      }
-
-      template<typename flavor>
-      inline flavor &variant () const
-      {
-       flavor *p = dynamic_cast<flavor *> (_m_value);
-       if (p == NULL)
-         throw std::runtime_error ("wrong value type");
-       return *p;
-      }
-
-    public:
-      attr_value (const attr_value &other) : _m_value (NULL)
-      {
-       init (other);
-      }
-      template<typename value>
-      attr_value (const value &other) : _m_value (NULL)
-      {
-       init (other);
-      }
-
-      attr_value () : _m_value (NULL) {}
-
-      ~attr_value ()
-      {
-       if (_m_value != NULL)
-         delete _m_value;
-      }
-
-      inline attr_value &operator= (const attr_value &other)
-      {
-       if (_m_value != NULL)
-         {
-           delete _m_value;
-           _m_value = NULL;
-         }
-       init (other);
-       return *this;
-      }
-      template<typename value>
-      inline attr_value &operator= (const value &other)
-      {
-       if (_m_value != NULL)
-         {
-           delete _m_value;
-           _m_value = NULL;
-         }
-       init (other);
-       return *this;
-      }
-
-      dwarf::value_space what_space () const;
-      inline std::string to_string () const;
-
-      inline bool &flag () const
-      {
-       return variant<value_flag> ().flag;
-      }
-
-      // XXX dwfl, reloc
-      inline ::Dwarf_Addr &address () const
-      {
-       return variant<value_address> ().addr;
-      }
-
-      inline debug_info_entry::children_type::iterator reference () const
-      {
-       return variant<value_reference> ().ref;
-      }
-      inline compile_units::iterator unit_reference () const
-      {
-       return variant<value_unit_reference> ().ref;
-      }
-
-      inline location_attr &location () const
-      {
-       return static_cast<location_attr &> (variant<value_location> ());
-      }
-
-      inline std::string &string () const
-      {
-       return static_cast<std::string &> (variant<value_string> ());
-      }
-      inline std::string &identifier () const
-      {
-       return string ();
-      }
-
-      inline dwarf_edit::source_file &source_file () const
-      {
-       return static_cast<dwarf_edit::source_file &>
-         (variant<value_source_file> ());
-      }
-
-      inline unsigned int &source_line () const
-      {
-       return variant<value_source_line> ().n;
-      }
-
-      inline unsigned int &source_column () const
-      {
-       return variant<value_source_column> ().n;
-      }
-
-      inline ::Dwarf_Word &constant () const
-      {
-       return variant<value_constant> ().word;
-      }
-
-      inline ::Dwarf_Sword &signed_constant () const
-      {
-       return variant<value_constant> ().sword;
-      }
-
-      inline std::vector<uint8_t> &constant_block () const
-      {
-       return static_cast<std::vector<uint8_t> &>
-         (variant<value_constant_block> ());
-      }
-
-      inline dwarf_enum &dwarf_constant () const
-      {
-       return variant<value_dwarf_constant> ();
-      }
-
-      inline bool constant_is_integer () const
-      {
-       return dynamic_cast<value_constant *> (_m_value) != NULL;
-      }
-
-      inline range_list &ranges () const
-      {
-       return static_cast<range_list &> (variant<value_rangelistptr> ());
-      }
-
-      inline line_info_table &line_info () const
-      {
-       return static_cast<line_info_table &> (variant<value_lineptr> ());
-      }
-
-      // macptr
-
-      template<typename value>
-      inline bool operator== (const value &other) const
-      {
-       const dwarf::value_space what = what_space ();
-       if (likely (other.what_space () == what))
-         switch (what)
-           {
-           case dwarf::VS_identifier:
-             return identifier () == other.identifier ();
-           case dwarf::VS_string:
-             return string () == other.string ();
-           case dwarf::VS_reference:
-             return reference () == other.reference ();
-           case dwarf::VS_unit_reference:
-             return unit_reference () == other.unit_reference ();
-           case dwarf::VS_flag:
-             return flag () == other.flag ();
-           case dwarf::VS_rangelistptr:
-             return ranges () == other.ranges ();
-           case dwarf::VS_lineptr:
-             return line_info () == other.line_info ();
-           case dwarf::VS_constant:
-             if (constant_is_integer ())
-               return (other.constant_is_integer ()
-                       && constant () == other.constant ());
-             return (!other.constant_is_integer ()
-                     && constant_block () == other.constant_block ());
-           case dwarf::VS_source_file:
-             return source_file () == other.source_file ();
-           case dwarf::VS_source_line:
-             return source_line () == other.source_line ();
-           case dwarf::VS_source_column:
-             return source_column () == other.source_column ();
-           case dwarf::VS_address:
-             return address () == other.address ();
-           case dwarf::VS_location:
-             return location () == other.location ();
-           case dwarf::VS_dwarf_constant:
-             return dwarf_constant () == other.dwarf_constant ();
-#if 0
-           case dwarf::VS_macptr:
-             return macptr () == other.macptr ();
-#endif
-           default:
-           case dwarf::VS_discr_list:
-             throw std::runtime_error ("XXX unimplemented");
-           }
-       return false;
-      }
-      template<typename value>
-      inline bool operator!= (const value &other) const
-      {
-       return !(*this == other);
-      }
-    };
-
   private:
     compile_units _m_units;
 
@@ -1200,17 +315,7 @@ namespace elfutils
   template<>
   std::string to_string<dwarf_edit::attribute> (const dwarf_edit::attribute &);
   template<>
-  std::string to_string<dwarf_edit::attr_value> (const dwarf_edit::attr_value&);
-  inline std::string dwarf_edit::attr_value::to_string () const
-  {
-    return elfutils::to_string (*this); // Use that.
-  }
-  template<>
-  std::string to_string<dwarf_edit::dwarf_enum> (const dwarf_edit::dwarf_enum&);
-  inline std::string dwarf_edit::dwarf_enum::to_string () const
-  {
-    return elfutils::to_string (*this); // Use that.
-  }
+  std::string to_string<dwarf_edit::attr_value> (const dwarf_edit::attr_value &);
 };
 
 #endif // <elfutils/dwarf_edit>
index ac015c74e10f222e4367a00b073a0de0334a9f88..bd1b10ee35e22243ed974fe37dde8e6838c389a2 100644 (file)
@@ -50,7 +50,7 @@
 #ifndef _ELFUTILS_DWARF_OUTPUT
 #define _ELFUTILS_DWARF_OUTPUT 1
 
-#include "dwarf"
+#include "dwarf_edit"
 
 /* Read the comments for elfutils::dwarf first.
 
@@ -67,6 +67,7 @@ namespace elfutils
 {
   class dwarf_output_collector;
 
+#if 0
   class dwarf_output
   {
   public:
@@ -89,7 +90,6 @@ namespace elfutils
             const typename input::debug_info_entry &);
 
   public:
-    class compile_units;
 
     // XXX later
     class attr_value : public dwarf::attr_value
@@ -102,19 +102,20 @@ namespace elfutils
     {
       friend class dwarf_output;
 
-    private:
-      typedef subr::hashed_unordered_map<int, attr_value> _attributes;
-      typedef subr::hashed_vector<debug_info_entry> _children;
+    public:
+      typedef subr::hashed_unordered_map<int, attr_value> attributes_type;
+      typedef subr::hashed_vector<debug_info_entry> children_type;
 
+    private:
       const int _m_tag;
-      const _attributes _m_attributes;
-      const _children _m_children;
+      const attributes_type _m_attributes;
+      const children_type _m_children;
       size_t _m_hash;
 
       /* The template constructor lets us copy in from any class that has
         compatibly iterable containers for attributes and children.  */
       template<typename die_type>
-      debug_info_entry (const die_type &die)
+      debug_info_entry (const die_type &die, dwarf_output_collector *c)
        : _m_tag (die.tag ()),
          _m_attributes (die.attributes ()),
          _m_children (die.children ()),
@@ -136,12 +137,12 @@ namespace elfutils
        return !_m_children.empty ();
       }
 
-      inline const _children &children () const
+      inline const children_type &children () const
       {
        return _m_children;
       }
 
-      inline const _attributes &attributes () const
+      inline const attributes_type &attributes () const
       {
        return _m_attributes;
       }
@@ -159,7 +160,7 @@ namespace elfutils
       }
     };
 
-    typedef debug_info_entry::_attributes::value_type attribute;
+    typedef debug_info_entry::attributes_type::value_type attribute;
 
   public:
     /* Main container anchoring all the output.
@@ -216,7 +217,7 @@ namespace elfutils
       template<typename other_children>
       bool operator== (const other_children &other) const
       {
-       return std::equal (begin (), end (), other.begin ());
+       return subr::container_equal (*this, other);
       }
       template<typename other_children>
       bool operator!= (const other_children &other) const
@@ -265,21 +266,307 @@ namespace elfutils
     }
   };
 
+#else  // XXX temp
+
+  class dwarf_output
+  {
+  public:
+    typedef dwarf_data::source_file source_file;
+    typedef dwarf_data::directory_table directory_table;
+    typedef dwarf_data::line_entry<source_file> line_entry;
+    typedef dwarf_data::line_table<line_entry> line_table;
+    typedef dwarf_data::line_info_table<directory_table,
+                                       line_table> line_info_table;
+    typedef dwarf_data::dwarf_enum dwarf_enum;
+    typedef dwarf_data::range_list range_list;
+    typedef dwarf_data::location_attr location_attr;
+    typedef dwarf_data::attr_value<dwarf_output> attr_value;
+
+  protected:
+    template<typename input>
+    static inline const range_list &
+    collect (dwarf_output_collector *, const typename input::range_list &);
+
+    /* An iterator adapter for use in iterator-based constructors.
+       collectify (iterator) yields an iterator on input where *i
+       constructs output::value_type (input::value_type v, collector).  */
+    template<typename input, typename output>
+    struct collectify
+      : public std::unary_function<typename input::const_iterator,
+                                  typename output::iterator>
+    {
+      typedef typename input::const_iterator inny;
+      typedef typename output::iterator outty;
+      typedef typename input::value_type inlet;
+      typedef typename output::value_type outlet;
+
+      /* Wrapper worker passed to wrapped_input_iterator.
+        This object holds the collector pointer.  */
+      struct maker
+       : public std::unary_function<inlet, outlet>
+      {
+       dwarf_output_collector *_m_collector;
+       explicit inline maker (dwarf_output_collector *c) : _m_collector (c) {}
+
+       inline outlet operator () (const inlet &x) const
+       {
+         return outlet (x, _m_collector);
+       }
+      } _m_maker;
+
+      explicit inline collectify (dwarf_output_collector *c) : _m_maker (c) {}
+
+      typedef subr::wrapped_input_iterator<input, maker> wrapped;
+
+      inline wrapped operator () (const inny &i)
+      {
+       return wrapped (i, _m_maker);
+      }
+    };
+
+  public:
+    class compile_units;
+
+    class debug_info_entry
+    {
+    public:
+
+      class children_type : public std::list<debug_info_entry>
+      {
+       friend class debug_info_entry;
+      private:
+        children_type () {}
+
+       template<typename childrens>
+       children_type (const childrens &other)
+         : std::list<debug_info_entry> (other.begin (), other.end ()) {}
+
+      public:
+       typedef debug_info_entry value_type;
+      };
+
+      class attributes_type : public std::map<int, attr_value>
+      {
+       friend class debug_info_entry;
+      private:
+       typedef std::map<int, attr_value> base_type;
+
+       attributes_type () {}
+
+       template<typename attrs>
+       attributes_type (const attrs &other)
+         : std::map<int, attr_value> (other.begin (), other.end ()) {}
+
+      public:
+       typedef base_type::key_type key_type;
+       typedef base_type::value_type value_type;
+       typedef base_type::mapped_type mapped_type;
+
+       static const bool ordered = true;
+
+       template<typename attrs>
+       inline operator attrs () const
+       {
+         return attrs (begin (), end ());
+       }
+      };
+
+    private:
+      const int _m_tag;
+      attributes_type _m_attributes;
+      children_type _m_children;
+
+    public:
+      explicit debug_info_entry (int t) : _m_tag (t)
+      {
+       if (unlikely (t <= 0))
+         throw std::invalid_argument ("invalid tag");
+      }
+
+      /* The template constructor lets us copy in from any class that has
+        compatibly iterable containers for attributes and children.  */
+      template<typename die_type>
+      debug_info_entry (const die_type &die)
+       : _m_tag (die.tag ()),
+         _m_attributes (die.attributes ()),
+         _m_children (die.children ())
+      {}
+
+      inline int tag () const
+      {
+       return _m_tag;
+      }
+
+      inline bool has_children () const
+      {
+       return !_m_children.empty ();
+      }
+
+      inline children_type &children ()
+      {
+       return _m_children;
+      }
+      inline const children_type &children () const
+      {
+       return _m_children;
+      }
+
+      inline attributes_type &attributes ()
+      {
+       return _m_attributes;
+      }
+      inline const attributes_type &attributes () const
+      {
+       return _m_attributes;
+      }
+
+      template<typename die>
+      bool operator== (const die &other) const
+      {
+       return (other.tag () == tag ()
+               && other.attributes () == attributes ()
+               && other.children () == children ());
+      }
+      template<typename die>
+      bool operator!= (const die &other) const
+      {
+       return !(*this == other);;
+      }
+
+      inline ::Dwarf_Off identity () const
+      {
+       return (uintptr_t) this;
+      }
+
+      inline ::Dwarf_Off offset () const
+      {
+       return identity ();
+      }
+    };
+
+    typedef debug_info_entry::attributes_type::value_type attribute;
+
+    class compile_unit : public debug_info_entry
+    {
+      friend class compile_units;
+    private:
+      inline compile_unit () : debug_info_entry (::DW_TAG_compile_unit) {}
+
+      // XXX should be private
+    public:
+      template<typename die_type>
+      compile_unit (const die_type &die, dwarf_output_collector *c)
+       : debug_info_entry (die)
+      {
+       if (die.tag () != ::DW_TAG_compile_unit)
+         throw std::invalid_argument ("not a compile_unit entry");
+      }
+
+      /* XXX doesn't help
+       public:
+       compile_unit (const compile_unit &u) : debug_info_entry (u) {}
+      */
+    };
+
+    // Main container anchoring all the output.
+    class compile_units
+      : public std::list<compile_unit>
+    {
+      friend class dwarf_output;
+    private:
+      typedef std::list<compile_unit> _base;
+
+      // Default constructor: an empty container, no CUs.
+      inline compile_units ()
+       : _base ()
+      {}
+
+      // Constructor copying CUs from input container.
+      template<typename input>
+      compile_units (const input &units, dwarf_output_collector *c)
+       : _base (collectify<input, compile_units> (c) (units.begin ()),
+                collectify<input, compile_units> (c) (units.end ()))
+      {
+      }
+
+    public:
+      typedef compile_unit value_type;
+      typedef _base::iterator iterator;
+      typedef _base::const_iterator const_iterator;
+
+      template<typename other_children>
+      bool operator== (const other_children &other) const
+      {
+       return subr::container_equal (*this, other);
+      }
+      template<typename other_children>
+      bool operator!= (const other_children &other) const
+      {
+       return !(*this == other);
+      }
+    };
+
+  private:
+    compile_units _m_units;
+
+  public:
+    class compile_units &compile_units ()
+    {
+      return _m_units;
+    }
+    const class compile_units &compile_units () const
+    {
+      return _m_units;
+    }
+
+  public:
+    // Constructor for an empty file, can add to its compile_units ().
+    dwarf_output ()
+      : _m_units ()
+    {}
+
+    // Constructor copying CUs from an input file (can be any of dwarf,
+    // dwarf_edit, or dwarf_output).
+    template<typename input>
+    dwarf_output (const input &dw, dwarf_output_collector *c)
+      : _m_units (dw.compile_units (), c)
+    {}
+
+    template<typename file>
+    inline bool operator== (const file &other) const
+    {
+      return compile_units () == other.compile_units ();
+    }
+    template<typename file>
+    inline bool operator!= (const file &other) const
+    {
+      return !(*this == other);
+    }
+  };
+
+  // Explicit specializations.
+  template<>
+  std::string to_string<dwarf_output::attribute> (const dwarf_output::attribute &);
+  template<>
+  std::string to_string<dwarf_output::attr_value> (const dwarf_output::attr_value&);
+
+#endif
+
   class dwarf_output_collector
   {
     friend class dwarf_output;
 
   private:
-    subr::value_set<dwarf_output::debug_info_entry> _m_die;
+    subr::value_set<dwarf_output::range_list> _m_ranges;
 
   };
 
   template<typename input>
-  inline const dwarf_output::debug_info_entry &
+  inline const dwarf_output::range_list &
   dwarf_output::collect (dwarf_output_collector *c,
-                        const typename input::debug_info_entry &die)
+                        const typename input::range_list &rl)
   {
-    return c->_m_die.add (die);
+    return c->_m_ranges.add (rl);
   }
 
 };
index eb957492a9bfa0fdd9254dda58b85d0fc0d8a920..aaa8a2768542135d48a97b6c274d14016d443b38 100644 (file)
 
 #include <config.h>
 #include "dwarf_edit"
-
-#include <typeinfo>
+#include "data-values.hh"
 
 using namespace elfutils;
 
-
-dwarf::value_space
-dwarf_edit::attr_value::what_space () const
-{
-  if (typeid (*_m_value) == typeid (value_flag))
-    return dwarf::VS_flag;
-  if (typeid (*_m_value) == typeid (value_dwarf_constant))
-    return dwarf::VS_dwarf_constant;
-  if (typeid (*_m_value) == typeid (value_reference))
-    return dwarf::VS_reference;
-  if (typeid (*_m_value) == typeid (value_unit_reference))
-    return dwarf::VS_unit_reference;
-  if (typeid (*_m_value) == typeid (value_lineptr))
-    return dwarf::VS_lineptr;
-  if (typeid (*_m_value) == typeid (value_macptr))
-    return dwarf::VS_macptr;
-  if (typeid (*_m_value) == typeid (value_rangelistptr))
-    return dwarf::VS_rangelistptr;
-  if (typeid (*_m_value) == typeid (value_identifier))
-    return dwarf::VS_identifier;
-  if (typeid (*_m_value) == typeid (value_string))
-    return dwarf::VS_string;
-  if (typeid (*_m_value) == typeid (value_source_file))
-    return dwarf::VS_source_file;
-  if (typeid (*_m_value) == typeid (value_source_line))
-    return dwarf::VS_source_line;
-  if (typeid (*_m_value) == typeid (value_source_column))
-    return dwarf::VS_source_column;
-  if (typeid (*_m_value) == typeid (value_address))
-    return dwarf::VS_address;
-  if (typeid (*_m_value) == typeid (value_constant)
-      || typeid (*_m_value) == typeid (value_constant_block))
-    return dwarf::VS_constant;
-  if (typeid (*_m_value) == typeid (value_location))
-    return dwarf::VS_location;
-
-  throw std::runtime_error ("XXX impossible");
-}
+template
+dwarf::value_space dwarf_data::attr_value<dwarf_edit>::what_space () const;
 
 template<>
 std::string
@@ -104,7 +67,7 @@ to_string<dwarf_edit::attribute> (const dwarf_edit::attribute &attr)
 }
 
 std::string
-dwarf_edit::source_file::to_string () const
+dwarf_data::source_file::to_string () const
 {
   if (likely (_m_mtime == 0) && likely (_m_size == 0))
     return "\"" + _m_name + "\"";
@@ -115,7 +78,7 @@ dwarf_edit::source_file::to_string () const
 }
 
 std::string
-dwarf_edit::location_attr::to_string () const
+dwarf_data::location_attr::to_string () const
 {
   return is_list () ? "XXX-loclist" : "XXX-expr";
 }
index 1bb84f1375183404c4ca950b34547f4721a3baba..a7788416e396a49788aa49b08da77c529495c066 100644 (file)
@@ -217,13 +217,13 @@ dwarf::dwarf_enum::name () const
 }
 
 const char *
-dwarf_edit::dwarf_enum::identifier () const
+dwarf_data::dwarf_enum::identifier () const
 {
   return enum_identifier (*this);
 }
 
 const char *
-dwarf_edit::dwarf_enum::name () const
+dwarf_data::dwarf_enum::name () const
 {
   return enum_name (*this);
 }
@@ -245,7 +245,7 @@ to_string<dwarf::dwarf_enum> (const dwarf::dwarf_enum &value)
 
 template<>
 string
-to_string<dwarf_edit::dwarf_enum> (const dwarf_edit::dwarf_enum &value)
+to_string<dwarf_data::dwarf_enum> (const dwarf_data::dwarf_enum &value)
 {
   return enum_string (value);
 }
diff --git a/libdw/c++/output-values.cc b/libdw/c++/output-values.cc
new file mode 100644 (file)
index 0000000..abba7fa
--- /dev/null
@@ -0,0 +1,69 @@
+/* elfutils::dwarf_output attribute value interfaces.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   In addition, as a special exception, Red Hat, Inc. gives You the
+   additional right to link the code of Red Hat elfutils with code licensed
+   under any Open Source Initiative certified open source license
+   (http://www.opensource.org/licenses/index.php) which requires the
+   distribution of source code with any binary distribution and to
+   distribute linked combinations of the two.  Non-GPL Code permitted under
+   this exception must only link to the code of Red Hat elfutils through
+   those well defined interfaces identified in the file named EXCEPTION
+   found in the source code files (the "Approved Interfaces").  The files
+   of Non-GPL Code may instantiate templates or use macros or inline
+   functions from the Approved Interfaces without causing the resulting
+   work to be covered by the GNU General Public License.  Only Red Hat,
+   Inc. may make changes or additions to the list of Approved Interfaces.
+   Red Hat's grant of this exception is conditioned upon your not adding
+   any new exceptions.  If you wish to add a new Approved Interface or
+   exception, please contact Red Hat.  You must obey the GNU General Public
+   License in all respects for all of the Red Hat elfutils code and other
+   code used in conjunction with Red Hat elfutils except the Non-GPL Code
+   covered by this exception.  If you modify this file, you may extend this
+   exception to your version of the file, but you are not obligated to do
+   so.  If you do not wish to provide this exception without modification,
+   you must delete this exception statement from your version and license
+   this file solely under the GPL without exception.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#include <config.h>
+#include "dwarf_output"
+#include "data-values.hh"
+
+#include <typeinfo>
+
+using namespace elfutils;
+
+template
+dwarf::value_space dwarf_data::attr_value<dwarf_output>::what_space () const;
+
+template<>
+std::string
+to_string<dwarf_output::attribute> (const dwarf_output::attribute &attr)
+{
+  std::string result = dwarf::attributes::name (attr.first);
+  result += "=";
+  result += attr.second.to_string ();
+  return result;
+}
index 527f0c073193247bc20c262926369f716a4f97ea..6b4508ba4f532ab775330fcfbf5b0b36b69dfe6b 100644 (file)
 #include <tr1/unordered_set>
 #include <vector>
 #include <algorithm>
+#include <utility>
 
 namespace elfutils
 {
   namespace subr
   {
-    // XXX
     template<typename T>
-    struct hash };
+    struct hash : public T::hasher {};
 
     template <typename T>
     inline void hash_combine (size_t &seed, const T &v)
     {
-      seed ^= hash<T> (v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+      seed ^= hash<T> () (v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
     }
 
+    template <typename T1, typename T2>
+    inline void hash_combine (size_t &seed, const std::pair<T1,T2> &v)
+    {
+      hash_combine (seed, v.first);
+      hash_combine (seed, v.second);
+    }
+
+    template<typename T>
+    struct integer_hash : public std::unary_function<T, size_t>
+    {
+      inline size_t operator () (const T &x) const
+      {
+       return x;
+      }
+    };
+    template<>
+    struct hash<int> : public integer_hash<int> {};
+    template<>
+    struct hash<uint64_t> : public integer_hash<uint64_t> {};
+
+    template<typename T>
+    struct container_hasher : public std::unary_function<T, size_t>
+    {
+      struct hasher
+      {
+       size_t _m_hash;
+       inline hasher () : _m_hash (0) {}
+       inline void operator () (const typename T::value_type &x)
+       {
+         subr::hash_combine (_m_hash, subr::hash<typename T::value_type> (x));
+       }
+      };
+
+      inline size_t operator () (const T &x) const
+      {
+       hasher h;
+       std::for_each (x.begin (), x.end (), h);
+       return h._m_hash;
+      }
+    };
+
+    template<>
+    struct hash<std::string>
+    {
+    private:
+      struct hasher : public container_hasher<std::string>::hasher
+      {
+       inline void operator () (std::string::value_type c)
+       {
+         _m_hash = 5 * _m_hash + c;
+       }
+      };
+    public:
+      inline size_t operator () (const std::string &x) const
+      {
+       hasher h;
+       std::for_each (x.begin (), x.end (), h);
+       return h._m_hash;
+      }
+    };
+
+    template<class T>
+    struct hashed_hasher
+      : public std::unary_function<T, size_t>
+    {
+      size_t operator () (const T &v)
+      {
+       return v._m_hash;
+      }
+    };
+
     template<typename string>
     struct name_equal : public std::binary_function<const char *, string, bool>
     {
@@ -278,33 +349,34 @@ namespace elfutils
     };
 
     // Pair of some value and its precomputed hash.
-    template<typename value_type>
+    template<typename T>
     class hashed_value
-      : public std::pair<size_t, const value_type>
+      : public std::pair<size_t, const T>
     {
     private:
-      typedef std::pair<size_t, const value_type> _base;
+      typedef std::pair<size_t, const T> _base;
 
     public:
-      hashed_value (const value_type &v)
-       : _base (subr::hash<value_type> (v), v) {}
-      hashed_value (const hashed_value<value_type> &v)
-       : _base (v.first, v.second) {}
-
-      bool operator== (const hashed_value<value_type> &other)
-       const
-      {
-       return other.first == this->first && other.second == this->second;
-      }
+      typedef T value_type;
 
       struct hasher
-       : public std::unary_function<hashed_value<value_type>, size_t>
+       : public std::unary_function<hashed_value, size_t>
       {
-       size_t operator () (const hashed_value<value_type> &v)
+       inline size_t operator () (const hashed_value &v)
        {
          return v.first;
        }
       };
+
+      hashed_value (const value_type &v)
+       : _base (subr::hash<value_type> (v), v) {}
+      hashed_value (const hashed_value &v)
+       : _base (v.first, v.second) {}
+
+      bool operator== (const hashed_value &other) const
+      {
+       return other.first == this->first && other.second == this->second;
+      }
     };
 
     // Set of hashed_value's.
@@ -329,25 +401,26 @@ namespace elfutils
          {
            // XXX hook for collection: abbrev building, etc.
          }
-       return *p.first;
+       return p.first->second;
       };
     };
 
-    // A vector of hashed_value's that itself acts like a hashed_value.
-    template<typename value_type>
-    class hashed_vector
-      : public std::vector<hashed_value<value_type> >
+    // A container of hashed_value's that itself acts like a hashed_value.
+    // The parameter class should be a std::container<hashed_value<something>>.
+    template<typename container>
+    class hashed_container : public container
     {
     private:
-      typedef hashed_value<value_type> elt_type;
-      typedef std::vector<elt_type> _base;
+      typedef container _base;
+      typedef typename container::value_type elt_type;
 
+    public:
+      typedef typename elt_type::value_type value_type;
+
+    private:
       size_t _m_hash;
 
-    public:
-      template<typename iterator>
-      hashed_vector (iterator first, iterator last)
-       : _base (first, last), _m_hash (0)
+      inline void set_hash ()
       {
        struct hashit
        {
@@ -361,29 +434,48 @@ namespace elfutils
        std::for_each (_base::begin (), _base::end (), hashit (_m_hash));
       }
 
-      template<typename container>
-      hashed_vector (const container &other)
-       : hashed_vector (other.begin (), other.end ())
-      {}
+    public:
+      friend class hashed_hasher<hashed_container>;
+      typedef hashed_hasher<hashed_container> hasher;
+
+      template<typename iterator>
+      hashed_container (iterator first, iterator last)
+       : _base (first, last), _m_hash (0)
+      {
+       set_hash ();
+      }
+
+      template<typename other_container>
+      hashed_container (const other_container &other)
+       : _base (other.begin (), other.end ()), _m_hash (0)
+      {
+       set_hash ();
+      }
 
-      bool operator== (const hashed_vector &other) const
+      bool operator== (const hashed_container &other) const
       {
        return (other._m_hash == _m_hash &&
                other.size () == _base::size ()
                && std::equal (_base::begin (), _base::end (), other.begin ()));
       }
-
-      struct hasher
-       : public std::unary_function<hashed_vector<value_type>, size_t>
-      {
-       size_t operator () (const hashed_vector<value_type> &v)
-       {
-         return v._m_hash;
-       }
-      };
     };
 
+    // A vector of hashed_value's that itself acts like a hashed_value.
+    template<typename value_type>
+    struct hashed_vector
+      : public hashed_container<std::vector<hashed_value<value_type> > >
+    {};
+
     // An unordered_map of hashed_value's that itself acts like a hashed_value.
+    template<typename key_type, typename value_type>
+    class hashed_unordered_map
+      : public hashed_container<std::tr1::unordered_map<
+                                 key_type,
+                                 hashed_value<value_type>,
+                                 class hashed_value<value_type>::hasher>
+                               >
+    {};
+#if 0
     template<typename key_type, typename value_type>
     class hashed_unordered_map
       : public std::tr1::unordered_map<key_type,
@@ -398,17 +490,14 @@ namespace elfutils
 
       size_t _m_hash;
 
-    public:
-      template<typename iterator>
-      hashed_unordered_map (iterator first, iterator last)
-       : _base (first, last), _m_hash (0)
+      inline void set_hash ()
       {
-       class hashit
+       struct hashit
        {
          size_t &_m_hash;
          hashit (size_t &h) : _m_hash (h) {}
 
-         void operator () (const typename _base::value_type &p)
+         inline void operator () (const typename _base::value_type &p)
          {
            subr::hash_combine (_m_hash, subr::hash<key_type> (p.first));
            subr::hash_combine (_m_hash, p.second.first);
@@ -417,11 +506,25 @@ namespace elfutils
        std::for_each (_base::begin (), _base::end (), hashit (_m_hash));
       }
 
+    public:
+      friend class hashed_hasher<hashed_unordered_map>;
+      typedef hashed_hasher<hashed_unordered_map> hasher;
+
+      template<typename iterator>
+      hashed_unordered_map (iterator first, iterator last)
+       : _base (first, last), _m_hash (0)
+      {
+       set_hash ();
+      }
+
       template<typename container>
       hashed_unordered_map (const container &other)
-       : hashed_unordered_map (other.begin (), other.end ())
-      {}
+       : _base (other.begin (), other.end ()), _m_hash (0)
+      {
+       set_hash ();
+      }
     };
+#endif
 
     template<typename T>
     class auto_ref
@@ -442,8 +545,52 @@ namespace elfutils
       auto_ref (const auto_ref<T> &other)
        : _m_ptr (other._m_ptr)
       {}
+
+      template<typename other>
+      inline bool operator== (const auto_ref<other> &x) const
+      {
+       return *_m_ptr == static_cast<other &> (x);
+      }
+      template<typename other>
+      inline bool operator== (const other &x) const
+      {
+       return *_m_ptr == x;
+      }
+      template<typename other>
+      inline bool operator!= (const other &x) const
+      {
+       return !(*this == x);
+      }
     };
 
+    /* A wrapped_input_iterator is like an input::const_iterator,
+       but *i returns wrapper (*i) instead; wrapper returns element
+       (or const element & or something).  */
+    template<typename input, typename wrapper,
+            typename element = typename wrapper::result_type>
+    class wrapped_input_iterator : public input::const_iterator
+    {
+    private:
+      typedef typename input::const_iterator _base;
+
+      wrapper *_m_wrapper;
+
+    public:
+      typedef element value_type;
+
+      inline wrapped_input_iterator (const _base &i, wrapper &w)
+       : _base (static_cast<_base> (i)), _m_wrapper (&w)
+      {}
+
+      inline wrapped_input_iterator (const wrapped_input_iterator &i)
+       : _base (static_cast<_base> (i)), _m_wrapper (i._m_wrapper)
+      {}
+
+      inline typename wrapper::result_type operator* () const
+      {
+       return (*_m_wrapper) (_base::operator* ());
+      }
+    };
   };
 };
 
index 5e0eda23fd925892b406a5f978cd49afcc69ef47..109db05a8d0d5368472e90351230b08fa841f0ed 100644 (file)
@@ -51,6 +51,7 @@
 #include <cassert>
 #include "dwarf"
 #include "dwarf_edit"
+#include "dwarf_output"
 
 extern "C"
 {
@@ -232,6 +233,16 @@ value_string (const value_type &value)
   throw std::runtime_error ("XXX unsupported value space");
 }
 
+template<>
+string
+to_string<dwarf::attribute> (const dwarf::attribute &attr)
+{
+  std::string result = dwarf::attributes::name (attr.first);
+  result += "=";
+  result += attr.second.to_string ();
+  return result;
+}
+
 template<>
 string
 to_string<dwarf::attr_value> (const dwarf::attr_value &value)
@@ -246,6 +257,12 @@ to_string<dwarf_edit::attr_value> (const dwarf_edit::attr_value &value)
   return value_string (value);
 }
 
+template<>
+string
+to_string<dwarf_output::attr_value> (const dwarf_output::attr_value &value)
+{
+  return value_string (value);
+}
 
 // A few cases are trivial.
 #define SIMPLE(type, name, form)                                       \
index 370f1ad06795d8a0e96862da55e9af5dad1e1145..cffa5fa1661dda8c4f65766bbd878b7b7c719883 100644 (file)
@@ -133,8 +133,8 @@ struct talker : public dwarf_ref_tracker<dwarf1, dwarf2>
   typedef typename _base::cu2 cu2;
   typedef typename _base::die1 die1;
   typedef typename _base::die2 die2;
-  typedef typename die1::value_type::attributes_type::const_iterator attr1;
-  typedef typename die2::value_type::attributes_type::const_iterator attr2;
+  typedef typename _base::dwarf1_die::attributes_type::const_iterator attr1;
+  typedef typename _base::dwarf2_die::attributes_type::const_iterator attr2;
 
   const typename dwarf1::debug_info_entry *a_;
   const typename dwarf2::debug_info_entry *b_;