From: Roland McGrath Date: Sat, 27 Jun 2009 00:13:20 +0000 (-0700) Subject: new tack, still unfinished X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a43ebb2fcedd4e99a4cfff2a11b30a714dc80cd;p=thirdparty%2Felfutils.git new tack, still unfinished --- diff --git a/libdw/Makefile.am b/libdw/Makefile.am index b957c168d..9f3a910d5 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,7 +94,8 @@ libdwpp_a_SOURCES = c++/values.cc \ c++/exception.cc \ c++/known.cc \ c++/line_info.cc \ - c++/edit-values.cc + c++/edit-values.cc \ + c++/output-values.cc noinst_HEADERS = c++/dwarf-knowledge.cc if MAINTAINER_MODE diff --git a/libdw/c++/data-values.hh b/libdw/c++/data-values.hh new file mode 100644 index 000000000..e20cc25f4 --- /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 (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"); + } + + +}; diff --git a/libdw/c++/dwarf b/libdw/c++/dwarf index cf24cc209..a3bee5dd1 100644 --- a/libdw/c++/dwarf +++ b/libdw/c++/dwarf @@ -1899,13 +1899,7 @@ namespace elfutils return !(*this == other); } - inline std::string to_string () const - { - std::string result = attributes::name (::dwarf_whatattr (thisattr ())); - result += "="; - result += second.to_string (); - return result; - } + inline std::string to_string () const; }; /* This works like range_list, but is based on a debug_info_entry using @@ -2363,15 +2357,19 @@ namespace elfutils return const_iterator (*this, 1); } - // Explicit specialization. + // Explicit specializations. + template<> + std::string to_string (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..ba324f035 --- /dev/null +++ b/libdw/c++/dwarf_data @@ -0,0 +1,1059 @@ +/* elfutils::dwarf_data -- internal DWARF data representations in -*- C++ -*- + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifndef _ELFUTILS_DWARF_DATA +#define _ELFUTILS_DWARF_DATA 1 + +#include "dwarf" +#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; + + 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= (const dwarf_enum& other) + { + this->first = other.first; + this->second = other.second; + 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; + }; + + 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) {} + }; + + template + struct value_reference : public value_dispatch + { + typename impl::debug_info_entry::children_type::iterator ref; + value_reference (const typename + impl::debug_info_entry::children_type::iterator &i) + : ref (i) {} + + template // XXX dummy + value_reference (const iter &i) : ref () {} + }; + + template + struct value_unit_reference : public value_dispatch + { + typename impl::compile_units::iterator ref; + value_unit_reference (const typename impl::compile_units::iterator &i) + : ref (i) + {} + + template // 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) {} + }; + + template + struct value_lineptr : public value_dispatch, public impl::line_info_table + { + template + value_lineptr (const table &other) : impl::line_info_table (other) {} + }; + + struct value_constant : public value_dispatch + { + union + { + ::Dwarf_Word word; + ::Dwarf_Sword sword; + }; + value_constant (::Dwarf_Word x) : word (x) {} + }; + + struct value_constant_block : public value_dispatch, + public std::vector + { + 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: + template + 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 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 () const + { + return static_cast (variant ()); + } + inline std::string &identifier () const + { + return string (); + } + + inline typename impl::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 typename impl::dwarf_enum &dwarf_constant () const + { + return variant (); + } + + inline bool constant_is_integer () const + { + return dynamic_cast (_m_value) != NULL; + } + + inline typename impl::range_list &ranges () const + { + return static_cast (variant ()); + } + + inline typename impl::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); + } + }; + + }; + + // 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..50714de25 100644 --- a/libdw/c++/dwarf_edit +++ b/libdw/c++/dwarf_edit @@ -51,7 +51,7 @@ #define _ELFUTILS_DWARF_EDIT 1 #include "dwarf" -#include +#include "dwarf_data" /* Read the comments for elfutils::dwarf first. @@ -86,8 +86,18 @@ namespace elfutils class dwarf_edit { public: + typedef dwarf_data::source_file source_file; + typedef dwarf_data::directory_table directory_table; + typedef dwarf_data::line_entry 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 { @@ -268,901 +278,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; @@ -1200,17 +315,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 ac015c74e..bd1b10ee3 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -50,7 +50,7 @@ #ifndef _ELFUTILS_DWARF_OUTPUT #define _ELFUTILS_DWARF_OUTPUT 1 -#include "dwarf" +#include "dwarf_edit" /* Read the comments for elfutils::dwarf first. @@ -67,6 +67,7 @@ namespace elfutils { class dwarf_output_collector; +#if 0 class dwarf_output { public: @@ -89,7 +90,6 @@ namespace elfutils const typename input::debug_info_entry &); public: - class compile_units; // XXX later class attr_value : public dwarf::attr_value @@ -102,19 +102,20 @@ namespace elfutils { friend class dwarf_output; - private: - typedef subr::hashed_unordered_map _attributes; - typedef subr::hashed_vector _children; + public: + typedef subr::hashed_unordered_map attributes_type; + typedef subr::hashed_vector children_type; + private: const int _m_tag; - const _attributes _m_attributes; - const _children _m_children; + const attributes_type _m_attributes; + const children_type _m_children; size_t _m_hash; /* The template constructor lets us copy in from any class that has compatibly iterable containers for attributes and children. */ template - debug_info_entry (const die_type &die) + debug_info_entry (const die_type &die, dwarf_output_collector *c) : _m_tag (die.tag ()), _m_attributes (die.attributes ()), _m_children (die.children ()), @@ -136,12 +137,12 @@ namespace elfutils return !_m_children.empty (); } - inline const _children &children () const + inline const children_type &children () const { return _m_children; } - inline const _attributes &attributes () const + inline const attributes_type &attributes () const { return _m_attributes; } @@ -159,7 +160,7 @@ namespace elfutils } }; - typedef debug_info_entry::_attributes::value_type attribute; + typedef debug_info_entry::attributes_type::value_type attribute; public: /* Main container anchoring all the output. @@ -216,7 +217,7 @@ namespace elfutils template 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 @@ -265,21 +266,307 @@ namespace elfutils } }; +#else // XXX temp + + class dwarf_output + { + public: + typedef dwarf_data::source_file source_file; + typedef dwarf_data::directory_table directory_table; + typedef dwarf_data::line_entry 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; + + protected: + template + static inline const range_list & + collect (dwarf_output_collector *, const typename input::range_list &); + + /* An iterator adapter for use in iterator-based constructors. + collectify (iterator) yields an iterator on input where *i + constructs output::value_type (input::value_type v, collector). */ + template + struct collectify + : 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 + { + dwarf_output_collector *_m_collector; + explicit inline maker (dwarf_output_collector *c) : _m_collector (c) {} + + inline outlet operator () (const inlet &x) const + { + return outlet (x, _m_collector); + } + } _m_maker; + + explicit inline collectify (dwarf_output_collector *c) : _m_maker (c) {} + + typedef subr::wrapped_input_iterator wrapped; + + inline wrapped operator () (const inny &i) + { + return wrapped (i, _m_maker); + } + }; + + public: + class compile_units; + + class debug_info_entry + { + public: + + class children_type : public std::list + { + friend class debug_info_entry; + private: + children_type () {} + + template + children_type (const childrens &other) + : std::list (other.begin (), other.end ()) {} + + public: + typedef debug_info_entry value_type; + }; + + class attributes_type : public std::map + { + 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 ()) {} + + public: + typedef base_type::key_type key_type; + typedef base_type::value_type value_type; + typedef base_type::mapped_type mapped_type; + + static const bool ordered = true; + + template + inline operator attrs () const + { + return attrs (begin (), end ()); + } + }; + + private: + const int _m_tag; + attributes_type _m_attributes; + children_type _m_children; + + public: + explicit debug_info_entry (int t) : _m_tag (t) + { + if (unlikely (t <= 0)) + throw std::invalid_argument ("invalid tag"); + } + + /* The template constructor lets us copy in from any class that has + compatibly iterable containers for attributes and children. */ + template + debug_info_entry (const die_type &die) + : _m_tag (die.tag ()), + _m_attributes (die.attributes ()), + _m_children (die.children ()) + {} + + inline int tag () const + { + return _m_tag; + } + + inline bool has_children () const + { + return !_m_children.empty (); + } + + inline children_type &children () + { + return _m_children; + } + inline const children_type &children () const + { + return _m_children; + } + + inline attributes_type &attributes () + { + return _m_attributes; + } + inline const attributes_type &attributes () const + { + return _m_attributes; + } + + template + bool operator== (const die &other) const + { + return (other.tag () == tag () + && other.attributes () == attributes () + && other.children () == children ()); + } + template + bool operator!= (const die &other) const + { + return !(*this == other);; + } + + inline ::Dwarf_Off identity () const + { + return (uintptr_t) this; + } + + inline ::Dwarf_Off offset () const + { + return identity (); + } + }; + + typedef debug_info_entry::attributes_type::value_type attribute; + + class compile_unit : public debug_info_entry + { + friend class compile_units; + private: + inline compile_unit () : debug_info_entry (::DW_TAG_compile_unit) {} + + // XXX should be private + public: + template + compile_unit (const die_type &die, dwarf_output_collector *c) + : debug_info_entry (die) + { + if (die.tag () != ::DW_TAG_compile_unit) + throw std::invalid_argument ("not a compile_unit entry"); + } + + /* XXX doesn't help + public: + compile_unit (const compile_unit &u) : debug_info_entry (u) {} + */ + }; + + // Main container anchoring all the output. + class compile_units + : public std::list + { + 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, dwarf_output_collector *c) + : _base (collectify (c) (units.begin ()), + collectify (c) (units.end ())) + { + } + + 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 subr::container_equal (*this, other); + } + template + bool operator!= (const other_children &other) const + { + return !(*this == other); + } + }; + + private: + compile_units _m_units; + + public: + class compile_units &compile_units () + { + return _m_units; + } + const class compile_units &compile_units () const + { + return _m_units; + } + + public: + // Constructor for an empty file, can add to its compile_units (). + dwarf_output () + : _m_units () + {} + + // Constructor copying CUs from an input file (can be any of dwarf, + // dwarf_edit, or dwarf_output). + template + dwarf_output (const input &dw, dwarf_output_collector *c) + : _m_units (dw.compile_units (), c) + {} + + 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); + } + }; + + // 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_die; + subr::value_set _m_ranges; }; template - inline const dwarf_output::debug_info_entry & + inline const dwarf_output::range_list & dwarf_output::collect (dwarf_output_collector *c, - const typename input::debug_info_entry &die) + const typename input::range_list &rl) { - return c->_m_die.add (die); + return c->_m_ranges.add (rl); } }; diff --git a/libdw/c++/edit-values.cc b/libdw/c++/edit-values.cc index eb957492a..aaa8a2768 100644 --- a/libdw/c++/edit-values.cc +++ b/libdw/c++/edit-values.cc @@ -49,49 +49,12 @@ #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_data::attr_value::what_space () const; template<> std::string @@ -104,7 +67,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 +78,7 @@ dwarf_edit::source_file::to_string () const } std::string -dwarf_edit::location_attr::to_string () const +dwarf_data::location_attr::to_string () const { return is_list () ? "XXX-loclist" : "XXX-expr"; } 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..abba7fa09 --- /dev/null +++ b/libdw/c++/output-values.cc @@ -0,0 +1,69 @@ +/* elfutils::dwarf_output attribute value interfaces. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#include +#include "dwarf_output" +#include "data-values.hh" + +#include + +using namespace elfutils; + +template +dwarf::value_space dwarf_data::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 527f0c073..6b4508ba4 100644 --- a/libdw/c++/subr.hh +++ b/libdw/c++/subr.hh @@ -14,21 +14,92 @@ #include #include #include +#include namespace elfutils { namespace subr { - // XXX template - struct hash { }; + struct hash : public T::hasher {}; template inline void hash_combine (size_t &seed, const T &v) { - seed ^= hash (v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= hash () (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, subr::hash (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) + { + return v._m_hash; + } + }; + template struct name_equal : public std::binary_function { @@ -278,33 +349,34 @@ namespace elfutils }; // Pair of some value and its precomputed hash. - template + template class hashed_value - : public std::pair + : public std::pair { private: - typedef std::pair _base; + typedef std::pair _base; public: - hashed_value (const value_type &v) - : _base (subr::hash (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; - } + typedef T value_type; struct hasher - : public std::unary_function, size_t> + : public std::unary_function { - size_t operator () (const hashed_value &v) + inline size_t operator () (const hashed_value &v) { return v.first; } }; + + hashed_value (const value_type &v) + : _base (subr::hash (v), v) {} + hashed_value (const hashed_value &v) + : _base (v.first, v.second) {} + + bool operator== (const hashed_value &other) const + { + return other.first == this->first && other.second == this->second; + } }; // Set of hashed_value's. @@ -329,25 +401,26 @@ namespace elfutils { // XXX hook for collection: abbrev building, etc. } - return *p.first; + return p.first->second; }; }; - // A vector of hashed_value's that itself acts like a hashed_value. - template - class hashed_vector - : public std::vector > + // 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 hashed_value elt_type; - typedef std::vector _base; + typedef container _base; + typedef typename container::value_type elt_type; + public: + typedef typename elt_type::value_type value_type; + + private: size_t _m_hash; - public: - template - hashed_vector (iterator first, iterator last) - : _base (first, last), _m_hash (0) + inline void set_hash () { struct hashit { @@ -361,29 +434,48 @@ namespace elfutils std::for_each (_base::begin (), _base::end (), hashit (_m_hash)); } - template - hashed_vector (const container &other) - : hashed_vector (other.begin (), other.end ()) - {} + 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_vector &other) const + bool operator== (const hashed_container &other) const { return (other._m_hash == _m_hash && other.size () == _base::size () && std::equal (_base::begin (), _base::end (), other.begin ())); } - - struct hasher - : public std::unary_function, size_t> - { - size_t operator () (const hashed_vector &v) - { - return v._m_hash; - } - }; }; + // 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 - hashed_unordered_map (iterator first, iterator last) - : _base (first, last), _m_hash (0) + inline void set_hash () { - class hashit + struct hashit { size_t &_m_hash; hashit (size_t &h) : _m_hash (h) {} - void operator () (const typename _base::value_type &p) + inline void operator () (const typename _base::value_type &p) { subr::hash_combine (_m_hash, subr::hash (p.first)); subr::hash_combine (_m_hash, p.second.first); @@ -417,11 +506,25 @@ namespace elfutils std::for_each (_base::begin (), _base::end (), hashit (_m_hash)); } + public: + friend class hashed_hasher; + 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) - : hashed_unordered_map (other.begin (), other.end ()) - {} + : _base (other.begin (), other.end ()), _m_hash (0) + { + set_hash (); + } }; +#endif template class auto_ref @@ -442,8 +545,52 @@ namespace elfutils 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* ()); + } + }; }; }; 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/dwarfcmp.cc b/src/dwarfcmp.cc index 370f1ad06..cffa5fa16 100644 --- a/src/dwarfcmp.cc +++ b/src/dwarfcmp.cc @@ -133,8 +133,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_;