From: Roland McGrath Date: Thu, 2 Jul 2009 09:11:12 +0000 (-0700) Subject: Major revamp of dwarf_edit/dwarf_output. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5ae0cd5936a9d563b8e7819db9c29bc100e3edf1;p=thirdparty%2Felfutils.git Major revamp of dwarf_edit/dwarf_output. --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 28cc39a5b..a269182eb 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,24 @@ +2009-07-02 Roland McGrath + + * 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 * c++/dwarf_tracker: Major revamp for efficiency and to handle diff --git a/libdw/Makefile.am b/libdw/Makefile.am index b957c168d..f358840c4 100644 --- a/libdw/Makefile.am +++ b/libdw/Makefile.am @@ -48,8 +48,8 @@ endif include_HEADERS = dwarf.h pkginclude_HEADERS = libdw.h \ - c++/subr.hh \ - c++/dwarf c++/dwarf_edit \ + c++/subr.hh c++/dwarf_data \ + c++/dwarf c++/dwarf_edit c++/dwarf_output \ c++/dwarf_tracker c++/dwarf_comparator libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \ @@ -94,8 +94,10 @@ libdwpp_a_SOURCES = c++/values.cc \ 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 diff --git a/libdw/c++/data-values.hh b/libdw/c++/data-values.hh new file mode 100644 index 000000000..55860f5c5 --- /dev/null +++ b/libdw/c++/data-values.hh @@ -0,0 +1,97 @@ +/* elfutils::dwarf_data common internal templates. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#include "dwarf_data" + +#include + +namespace elfutils +{ + + template + dwarf::value_space + dwarf_data::attr_value::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"); + } + + +}; diff --git a/libdw/c++/dwarf b/libdw/c++/dwarf index 9f2d37f1d..311591fe6 100644 --- a/libdw/c++/dwarf +++ b/libdw/c++/dwarf @@ -1903,13 +1903,7 @@ namespace elfutils return !(*this == other); } - inline std::string to_string () const - { - std::string result = attributes::name (::dwarf_whatattr (thisattr ())); - result += "="; - result += second.to_string (); - return result; - } + inline std::string to_string () const; }; /* This works like range_list, but is based on a debug_info_entry using @@ -2367,15 +2361,19 @@ namespace elfutils return const_iterator (*this, 1); } - // Explicit specialization. + // Explicit specializations. + template<> + std::string to_string (const dwarf::attribute &); + inline std::string dwarf::attribute::to_string () const + { + return elfutils::to_string (*this); // Use that. + } template<> std::string to_string (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 (const dwarf::dwarf_enum &); inline std::string dwarf::dwarf_enum::to_string () const diff --git a/libdw/c++/dwarf_data b/libdw/c++/dwarf_data new file mode 100644 index 000000000..6d039009e --- /dev/null +++ b/libdw/c++/dwarf_data @@ -0,0 +1,1267 @@ +/* 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 + . */ + +#ifndef _ELFUTILS_DWARF_DATA +#define _ELFUTILS_DWARF_DATA 1 + +#include "dwarf" +#include +#include + +/* 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 + { + 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 + source_file (const file &other) + : _m_name (other.name ()), + _m_mtime (other.mtime ()), _m_size (other.size ()) {} + + template + 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 + 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 + 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 + { + private: + typedef std::vector _base; + + public: + struct hasher : public subr::container_hasher {}; + + directory_table () {} + + template + directory_table (const table &other) + : _base (other.begin (), other.end ()) {} + + template + inline bool operator== (const table &other) const + { + return size () == other.size () && subr::container_equal (*this, other); + } + template + inline bool operator!= (const table &other) const + { + return !(*this == other); + } + }; + + private: + + /* This is the common base class for all line_entry instantiations. + For some reason beyond my ken, std::bitset::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 _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::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 + 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 + { + 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 + line_entry (const entry &other) + : line_entry_common (), _m_addr (0), _m_file () + { + *this = other; + } + + template + 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 + bool operator< (const entry &other) const + { + return address () < other.address (); + } + template + bool operator> (const entry &other) const + { + return address () > other.address (); + } + template + bool operator<= (const entry &other) const + { + return address () <= other.address (); + } + template + bool operator>= (const entry &other) const + { + return address () >= other.address (); + } + + template + 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 + inline bool operator!= (const entry &other) const + { + return !(*this == other); + } + }; + + /* This holds a line table. + It's parameterized by the line_entry representation. */ + template + class line_table : public std::vector + { + private: + typedef std::vector _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 () {} + + template + line_table (const table &other) : _base (other.begin (), other.end ()) {} + + template + inline bool operator== (const table &other) const + { + return (_base::size () == other.size () + && subr::container_equal (*this, other)); + } + template + 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 + class line_info_table + : private std::pair + { + private: + typedef std::pair _base; + + public: + inline line_info_table () : _base () {} + + template + inline line_info_table (const table &other) + : _base (other.include_directories (), other.lines ()) + {} + + template + 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 + inline bool operator== (const table &other) const + { + return (include_directories () == other.include_directories () + && lines () == other.lines ()); + } + template + 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 + inline dwarf_enum (const constant &other) + : _base (static_cast (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 + 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 + inline bool operator== (const constant &other) const + { + return (static_cast (*this) + == static_cast (other)); + } + template + inline bool operator!= (const constant &other) const + { + return !(*this == other); + } + }; + + // Same as set>. + class range_list : public dwarf::arange_list + { + public: + struct hasher : public subr::container_hasher {}; + + template + range_list (const list &other) + : dwarf::arange_list (other.begin (), other.end ()) {} + }; + + class location_attr + : public std::map > + { + private: + typedef std::map > _base; + + template + struct nonempty : public std::unary_function + { + 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 {}; + + inline location_attr () : _base () {} + inline location_attr (const location_attr &other) + : _base (static_cast (other)) {} + template + inline location_attr (const loc &other) : _base () + { + *this = other; + } + + template + 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 + bool operator== (const other_attr &other) const + { + if (empty ()) + return (other.empty () + || std::find_if (other.begin (), other.end (), + nonempty () + ) == 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 + inline bool operator!= (const other_attr &other) const + { + return !(*this == other); + } + + std::string to_string () const; + }; + + public: + struct nothing {}; + + template + struct value + { + struct value_dispatch + { + virtual ~value_dispatch () {} + }; + + template + 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 + 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 + 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 + inline value_reference + (const typename impl::debug_info_entry::children_type::iterator &i, + const arg_type &arg) + : ref (i) + {} + + template // 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 + inline value_unit_reference + (const typename impl::compile_units::iterator &i, + const arg_type &arg) + : ref (i) + {} + + template // 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 + 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 + 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 + 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 + 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 + inline value_constant (::Dwarf_Word x, const arg_type &arg) + : word (x) + {} + }; + + struct value_constant_block : public value_dispatch, + public std::vector + { + inline value_constant_block () {} + + template + inline value_constant_block (const block &b, const arg_type &arg) + : std::vector (b.begin (), b.end ()) + {} + }; + + struct value_dwarf_constant : public value_dispatch, public dwarf_enum + { + inline value_dwarf_constant () {} + + template + 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 + 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 + 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 + inline value_location (const loc &other, const arg_type &arg) + : location_attr (other) + {} + }; + }; + + template > + class attr_value + { + private: + typename vw::value_dispatch *_m_value; + + template + 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 + inline flavor &const_variant () const + { + flavor *p = dynamic_cast (_m_value); + if (p == NULL) + throw std::runtime_error ("wrong value type"); + return *p; + } + + template + inline flavor &variant () const + { + return const_variant (); + } + + template + inline flavor &variant () + { + if (_m_value == NULL) + _m_value = new flavor; + return const_variant (); + } + + public: + attr_value (const attr_value &other) + : _m_value (NULL) + { + if (other._m_value != NULL) + init me (this, other); + } + + template + attr_value (const value &other, const arg_type &arg) + : _m_value (NULL) + { + init 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 me (this, other); + return *this; + } + template + inline attr_value &operator= (const value &other) + { + if (_m_value != NULL) + { + delete _m_value; + _m_value = NULL; + } + init me (this, other); + return *this; + } + + dwarf::value_space what_space () const; + inline std::string to_string () const; + + inline bool &flag () const + { + return variant ().flag; + } + + // XXX dwfl, reloc + inline ::Dwarf_Addr &address () const + { + return variant ().addr; + } + + inline typename impl::debug_info_entry::children_type::iterator + reference () const + { + return variant ().ref; + } + inline typename impl::compile_units::iterator + unit_reference () const + { + return variant ().ref; + } + + inline location_attr &location () const + { + return static_cast + (variant ()); + } + + inline std::string &string () + { + return static_cast + (variant ()); + } + inline const std::string &string () const + { + return static_cast + (variant ()); + } + 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 + (variant ()); + } + + inline typename impl::source_file &source_file () + { + return static_cast + (variant ()); + } + + inline const unsigned int &source_line () const + { + return variant ().n; + } + + inline unsigned int &source_line () + { + return variant ().n; + } + + inline const unsigned int &source_column () const + { + return variant ().n; + } + + inline unsigned int &source_column () + { + return variant ().n; + } + + inline const ::Dwarf_Word &constant () const + { + return variant ().word; + } + + inline ::Dwarf_Word &constant () + { + return variant ().word; + } + + inline const ::Dwarf_Sword &signed_constant () const + { + return variant ().sword; + } + + inline ::Dwarf_Sword &signed_constant () + { + return variant ().sword; + } + + inline const std::vector &constant_block () const + { + return static_cast &> + (variant ()); + } + + inline std::vector &constant_block () + { + return static_cast &> + (variant ()); + } + + inline const typename impl::dwarf_enum &dwarf_constant () const + { + return variant (); + } + + inline typename impl::dwarf_enum &dwarf_constant () + { + return variant (); + } + + inline bool constant_is_integer () const + { + return dynamic_cast (_m_value) != NULL; + } + + inline const typename impl::range_list &ranges () const + { + return static_cast + (variant ()); + } + + inline typename impl::range_list &ranges () + { + return static_cast + (variant ()); + } + + inline const typename impl::line_info_table &line_info () const + { + return static_cast + (variant ()); + } + + inline typename impl::line_info_table &line_info () + { + return static_cast + (variant ()); + } + + // macptr + + template + 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 + inline bool operator!= (const value &other) const + { + return !(*this == other); + } + }; + + template > + class attributes_type + : public std::map > + { + friend class impl::debug_info_entry; + private: + typedef std::map > base_type; + + protected: + inline attributes_type () {} + + public: // XXX should be protected + template + inline attributes_type (const input &other, const arg_type &c) + : base_type (subr::argify2nd + (other.begin (), c), + subr::argify2nd + (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 + inline operator attrs () const + { + return attrs (base_type::begin (), base_type::end ()); + } + }; + + }; + + // Explicit specializations. + template<> + std::string to_string (const dwarf_data::dwarf_enum&); + inline std::string dwarf_data::dwarf_enum::to_string () const + { + return elfutils::to_string (*this); // Use that. + } + + template + inline std::string dwarf_data::attr_value::to_string () const + { + return elfutils::to_string (*this); // Use that. + } + +}; + +#endif diff --git a/libdw/c++/dwarf_edit b/libdw/c++/dwarf_edit index 00698b540..8e12c5da7 100644 --- a/libdw/c++/dwarf_edit +++ b/libdw/c++/dwarf_edit @@ -51,7 +51,8 @@ #define _ELFUTILS_DWARF_EDIT 1 #include "dwarf" -#include +#include "dwarf_data" +#include "dwarf_tracker" /* Read the comments for elfutils::dwarf first. @@ -86,8 +87,18 @@ namespace elfutils class dwarf_edit { public: + typedef dwarf_data::source_file source_file; + typedef dwarf_data::directory_table directory_table; + typedef dwarf_data::line_entry line_entry; + typedef dwarf_data::line_table line_table; + typedef dwarf_data::line_info_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 attr_value; + class compile_units; - class attr_value; class debug_info_entry { @@ -99,38 +110,36 @@ namespace elfutils private: children_type () {} - template - children_type (const childrens &other) - : std::list (other.begin (), other.end ()) {} + template + children_type (const input &other, tracker *t) + : std::list + (subr::argify (other.begin (), t), + subr::argify (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 + class attributes_type + : public dwarf_data::attributes_type { friend class debug_info_entry; private: - typedef std::map base_type; - - attributes_type () {} - - template - attributes_type (const attrs &other) - : std::map (other.begin (), other.end ()) {} + typedef dwarf_data::attributes_type 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 - inline operator attrs () const - { - return attrs (begin (), end ()); - } + template + inline attributes_type (const attrs &other, tracker *t) + : base_type (other, t) + {} }; private: @@ -147,11 +156,11 @@ namespace elfutils /* The template constructor lets us copy in from any class that has compatibly iterable containers for attributes and children. */ - template - debug_info_entry (const die_type &die) + template + 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 @@ -204,6 +213,12 @@ namespace elfutils { 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; @@ -216,8 +231,9 @@ namespace elfutils // XXX should be private public: - template - compile_unit (const die_type &die) : debug_info_entry (die) + template + 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"); @@ -237,22 +253,26 @@ namespace elfutils typedef std::list _base; // Default constructor: an empty container, no CUs. - inline compile_units () {} + inline compile_units () + {} // Constructor copying CUs from input container. - template - compile_units(const input &units) - : _base (units.begin (), units.end ()) {} + template + inline compile_units (const input &units, tracker *t) + : _base (subr::argify + (units.begin (), t), + subr::argify + (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 (); } @@ -268,901 +288,6 @@ namespace elfutils } }; - // Same as set>. - class range_list : public dwarf::arange_list - { - public: - template - 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 - source_file (const file &other) - : _m_name (other.name ()), - _m_mtime (other.mtime ()), _m_size (other.size ()) {} - - template - 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 - 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 - 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 - { - private: - typedef std::vector _base; - - public: - directory_table () {} - - template - directory_table (const table &other) - : _base (other.begin (), other.end ()) {} - - template - inline bool operator== (const table &other) const - { - return size () == other.size () && subr::container_equal (*this, other); - } - template - 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 _m_flags; - - public: - line_entry (::Dwarf_Addr addr) - : _m_addr (addr), _m_file (), _m_line (0), _m_column (0) {} - - template - line_entry (const entry &other) - : _m_addr (0), _m_file (), _m_line (0), _m_column (0) - { - *this = other; - } - - template - 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::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 - bool operator< (const entry &other) const - { - return address () < other.address (); - } - template - bool operator> (const entry &other) const - { - return address () > other.address (); - } - template - bool operator<= (const entry &other) const - { - return address () <= other.address (); - } - template - bool operator>= (const entry &other) const - { - return address () >= other.address (); - } - - template - 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 - inline bool operator!= (const entry &other) const - { - return !(*this == other); - } - }; - - class line_table : public std::vector - { - private: - typedef std::vector _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 - line_table (const table &other) : _base (other.begin (), other.end ()) {} - - template - inline bool operator== (const table &other) const - { - return size () == other.size () && subr::container_equal (*this, other); - } - template - 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 - line_info_table (const table &other) - : _m_dirs (other.include_directories ()), _m_lines (other.lines ()) {} - - template - 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 - inline bool operator== (const table &other) const - { - return (include_directories () == other.include_directories () - && lines () == other.lines ()); - } - template - inline bool operator!= (const table &other) const - { - return !(*this == other); - } - }; - - class location_attr : public std::map > - { - private: - typedef std::map > _base; - - template - struct nonempty : public std::unary_function - { - 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 (other)) {} - template - inline location_attr (const loc &other) : _base () - { - *this = other; - } - - template - 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 - bool operator== (const other_attr &other) const - { - if (empty ()) - return (other.empty () - || std::find_if (other.begin (), other.end (), - nonempty () - ) == 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 - 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 - inline dwarf_enum (const constant &other) - : _m_value (static_cast (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 - 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 - inline bool operator== (const constant &other) const - { - return (static_cast (*this) - == static_cast (other)); - } - template - 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 - 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 - 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 // 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 // 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 - value_rangelistptr (const list &other) : range_list (other) {} - }; - - struct value_lineptr : public value_dispatch, public line_info_table - { - template - 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 - { - template - value_constant_block (const block &b) - : std::vector (b.begin (), b.end ()) {} - }; - - struct value_dwarf_constant : public value_dispatch, public dwarf_enum - { - template - value_dwarf_constant (const constant &other) : dwarf_enum (other) {} - }; - - struct value_source_file : public value_dispatch, public source_file - { - template - 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 - value_location (const loc &other) : location_attr (other) {} - }; - - public: - class attr_value - { - private: - value_dispatch *_m_value; - - template - 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 - inline flavor &variant () const - { - flavor *p = dynamic_cast (_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 - 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 - 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 ().flag; - } - - // XXX dwfl, reloc - inline ::Dwarf_Addr &address () const - { - return variant ().addr; - } - - inline debug_info_entry::children_type::iterator reference () const - { - return variant ().ref; - } - inline compile_units::iterator unit_reference () const - { - return variant ().ref; - } - - inline location_attr &location () const - { - return static_cast (variant ()); - } - - inline std::string &string () const - { - return static_cast (variant ()); - } - inline std::string &identifier () const - { - return string (); - } - - inline dwarf_edit::source_file &source_file () const - { - return static_cast - (variant ()); - } - - inline unsigned int &source_line () const - { - return variant ().n; - } - - inline unsigned int &source_column () const - { - return variant ().n; - } - - inline ::Dwarf_Word &constant () const - { - return variant ().word; - } - - inline ::Dwarf_Sword &signed_constant () const - { - return variant ().sword; - } - - inline std::vector &constant_block () const - { - return static_cast &> - (variant ()); - } - - inline dwarf_enum &dwarf_constant () const - { - return variant (); - } - - inline bool constant_is_integer () const - { - return dynamic_cast (_m_value) != NULL; - } - - inline range_list &ranges () const - { - return static_cast (variant ()); - } - - inline line_info_table &line_info () const - { - return static_cast (variant ()); - } - - // macptr - - template - 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 - inline bool operator!= (const value &other) const - { - return !(*this == other); - } - }; - private: compile_units _m_units; @@ -1176,13 +301,21 @@ namespace elfutils 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 - dwarf_edit (const input &dw) : _m_units (dw.compile_units ()) {} + template + dwarf_edit (const input &dw, tracker *t) + : _m_units (dw.compile_units (), t) + {} template inline bool operator== (const file &other) const @@ -1200,17 +333,7 @@ namespace elfutils template<> std::string to_string (const dwarf_edit::attribute &); template<> - std::string to_string (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 (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 (const dwarf_edit::attr_value &); }; #endif // diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output index d4d2ee611..ff2621ba5 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -50,7 +50,8 @@ #ifndef _ELFUTILS_DWARF_OUTPUT #define _ELFUTILS_DWARF_OUTPUT 1 -#include "dwarf" +#include "dwarf_edit" +#include /* Read the comments for elfutils::dwarf first. @@ -65,10 +66,31 @@ 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 + static inline const input & + collect (dwarf_output_collector *c, + const subr::auto_ref &p) + { + return static_cast (p); + } + + template + 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 @@ -79,50 +101,312 @@ namespace elfutils class debug_info_entry { + friend class dwarf_output; + public: + typedef subr::hashed_unordered_map attributes_type; + typedef subr::hashed_vector 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 + /* The template constructor lets us copy in from any class that has + compatibly iterable containers for attributes and children. */ + template + 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 + bool operator== (const die &other) const + { + return (other.attributes () == attributes () + && other.children () == children ()); + } + template + 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 > + { + friend class dwarf_output; + private: + typedef std::vector > _base; + + template + struct make + : public std::binary_function + { + _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 + 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 () (*it, c)); + } + + public: + template + bool operator== (const other_children &other) const + { + return subr::container_equal (*this, other); + } + template + bool operator!= (const other_children &other) const + { + return !(*this == other); + } + + void recollect (dwarf_output_collector *c) + { + std::transform (begin (), end (), begin (), + std::bind2nd (make (), 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 + dwarf_output (const input &dw, dwarf_output_collector *c) + : _m_units (dw.compile_units (), c) + {} - template - children (const childrens &other) - : std::vector (other.begin (), other.end ()) {} + template + inline bool operator== (const file &other) const + { + return compile_units () == other.compile_units (); + } + template + 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 line_entry; + typedef dwarf_data::line_table line_table; + typedef dwarf_data::line_info_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 + 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 + static inline typename subr::argifier::wrapped + collectify (const typename input::const_iterator &in, + dwarf_output_collector *c) + { + return subr::argifier (c) (in); + } + + struct value_wrapper + : public dwarf_data::value + { + struct value_string : public value_dispatch + { + const std::string &_m_str; + + template + 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 + template + 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 + static inline value_dispatch * + make (flavor *&result, const input &x, const arg_type &arg) + { + return result = new flavor (x, arg); + } + + template + 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 attr_value; + + class compile_units; + + class debug_info_entry + { + public: + + class children_type : public std::list { friend class debug_info_entry; private: - attributes () {} + children_type () {} - template - attributes (const attrs &other) - : std::map (other.begin (), other.end ()) {} + template + inline children_type (const input &other, dwarf_output_collector *c) + : std::list + (collectify (other.begin (), c), + collectify (other.end (), c)) + {} public: - template - inline operator attrs () const - { - return attrs (begin (), end ()); - } + typedef debug_info_entry value_type; + }; + + class attributes_type + : public dwarf_data::attributes_type + { + friend class debug_info_entry; + private: + typedef dwarf_data::attributes_type base_type; + + template + 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 - debug_info_entry (const die &die) + template + 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 @@ -135,20 +419,20 @@ namespace elfutils 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; } @@ -156,7 +440,8 @@ namespace elfutils template bool operator== (const die &other) const { - return (other.attributes () == attributes () + return (other.tag () == tag () + && other.attributes () == attributes () && other.children () == children ()); } template @@ -164,30 +449,70 @@ namespace elfutils { 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 + 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 + class compile_units + : public std::list { friend class dwarf_output; private: + typedef std::list _base; + + // Default constructor: an empty container, no CUs. + inline compile_units () + : _base () + {} + // Constructor copying CUs from input container. template - compile_units(const input &units) - : std::vector (units.begin (), units.end ()) - {} + compile_units (const input &units, dwarf_output_collector *c) + : _base (collectify (units.begin (), c), + collectify (units.end (), c)) + { + } public: + typedef compile_unit value_type; + typedef _base::iterator iterator; + typedef _base::const_iterator const_iterator; + template bool operator== (const other_children &other) const { - return std::equal (begin (), end (), other.begin ()); + return subr::container_equal (*this, other); } template bool operator!= (const other_children &other) const @@ -197,18 +522,30 @@ namespace elfutils }; 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 - 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 inline bool operator== (const file &other) const @@ -221,4 +558,32 @@ namespace elfutils return !(*this == other); } }; -} + + // Explicit specializations. + template<> + std::string to_string (const dwarf_output::attribute &); + template<> + std::string to_string (const dwarf_output::attr_value&); + +#endif + + class dwarf_output_collector + { + friend class dwarf_output; + + private: + subr::value_set _m_strings; + subr::value_set _m_ranges; + + }; + + template + inline const std::string & + dwarf_output::collect_string (dwarf_output_collector *c, const input &s) + { + return c->_m_strings.add (s); + } + +}; + +#endif // diff --git a/libdw/c++/edit-values.cc b/libdw/c++/edit-values.cc index eb957492a..7640b4caa 100644 --- a/libdw/c++/edit-values.cc +++ b/libdw/c++/edit-values.cc @@ -49,49 +49,11 @@ #include #include "dwarf_edit" - -#include +#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 @@ -104,7 +66,7 @@ to_string (const dwarf_edit::attribute &attr) } std::string -dwarf_edit::source_file::to_string () const +dwarf_data::source_file::to_string () const { if (likely (_m_mtime == 0) && likely (_m_size == 0)) return "\"" + _m_name + "\""; @@ -115,7 +77,7 @@ dwarf_edit::source_file::to_string () const } std::string -dwarf_edit::location_attr::to_string () const +dwarf_data::location_attr::to_string () const { return is_list () ? "XXX-loclist" : "XXX-expr"; } diff --git a/libdw/c++/known.cc b/libdw/c++/known.cc index 1bb84f137..a7788416e 100644 --- a/libdw/c++/known.cc +++ b/libdw/c++/known.cc @@ -217,13 +217,13 @@ dwarf::dwarf_enum::name () const } const char * -dwarf_edit::dwarf_enum::identifier () const +dwarf_data::dwarf_enum::identifier () const { return enum_identifier (*this); } const char * -dwarf_edit::dwarf_enum::name () const +dwarf_data::dwarf_enum::name () const { return enum_name (*this); } @@ -245,7 +245,7 @@ to_string (const dwarf::dwarf_enum &value) template<> string -to_string (const dwarf_edit::dwarf_enum &value) +to_string (const dwarf_data::dwarf_enum &value) { return enum_string (value); } diff --git a/libdw/c++/output-values.cc b/libdw/c++/output-values.cc new file mode 100644 index 000000000..d50abb8eb --- /dev/null +++ b/libdw/c++/output-values.cc @@ -0,0 +1,68 @@ +/* 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 + . */ + +#include +#include "dwarf_output" +#include "data-values.hh" + +#include + +using namespace elfutils; + +template dwarf::value_space dwarf_output::attr_value::what_space () const; + +template<> +std::string +to_string (const dwarf_output::attribute &attr) +{ + std::string result = dwarf::attributes::name (attr.first); + result += "="; + result += attr.second.to_string (); + return result; +} diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh index e11846279..7a799eeb8 100644 --- a/libdw/c++/subr.hh +++ b/libdw/c++/subr.hh @@ -10,16 +10,107 @@ #include #include #include +#include +#include +#include +#include +#include namespace elfutils { namespace subr { + template + struct hash : public T::hasher {}; + + template + static inline size_t hash_this (const T &v) + { + return hash () (v); + } + + template + inline void hash_combine (size_t &seed, const T &v) + { + seed ^= hash_this (v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } + + template + inline void hash_combine (size_t &seed, const std::pair &v) + { + hash_combine (seed, v.first); + hash_combine (seed, v.second); + } + + template + struct integer_hash : public std::unary_function + { + inline size_t operator () (const T &x) const + { + return x; + } + }; + template<> + struct hash : public integer_hash {}; + template<> + struct hash : public integer_hash {}; + + template + struct container_hasher : public std::unary_function + { + 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 + { + private: + struct hasher : public container_hasher::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 + struct hashed_hasher + : public std::unary_function + { + size_t operator () (const T &v) const + { + return v._m_hash; + } + }; + template struct name_equal : public std::binary_function { template - inline bool operator () (const mystring &me, const string &you) + inline bool operator () (const mystring &me, const string &you) const { return you == me; } @@ -30,12 +121,12 @@ namespace elfutils struct name_equal : public std::binary_function { - bool operator () (const char *me, const char *you) + bool operator () (const char *me, const char *you) const { return !strcmp (me, you); } template - inline bool operator () (const mystring &me, const char *you) + inline bool operator () (const mystring &me, const char *you) const { return me == you; } @@ -71,7 +162,7 @@ namespace elfutils template struct equal_to : public std::binary_function { - inline bool operator () (const t1 &a, const t2 &b) + inline bool operator () (const t1 &a, const t2 &b) const { return a == b; } @@ -96,7 +187,7 @@ namespace elfutils {} 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); } @@ -262,6 +353,348 @@ namespace elfutils return indexed_iterator (_m_contents, _m_idx--); } }; + + // Pair of some value and its precomputed hash. + template + class hashed_value + : public std::pair + { + private: + typedef std::pair _base; + + public: + typedef T value_type; + + struct hasher + : public std::unary_function + { + 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 + class value_set + : public std::tr1::unordered_set, + struct hashed_value::hasher> + { + public: + typedef hashed_value hashed_value_type; + + private: + typedef std::tr1::unordered_set _base; + + public: + const value_type &add (const value_type &v) + { + std::pair p + = _base::insert (hashed_value_type (v)); + if (p.second) + { + // XXX hook for collection: abbrev building, etc. + } + return p.first->second; + }; + + template + 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>. + template + 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; + typedef hashed_hasher hasher; + + template + hashed_container (iterator first, iterator last) + : _base (first, last), _m_hash (0) + { + set_hash (); + } + + template + 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 + struct hashed_vector + : public hashed_container > > + {}; + + // An unordered_map of hashed_value's that itself acts like a hashed_value. + template + class hashed_unordered_map + : public hashed_container, + class hashed_value::hasher> + > + {}; +#if 0 + template + class hashed_unordered_map + : public std::tr1::unordered_map, + class hashed_value::hasher> + { + private: + typedef std::tr1::unordered_map, + class hashed_value::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; + typedef hashed_hasher hasher; + + template + hashed_unordered_map (iterator first, iterator last) + : _base (first, last), _m_hash (0) + { + set_hash (); + } + + template + hashed_unordered_map (const container &other) + : _base (other.begin (), other.end ()), _m_hash (0) + { + set_hash (); + } + }; +#endif + + template + 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 &other) + : _m_ptr (other._m_ptr) + {} + + template + inline bool operator== (const auto_ref &x) const + { + return *_m_ptr == static_cast (x); + } + template + inline bool operator== (const other &x) const + { + return *_m_ptr == x; + } + template + 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 + 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 + struct argifier + : public std::unary_function + { + 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 + { + 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 wrapped; + + inline wrapped operator () (const inny &i) + { + return wrapped (i, _m_maker); + } + }; + + template + static inline typename argifier::wrapped + argify (const typename input::const_iterator &in, const arg_type &arg) + { + return argifier (arg) (in); + } + + template + struct argifier2nd + : public std::unary_function + { + 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 + { + 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 wrapped; + + inline wrapped operator () (const inny &i) + { + return wrapped (i, _m_maker); + } + }; + + template + static inline typename argifier2nd::wrapped + argify2nd (const typename input::const_iterator &in, const arg_type &arg) + { + return argifier2nd (arg) (in); + } + }; }; diff --git a/libdw/c++/values.cc b/libdw/c++/values.cc index 5e0eda23f..109db05a8 100644 --- a/libdw/c++/values.cc +++ b/libdw/c++/values.cc @@ -51,6 +51,7 @@ #include #include "dwarf" #include "dwarf_edit" +#include "dwarf_output" extern "C" { @@ -232,6 +233,16 @@ value_string (const value_type &value) throw std::runtime_error ("XXX unsupported value space"); } +template<> +string +to_string (const dwarf::attribute &attr) +{ + std::string result = dwarf::attributes::name (attr.first); + result += "="; + result += attr.second.to_string (); + return result; +} + template<> string to_string (const dwarf::attr_value &value) @@ -246,6 +257,12 @@ to_string (const dwarf_edit::attr_value &value) return value_string (value); } +template<> +string +to_string (const dwarf_output::attr_value &value) +{ + return value_string (value); +} // A few cases are trivial. #define SIMPLE(type, name, form) \ diff --git a/src/ChangeLog b/src/ChangeLog index 190a33d7c..e521df840 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2009-07-02 Roland McGrath + + * dwarfcmp.cc (main): Update -T constructors using tracker. + Instantiate and test dwarf_output for -T too. + 2009-07-01 Roland McGrath * dwarfcmp.cc (talker): Update constructor parameters. diff --git a/src/dwarfcmp.cc b/src/dwarfcmp.cc index 4deff59dc..677a5beba 100644 --- a/src/dwarfcmp.cc +++ b/src/dwarfcmp.cc @@ -47,6 +47,7 @@ #include "c++/dwarf_edit" #include "c++/dwarf_comparator" #include "c++/dwarf_tracker" +#include "c++/dwarf_output" using namespace elfutils; using namespace std; @@ -133,8 +134,8 @@ struct talker : public dwarf_ref_tracker 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_; @@ -324,9 +325,28 @@ main (int argc, char *argv[]) if (test_writer) { - dwarf_edit out1 (file1); - dwarf_edit out2 (file2); - test_classes (file1, file2, out1, out2, same); + dwarf_ref_tracker t1; + dwarf_ref_tracker 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; diff --git a/tests/ChangeLog b/tests/ChangeLog index b988cfec0..d7c99a187 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2009-07-02 Roland McGrath + + * 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 * run-dwarfcmp-self.sh: Run on dwarflint too. diff --git a/tests/Makefile.am b/tests/Makefile.am index ba9500885..41cd9f328 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -52,6 +52,8 @@ else 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 \ @@ -60,7 +62,8 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ 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 @@ -87,7 +90,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ 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 @@ -122,7 +126,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ 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 \ @@ -193,6 +197,9 @@ libdwpp = ../libdw/libdwpp.a $(libdw) 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) diff --git a/tests/dwarf-print.cc b/tests/dwarf-print.cc index d37a006a0..36b9415be 100644 --- a/tests/dwarf-print.cc +++ b/tests/dwarf-print.cc @@ -30,17 +30,14 @@ #include #include #include -#include -#include -#include -#include -#include #include "c++/dwarf" using namespace elfutils; using namespace std; +#include "print-die.hh" + static Dwarf * open_file (const char *fname) { @@ -57,75 +54,14 @@ 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 << "\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; } diff --git a/tests/dwarf_edit.cc b/tests/dwarf_edit.cc new file mode 100644 index 000000000..5510be1ce --- /dev/null +++ b/tests/dwarf_edit.cc @@ -0,0 +1,59 @@ +/* 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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#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; +} diff --git a/tests/print-die.hh b/tests/print-die.hh new file mode 100644 index 000000000..91d70c997 --- /dev/null +++ b/tests/print-die.hh @@ -0,0 +1,117 @@ +/* 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 + . */ + +#include +#include +#include +#include +#include +#include + +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 +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 (*i, indent + 1, limit); + + cout << prefix << "\n"; + } + else + cout << "/>\n"; +} + +template +static void +print_cu (const typename file::compile_unit &cu, const unsigned int limit) +{ + print_die (static_cast (cu), + 1, limit); +} + +template +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 (*i, limit); +} diff --git a/tests/run-dwarf-attributes.sh b/tests/run-dwarf-attributes.sh index 22c7289d9..4aa170ba7 100755 --- a/tests/run-dwarf-attributes.sh +++ b/tests/run-dwarf-attributes.sh @@ -27,7 +27,7 @@ testfiles testfile -testrun_compare ./dwarf-print --depth=1 testfile <<\EOF +testrun_compare ./dwarf-print --offsets --depth=1 testfile <<\EOF testfile: ... ... diff --git a/tests/run-dwarf_edit.sh b/tests/run-dwarf_edit.sh new file mode 100755 index 000000000..a7b0baf6e --- /dev/null +++ b/tests/run-dwarf_edit.sh @@ -0,0 +1,35 @@ +#! /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 +# . + +. $srcdir/test-subr.sh + +testrun_compare ./dwarf_edit <<\EOF +consed: + + + +EOF + +exit 0