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 \
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
--- /dev/null
+/* 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");
+ }
+
+
+};
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
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
--- /dev/null
+/* 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
#define _ELFUTILS_DWARF_EDIT 1
#include "dwarf"
-#include <bitset>
+#include "dwarf_data"
/* Read the comments for elfutils::dwarf first.
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
{
}
};
- // 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;
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>
#ifndef _ELFUTILS_DWARF_OUTPUT
#define _ELFUTILS_DWARF_OUTPUT 1
-#include "dwarf"
+#include "dwarf_edit"
/* Read the comments for elfutils::dwarf first.
{
class dwarf_output_collector;
+#if 0
class dwarf_output
{
public:
const typename input::debug_info_entry &);
public:
- class compile_units;
// XXX later
class attr_value : public dwarf::attr_value
{
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 ()),
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;
}
}
};
- typedef debug_info_entry::_attributes::value_type attribute;
+ typedef debug_info_entry::attributes_type::value_type attribute;
public:
/* Main container anchoring all the output.
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
}
};
+#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);
}
};
#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
}
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 + "\"";
}
std::string
-dwarf_edit::location_attr::to_string () const
+dwarf_data::location_attr::to_string () const
{
return is_list () ? "XXX-loclist" : "XXX-expr";
}
}
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);
}
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);
}
--- /dev/null
+/* 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;
+}
#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>
{
};
// 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.
{
// 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
{
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,
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);
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
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* ());
+ }
+ };
};
};
#include <cassert>
#include "dwarf"
#include "dwarf_edit"
+#include "dwarf_output"
extern "C"
{
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)
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) \
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_;