: _m_size (v._m_size), _m_array (v._m_array) {}
const_vector (const elt *start, const elt *stop)
: _m_size (stop - start), _m_array (start) {}
+ const_vector (const ::Dwarf_Block &b)
+ : _m_size (b.length), _m_array (reinterpret_cast<const elt *> (b.data)) {}
inline const_vector &operator= (const const_vector &v)
{
return os.str ();
}
+ template<typename string>
+ struct name_equal : public std::binary_function<const char *, string, bool>
+ {
+ bool operator () (const char *me, const string &you)
+ {
+ return you == me;
+ }
+ };
+
public:
static const char *known_attribute (int);
static const char *known_tag (int);
: attributes_base (raw) {}
public:
+ typedef int key_type;
+ typedef attr_value mapped_type;
typedef attribute value_type;
inline attributes (const class attributes &a)
{
/* Our container is unordered (i.e., in file order). A set of
attributes is conceptually equal if all the pairs match,
- regardless of the order. But the std::equal algorithm will
+ regardless of the order. But the container_equal algorithm will
compare corresponding elements in order. So we need an ordered
map of our attributes for the comparison. */
const std::map<int, attr_value> mine = *this;
- const std::map<int, attr_value> his = other;
- return mine == his;
+ const std::map<int, typename attrs::mapped_type> his = other;
+ return mine.size () == his.size () && subr::container_equal (mine, his);
}
template<typename attrs>
if (other_size != 0 && other_size != size ())
return false;
}
- return !strcmp (name (), other.name ());
+ return name_equal<typeof (other.name ())> () (name (), other.name ());
}
-
template<typename other_file>
inline bool operator!= (const other_file &other) const
{
friend class location_attr;
friend class range_list;
private:
- const ::Dwarf_Attribute _m_attr;
+ ::Dwarf_Attribute _m_attr;
inline ::Dwarf_Attribute *thisattr () const
{
return const_cast< ::Dwarf_Attribute *> (&_m_attr);
attr_value (const ::Dwarf_Attribute &attr) : _m_attr (attr) {}
+ inline bool same (const attr_value &other) const
+ {
+ return _m_attr.valp == other._m_attr.valp;
+ }
+
public:
// not copyable, don't worry about ref lifetime(?)
// attr_value (const attr_value &v) : _m_attr (v.attr) {}
{
return debug_info_entry::raw_children::const_iterator (thisattr ());
}
+ inline debug_info_entry::raw_children::const_iterator
+ unit_reference () const
+ {
+ return reference ();
+ }
// XXX reloc, dwfl
::Dwarf_Addr address () const;
}
const dwarf::source_file source_file () const;
+ inline unsigned int source_line () const
+ {
+ return constant ();
+ }
+ inline unsigned int source_column () const
+ {
+ return constant ();
+ }
// XXX reloc
::Dwarf_Word constant () const;
{
case VS_reference:
case VS_unit_reference:
- // XXX Reference identity check (?)
- return reference ()->offset () == other.reference ()->offset ();
+ return true; // XXX Reference identity check (?)
+ //return reference ()->offset () == other.reference ()->offset ();
case VS_flag:
return flag () == other.flag ();
/*FALLTHRU*/
case VS_constant:
case VS_dwarf_constant:
+ return constant () == other.constant ();
+
case VS_source_line:
+ return source_line () == other.source_line ();
case VS_source_column:
- return constant () == other.constant ();
+ return source_column () == other.source_column ();
case VS_identifier:
- return !strcmp (identifier (), other.identifier ());
+ return name_equal<typeof (other.identifier ())> ()
+ (identifier (), other.identifier ());
case VS_string:
- return !strcmp (string (), other.string ());
+ return name_equal<typeof (other.string ())> ()
+ (string (), other.string ());
case VS_address:
return address () == other.address ();
return source_file () == other.source_file ();
case VS_location:
- return location () == other; // XXX will be other.location ()
+ return location () == other.location ();
case VS_discr_list:
throw std::runtime_error ("XXX unimplemented");
}
return false;
}
- inline bool operator!= (const attr_value &other) const
+ template<typename value>
+ inline bool operator!= (const value &other) const
{
return !(*this == other);
}
{
friend class attr_value;
private:
- const attr_value _m_attr;
+ attr_value _m_attr;
location_attr (const attr_value &attr) : _m_attr (attr) {}
- bool singleton () const; // XXX temp hack
+ 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 &x)
+ {
+ 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;
+ 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
{
- // XXX hack, real location interface later
- if (singleton ())
- return _m_attr.constant_block () == other.constant_block ();
- // loclistptr XXX punt for now, treat as constant
- return _m_attr.constant () == other.constant ();
- }
+ if (empty ())
+ return (other.empty ()
+ || std::find_if (other.begin (), other.end (),
+ nonempty<value_type> ()) == other.end ());
+ if (!is_list ())
+ return !other.is_list () && 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
+ */
+ };
+
+ 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;
+ ::Dwarf_Addr _m_begin;
+ ::Dwarf_Addr _m_end;
+ 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.
private:
::Dwarf_Files *_m_files;
- template<typename string>
- struct name_equal
- : public std::binary_function<const char *, string, bool>
- {
- bool operator () (const char *me, const string &you)
- {
- return you == me;
- }
- };
template<typename table>
inline bool table_equal (const table &other) const
{
template<typename table>
inline bool operator== (const table &other) const
{
- return subr::container_equal (*this, other);
+ return size () == other.size () && subr::container_equal (*this, other);
}
template<typename table>
inline bool operator!= (const table &other) const
private:
typedef std::set<std::pair< ::Dwarf_Addr, ::Dwarf_Addr> > _base;
+ protected:
+ template<typename iterator>
+ arange_list (iterator first, iterator last) : _base (first, last) {}
+
public:
typedef _base::key_type key_type;
typedef _base::value_type value_type;
// Explicit specialization used inside dwarf::directory_table::operator==.
template<>
- struct dwarf::directory_table::name_equal<const char *>
+ struct dwarf::name_equal<const char *>
: public std::binary_function<const char *, const char *, bool>
{
bool operator () (const char *me, const char *you)
{
return attributes::attributes (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);
+ }
};
#endif // <elfutils/dwarf>
throw std::runtime_error ("XXX wrong form");
}
- const uint8_t *const begin = reinterpret_cast<const uint8_t *> (block.data);
- const uint8_t *const end = begin + block.length;
- return const_vector<uint8_t> (begin, end);
-}
-\f
-// dwarf::location_attr
-
-const dwarf::location_attr
-dwarf::attr_value::location () const
-{
- if (what_space () != VS_location)
- throw std::runtime_error ("XXX not a location");
-
- return location_attr (*this);
-}
-
-bool
-dwarf::location_attr::singleton () const
-{
- switch (dwarf_whatform (_m_attr.thisattr ()))
- {
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_block2:
- case DW_FORM_block4:
- return true;
- }
-
- return false;
-}
-
-string
-dwarf::location_attr::to_string () const
-{
- if (singleton ())
- return "XXX";
- return hex_string (_m_attr.constant (), "#");
+ return const_vector<uint8_t> (block);
}
\f
// dwarf::range_list
{
}
-dwarf::range_list::const_iterator &
-dwarf::range_list::const_iterator::operator++ ()
+static bool
+range_list_advance (int secndx,
+ Dwarf_CU *cu,
+ Dwarf_Addr &base,
+ Dwarf_Addr &begin,
+ Dwarf_Addr &end,
+ ptrdiff_t &offset,
+ unsigned char **valp)
{
- const Elf_Data *d = _m_cu->dbg->sectiondata[IDX_debug_ranges];
+ const Elf_Data *d = cu->dbg->sectiondata[secndx];
if (unlikely (d == NULL))
throw std::runtime_error ("XXX no ranges");
- if (unlikely (_m_offset < 0) || unlikely ((size_t) _m_offset >= d->d_size))
+ if (unlikely (offset < 0) || unlikely ((size_t) offset >= d->d_size))
throw std::runtime_error ("XXX bad offset in ranges iterator");
- unsigned char *readp = (reinterpret_cast<unsigned char *> (d->d_buf)
- + _m_offset);
+ unsigned char *readp = reinterpret_cast<unsigned char *> (d->d_buf) + offset;
+ unsigned char *const readendp
+ = reinterpret_cast<unsigned char *> (d->d_buf) + d->d_size;
while (true)
{
- if ((unsigned char *) d->d_buf + d->d_size - readp
- < _m_cu->address_size * 2)
+ if (readendp - readp < cu->address_size * 2)
throw std::runtime_error ("XXX bad ranges");
- if (_m_cu->address_size == 8)
+ if (cu->address_size == 8)
{
- _m_begin = read_8ubyte_unaligned_inc (_m_cu->dbg, readp);
- _m_end = read_8ubyte_unaligned_inc (_m_cu->dbg, readp);
- if (_m_begin == (uint64_t) -1l) /* Base address entry. */
+ begin = read_8ubyte_unaligned_inc (cu->dbg, readp);
+ end = read_8ubyte_unaligned_inc (cu->dbg, readp);
+ if (begin == (uint64_t) -1l) /* Base address entry. */
{
- _m_base = _m_end;
+ base = end;
continue;
}
}
else
{
- _m_begin = read_4ubyte_unaligned_inc (_m_cu->dbg, readp);
- _m_end = read_4ubyte_unaligned_inc (_m_cu->dbg, readp);
- if (_m_begin == (uint32_t) -1) /* Base address entry. */
+ begin = read_4ubyte_unaligned_inc (cu->dbg, readp);
+ end = read_4ubyte_unaligned_inc (cu->dbg, readp);
+ if (begin == (uint32_t) -1) /* Base address entry. */
{
- _m_base = _m_end;
+ base = end;
continue;
}
}
break;
}
- if (_m_begin == 0 && _m_end == 0) /* End of list entry. */
- _m_offset = 1;
+ if (begin == 0 && end == 0) /* End of list entry. */
+ offset = 1;
else
{
- _m_offset = readp - reinterpret_cast<unsigned char *> (d->d_buf);
+ if (valp)
+ *valp = readp;
+ offset = readp - reinterpret_cast<unsigned char *> (d->d_buf);
- if (_m_base == (Dwarf_Addr) -1)
+ if (base == (Dwarf_Addr) -1)
{
- CUDIE (cudie, _m_cu);
+ CUDIE (cudie, cu);
/* Find the base address of the compilation unit. It will
normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
for compilation units with discontinuous ranges. */
Dwarf_Attribute attr_mem;
- if (unlikely (dwarf_lowpc (&cudie, &_m_base) != 0)
+ if (unlikely (dwarf_lowpc (&cudie, &base) != 0)
&& dwarf_formaddr (dwarf_attr (&cudie,
DW_AT_entry_pc,
&attr_mem),
- &_m_base) != 0)
+ &base) != 0)
{
- xif (true); // XXX
+ return true; // XXX
}
}
}
+ return false;
+}
+
+dwarf::range_list::const_iterator &
+dwarf::range_list::const_iterator::operator++ ()
+{
+ xif (range_list_advance (IDX_debug_ranges, _m_cu, _m_base,
+ _m_begin, _m_end, _m_offset, NULL));
return *this;
}
+
template<typename container>
string
__libdw_ranges_to_string (const container &c)
return result;
}
+\f
+// dwarf::location_attr
+
+const dwarf::location_attr
+dwarf::attr_value::location () const
+{
+ if (what_space () != VS_location)
+ throw std::runtime_error ("XXX not a location");
+
+ return location_attr (*this);
+}
+
+bool
+dwarf::location_attr::is_list () const
+{
+ switch (dwarf_whatform (_m_attr.thisattr ()))
+ {
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ return false;
+ }
+
+ return true;
+}
+
+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)
+ // Singleton, now at end.
+ _m_offset = 1;
+ else
+ {
+ // Advance to next list entry.
+ xif (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);
+ }
+ }
+
+ return *this;
+}
+
+string
+dwarf::location_attr::to_string () const
+{
+ if (is_list ())
+ return hex_string (_m_attr.constant (), "#");
+ return "XXX";
+}