+2009-03-25 Roland McGrath <roland@redhat.com>
+
+ * c++/dwarf, c++/values.cc: Proper dwarf_constant support.
+ * c++/dwarf_edit, c++/edit-values.cc: Likewise.
+ * c++/known.cc: New file.
+ * Makefile.am (libdwpp_a_SOURCES): Add it.
+
2009-03-24 Petr Machata <pmachata@redhat.com>
* c++/dwarf (dwarf::debug_info_entry::raw_attributes):
return attributes::name (code);
}
+ template<int key>
+ class known_enum
+ {
+ public:
+ static size_t prefix_length ();
+ static const char *identifier (int);
+ inline static const char *name (int value)
+ {
+ const char *id = identifier (value);
+ return id != NULL ? id + prefix_length () : NULL;
+ }
+
+ // XXX perhaps have iterator/lookup methods like a read-only map?
+ };
+
+ typedef known_enum< ::DW_AT_producer> forms;
+ typedef known_enum< ::DW_AT_location> ops;
+
private:
// XXX make this an instance method to include irritant context
static void throw_libdw (void) // XXX raises (...)
class file_table;
class line_table;
class line_entry;
+ class dwarf_enum;
class debug_info_entry
{
friend class attribute;
friend class location_attr;
friend class range_list;
+ friend class dwarf_enum;
private:
const int _m_tag;
::Dwarf_Attribute _m_attr;
{
return const_cast< ::Dwarf_Attribute *> (&_m_attr);
}
+ inline int whatattr () const
+ {
+ return ::dwarf_whatattr (thisattr ());
+ }
attr_value (int tag, const ::Dwarf_Attribute &attr)
: _m_tag (tag), _m_attr (attr) {}
::Dwarf_Word constant () const;
::Dwarf_Sword signed_constant () const;
const_vector<uint8_t> constant_block () const;
+ bool constant_is_integer () const;
- // XXX known enums
- // dwarf_enum dwarf_constant () const;
+ inline const dwarf_enum dwarf_constant () const
+ {
+ return dwarf_enum (*this);
+ }
inline const range_list ranges () const
{
case VS_macptr: // XXX punt for now, treat as constant
/*FALLTHRU*/
- case VS_constant:
case VS_dwarf_constant:
return constant () == other.constant ();
+ case 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 VS_source_line:
return source_line () == other.source_line ();
case VS_source_column:
}
};
+ class dwarf_enum
+ {
+ friend class attr_value;
+ private:
+ const attr_value _m_attr;
+
+ dwarf_enum (const attr_value &attr) : _m_attr (attr) {}
+
+ public:
+ inline operator unsigned int () const
+ {
+ return _m_attr.constant ();
+ }
+
+ std::string to_string () const;
+
+ const char *identifier () const;
+ const char *name () const;
+ };
+
// This describes one attribute, equivalent to pair<const int, attr_value>.
class attribute
{
_m_value = new value_address (other.address ());
break;
case dwarf::VS_constant:
- _m_value = new value_constant (other.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 ());
_m_value = new value_source_file (other.source_file ());
break;
case dwarf::VS_dwarf_constant:
- _m_value = new value_dwarf_constant (other.constant ()); // XXX
+ _m_value = new value_dwarf_constant (other.dwarf_constant ());
break;
case dwarf::VS_reference:
_m_value = new value_reference (other.reference ());
(variant<value_constant_block> ());
}
- // dwarf_constant<>
+ inline ::Dwarf_Word &dwarf_constant () const
+ {
+ return variant<value_dwarf_constant> ().word;
+ }
+
+ inline bool constant_is_integer () const
+ {
+ return dynamic_cast<value_constant *> (_m_value) != NULL;
+ }
inline range_list &ranges () const
{
case dwarf::VS_lineptr:
return line_info () == other.line_info ();
case dwarf::VS_constant:
- return constant () == other.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 dwarf::VS_source_column;
if (typeid (*_m_value) == typeid (value_address))
return dwarf::VS_address;
- if (typeid (*_m_value) == typeid (value_constant))
+ 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;
+/* Known named integer values in DWARF.
+ Copyright (C) 2009 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the
+ additional right to link the code of Red Hat elfutils with code licensed
+ under any Open Source Initiative certified open source license
+ (http://www.opensource.org/licenses/index.php) which requires the
+ distribution of source code with any binary distribution and to
+ distribute linked combinations of the two. Non-GPL Code permitted under
+ this exception must only link to the code of Red Hat elfutils through
+ those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files
+ of Non-GPL Code may instantiate templates or use macros or inline
+ functions from the Approved Interfaces without causing the resulting
+ work to be covered by the GNU General Public License. Only Red Hat,
+ Inc. may make changes or additions to the list of Approved Interfaces.
+ Red Hat's grant of this exception is conditioned upon your not adding
+ any new exceptions. If you wish to add a new Approved Interface or
+ exception, please contact Red Hat. You must obey the GNU General Public
+ License in all respects for all of the Red Hat elfutils code and other
+ code used in conjunction with Red Hat elfutils except the Non-GPL Code
+ covered by this exception. If you modify this file, you may extend this
+ exception to your version of the file, but you are not obligated to do
+ so. If you do not wish to provide this exception without modification,
+ you must delete this exception statement from your version and license
+ this file solely under the GPL without exception.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
#include <config.h>
#include "dwarf"
#include "known-dwarf.h"
}
return NULL;
}
+
+namespace elfutils
+{
+ template<int key>
+ size_t
+ dwarf::known_enum<key>::prefix_length ()
+ {
+ return 0;
+ }
+
+ template<int key>
+ const char *
+ dwarf::known_enum<key>::identifier (int value)
+ {
+ return NULL;
+ }
+
+#define ALL_KNOWN_ENUM \
+ KNOWN_ENUM (accessibility, ACCESS) \
+ KNOWN_ENUM (encoding, ATE) \
+ KNOWN_ENUM (calling_convention, CC) \
+ KNOWN_ENUM (decimal_sign, DS) \
+ KNOWN_ENUM (endianity, END) \
+ KNOWN_ENUM (identifier_case, ID) \
+ KNOWN_ENUM (inline, INL) \
+ KNOWN_ENUM (language, LANG) \
+ KNOWN_ENUM (ordering, ORD) \
+ KNOWN_ENUM (virtuality, VIRTUALITY) \
+ KNOWN_ENUM (visibility, VIS)
+
+#define ONE_KNOWN_DW_ACCESS(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_ATE(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_CC(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_DS(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_END(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_ID(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_INL(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_LANG(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_LANG_DESC(name, id, desc) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_ORD(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_INL(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_VIRTUALITY(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_VIS(name, id) KNOWN_ENUM_CASE (id)
+
+ // Stupid C++ doesn't do [x] = y initializers.
+#define KNOWN_ENUM(attr, enum) \
+ template<> \
+ size_t \
+ dwarf::known_enum<DW_AT_##attr>::prefix_length () \
+ { \
+ return sizeof ("DW_" #enum "_") - 1; \
+ } \
+ template<> \
+ const char * \
+ dwarf::known_enum<DW_AT_##attr>::identifier (int value) \
+ { \
+ switch (value) \
+ { \
+ ALL_KNOWN_DW_##enum \
+ } \
+ return NULL; \
+ }
+#define KNOWN_ENUM_CASE(id) case id: return #id;
+
+ ALL_KNOWN_ENUM
+
+ // Not really enum cases, but pretend they are.
+#define ONE_KNOWN_DW_FORM(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_OP(name, id) KNOWN_ENUM_CASE (id)
+#define ONE_KNOWN_DW_OP_DESC(name, id, desc) KNOWN_ENUM_CASE (id)
+ KNOWN_ENUM (producer, FORM)
+ KNOWN_ENUM (location, OP)
+
+#undef KNOWN_ENUM
+#undef KNOWN_ENUM_CASE
+};
+
+const char *
+dwarf::dwarf_enum::identifier () const
+{
+ switch (_m_attr.whatattr ())
+ {
+# define KNOWN_ENUM(attr, enum) \
+ case DW_AT_##attr: \
+ return dwarf::known_enum<DW_AT_##attr>::identifier (*this);
+
+ ALL_KNOWN_ENUM
+
+# undef KNOWN_ENUM
+ }
+
+ return NULL;
+}
+
+const char *
+dwarf::dwarf_enum::name () const
+{
+ switch (_m_attr.whatattr ())
+ {
+# define KNOWN_ENUM(attr, enum) \
+ case DW_AT_##attr: \
+ return dwarf::known_enum<DW_AT_##attr>::name (*this);
+
+ ALL_KNOWN_ENUM
+
+# undef KNOWN_ENUM
+ }
+
+ return NULL;
+}
+
+std::string
+dwarf::dwarf_enum::to_string () const
+{
+ const char *known = name ();
+ return known == NULL ? subr::hex_string (*this) : std::string (known);
+}
case VS_lineptr: // XXX punt for now, treat as constant
case VS_macptr: // XXX punt for now, treat as constant
case VS_constant:
- case VS_dwarf_constant:
return hex_string (constant ());
+ case VS_dwarf_constant:
+ return dwarf_constant ().to_string ();
+
case VS_source_line:
case VS_source_column:
return dec_string (constant ());
return result;
}
+bool
+dwarf::attr_value::constant_is_integer () const
+{
+ switch (dwarf_whatform (thisattr ()))
+ {
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ return false;
+
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ case DW_FORM_udata:
+ case DW_FORM_sdata:
+ return true;
+
+ default:
+ throw std::runtime_error ("XXX wrong form");
+ }
+}
+
+
const_vector<uint8_t>
dwarf::attr_value::constant_block () const
{
#! /bin/sh
-# Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Red Hat, Inc.
+# Copyright (C) 2009 Red Hat, Inc.
# This file is part of Red Hat elfutils.
-# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
#
# 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
testrun_compare ./dwarf-print --depth=1 testfile <<\EOF
testfile:
- <compile_unit offset=[0xb] stmt_list=0 high_pc=0x804845a low_pc=0x804842c name="m.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=0x1>...
- <compile_unit offset=[0xca] stmt_list=0x4b high_pc=0x8048466 low_pc=0x804845c name="b.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=0x1>...
- <compile_unit offset=[0x15fc] stmt_list=0x1e0 high_pc=0x8048472 low_pc=0x8048468 name="f.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=0x1>...
+ <compile_unit offset=[0xb] stmt_list=0 high_pc=0x804845a low_pc=0x804842c name="m.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
+ <compile_unit offset=[0xca] stmt_list=0x4b high_pc=0x8048466 low_pc=0x804845c name="b.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
+ <compile_unit offset=[0x15fc] stmt_list=0x1e0 high_pc=0x8048472 low_pc=0x8048468 name="f.c" comp_dir="/home/drepper/gnu/new-bu/build/ttt" producer="GNU C 2.96 20000731 (Red Hat Linux 7.0)" language=C89>...
EOF
exit 0