+2009-07-02 Roland McGrath <roland@redhat.com>
+
+ * c++/dwarf_output: Rewrite.
+ * c++/subr.hh: New helpers for dwarf_output/dwarf_data.
+
+ * c++/dwarf_edit: Much guts moved to ...
+ * c++/dwarf_data: ... here, new file.
+ * c++/known.cc: Update specializations.
+
+ * libdw/c++/edit-values.cc (what_space): Moved to ...
+ * c++/data-values.hh: ... here, new file.
+
+ * Makefile.am (noinst_HEADERS): Add it.
+
+ * c++/output-values.cc: New file.
+ * Makefile.am (libdwpp_a_SOURCES): Add it.
+ Makefile.am (pkginclude_HEADERS): Add dwarf_data, dwarf_output.
+
+ * c++/dwarf: Use to_string function overload, not to_string method.
+ * c++/values.cc: Define to_string specializations.
+
2009-07-01 Roland McGrath <roland@redhat.com>
* c++/dwarf_tracker: Major revamp for efficiency and to handle
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
-noinst_HEADERS = c++/dwarf-knowledge.cc
+ c++/edit-values.cc \
+ c++/output-values.cc
+noinst_HEADERS = c++/dwarf-knowledge.cc \
+ c++/data-values.hh
if MAINTAINER_MODE
BUILT_SOURCES = $(srcdir)/known-dwarf.h
--- /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, typename v>
+ dwarf::value_space
+ dwarf_data::attr_value<impl, v>::what_space () const
+ {
+ if (typeid (*_m_value) == typeid (typename v::value_flag))
+ return dwarf::VS_flag;
+ if (typeid (*_m_value) == typeid (typename v::value_dwarf_constant))
+ return dwarf::VS_dwarf_constant;
+ if (typeid (*_m_value) == typeid (typename v::value_reference))
+ return dwarf::VS_reference;
+ if (typeid (*_m_value) == typeid (typename v::value_unit_reference))
+ return dwarf::VS_unit_reference;
+ if (typeid (*_m_value) == typeid (typename v::value_lineptr))
+ return dwarf::VS_lineptr;
+ if (typeid (*_m_value) == typeid (typename v::value_macptr))
+ return dwarf::VS_macptr;
+ if (typeid (*_m_value) == typeid (typename v::value_rangelistptr))
+ return dwarf::VS_rangelistptr;
+ if (typeid (*_m_value) == typeid (typename v::value_identifier))
+ return dwarf::VS_identifier;
+ if (typeid (*_m_value) == typeid (typename v::value_string))
+ return dwarf::VS_string;
+ if (typeid (*_m_value) == typeid (typename v::value_source_file))
+ return dwarf::VS_source_file;
+ if (typeid (*_m_value) == typeid (typename v::value_source_line))
+ return dwarf::VS_source_line;
+ if (typeid (*_m_value) == typeid (typename v::value_source_column))
+ return dwarf::VS_source_column;
+ if (typeid (*_m_value) == typeid (typename v::value_address))
+ return dwarf::VS_address;
+ if (typeid (*_m_value) == typeid (typename v::value_constant)
+ || typeid (*_m_value) == typeid (typename v::value_constant_block))
+ return dwarf::VS_constant;
+ if (typeid (*_m_value) == typeid (typename v::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>
+#include <typeinfo>
+
+/* 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;
+
+ inline dwarf_enum ()
+ : _base (0, 0)
+ {}
+
+ 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= (::Dwarf_Word value)
+ {
+ this->first = value;
+ return *this;
+ }
+
+ inline dwarf_enum &operator= (const dwarf_enum& other)
+ {
+ if (this->second == 0)
+ {
+ throw std::logic_error("dwarf_enum default constructed");
+ this->second = other.second;
+ }
+ else if (this->second != other.second)
+ throw std::runtime_error
+ ("cannot assign dwarf_constant () from "
+ + dwarf::attributes::name (other.second) + "to "
+ + dwarf::attributes::name (this->second));
+
+ this->first = other.first;
+ 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;
+ };
+
+ public:
+ struct nothing {};
+
+ template<typename impl>
+ struct value
+ {
+ struct value_dispatch
+ {
+ virtual ~value_dispatch () {}
+ };
+
+ template<typename flavor, typename input, typename arg_type>
+ static inline value_dispatch *
+ make (flavor *&result, const input &x, const arg_type &arg)
+ {
+ return result = new flavor (x, arg);
+ }
+
+ struct value_string : public value_dispatch, public std::string
+ {
+ inline value_string () {}
+
+ template<typename string, typename arg_type>
+ inline value_string (const string &s, const arg_type &arg)
+ : 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, typename arg_type>
+ inline value_identifier (const id &s, const arg_type &arg)
+ : value_string (s, arg)
+ {}
+ };
+
+ struct value_reference : public value_dispatch
+ {
+ typename impl::debug_info_entry::children_type::iterator ref;
+
+ template<typename arg_type>
+ inline value_reference
+ (const typename impl::debug_info_entry::children_type::iterator &i,
+ const arg_type &arg)
+ : ref (i)
+ {}
+
+ template<typename iter, typename arg_type> // XXX dummy
+ inline value_reference (const iter &i, const arg_type &arg)
+ : ref () {}
+ };
+
+ struct value_unit_reference : public value_dispatch
+ {
+ typename impl::compile_units::iterator ref;
+
+ template<typename arg_type>
+ inline value_unit_reference
+ (const typename impl::compile_units::iterator &i,
+ const arg_type &arg)
+ : ref (i)
+ {}
+
+ template<typename iter, typename arg_type> // XXX dummy
+ inline value_unit_reference (const iter &i, const arg_type &arg)
+ : ref ()
+ {}
+ };
+
+ struct value_flag : public value_dispatch
+ {
+ bool flag;
+
+ inline value_flag ()
+ : flag (true)
+ {}
+
+ template<typename arg_type>
+ inline value_flag (bool t, const arg_type &arg)
+ : flag (t)
+ {}
+ };
+
+ struct value_address : public value_dispatch
+ {
+ // XXX dwfl, reloc
+ ::Dwarf_Addr addr;
+
+ inline value_address ()
+ : addr (0)
+ {}
+
+ template<typename arg_type>
+ inline value_address (::Dwarf_Addr x, const arg_type &arg)
+ : addr (x)
+ {}
+ };
+
+ struct value_rangelistptr : public value_dispatch, public range_list
+ {
+ inline value_rangelistptr () {}
+
+ template<typename list, typename arg_type>
+ inline value_rangelistptr (const list &other, const arg_type &arg)
+ : range_list (other)
+ {}
+ };
+
+ struct value_lineptr : public value_dispatch, public impl::line_info_table
+ {
+ inline value_lineptr () {}
+
+ template<typename table, typename arg_type>
+ inline value_lineptr (const table &other, const arg_type &arg)
+ : impl::line_info_table (other)
+ {}
+ };
+
+ struct value_constant : public value_dispatch
+ {
+ union
+ {
+ ::Dwarf_Word word;
+ ::Dwarf_Sword sword;
+ };
+
+ inline value_constant ()
+ : word (0)
+ {}
+
+ template<typename arg_type>
+ inline value_constant (::Dwarf_Word x, const arg_type &arg)
+ : word (x)
+ {}
+ };
+
+ struct value_constant_block : public value_dispatch,
+ public std::vector<uint8_t>
+ {
+ inline value_constant_block () {}
+
+ template<typename block, typename arg_type>
+ inline value_constant_block (const block &b, const arg_type &arg)
+ : std::vector<uint8_t> (b.begin (), b.end ())
+ {}
+ };
+
+ struct value_dwarf_constant : public value_dispatch, public dwarf_enum
+ {
+ inline value_dwarf_constant () {}
+
+ template<typename constant, typename arg_type>
+ inline value_dwarf_constant (const constant &other, const arg_type &arg)
+ : dwarf_enum (other)
+ {}
+ };
+
+ struct value_source_file : public value_dispatch, public source_file
+ {
+ inline value_source_file () {}
+
+ template<typename file, typename arg_type>
+ inline value_source_file (const file &other, const arg_type &arg)
+ : source_file (other)
+ {}
+ };
+
+ struct value_source_line : public value_dispatch
+ {
+ unsigned int n;
+
+ inline value_source_line ()
+ : n (0)
+ {}
+
+ template<typename arg_type>
+ inline value_source_line (unsigned int m, const arg_type &arg)
+ : n (m)
+ {}
+ };
+ typedef value_source_line value_source_column;
+
+ struct value_macptr : public value_dispatch {};
+
+ struct value_location : public value_dispatch, public location_attr
+ {
+ inline value_location () {}
+
+ template<typename loc, typename arg_type>
+ inline value_location (const loc &other, const arg_type &arg)
+ : location_attr (other)
+ {}
+ };
+ };
+
+ template<class impl, typename vw = value<impl> >
+ class attr_value
+ {
+ private:
+ typename vw::value_dispatch *_m_value;
+
+ template<typename value, typename arg_type = nothing>
+ struct init
+ {
+ inline init (attr_value *av,
+ const value &other, const arg_type &arg = arg_type ())
+ {
+ switch (other.what_space ())
+ {
+#define _DWARF_DATA_AV_MAKE(flavor, fetch) \
+ case dwarf::VS_##flavor: \
+ { \
+ typename vw::value_##flavor *p; \
+ av->_m_value = vw::make (p, other.fetch (), arg); \
+ } \
+ break
+
+ _DWARF_DATA_AV_MAKE (identifier, identifier);
+ _DWARF_DATA_AV_MAKE (string, string);
+ _DWARF_DATA_AV_MAKE (flag, flag);
+ _DWARF_DATA_AV_MAKE (rangelistptr, ranges);
+ _DWARF_DATA_AV_MAKE (lineptr, line_info);
+ _DWARF_DATA_AV_MAKE (address, address);
+ _DWARF_DATA_AV_MAKE (source_line, source_line);
+ _DWARF_DATA_AV_MAKE (source_file, source_file);
+ _DWARF_DATA_AV_MAKE (dwarf_constant, dwarf_constant);
+ _DWARF_DATA_AV_MAKE (reference, reference);
+ _DWARF_DATA_AV_MAKE (unit_reference, unit_reference);
+ _DWARF_DATA_AV_MAKE (location, location);
+ //_DWARF_DATA_AV_MAKE (macptr, macros); XXX
+
+ case dwarf::VS_constant:
+ if (other.constant_is_integer ())
+ {
+ typename vw::value_constant *p;
+ av->_m_value = vw::make (p, other.constant (), arg);
+ }
+ else
+ {
+ typename vw::value_constant_block *p;
+ av->_m_value = vw::make (p, other.constant_block (), arg);
+ }
+ break;
+
+ default:
+ case dwarf::VS_discr_list:
+ throw std::runtime_error ("XXX unimplemented");
+
+#undef _DWARF_DATA_AV_MAKE
+ }
+ }
+ };
+
+ template<typename flavor>
+ inline flavor &const_variant () const
+ {
+ flavor *p = dynamic_cast<flavor *> (_m_value);
+ if (p == NULL)
+ throw std::runtime_error ("wrong value type");
+ return *p;
+ }
+
+ template<typename flavor>
+ inline flavor &variant () const
+ {
+ return const_variant<flavor> ();
+ }
+
+ template<typename flavor>
+ inline flavor &variant ()
+ {
+ if (_m_value == NULL)
+ _m_value = new flavor;
+ return const_variant<flavor> ();
+ }
+
+ public:
+ attr_value (const attr_value &other)
+ : _m_value (NULL)
+ {
+ if (other._m_value != NULL)
+ init<attr_value> me (this, other);
+ }
+
+ template<typename value, typename arg_type>
+ attr_value (const value &other, const arg_type &arg)
+ : _m_value (NULL)
+ {
+ init<value, arg_type> me (this, other, arg);
+ }
+
+ inline 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<attr_value> me (this, other);
+ return *this;
+ }
+ template<typename value>
+ inline attr_value &operator= (const value &other)
+ {
+ if (_m_value != NULL)
+ {
+ delete _m_value;
+ _m_value = NULL;
+ }
+ init<value> me (this, other);
+ return *this;
+ }
+
+ dwarf::value_space what_space () const;
+ inline std::string to_string () const;
+
+ inline bool &flag () const
+ {
+ return variant<typename vw::value_flag> ().flag;
+ }
+
+ // XXX dwfl, reloc
+ inline ::Dwarf_Addr &address () const
+ {
+ return variant<typename vw::value_address> ().addr;
+ }
+
+ inline typename impl::debug_info_entry::children_type::iterator
+ reference () const
+ {
+ return variant<typename vw::value_reference> ().ref;
+ }
+ inline typename impl::compile_units::iterator
+ unit_reference () const
+ {
+ return variant<typename vw::value_unit_reference> ().ref;
+ }
+
+ inline location_attr &location () const
+ {
+ return static_cast<location_attr &>
+ (variant<typename vw::value_location> ());
+ }
+
+ inline std::string &string ()
+ {
+ return static_cast<std::string &>
+ (variant<typename vw::value_string> ());
+ }
+ inline const std::string &string () const
+ {
+ return static_cast<const std::string &>
+ (variant<typename vw::value_string> ());
+ }
+ inline std::string &identifier ()
+ {
+ return string ();
+ }
+ inline const std::string &identifier () const
+ {
+ return string ();
+ }
+
+ inline const typename impl::source_file &source_file () const
+ {
+ return static_cast<typename impl::source_file &>
+ (variant<typename vw::value_source_file> ());
+ }
+
+ inline typename impl::source_file &source_file ()
+ {
+ return static_cast<typename impl::source_file &>
+ (variant<typename vw::value_source_file> ());
+ }
+
+ inline const unsigned int &source_line () const
+ {
+ return variant<typename vw::value_source_line> ().n;
+ }
+
+ inline unsigned int &source_line ()
+ {
+ return variant<typename vw::value_source_line> ().n;
+ }
+
+ inline const unsigned int &source_column () const
+ {
+ return variant<typename vw::value_source_column> ().n;
+ }
+
+ inline unsigned int &source_column ()
+ {
+ return variant<typename vw::value_source_column> ().n;
+ }
+
+ inline const ::Dwarf_Word &constant () const
+ {
+ return variant<typename vw::value_constant> ().word;
+ }
+
+ inline ::Dwarf_Word &constant ()
+ {
+ return variant<typename vw::value_constant> ().word;
+ }
+
+ inline const ::Dwarf_Sword &signed_constant () const
+ {
+ return variant<typename vw::value_constant> ().sword;
+ }
+
+ inline ::Dwarf_Sword &signed_constant ()
+ {
+ return variant<typename vw::value_constant> ().sword;
+ }
+
+ inline const std::vector<uint8_t> &constant_block () const
+ {
+ return static_cast<std::vector<uint8_t> &>
+ (variant<typename vw::value_constant_block> ());
+ }
+
+ inline std::vector<uint8_t> &constant_block ()
+ {
+ return static_cast<std::vector<uint8_t> &>
+ (variant<typename vw::value_constant_block> ());
+ }
+
+ inline const typename impl::dwarf_enum &dwarf_constant () const
+ {
+ return variant<typename vw::value_dwarf_constant> ();
+ }
+
+ inline typename impl::dwarf_enum &dwarf_constant ()
+ {
+ return variant<typename vw::value_dwarf_constant> ();
+ }
+
+ inline bool constant_is_integer () const
+ {
+ return dynamic_cast<typename vw::value_constant *> (_m_value) != NULL;
+ }
+
+ inline const typename impl::range_list &ranges () const
+ {
+ return static_cast<range_list &>
+ (variant<typename vw::value_rangelistptr> ());
+ }
+
+ inline typename impl::range_list &ranges ()
+ {
+ return static_cast<range_list &>
+ (variant<typename vw::value_rangelistptr> ());
+ }
+
+ inline const typename impl::line_info_table &line_info () const
+ {
+ return static_cast<typename impl::line_info_table &>
+ (variant<typename vw::value_lineptr> ());
+ }
+
+ inline typename impl::line_info_table &line_info ()
+ {
+ return static_cast<typename impl::line_info_table &>
+ (variant<typename vw::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);
+ }
+ };
+
+ template<class impl, typename arg = nothing, typename v = value<impl> >
+ class attributes_type
+ : public std::map<int, attr_value<impl, v> >
+ {
+ friend class impl::debug_info_entry;
+ private:
+ typedef std::map<int, attr_value<impl, v> > base_type;
+
+ protected:
+ inline attributes_type () {}
+
+ public: // XXX should be protected
+ template<typename input, typename arg_type>
+ inline attributes_type (const input &other, const arg_type &c)
+ : base_type (subr::argify2nd<input, attributes_type, arg_type>
+ (other.begin (), c),
+ subr::argify2nd<input, attributes_type, arg_type>
+ (other.end (), c))
+ {}
+
+ public:
+ typedef typename base_type::key_type key_type;
+ typedef typename base_type::value_type value_type;
+ typedef typename base_type::mapped_type mapped_type;
+
+ static const bool ordered = true;
+
+ template<typename attrs>
+ inline operator attrs () const
+ {
+ return attrs (base_type::begin (), base_type::end ());
+ }
+ };
+
+ };
+
+ // 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, typename v>
+ inline std::string dwarf_data::attr_value<impl, v>::to_string () const
+ {
+ return elfutils::to_string (*this); // Use that.
+ }
+
+};
+
+#endif
#define _ELFUTILS_DWARF_EDIT 1
#include "dwarf"
-#include <bitset>
+#include "dwarf_data"
+#include "dwarf_tracker"
/* 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
{
private:
children_type () {}
- template<typename childrens>
- children_type (const childrens &other)
- : std::list<debug_info_entry> (other.begin (), other.end ()) {}
+ template<typename input, typename tracker>
+ children_type (const input &other, tracker *t)
+ : std::list<debug_info_entry>
+ (subr::argify<input, children_type, tracker *> (other.begin (), t),
+ subr::argify<input, children_type, tracker *> (other.end (), t))
+ {}
public:
typedef debug_info_entry value_type;
+
+ inline debug_info_entry &add_entry (int tag)
+ {
+ push_back (debug_info_entry (tag));
+ return back ();
+ }
};
- class attributes_type : public std::map<int, attr_value>
+ class attributes_type
+ : public dwarf_data::attributes_type<dwarf_edit>
{
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 ()) {}
+ typedef dwarf_data::attributes_type<dwarf_edit> base_type;
- 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;
+ inline attributes_type () {}
- template<typename attrs>
- inline operator attrs () const
- {
- return attrs (begin (), end ());
- }
+ template<typename attrs, typename tracker>
+ inline attributes_type (const attrs &other, tracker *t)
+ : base_type (other, t)
+ {}
};
private:
/* 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)
+ template<typename die_type, typename tracker>
+ debug_info_entry (const die_type &die, tracker *t)
: _m_tag (die.tag ()),
- _m_attributes (die.attributes ()),
- _m_children (die.children ())
+ _m_attributes (die.attributes (), t),
+ _m_children (die.children (), t)
{}
inline int tag () const
{
return identity ();
}
+
+ // Convenience entry points.
+ inline debug_info_entry &add_entry (int child_tag)
+ {
+ return children ().add_entry (child_tag);
+ }
};
typedef debug_info_entry::attributes_type::value_type attribute;
// XXX should be private
public:
- template<typename die_type>
- compile_unit (const die_type &die) : debug_info_entry (die)
+ template<typename die_type, typename tracker>
+ inline compile_unit (const die_type &die, tracker *t)
+ : debug_info_entry (die, t)
{
if (die.tag () != ::DW_TAG_compile_unit)
throw std::invalid_argument ("not a compile_unit entry");
typedef std::list<compile_unit> _base;
// Default constructor: an empty container, no CUs.
- inline compile_units () {}
+ inline compile_units ()
+ {}
// Constructor copying CUs from input container.
- template<typename input>
- compile_units(const input &units)
- : _base (units.begin (), units.end ()) {}
+ template<typename input, typename tracker>
+ inline compile_units (const input &units, tracker *t)
+ : _base (subr::argify<input, compile_units, tracker *>
+ (units.begin (), t),
+ subr::argify<input, compile_units, tracker *>
+ (units.end (), t))
+ {}
public:
typedef compile_unit value_type;
typedef _base::iterator iterator;
typedef _base::const_iterator const_iterator;
- inline compile_unit &new_unit ()
+ inline compile_unit &add_unit ()
{
- compile_unit nu;
- push_back (nu);
+ push_back (compile_unit ());
return back ();
}
}
};
- // 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;
return _m_units;
}
+ // Convenience entry point.
+ inline compile_unit &add_unit ()
+ {
+ return compile_units ().add_unit ();
+ }
+
public:
// Default constructor: an empty container, no CUs.
inline dwarf_edit () {}
// Constructor copying CUs from an input file (dwarf or dwarf_edit).
- template<typename input>
- dwarf_edit (const input &dw) : _m_units (dw.compile_units ()) {}
+ template<typename input, typename tracker>
+ dwarf_edit (const input &dw, tracker *t)
+ : _m_units (dw.compile_units (), t)
+ {}
template<typename file>
inline bool operator== (const file &other) const
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"
+#include <functional>
/* Read the comments for elfutils::dwarf first.
namespace elfutils
{
+ class dwarf_output_collector;
+
+#if 0
class dwarf_output
{
public:
class compile_units;
+ class debug_info_entry;
+ typedef debug_info_entry compile_unit;
+
+ private:
+ template<typename input>
+ static inline const input &
+ collect (dwarf_output_collector *c,
+ const subr::auto_ref<const input> &p)
+ {
+ return static_cast<const input &> (p);
+ }
+
+ template<typename input>
+ static inline const debug_info_entry &
+ collect (dwarf_output_collector *,
+ const typename input::debug_info_entry &);
+
+ public:
// XXX later
class attr_value : public dwarf::attr_value
class debug_info_entry
{
+ friend class dwarf_output;
+
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_type _m_attributes;
+ const children_type _m_children;
+ size_t _m_hash;
- class children : public std::vector<debug_info_entry>
+ /* 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, dwarf_output_collector *c)
+ : _m_tag (die.tag ()),
+ _m_attributes (die.attributes ()),
+ _m_children (die.children ()),
+ _m_hash (0)
{
- friend class debug_info_entry;
- private:
- children () {}
+ subr::hash_combine (_m_hash, _m_tag);
+ subr::hash_combine (_m_hash, _m_attributes);
+ subr::hash_combine (_m_hash, _m_children);
+ }
+
+ public:
+ inline int tag () const
+ {
+ return _m_tag;
+ }
+
+ inline bool has_children () const
+ {
+ return !_m_children.empty ();
+ }
+
+ inline const children_type &children () const
+ {
+ return _m_children;
+ }
+
+ inline const attributes_type &attributes () const
+ {
+ return _m_attributes;
+ }
+
+ template<typename die>
+ bool operator== (const die &other) const
+ {
+ return (other.attributes () == attributes ()
+ && other.children () == children ());
+ }
+ template<typename die>
+ bool operator!= (const die &other) const
+ {
+ return !(*this == other);
+ }
+ };
+
+ typedef debug_info_entry::attributes_type::value_type attribute;
+
+ public:
+ /* Main container anchoring all the output.
+
+ This is the only container that actually lives in the dwarf_output
+ object. All others live in the dwarf_output_collector's sets, and
+ we return const references to those copies.
+
+ This vector is actually mutable as a std::vector. But note that you
+ should never remove a compile_unit, though you can reorder the
+ vector. Nothing is ever removed from the collector, so your final
+ output file can wind up with unreferenced data being encoded. If
+ you do remove any elements, then you should start a fresh collector
+ and construct a new dwarf_output object by copying using that
+ collector (or, equivalently, call o.compile_units ().recollect (C)
+ on the new collector C). */
+ class compile_units
+ : public std::vector<subr::auto_ref<const debug_info_entry> >
+ {
+ friend class dwarf_output;
+ private:
+ typedef std::vector<subr::auto_ref<const debug_info_entry> > _base;
+
+ template<typename input>
+ struct make
+ : public std::binary_function<typename input::value_type,
+ dwarf_output_collector *,
+ _base::value_type>
+ {
+ _base::value_type operator () (const typename input::value_type &cu,
+ dwarf_output_collector *c) const
+ {
+ return _base::value_type (collect (c, cu));
+ }
+ };
+
+ // Construct empty container.
+ compile_units ()
+ : _base ()
+ {}
+
+ // Constructor copying CUs from input container.
+ template<typename input>
+ compile_units (const input &units, dwarf_output_collector *c)
+ : _base ()
+ {
+ for (typename input::const_iterator it = units.begin ();
+ it != units.end ();
+ ++it)
+ push_back (make<input> () (*it, c));
+ }
+
+ public:
+ 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);
+ }
+
+ void recollect (dwarf_output_collector *c)
+ {
+ std::transform (begin (), end (), begin (),
+ std::bind2nd (make<compile_units> (), c));
+ }
+ };
+
+ private:
+ const compile_units _m_units;
+
+ public:
+ 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 childrens>
- children (const childrens &other)
- : std::vector<debug_info_entry> (other.begin (), other.end ()) {}
+ 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);
+ }
+ };
+
+#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;
+
+ class compile_units;
+ class debug_info_entry;
+
+ protected:
+
+ template<typename input>
+ static inline const std::string &
+ collect_string (dwarf_output_collector *, const input &);
+
+ /* 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>
+ static inline typename subr::argifier<input, output,
+ dwarf_output_collector *>::wrapped
+ collectify (const typename input::const_iterator &in,
+ dwarf_output_collector *c)
+ {
+ return subr::argifier<input, output, dwarf_output_collector *> (c) (in);
+ }
+
+ struct value_wrapper
+ : public dwarf_data::value<dwarf_output>
+ {
+ struct value_string : public value_dispatch
+ {
+ const std::string &_m_str;
+
+ template<typename string>
+ inline value_string (const string &s, dwarf_output_collector *c)
+ : _m_str (collect_string (c, s))
+ {}
+
+ inline operator const std::string & () const
+ {
+ return _m_str;
+ }
+
+ std::string to_string () const
+ {
+ std::string result ("\"");
+ result += _m_str;
+ result += "\"";
+ return result;
+ }
};
- class attributes : public std::map<int, attr_value>
+ template<typename flavor, typename input>
+ static inline value_dispatch *
+ make (flavor *&result, const input &x, const dwarf_data::nothing &)
+ {
+ throw std::logic_error ("dwarf_output cannot be default-constructed");
+ }
+
+ template<typename flavor, typename input, typename arg_type>
+ static inline value_dispatch *
+ make (flavor *&result, const input &x, const arg_type &arg)
+ {
+ return result = new flavor (x, arg);
+ }
+
+ template<typename input>
+ static inline value_dispatch *
+ make (value_string *&result, const input &x, dwarf_output_collector *c)
+ {
+ return result = new value_string (x, c);
+ }
+
+ };
+
+ public:
+
+ typedef dwarf_data::attr_value<dwarf_output, value_wrapper> attr_value;
+
+ class compile_units;
+
+ class debug_info_entry
+ {
+ public:
+
+ class children_type : public std::list<debug_info_entry>
{
friend class debug_info_entry;
private:
- attributes () {}
+ children_type () {}
- template<typename attrs>
- attributes (const attrs &other)
- : std::map<int, attr_value> (other.begin (), other.end ()) {}
+ template<typename input>
+ inline children_type (const input &other, dwarf_output_collector *c)
+ : std::list<debug_info_entry>
+ (collectify<input, children_type> (other.begin (), c),
+ collectify<input, children_type> (other.end (), c))
+ {}
public:
- template<typename attrs>
- inline operator attrs () const
- {
- return attrs (begin (), end ());
- }
+ typedef debug_info_entry value_type;
+ };
+
+ class attributes_type
+ : public dwarf_data::attributes_type<dwarf_output,
+ dwarf_output_collector *,
+ value_wrapper>
+ {
+ friend class debug_info_entry;
+ private:
+ typedef dwarf_data::attributes_type<dwarf_output,
+ dwarf_output_collector *,
+ value_wrapper> base_type;
+
+ template<typename input>
+ inline attributes_type (const input &other, dwarf_output_collector *c)
+ : base_type (other, c)
+ {}
};
private:
const int _m_tag;
- const attributes _m_attributes;
- const children _m_children;
+ attributes_type _m_attributes;
+ children_type _m_children;
public:
- /* The template constructor lets us copy in from any class that has
- compatibly iterable containers for attributes and children. */
- template<typename die>
- debug_info_entry (const die &die)
+ template<typename die_type>
+ debug_info_entry (const die_type &die, dwarf_output_collector *c)
: _m_tag (die.tag ()),
- _m_attributes (die.attributes ()),
- _m_children (die.children ())
+ _m_attributes (die.attributes (), c),
+ _m_children (die.children (), c)
{}
inline int tag () const
return !_m_children.empty ();
}
- inline class children &children ()
+ inline children_type &children ()
{
return _m_children;
}
- inline const class children &children () const
+ inline const children_type &children () const
{
return _m_children;
}
- inline class attributes &attributes ()
+ inline attributes_type &attributes ()
{
return _m_attributes;
}
- inline const class attributes &attributes () const
+ inline const attributes_type &attributes () const
{
return _m_attributes;
}
template<typename die>
bool operator== (const die &other) const
{
- return (other.attributes () == attributes ()
+ return (other.tag () == tag ()
+ && other.attributes () == attributes ()
&& other.children () == children ());
}
template<typename die>
{
return !(*this == other);;
}
+
+ inline ::Dwarf_Off identity () const
+ {
+ return (uintptr_t) this;
+ }
+
+ inline ::Dwarf_Off offset () const
+ {
+ return identity ();
+ }
};
- typedef debug_info_entry::attributes::value_type attribute;
+ typedef debug_info_entry::attributes_type::value_type attribute;
class compile_unit : public debug_info_entry
{
+ friend class compile_units;
+
+ // XXX should be private
+ public:
+ template<typename die_type>
+ compile_unit (const die_type &die, dwarf_output_collector *c)
+ : debug_info_entry (die, c)
+ {
+ 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::vector<compile_unit>
+ 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)
- : std::vector<compile_unit> (units.begin (), units.end ())
- {}
+ compile_units (const input &units, dwarf_output_collector *c)
+ : _base (collectify<input, compile_units> (units.begin (), c),
+ collectify<input, compile_units> (units.end (), c))
+ {
+ }
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 std::equal (begin (), end (), other.begin ());
+ return subr::container_equal (*this, other);
}
template<typename other_children>
bool operator!= (const other_children &other) const
};
private:
- const compile_units _m_units;
+ 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 copying CUs from an input file (dwarf or dwarf_output).
+ // 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) : _m_units (dw.compile_units ()) {}
+ 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 !(*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<std::string> _m_strings;
+ subr::value_set<dwarf_output::range_list> _m_ranges;
+
+ };
+
+ template<typename input>
+ inline const std::string &
+ dwarf_output::collect_string (dwarf_output_collector *c, const input &s)
+ {
+ return c->_m_strings.add (s);
+ }
+
+};
+
+#endif // <elfutils/dwarf_output>
#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_edit::attr_value::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_output::attr_value::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 <cstring>
#include <iostream>
#include <sstream>
+#include <tr1/unordered_map>
+#include <tr1/unordered_set>
+#include <vector>
+#include <algorithm>
+#include <utility>
namespace elfutils
{
namespace subr
{
+ template<typename T>
+ struct hash : public T::hasher {};
+
+ template<typename T>
+ static inline size_t hash_this (const T &v)
+ {
+ return hash<T> () (v);
+ }
+
+ template <typename T>
+ inline void hash_combine (size_t &seed, const T &v)
+ {
+ seed ^= hash_this (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, hash_this (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) const
+ {
+ return v._m_hash;
+ }
+ };
+
template<typename string>
struct name_equal : public std::binary_function<const char *, string, bool>
{
template<typename mystring>
- inline bool operator () (const mystring &me, const string &you)
+ inline bool operator () (const mystring &me, const string &you) const
{
return you == me;
}
struct name_equal<const char *>
: public std::binary_function<const char *, const char *, bool>
{
- bool operator () (const char *me, const char *you)
+ bool operator () (const char *me, const char *you) const
{
return !strcmp (me, you);
}
template<typename mystring>
- inline bool operator () (const mystring &me, const char *you)
+ inline bool operator () (const mystring &me, const char *you) const
{
return me == you;
}
template<typename t1, typename t2>
struct equal_to : public std::binary_function<t1, t2, bool>
{
- inline bool operator () (const t1 &a, const t2 &b)
+ inline bool operator () (const t1 &a, const t2 &b) const
{
return a == b;
}
{}
inline bool operator () (const typename t1::const_iterator &a,
- const typename t2::const_iterator &b)
+ const typename t2::const_iterator &b) const
{
return _m_pred (*a, *b);
}
return indexed_iterator (_m_contents, _m_idx--);
}
};
+
+ // Pair of some value and its precomputed hash.
+ template<typename T>
+ class hashed_value
+ : public std::pair<size_t, const T>
+ {
+ private:
+ typedef std::pair<size_t, const T> _base;
+
+ public:
+ typedef T value_type;
+
+ struct hasher
+ : public std::unary_function<hashed_value, size_t>
+ {
+ inline size_t operator () (const hashed_value &v) const
+ {
+ return v.first;
+ }
+ };
+
+ hashed_value (const value_type &v)
+ : _base (hash_this (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.
+ template<typename value_type>
+ class value_set
+ : public std::tr1::unordered_set<hashed_value<value_type>,
+ struct hashed_value<value_type>::hasher>
+ {
+ public:
+ typedef hashed_value<value_type> hashed_value_type;
+
+ private:
+ typedef std::tr1::unordered_set<hashed_value_type,
+ struct hashed_value_type::hasher> _base;
+
+ public:
+ const value_type &add (const value_type &v)
+ {
+ std::pair<class _base::iterator, bool> p
+ = _base::insert (hashed_value_type (v));
+ if (p.second)
+ {
+ // XXX hook for collection: abbrev building, etc.
+ }
+ return p.first->second;
+ };
+
+ template<typename input>
+ const value_type &add (const input &v)
+ {
+ return add (value_type (v));
+ }
+ };
+
+ // 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 container _base;
+ typedef typename container::value_type elt_type;
+
+ public:
+ typedef typename elt_type::value_type value_type;
+
+ private:
+ size_t _m_hash;
+
+ inline void set_hash ()
+ {
+ struct hashit
+ {
+ size_t &_m_hash;
+ hashit (size_t &h) : _m_hash (h) {}
+ inline void operator () (const elt_type &p)
+ {
+ subr::hash_combine (_m_hash, p.first);
+ }
+ };
+ std::for_each (_base::begin (), _base::end (), hashit (_m_hash));
+ }
+
+ 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_container &other) const
+ {
+ return (other._m_hash == _m_hash &&
+ other.size () == _base::size ()
+ && std::equal (_base::begin (), _base::end (), other.begin ()));
+ }
+ };
+
+ // 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,
+ hashed_value<value_type>,
+ class hashed_value<value_type>::hasher>
+ {
+ private:
+ typedef std::tr1::unordered_map<key_type,
+ hashed_value<value_type>,
+ class hashed_value<value_type>::hasher>
+ _base;
+
+ size_t _m_hash;
+
+ inline void set_hash ()
+ {
+ struct hashit
+ {
+ size_t &_m_hash;
+ hashit (size_t &h) : _m_hash (h) {}
+
+ inline void operator () (const typename _base::value_type &p)
+ {
+ subr::hash_combine (_m_hash, hash_this (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)
+ : _base (other.begin (), other.end ()), _m_hash (0)
+ {
+ set_hash ();
+ }
+ };
+#endif
+
+ template<typename T>
+ class auto_ref
+ {
+ private:
+ T *_m_ptr;
+
+ public:
+ auto_ref (const T &other)
+ : _m_ptr (&other)
+ {}
+
+ inline operator T& () const
+ {
+ return *_m_ptr;
+ }
+
+ 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* ());
+ }
+ };
+
+ /* 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, typename arg_type>
+ struct argifier
+ : 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>
+ {
+ arg_type _m_arg;
+ explicit inline maker (const arg_type &c) : _m_arg (c) {}
+
+ inline outlet operator () (const inlet &x) const
+ {
+ return outlet (x, _m_arg);
+ }
+ } _m_maker;
+
+ explicit inline argifier (const arg_type &c)
+ : _m_maker (c)
+ {}
+
+ typedef subr::wrapped_input_iterator<input, maker> wrapped;
+
+ inline wrapped operator () (const inny &i)
+ {
+ return wrapped (i, _m_maker);
+ }
+ };
+
+ template<typename input, typename output, typename arg_type>
+ static inline typename argifier<input, output, arg_type>::wrapped
+ argify (const typename input::const_iterator &in, const arg_type &arg)
+ {
+ return argifier<input, output, arg_type> (arg) (in);
+ }
+
+ template<typename input, typename output, typename arg_type>
+ struct argifier2nd
+ : 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>
+ {
+ arg_type _m_arg;
+ explicit inline maker (const arg_type &c) : _m_arg (c) {}
+
+ inline outlet operator () (const inlet &x) const
+ {
+ return std::make_pair (x.first,
+ typename outlet::second_type (x.second,
+ _m_arg));
+ }
+ } _m_maker;
+
+ explicit inline argifier2nd (const arg_type &c)
+ : _m_maker (c)
+ {}
+
+ typedef subr::wrapped_input_iterator<input, maker> wrapped;
+
+ inline wrapped operator () (const inny &i)
+ {
+ return wrapped (i, _m_maker);
+ }
+ };
+
+ template<typename input, typename output, typename arg_type>
+ static inline typename argifier2nd<input, output, arg_type>::wrapped
+ argify2nd (const typename input::const_iterator &in, const arg_type &arg)
+ {
+ return argifier2nd<input, output, arg_type> (arg) (in);
+ }
+
};
};
#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) \
+2009-07-02 Roland McGrath <roland@redhat.com>
+
+ * dwarfcmp.cc (main): Update -T constructors using tracker.
+ Instantiate and test dwarf_output for -T too.
+
2009-07-01 Roland McGrath <roland@redhat.com>
* dwarfcmp.cc (talker): Update constructor parameters.
#include "c++/dwarf_edit"
#include "c++/dwarf_comparator"
#include "c++/dwarf_tracker"
+#include "c++/dwarf_output"
using namespace elfutils;
using namespace std;
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_;
if (test_writer)
{
- dwarf_edit out1 (file1);
- dwarf_edit out2 (file2);
- test_classes (file1, file2, out1, out2, same);
+ dwarf_ref_tracker<dwarf_edit, dwarf> t1;
+ dwarf_ref_tracker<dwarf_edit, dwarf> t2;
+ dwarf_edit edit1 (file1, &t1);
+ dwarf_edit edit2 (file2, &t2);
+ test_classes (file1, file2, edit1, edit2, same);
+
+ {
+ dwarf_output_collector c1;
+ dwarf_output_collector c2;
+ dwarf_output out1 (file1, &c1);
+ dwarf_output out2 (file2, &c2);
+ test_classes (file1, file2, out1, out2, same);
+ test_classes (edit1, edit2, out1, out2, same);
+ }
+ {
+ dwarf_output_collector c1;
+ dwarf_output_collector c2;
+ dwarf_output out1 (edit1, &c1);
+ dwarf_output out2 (edit2, &c2);
+ test_classes (file1, file2, out1, out2, same);
+ test_classes (edit1, edit2, out1, out2, same);
+ }
}
result = !same;
+2009-07-02 Roland McGrath <roland@redhat.com>
+
+ * run-dwarf_edit.sh: New file.
+ * dwarf_edit.cc: New file.
+ * Makefile.am (noinst_PROGRAMS, TESTS, EXTRA_DIST): Add them.
+ (dwarf_edit_SOURCES, dwarf_edit_LDADD): New variables.
+
+ * dwarf-print.cc (print_die): Templatify and move ...
+ * print-die.hh: ... here, new file.
+ * Makefile.am (noinst_HEADERS): New variable, add it.
+
2009-07-01 Roland McGrath <roland@redhat.com>
* run-dwarfcmp-self.sh: Run on dwarflint too.
tests_rpath = no
endif
+noinst_HEADERS = print-die.hh
+
noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
showptable update1 update2 update3 update4 test-nlist \
show-die-info get-files get-lines get-pubnames \
find-prologues funcretval allregs rdwrmmap \
dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \
dwfl-addr-sect dwfl-bug-report early-offscn \
- dwfl-bug-getmodules dwarf-getmacros dwarf-print
+ dwfl-bug-getmodules dwarf-getmacros dwarf-print \
+ dwarf_edit
# get-ciefde
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
run-dwfl-bug-offline-rel.sh run-dwfl-addr-sect.sh \
run-disasm-x86.sh run-disasm-x86-64.sh \
run-early-offscn.sh run-dwarf-getmacros.sh \
- run-dwarfcmp-self.sh run-dwarflint-self.sh run-dwarf-attributes.sh
+ run-dwarfcmp-self.sh run-dwarflint-self.sh run-dwarf-attributes.sh \
+ run-dwarf_edit.sh
# run-show-ciefde.sh
if !STANDALONE
run-dwfl-addr-sect.sh run-early-offscn.sh \
run-dwarf-getmacros.sh \
run-dwarfcmp-self.sh run-dwarflint-self.sh \
- run-dwarf-attributes.sh \
+ run-dwarf-attributes.sh run-dwarf_edit.sh \
testfile15.bz2 testfile15.debug.bz2 \
testfile16.bz2 testfile16.debug.bz2 \
testfile17.bz2 testfile17.debug.bz2 \
dwarf_print_SOURCES = dwarf-print.cc
dwarf_print_LDADD = $(libdwpp) $(libmudflap) -ldl
+dwarf_edit_SOURCES = dwarf_edit.cc
+dwarf_edit_LDADD = $(libdwpp) $(libmudflap) -ldl
+
arextract_LDADD = $(libelf) $(libmudflap)
arsymtest_LDADD = $(libelf) $(libmudflap)
newfile_LDADD = $(libelf) $(libmudflap)
#include <errno.h>
#include <error.h>
#include <fcntl.h>
-#include <clocale>
-#include <cstdio>
-#include <libintl.h>
-#include <ostream>
-#include <iomanip>
#include "c++/dwarf"
using namespace elfutils;
using namespace std;
+#include "print-die.hh"
+
static Dwarf *
open_file (const char *fname)
{
return dw;
}
-static void
-print_die (const dwarf::debug_info_entry &die,
- unsigned int indent, unsigned int limit)
-{
- string prefix (indent, ' ');
- const string tag = dwarf::tags::name (die.tag ());
-
- cout << prefix << "<" << tag << " offset=[" << die.offset () << "]";
-
- for (dwarf::debug_info_entry::attributes_type::const_iterator i
- = die.attributes ().begin (); i != die.attributes ().end (); ++i)
- cout << " " << (*i).to_string ();
-
- if (die.has_children ())
- {
- if (limit != 0 && indent >= limit)
- {
- cout << ">...\n";
- return;
- }
-
- cout << ">\n";
-
- for (dwarf::debug_info_entry::children_type::const_iterator i
- = die.children ().begin (); i != die.children ().end (); ++i)
- print_die (*i, indent + 1, limit);
-
- cout << prefix << "</" << tag << ">\n";
- }
- else
- cout << "/>\n";
-}
-
-static void
-process_file (const char *file, unsigned int limit)
-{
- dwarf dw (open_file (file));
-
- cout << file << ":\n";
-
- for (dwarf::compile_units::const_iterator i = dw.compile_units ().begin ();
- i != dw.compile_units ().end ();
- ++i)
- print_die (*i, 1, limit);
-}
-
int
main (int argc, char *argv[])
{
- /* Set locale. */
- (void) setlocale (LC_ALL, "");
-
- /* Make sure the message catalog can be found. */
- (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
-
- /* Initialize the message catalog. */
- (void) textdomain (PACKAGE_TARNAME);
-
- cout << hex << setiosflags (ios::showbase);
-
- unsigned int depth = 0;
- if (argc > 1 && sscanf (argv[1], "--depth=%u", &depth) == 1)
- {
- --argc;
- ++argv;
- }
+ unsigned int depth;
+ print_die_main (argc, argv, depth);
for (int i = 1; i < argc; ++i)
- process_file (argv[i], depth);
+ print_file (argv[i], dwarf (open_file (argv[i])), depth);
return 0;
}
--- /dev/null
+/* Test program for elfutils::dwarf_edit basics.
+ 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.
+
+ 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>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "c++/dwarf_edit"
+
+using namespace elfutils;
+using namespace std;
+
+#include "print-die.hh"
+
+
+int
+main (int argc, char **argv)
+{
+ unsigned int depth;
+ print_die_main (argc, argv, depth);
+
+ dwarf_edit f;
+
+ dwarf_edit::compile_unit &cu = f.add_unit ();
+
+ cu.attributes ()[DW_AT_name].source_file () = "source-file.c";
+
+ dwarf_edit::debug_info_entry &ent = cu.add_entry (DW_TAG_subprogram);
+
+ ent.attributes ()[DW_AT_name].identifier () = "foo";
+
+ ent.attributes ()[DW_AT_description] = ent.attributes ()[DW_AT_name];
+
+ print_file ("consed", f, depth);
+
+ return 0;
+}
--- /dev/null
+/* Pseudo-XMLish printing for elfutils::dwarf* tests.
+ 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.
+
+ 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 <cstring>
+#include <cstdio>
+#include <clocale>
+#include <libintl.h>
+#include <ostream>
+#include <iomanip>
+
+static bool print_offset;
+
+static void
+print_die_main (int &argc, char **&argv, unsigned int &depth)
+{
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ /* Make sure the message catalog can be found. */
+ (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+ /* Initialize the message catalog. */
+ (void) textdomain (PACKAGE_TARNAME);
+
+ cout << hex << setiosflags (ios::showbase);
+
+ if (argc > 1 && !strcmp (argv[1], "--offsets"))
+ {
+ print_offset = true;
+ --argc;
+ ++argv;
+ }
+
+ depth = 0;
+ if (argc > 1 && sscanf (argv[1], "--depth=%u", &depth) == 1)
+ {
+ --argc;
+ ++argv;
+ }
+}
+
+template<typename file>
+static void
+print_die (const typename file::debug_info_entry &die,
+ unsigned int indent, unsigned int limit)
+{
+ string prefix (indent, ' ');
+ const string tag = dwarf::tags::name (die.tag ());
+
+ cout << prefix << "<" << tag;
+ if (print_offset)
+ cout << " offset=[" << die.offset () << "]";
+
+ for (typename file::debug_info_entry::attributes_type::const_iterator i
+ = die.attributes ().begin (); i != die.attributes ().end (); ++i)
+ cout << " " << to_string (*i);
+
+ if (die.has_children ())
+ {
+ if (limit != 0 && indent >= limit)
+ {
+ cout << ">...\n";
+ return;
+ }
+
+ cout << ">\n";
+
+ for (typename file::debug_info_entry::children_type::const_iterator i
+ = die.children ().begin (); i != die.children ().end (); ++i)
+ print_die<file> (*i, indent + 1, limit);
+
+ cout << prefix << "</" << tag << ">\n";
+ }
+ else
+ cout << "/>\n";
+}
+
+template<typename file>
+static void
+print_cu (const typename file::compile_unit &cu, const unsigned int limit)
+{
+ print_die<file> (static_cast<const typename file::debug_info_entry &> (cu),
+ 1, limit);
+}
+
+template<typename file>
+static void
+print_file (const char *name, const file &dw, const unsigned int limit)
+{
+ cout << name << ":\n";
+
+ for (typename file::compile_units::const_iterator i
+ = dw.compile_units ().begin (); i != dw.compile_units ().end (); ++i)
+ print_cu<file> (*i, limit);
+}
testfiles testfile
-testrun_compare ./dwarf-print --depth=1 testfile <<\EOF
+testrun_compare ./dwarf-print --offsets --depth=1 testfile <<\EOF
testfile:
<compile_unit offset=[0xb] stmt_list=0 high_pc=0x804845a low_pc=0x804842c name="m.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
<compile_unit offset=[0xca] stmt_list=0x4b high_pc=0x8048466 low_pc=0x804845c name="b.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
--- /dev/null
+#! /bin/sh
+# 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.
+#
+# 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>.
+
+. $srcdir/test-subr.sh
+
+testrun_compare ./dwarf_edit <<\EOF
+consed:
+ <compile_unit name="source-file.c">
+ <subprogram name="foo" description="foo"/>
+ </compile_unit>
+EOF
+
+exit 0