public:
inline const_iterator ()
- : _m_raw (), _m_end ()
+ : _m_raw (), _m_end (raw::end ())
{
}
}
inline const_iterator (const debug_info_entry &die, ptrdiff_t offset)
- : _m_die (die), _m_offset (offset), _m_attr () {}
+ : _m_die (die), _m_offset (offset), _m_attr ()
+ {}
+
+ inline const_iterator (ptrdiff_t offset)
+ : _m_die (), _m_offset (offset), _m_attr ()
+ {}
public:
+ // Default constructor: invalid for anything but operator=.
+ inline const_iterator ()
+ : _m_die (), _m_offset (-1), _m_attr ()
+ {}
+
inline const_iterator (const const_iterator &i)
- : _m_die (i._m_die), _m_offset (i._m_offset), _m_attr (i._m_attr) {}
+ : _m_die (i._m_die), _m_offset (i._m_offset), _m_attr (i._m_attr)
+ {}
inline const_iterator &operator= (const const_iterator &other)
{
(void *) this, _m_offset);
_m_die.xif (result < 0);
_m_offset = result;
+ if (result == 1)
+ // End iterators have no live pointers.
+ _m_die._m_die.addr = NULL;
return *this;
}
inline const_iterator operator++ (int) // postfix
const_iterator i = const_iterator (_m_die, 0);
return ++i;
}
- inline const_iterator end () const
+ static inline const_iterator end ()
{
- return const_iterator (_m_die, 1);
+ return const_iterator (1);
}
// XXX can do faster internal (?)
}
};
- /* A location attribute yields a location expression.
- Either it's a single expression, or a map of PC to location. */
- class location_attr
- {
- friend class attr_value;
- private:
- attr_value _m_attr;
-
- location_attr (const attr_value &attr) : _m_attr (attr) {}
-
- inline bool same (const location_attr &it) const
- {
- return _m_attr.same (it._m_attr);
- }
-
- template<typename pair>
- struct nonempty : public std::unary_function<pair, bool>
- {
- inline bool operator () (const pair &x)
- {
- return !x.second.empty ();
- }
- };
-
- template<typename pair>
- struct any : public std::unary_function<pair, bool>
- {
- inline bool operator () (const pair &)
- {
- return true;
- }
- };
-
- public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- // XXX need proper type for exprs
- typedef const_vector<uint8_t> mapped_type;
- typedef std::pair< ::Dwarf_Addr, ::Dwarf_Addr> key_type; // XXX reloc
- typedef std::pair<const key_type, mapped_type> value_type;
- class const_iterator; // below
-
- std::string to_string () const;
-
- bool is_list () const;
-
- inline mapped_type location () const
- {
- if (is_list ())
- throw std::runtime_error ("location is list, not single location");
- return _m_attr.constant_block ();
- }
-
- inline const_iterator begin () const;
- inline const_iterator end () const;
-
- inline bool empty () const
- {
- if (is_list ())
- return std::find_if (begin (), end (),
- nonempty<value_type> ()) == end ();
- return location ().empty ();
- }
- inline size_type size () const
- {
- if (is_list ())
- return std::count_if (begin (), end (), any<value_type> ());
- return location ().empty () ? 0 : 1;
- }
-
- template<typename other_attr>
- bool operator== (const other_attr &other) const
- {
- if (empty ())
- return (other.empty ()
- || std::find_if (other.begin (), other.end (),
- nonempty<typename other_attr::value_type> ()
- ) == other.end ());
- if (!is_list ())
- return (!other.is_list () && !other.empty ()
- && location () == other.location ());
-
- return other.is_list () && subr::container_equal (*this, other);
- }
- template<typename other_file>
- inline bool operator!= (const other_file &other) const
- {
- return !(*this == other);
- }
-
- /*
- XXX missing: find, at; by key_type or by PC
- XXX worse than that: multiple overlapping matches!
- */
- };
-
- class location_attr::const_iterator
- : public std::iterator<std::input_iterator_tag, location_attr::value_type>
- {
- friend class location_attr;
- private:
- ::Dwarf_Addr _m_base; // XXX reloc
- ::Dwarf_Addr _m_begin; // XXX reloc
- ::Dwarf_Addr _m_end; // XXX reloc
- location_attr _m_attr;
- ptrdiff_t _m_offset;
-
- const_iterator (const location_attr &loc, ptrdiff_t offset)
- : _m_base (-1), _m_begin (1), _m_end (0),
- _m_attr (loc), _m_offset (offset) {}
-
- public:
-
- inline bool operator== (const const_iterator &it) const
- {
- return _m_offset == it._m_offset && _m_attr.same (it._m_attr);
- }
- inline bool operator!= (const const_iterator &it) const
- {
- return !(*this == it);
- };
-
- const_iterator &operator++ (); // prefix
- inline const_iterator operator++ (int) // postfix
- {
- const_iterator prev = *this;
- ++*this;
- return prev;
- }
-
- inline value_type operator* () const
- {
- if (unlikely (_m_offset == 1))
- throw std::runtime_error ("dereferencing end iterator");
-
- return value_type (key_type (_m_base + _m_begin, _m_base + _m_end),
- _m_attr.location ());
- }
- };
-
/* The DW_AT_ranges attribute yields a range list.
XXX reloc
This is equivalent to unordered_set<pair<Dwarf_Addr, Dwarf_Addr> >. */
: public std::iterator<std::input_iterator_tag, value_type>
{
friend class range_list;
- private:
+ protected:
::Dwarf_Addr _m_base; // XXX reloc
::Dwarf_Addr _m_begin; // XXX reloc
::Dwarf_Addr _m_end; // XXX reloc
const_iterator (Dwarf_Attribute *, ptrdiff_t);
public:
+ // Default constructor: only valid for operator=.
+ inline const_iterator ()
+ : _m_base (-1), _m_begin (0), _m_end (0), _m_cu (NULL), _m_offset (-1)
+ {}
+
inline const_iterator (const const_iterator &i)
: _m_base (i._m_base), _m_begin (i._m_begin), _m_end (i._m_end),
- _m_cu (i._m_cu), _m_offset (i._m_offset) {}
+ _m_cu (i._m_cu), _m_offset (i._m_offset)
+ {}
inline value_type operator* () const
{
}
};
+ /* A location attribute yields a location expression.
+ Either it's a single expression, or a map of PC to location. */
+ class location_attr
+ {
+ friend class attr_value;
+ private:
+ attr_value _m_attr;
+
+ location_attr (const attr_value &attr) : _m_attr (attr) {}
+
+ inline bool same (const location_attr &it) const
+ {
+ return _m_attr.same (it._m_attr);
+ }
+
+ template<typename pair>
+ struct nonempty : public std::unary_function<pair, bool>
+ {
+ inline bool operator () (const pair &x)
+ {
+ return !x.second.empty ();
+ }
+ };
+
+ template<typename pair>
+ struct any : public std::unary_function<pair, bool>
+ {
+ inline bool operator () (const pair &)
+ {
+ return true;
+ }
+ };
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ // XXX need proper type for exprs
+ typedef const_vector<uint8_t> mapped_type;
+ typedef std::pair< ::Dwarf_Addr, ::Dwarf_Addr> key_type; // XXX reloc
+ typedef std::pair<const key_type, mapped_type> value_type;
+
+ std::string to_string () const;
+
+ bool is_list () const;
+
+ inline mapped_type location () const
+ {
+ if (is_list ())
+ throw std::runtime_error ("location is list, not single location");
+ return _m_attr.constant_block ();
+ }
+
+ class const_iterator
+ : public range_list::const_iterator
+ {
+ friend class location_attr;
+ private:
+ ::Dwarf_Block _m_block;
+
+ void advance ();
+
+ inline const_iterator (Dwarf_Attribute *attr, ptrdiff_t offset)
+ : range_list::const_iterator (attr, offset), _m_block ()
+ {}
+
+ public:
+ typedef location_attr::value_type value_type;
+
+ inline const_iterator ()
+ : _m_block ()
+ {}
+
+ inline const_iterator (const const_iterator &i)
+ : range_list::const_iterator (i), _m_block (i._m_block)
+ {}
+
+ inline const_iterator &operator= (const const_iterator &i)
+ {
+ range_list::const_iterator::operator= (i);
+ _m_block = i._m_block;
+ return *this;
+ }
+
+ inline bool operator== (const const_iterator &it) const
+ {
+ return _m_block.data == it._m_block.data;
+ }
+ inline bool operator!= (const const_iterator &it) const
+ {
+ return !(*this == it);
+ };
+
+ const_iterator &operator++ (); // prefix
+ inline const_iterator operator++ (int) // postfix
+ {
+ const_iterator prev = *this;
+ ++*this;
+ return prev;
+ }
+
+ inline value_type operator* () const
+ {
+ if (unlikely (_m_block.data == NULL))
+ throw std::runtime_error ("dereferencing end iterator");
+
+ return value_type (key_type (_m_base + _m_begin, _m_base + _m_end),
+ const_vector<uint8_t> (_m_block));
+ }
+ };
+
+ const_iterator begin () const;
+ inline const_iterator end () const
+ {
+ return const_iterator (_m_attr.thisattr (), 1);
+ }
+
+ inline bool empty () const
+ {
+ if (is_list ())
+ return std::find_if (begin (), end (),
+ nonempty<value_type> ()) == end ();
+ return location ().empty ();
+ }
+ inline size_type size () const
+ {
+ if (is_list ())
+ return subr::length (begin (), end ());
+ return location ().empty () ? 0 : 1;
+ }
+
+ template<typename other_attr>
+ bool operator== (const other_attr &other) const
+ {
+ if (empty ())
+ return (other.empty ()
+ || std::find_if (other.begin (), other.end (),
+ nonempty<typename other_attr::value_type> ()
+ ) == other.end ());
+ if (!is_list ())
+ return (!other.is_list () && !other.empty ()
+ && location () == other.location ());
+
+ return other.is_list () && subr::container_equal (*this, other);
+ }
+ template<typename other_file>
+ inline bool operator!= (const other_file &other) const
+ {
+ return !(*this == other);
+ }
+
+ /*
+ XXX missing: find, at; by key_type or by PC
+ XXX worse than that: multiple overlapping matches!
+ */
+ };
+
// This describes a CU's directory table, a simple array of strings.
class directory_table
{
inline directory_table (const directory_table &t)
: _m_files (t._m_files) {}
+ std::string to_string () const;
+
typedef const char *const *const_iterator;
inline bool empty () const
return *this;
}
+ std::string to_string () const;
+
typedef subr::indexed_iterator<line_table> const_iterator;
inline bool empty () const
return *this;
}
+ std::string to_string () const;
+
inline const directory_table include_directories () const
{
return directory_table (_m_files);
const dwarf *_m_file; // XXX
::Dwarf_Off _m_next; // XXX
- inline const_iterator (const dwarf &file, ::Dwarf_Off next)
- : _m_file (&file), _m_next (next) {}
+ inline const_iterator (const dwarf &file)
+ : _m_file (&file), _m_next (0) {}
public:
inline const_iterator ()
inline bool operator== (const const_iterator &other) const
{
- return _m_file == other._m_file && _m_next == other._m_next;
+ return _m_next == other._m_next && _m_file == other._m_file;
}
inline bool operator!= (const const_iterator &other) const
{
// XXX should be rewritten to use libdw_findcu internals
// slow way for first crack to avoid DSO issues
_m_next = _m_file->nextcu (_m_next, _m_die.thisdie ());
+ if (_m_next == (::Dwarf_Off) -1)
+ // End iterators have no file pointer.
+ _m_file = NULL;
return *this;
}
inline const_iterator operator++ (int) // postfix
const_iterator begin () const
{
- const_iterator it (_m_file, 0);
+ const_iterator it (_m_file);
return ++it;
}
- inline const_iterator end () const
+ static inline const_iterator end ()
{
- return const_iterator (_m_file, -1);
+ return const_iterator ();
}
};
inline raw_compile_units raw_compile_units () const
return attributes_type::attributes_type (raw_attributes ());
}
- inline dwarf::location_attr::const_iterator
- dwarf::location_attr::begin () const
- {
- const_iterator it (*this, 0);
- if (is_list ())
- ++it;
- return it;
- }
- inline dwarf::location_attr::const_iterator dwarf::location_attr::end () const
- {
- return const_iterator (*this, 1);
- }
-
// Explicit specializations.
template<>
std::string to_string<dwarf::attribute> (const dwarf::attribute &);
}
static string
-dec_string (Dwarf_Word value)
+dec_string (Dwarf_Word value, const char *before = "", const char *after = "")
{
std::ostringstream os;
- os << value;
+ os << before << value << after;
return os.str ();
}
case dwarf::VS_rangelistptr:
return value.ranges ().to_string ();
- case dwarf::VS_lineptr: // XXX punt for now, treat as constant
+ case dwarf::VS_lineptr:
+ return value.line_info ().to_string ();
+
case dwarf::VS_macptr: // XXX punt for now, treat as constant
case dwarf::VS_constant:
return hex_string (value.constant ());
return value.dwarf_constant ().to_string ();
case dwarf::VS_source_line:
+ return dec_string (value.source_line ());
+
case dwarf::VS_source_column:
- return dec_string (value.constant ());
+ return dec_string (value.source_column ());
case dwarf::VS_identifier:
return plain_string (value.identifier ());
return true;
}
+inline void
+dwarf::location_attr::const_iterator::advance ()
+{
+ xif (_m_cu, range_list_advance (IDX_debug_loc, _m_cu,
+ _m_base, _m_begin, _m_end, _m_offset,
+ &_m_block.data));
+ if (_m_offset > 1)
+ _m_offset += 2 + (_m_block.length
+ = read_2ubyte_unaligned_inc (_m_cu->dbg, _m_block.data));
+ else
+ // End iterator.
+ _m_block = Dwarf_Block ();
+}
+
+dwarf::location_attr::const_iterator
+dwarf::location_attr::begin () const
+{
+ const_iterator i (_m_attr.thisattr (), 0);
+ if (is_list ())
+ i.advance ();
+ else
+ xif (_m_attr.thisattr (),
+ dwarf_formblock (_m_attr.thisattr (), &i._m_block) < 0);
+
+ return i;
+}
+
dwarf::location_attr::const_iterator &
dwarf::location_attr::const_iterator::operator++ ()
{
if (unlikely (_m_offset == 1))
throw std::runtime_error ("incrementing end iterator");
- else if (_m_offset == 0)
+
+ if (_m_offset == 0)
// Singleton, now at end.
_m_offset = 1;
else
- {
- // Advance to next list entry.
- xif (_m_attr._m_attr.thisattr (),
- range_list_advance (IDX_debug_loc, _m_attr._m_attr._m_attr.cu,
- _m_base, _m_begin, _m_end, _m_offset,
- &_m_attr._m_attr._m_attr.valp));
- if (_m_offset > 1)
- {
- _m_attr._m_attr._m_attr.form = DW_FORM_block2;
- _m_offset += read_2ubyte_unaligned (_m_attr._m_attr._m_attr.cu->dbg,
- _m_attr._m_attr._m_attr.valp);
- }
- }
+ // Advance to next list entry.
+ advance ();
return *this;
}
+template<typename locattr>
+static string
+locattr_string (const locattr *loc)
+{
+ return (loc->is_list () ? dec_string (loc->size (), "{loclist ", " entries}")
+ : "{locexpr}");
+}
+
string
dwarf::location_attr::to_string () const
{
- if (is_list ())
- return hex_string (_m_attr.constant (), "#");
- return "XXX-expr";
+ return locattr_string (this);
}
+
+string
+dwarf_data::location_attr::to_string () const
+{
+ return locattr_string (this);
+}
+\f
+// dwarf::line_info_table
+
+template<typename line_info_table>
+static inline std::string
+line_info_string (const line_info_table *table)
+{
+ return ("[" + table->include_directories ().to_string ()
+ + ", " + table->lines ().to_string () + "]");
+}
+
+std::string
+dwarf::line_info_table::to_string () const
+{
+ return line_info_string (this);
+}
+
+namespace elfutils
+{
+ template<>
+ std::string
+ dwarf_edit::line_info_table::to_string () const
+ {
+ return line_info_string (this);
+ }
+
+};
+\f
+// dwarf::directory_table
+
+static std::string
+dirtable_string (size_t ndirs)
+{
+ return dec_string (ndirs, "{", " dirs}");
+}
+
+std::string
+dwarf::directory_table::to_string () const
+{
+ return dirtable_string (_m_files->ndirs);
+}
+
+std::string
+dwarf_data::directory_table::to_string () const
+{
+ return dirtable_string (size ());
+}
+\f
+// dwarf::line_table
+
+std::string
+dwarf::line_table::to_string () const
+{
+ return dec_string (_m_lines->nlines, "{", " line entries}");
+}
+
+namespace elfutils
+{
+ template<>
+ std::string
+ dwarf_edit::line_table::to_string () const
+ {
+ return dec_string (size (), "{", " line entries}");
+ }
+};
#include <ostream>
#include <iomanip>
#include <tr1/unordered_map>
+#include <functional>
+#include <algorithm>
#include "c++/dwarf_edit"
#include "c++/dwarf_output"
static bool print_offset;
+static bool sort_attrs;
static enum { copy_none, copy_edit, copy_output } make_copy;
++argv;
}
+ if (argc > 1 && !strcmp (argv[1], "--sort-attrs"))
+ {
+ sort_attrs = true;
+ --argc;
+ ++argv;
+ }
+
if (argc > 1 && !strcmp (argv[1], "--edit"))
{
make_copy = copy_edit;
}
}
+static int next_ref = 1;
typedef tr1::unordered_map< ::Dwarf_Off, int> refs_map;
+template<typename attrs_type,
+ void (*act) (const typename attrs_type::value_type &, refs_map &)
+ >
+class attr_walker
+{
+private:
+ refs_map &refs;
+ inline attr_walker (refs_map &r) : refs (r) {}
+
+ typedef typename attrs_type::const_iterator iterator;
+ typedef typename iterator::value_type attr_type;
+
+public:
+ inline void operator () (const pair<int, iterator> &p) const
+ {
+ (*act) (*p.second, refs);
+ }
+
+ static inline void walk (const attrs_type &attrs, refs_map &r)
+ {
+ if (attrs_type::ordered || !sort_attrs)
+ for (iterator i = attrs.begin (); i != attrs.end (); ++i)
+ (*act) (*i, r);
+ else
+ {
+ map<int, iterator> sorted;
+ for (iterator i = attrs.begin (); i != attrs.end (); ++i)
+ sorted[(*i).first] = i;
+ for_each (sorted.begin (), sorted.end (),
+ attr_walker<attrs_type, act> (r));
+ }
+ }
+};
+
+template<typename attrs_type>
+void
+print_attr (const typename attrs_type::value_type &attr, refs_map &refs)
+{
+ if (!print_offset && attr.second.what_space () == dwarf::VS_reference)
+ cout << " " << dwarf::attributes::name (attr.first) << "=\"#ref"
+ << dec << refs[attr.second.reference ()->identity ()] << "\"";
+ else
+ cout << " " << to_string (attr);
+}
+
+template<typename attrs_type>
static void
-finish_refs_map (refs_map &refs)
+print_attrs (const attrs_type &attrs, refs_map &refs)
{
- int id = 0;
- for (refs_map::iterator it = refs.begin (); it != refs.end (); ++it)
- it->second = ++id;
+ attr_walker<attrs_type, print_attr<attrs_type> >::walk (attrs, refs);
+}
+
+template<typename attrs_type>
+void
+prewalk_attr (const typename attrs_type::value_type &attr, refs_map &refs)
+{
+ if (attr.second.what_space () == dwarf::VS_reference
+ && refs.insert (make_pair (attr.second.reference ()->identity (),
+ next_ref)).second)
+ ++next_ref;
+}
+
+template<typename attrs_type>
+static void
+prewalk_attrs (const attrs_type &attrs, refs_map &refs)
+{
+ attr_walker<attrs_type, prewalk_attr<attrs_type> >::walk (attrs, refs);
}
template<typename file>
= die.children ().begin (); i != die.children ().end (); ++i)
prewalk_die<file> (*i, refs);
- for (typename file::debug_info_entry::attributes_type::const_iterator i
- = die.attributes ().begin (); i != die.attributes ().end (); ++i)
- if ((*i).second.what_space () == dwarf::VS_reference)
- refs[(*i).second.reference ()->identity ()];
+ prewalk_attrs (die.attributes (), refs);
}
template<typename file>
{
refs_map::const_iterator it = refs.find (die.identity ());
if (it != refs.end ())
- cout << " ref=\"" << hex << it->second << "\"";
+ cout << " ref=\"ref" << dec << it->second << "\"";
}
- for (typename file::debug_info_entry::attributes_type::const_iterator i
- = die.attributes ().begin (); i != die.attributes ().end (); ++i)
- {
- if (!print_offset && (*i).second.what_space () == dwarf::VS_reference)
- cout << " " << dwarf::attributes::name ((*i).first) << "=\"#"
- << hex << refs[(*i).second.reference ()->identity ()] << "\"";
- else
- cout << " " << to_string (*i);
- }
+ print_attrs (die.attributes (), refs);
if (die.has_children ())
{
refs_map refs;
if (!print_offset)
- {
- prewalk_die<file> (die, refs);
- finish_refs_map (refs);
- }
+ prewalk_die<file> (die, refs);
print_die<file> (die, 1, limit, refs);
}