diff options
| -rw-r--r-- | libdw/c++/dwarf_data | 252 | ||||
| -rw-r--r-- | libdw/c++/dwarf_edit | 23 | ||||
| -rw-r--r-- | libdw/c++/dwarf_output | 22 | ||||
| -rw-r--r-- | tests/Makefile.am | 6 | ||||
| -rw-r--r-- | tests/dwarf-print.cc | 69 | ||||
| -rw-r--r-- | tests/dwarf_edit.cc | 68 | ||||
| -rw-r--r-- | tests/print-die.hh | 75 |
7 files changed, 384 insertions, 131 deletions
diff --git a/libdw/c++/dwarf_data b/libdw/c++/dwarf_data index 423028f2..6d039009 100644 --- a/libdw/c++/dwarf_data +++ b/libdw/c++/dwarf_data @@ -52,6 +52,7 @@ #include "dwarf" #include <bitset> +#include <typeinfo> /* This contains common classes/templates used by dwarf_output and dwarf_edit. @@ -470,7 +471,12 @@ namespace elfutils 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) {} @@ -491,10 +497,26 @@ namespace elfutils 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; - this->second = other.second; return *this; } @@ -654,9 +676,8 @@ namespace elfutils template<typename impl> struct value { - class value_dispatch + struct value_dispatch { - public: virtual ~value_dispatch () {} }; @@ -669,6 +690,8 @@ namespace elfutils struct value_string : public value_dispatch, public std::string { + inline value_string () {} + template<typename string, typename arg_type> inline value_string (const string &s, const arg_type &arg) : std::string (s) @@ -728,6 +751,10 @@ namespace elfutils { bool flag; + inline value_flag () + : flag (true) + {} + template<typename arg_type> inline value_flag (bool t, const arg_type &arg) : flag (t) @@ -739,6 +766,10 @@ namespace elfutils // XXX dwfl, reloc ::Dwarf_Addr addr; + inline value_address () + : addr (0) + {} + template<typename arg_type> inline value_address (::Dwarf_Addr x, const arg_type &arg) : addr (x) @@ -747,6 +778,8 @@ namespace elfutils struct value_rangelistptr : public value_dispatch, public range_list { + inline value_rangelistptr () {} + template<typename list, typename arg_type> inline value_rangelistptr (const list &other, const arg_type &arg) : range_list (other) @@ -755,6 +788,8 @@ namespace elfutils struct value_lineptr : public value_dispatch, public impl::line_info_table { + inline value_lineptr () {} + template<typename table, typename arg_type> inline value_lineptr (const table &other, const arg_type &arg) : impl::line_info_table (other) @@ -769,6 +804,10 @@ namespace elfutils ::Dwarf_Sword sword; }; + inline value_constant () + : word (0) + {} + template<typename arg_type> inline value_constant (::Dwarf_Word x, const arg_type &arg) : word (x) @@ -778,6 +817,8 @@ namespace elfutils struct value_constant_block : public value_dispatch, public std::vector<uint8_t> { + inline value_constant_block () {} + template<typename block, typename arg_type> inline value_constant_block (const block &b, const arg_type &arg) : std::vector<uint8_t> (b.begin (), b.end ()) @@ -786,6 +827,8 @@ namespace elfutils struct value_dwarf_constant : public value_dispatch, public dwarf_enum { + inline value_dwarf_constant () {} + template<typename constant, typename arg_type> inline value_dwarf_constant (const constant &other, const arg_type &arg) : dwarf_enum (other) @@ -794,6 +837,8 @@ namespace elfutils struct value_source_file : public value_dispatch, public source_file { + inline value_source_file () {} + template<typename file, typename arg_type> inline value_source_file (const file &other, const arg_type &arg) : source_file (other) @@ -804,6 +849,10 @@ namespace elfutils { unsigned int n; + inline value_source_line () + : n (0) + {} + template<typename arg_type> inline value_source_line (unsigned int m, const arg_type &arg) : n (m) @@ -815,6 +864,8 @@ namespace elfutils struct value_location : public value_dispatch, public location_attr { + inline value_location () {} + template<typename loc, typename arg_type> inline value_location (const loc &other, const arg_type &arg) : location_attr (other) @@ -828,56 +879,60 @@ namespace elfutils private: typename vw::value_dispatch *_m_value; - template<typename value, typename arg_type> - inline void init (const value &other, const arg_type &arg) + template<typename value, typename arg_type = nothing> + struct init { - switch (other.what_space ()) - { -#define _DWARF_DATA_AV_MAKE(flavor, fetch) \ - case dwarf::VS_##flavor: \ - { \ - typename vw::value_##flavor *p; \ - _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; - _m_value = vw::make (p, other.constant (), arg); - } - else - { - typename vw::value_constant_block *p; - _m_value = vw::make (p, other.constant_block (), arg); - } - break; - - default: - case dwarf::VS_discr_list: - throw std::runtime_error ("XXX unimplemented"); + inline init (attr_value *av, + const value &other, const arg_type &arg = arg_type ()) + { + switch (other.what_space ()) + { +#define _DWARF_DATA_AV_MAKE(flavor, fetch) \ + case dwarf::VS_##flavor: \ + { \ + typename vw::value_##flavor *p; \ + av->_m_value = vw::make (p, other.fetch (), arg); \ + } \ + break + + _DWARF_DATA_AV_MAKE (identifier, identifier); + _DWARF_DATA_AV_MAKE (string, string); + _DWARF_DATA_AV_MAKE (flag, flag); + _DWARF_DATA_AV_MAKE (rangelistptr, ranges); + _DWARF_DATA_AV_MAKE (lineptr, line_info); + _DWARF_DATA_AV_MAKE (address, address); + _DWARF_DATA_AV_MAKE (source_line, source_line); + _DWARF_DATA_AV_MAKE (source_file, source_file); + _DWARF_DATA_AV_MAKE (dwarf_constant, dwarf_constant); + _DWARF_DATA_AV_MAKE (reference, reference); + _DWARF_DATA_AV_MAKE (unit_reference, unit_reference); + _DWARF_DATA_AV_MAKE (location, location); + //_DWARF_DATA_AV_MAKE (macptr, macros); XXX + + case dwarf::VS_constant: + if (other.constant_is_integer ()) + { + typename vw::value_constant *p; + av->_m_value = vw::make (p, other.constant (), arg); + } + else + { + typename vw::value_constant_block *p; + av->_m_value = vw::make (p, other.constant_block (), arg); + } + break; + + default: + case dwarf::VS_discr_list: + throw std::runtime_error ("XXX unimplemented"); #undef _DWARF_DATA_AV_MAKE - } - } + } + } + }; template<typename flavor> - inline flavor &variant () const + inline flavor &const_variant () const { flavor *p = dynamic_cast<flavor *> (_m_value); if (p == NULL) @@ -885,20 +940,33 @@ namespace elfutils return *p; } + template<typename flavor> + inline flavor &variant () const + { + return const_variant<flavor> (); + } + + template<typename flavor> + inline flavor &variant () + { + if (_m_value == NULL) + _m_value = new flavor; + return const_variant<flavor> (); + } + public: - /* attr_value (const attr_value &other) : _m_value (NULL) { - init (other); + if (other._m_value != NULL) + init<attr_value> me (this, other); } - */ template<typename value, typename arg_type> attr_value (const value &other, const arg_type &arg) : _m_value (NULL) { - init (other, arg); + init<value, arg_type> me (this, other, arg); } inline attr_value () @@ -918,7 +986,7 @@ namespace elfutils delete _m_value; _m_value = NULL; } - init (other); + init<attr_value> me (this, other); return *this; } template<typename value> @@ -929,7 +997,7 @@ namespace elfutils delete _m_value; _m_value = NULL; } - init (other); + init<value> me (this, other); return *this; } @@ -964,49 +1032,95 @@ namespace elfutils (variant<typename vw::value_location> ()); } + inline std::string &string () + { + return static_cast<std::string &> + (variant<typename vw::value_string> ()); + } inline const std::string &string () const { return static_cast<const std::string &> (variant<typename vw::value_string> ()); } + inline std::string &identifier () + { + return string (); + } inline const std::string &identifier () const { return string (); } - inline typename impl::source_file &source_file () const + inline const typename impl::source_file &source_file () const + { + return static_cast<typename impl::source_file &> + (variant<typename vw::value_source_file> ()); + } + + inline typename impl::source_file &source_file () { return static_cast<typename impl::source_file &> (variant<typename vw::value_source_file> ()); } - inline unsigned int &source_line () const + inline const unsigned int &source_line () const + { + return variant<typename vw::value_source_line> ().n; + } + + inline unsigned int &source_line () { return variant<typename vw::value_source_line> ().n; } - inline unsigned int &source_column () const + inline const unsigned int &source_column () const + { + return variant<typename vw::value_source_column> ().n; + } + + inline unsigned int &source_column () { return variant<typename vw::value_source_column> ().n; } - inline ::Dwarf_Word &constant () const + inline const ::Dwarf_Word &constant () const + { + return variant<typename vw::value_constant> ().word; + } + + inline ::Dwarf_Word &constant () { return variant<typename vw::value_constant> ().word; } - inline ::Dwarf_Sword &signed_constant () const + inline const ::Dwarf_Sword &signed_constant () const + { + return variant<typename vw::value_constant> ().sword; + } + + inline ::Dwarf_Sword &signed_constant () { return variant<typename vw::value_constant> ().sword; } - inline std::vector<uint8_t> &constant_block () const + inline const std::vector<uint8_t> &constant_block () const + { + return static_cast<std::vector<uint8_t> &> + (variant<typename vw::value_constant_block> ()); + } + + inline std::vector<uint8_t> &constant_block () { return static_cast<std::vector<uint8_t> &> (variant<typename vw::value_constant_block> ()); } - inline typename impl::dwarf_enum &dwarf_constant () const + inline const typename impl::dwarf_enum &dwarf_constant () const + { + return variant<typename vw::value_dwarf_constant> (); + } + + inline typename impl::dwarf_enum &dwarf_constant () { return variant<typename vw::value_dwarf_constant> (); } @@ -1016,13 +1130,25 @@ namespace elfutils return dynamic_cast<typename vw::value_constant *> (_m_value) != NULL; } - inline typename impl::range_list &ranges () const + inline const typename impl::range_list &ranges () const + { + return static_cast<range_list &> + (variant<typename vw::value_rangelistptr> ()); + } + + inline typename impl::range_list &ranges () { return static_cast<range_list &> (variant<typename vw::value_rangelistptr> ()); } - inline typename impl::line_info_table &line_info () const + inline const typename impl::line_info_table &line_info () const + { + return static_cast<typename impl::line_info_table &> + (variant<typename vw::value_lineptr> ()); + } + + inline typename impl::line_info_table &line_info () { return static_cast<typename impl::line_info_table &> (variant<typename vw::value_lineptr> ()); diff --git a/libdw/c++/dwarf_edit b/libdw/c++/dwarf_edit index 239fb3f7..8e12c5da 100644 --- a/libdw/c++/dwarf_edit +++ b/libdw/c++/dwarf_edit @@ -119,6 +119,12 @@ namespace elfutils 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 @@ -207,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; @@ -258,10 +270,9 @@ namespace elfutils 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 (); } @@ -290,6 +301,12 @@ 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 () {} diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output index 255afa27..ff2621ba 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -328,6 +328,28 @@ namespace elfutils return result; } }; + + template<typename flavor, typename input> + static inline value_dispatch * + make (flavor *&result, const input &x, const dwarf_data::nothing &) + { + throw std::logic_error ("dwarf_output cannot be default-constructed"); + } + + template<typename flavor, typename input, typename arg_type> + static inline value_dispatch * + make (flavor *&result, const input &x, const arg_type &arg) + { + return result = new flavor (x, arg); + } + + template<typename input> + static inline value_dispatch * + make (value_string *&result, const input &x, dwarf_output_collector *c) + { + return result = new value_string (x, c); + } + }; public: diff --git a/tests/Makefile.am b/tests/Makefile.am index ba950088..3531c9d2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -60,7 +60,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 @@ -193,6 +194,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 d37a006a..8d09ba15 100644 --- a/tests/dwarf-print.cc +++ b/tests/dwarf-print.cc @@ -41,6 +41,8 @@ using namespace elfutils; using namespace std; +#include "print-die.hh" + static Dwarf * open_file (const char *fname) { @@ -57,75 +59,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 << "</" << tag << ">\n"; - } - else - cout << "/>\n"; -} - -static void -process_file (const char *file, unsigned int limit) -{ - dwarf dw (open_file (file)); - - cout << file << ":\n"; - - for (dwarf::compile_units::const_iterator i = dw.compile_units ().begin (); - i != dw.compile_units ().end (); - ++i) - print_die (*i, 1, limit); -} - int main (int argc, char *argv[]) { - /* Set locale. */ - (void) setlocale (LC_ALL, ""); - - /* Make sure the message catalog can be found. */ - (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); - - /* Initialize the message catalog. */ - (void) textdomain (PACKAGE_TARNAME); - - cout << hex << setiosflags (ios::showbase); - - unsigned int depth = 0; - if (argc > 1 && sscanf (argv[1], "--depth=%u", &depth) == 1) - { - --argc; - ++argv; - } + unsigned int depth; + print_die_main (argc, argv, depth); for (int i = 1; i < argc; ++i) - process_file (argv[i], depth); + print_file (argv[i], dwarf (open_file (argv[i])), depth); return 0; } diff --git a/tests/dwarf_edit.cc b/tests/dwarf_edit.cc new file mode 100644 index 00000000..35e6b1c2 --- /dev/null +++ b/tests/dwarf_edit.cc @@ -0,0 +1,68 @@ +/* Test program for elfutils::dwarf_edit basics. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <clocale> +#include <cstdio> +#include <libintl.h> +#include <ostream> +#include <iomanip> + +#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 00000000..c4ff8a25 --- /dev/null +++ b/tests/print-die.hh @@ -0,0 +1,75 @@ + +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); + + depth = 0; + if (argc > 1 && sscanf (argv[1], "--depth=%u", &depth) == 1) + { + --argc; + ++argv; + } +} + +template<typename file> +static void +print_die (const typename file::debug_info_entry &die, + unsigned int indent, unsigned int limit) +{ + string prefix (indent, ' '); + const string tag = dwarf::tags::name (die.tag ()); + + cout << prefix << "<" << tag << " offset=[" << die.offset () << "]"; + + for (typename file::debug_info_entry::attributes_type::const_iterator i + = die.attributes ().begin (); i != die.attributes ().end (); ++i) + cout << " " << to_string (*i); + + if (die.has_children ()) + { + if (limit != 0 && indent >= limit) + { + cout << ">...\n"; + return; + } + + cout << ">\n"; + + for (typename file::debug_info_entry::children_type::const_iterator i + = die.children ().begin (); i != die.children ().end (); ++i) + print_die<file> (*i, indent + 1, limit); + + cout << prefix << "</" << tag << ">\n"; + } + else + cout << "/>\n"; +} + +template<typename file> +static void +print_cu (const typename file::compile_unit &cu, const unsigned int limit) +{ + print_die<file> (static_cast<const typename file::debug_info_entry &> (cu), + 1, limit); +} + +template<typename file> +static void +print_file (const char *name, const file &dw, const unsigned int limit) +{ + cout << name << ":\n"; + + for (typename file::compile_units::const_iterator i + = dw.compile_units ().begin (); i != dw.compile_units ().end (); ++i) + print_cu<file> (*i, limit); +} |
