summaryrefslogtreecommitdiff
path: root/rtemstoolkit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2018-08-06 09:20:58 +1000
committerChris Johns <chrisj@rtems.org>2018-08-07 09:11:29 +1000
commitd3318eb3511cb450e89c74c3240b6ef21943c946 (patch)
tree56fbf71be0db0a05a501b984e0c87e0086a215de /rtemstoolkit
parent367bae8843ca24cf58f646f963a0ad1e755b3eb7 (diff)
rtemstoolkit/dwarf: C++ object relates fixes and a dump report.
- Various C++ object fixes that improve stability where data from libdwarf is moving between object instances. - Functions now provide better detail with inlined functions picking up attributes from an abstrtact DIE. - Dump to a provide stream not stdout.
Diffstat (limited to 'rtemstoolkit')
-rw-r--r--rtemstoolkit/rld-dwarf.cpp504
-rw-r--r--rtemstoolkit/rld-dwarf.h122
2 files changed, 477 insertions, 149 deletions
diff --git a/rtemstoolkit/rld-dwarf.cpp b/rtemstoolkit/rld-dwarf.cpp
index 9b92ec0..9cdd84a 100644
--- a/rtemstoolkit/rld-dwarf.cpp
+++ b/rtemstoolkit/rld-dwarf.cpp
@@ -82,7 +82,7 @@ namespace rld
std::ostringstream exe_where;
std::string what;
exe_where << "dwarf:" << where;
- what = dwarf_errmsg (error);
+ what = ::dwarf_errmsg (error);
throw rld::error (what, exe_where.str ());
}
}
@@ -299,7 +299,7 @@ namespace rld
}
void
- range::dump ()
+ range::dump (std::ostream& out) const
{
dwarf_ranges_type type_ = type ();
const char* type_s = "invalid";
@@ -310,10 +310,11 @@ namespace rld
};
if (type_ <= DW_RANGES_END)
type_s = type_labels[type_];
- std::cout << type_s << '-'
- << std::hex << std::setfill ('0')
- << "0x" << std::setw (8) << addr1 ()
- << ":0x" << std::setw (8) << addr2 ();
+ out << type_s << '-'
+ << std::hex << std::setfill ('0')
+ << "0x" << std::setw (8) << addr1 ()
+ << ":0x" << std::setw (8) << addr2 ()
+ << std::dec << std::setfill (' ');
}
address_ranges::address_ranges (file& debug)
@@ -344,7 +345,9 @@ namespace rld
address_ranges::address_ranges (const address_ranges& orig)
: debug (orig.debug),
- offset (orig.offset)
+ offset (orig.offset),
+ dranges (nullptr),
+ dranges_count (0)
{
load (orig.offset);
}
@@ -392,6 +395,8 @@ namespace rld
if (dranges != nullptr)
::dwarf_ranges_dealloc (debug, dranges, dranges_count);
+ ranges_.clear ();
+
dranges = nullptr;
dranges_count = 0;
@@ -444,18 +449,18 @@ namespace rld
}
void
- address_ranges::dump ()
+ address_ranges::dump (std::ostream& out) const
{
bool first = true;
- std::cout << '[';
+ out << '[';
for (auto& r : ranges_)
{
if (!first)
- std::cout << ',';
- r.dump ();
+ out << ',';
+ r.dump (out);
first = false;
}
- std::cout << ']';
+ out << ']';
}
line_addresses::line_addresses (file& debug,
@@ -576,9 +581,12 @@ namespace rld
external_ (false),
declaration_ (false),
inline_ (DW_INL_not_inlined),
+ entry_pc_ (0),
+ has_entry_pc_ (false),
pc_low_ (0),
pc_high_ (0),
- ranges_ (debug)
+ ranges_ (debug),
+ call_line_ (0)
{
dwarf_bool db;
@@ -588,16 +596,18 @@ namespace rld
if (die.attribute (DW_AT_declaration, db, false))
declaration_ = db ? true : false;
+ if (die.attribute (DW_AT_entry_pc, entry_pc_, false))
+ has_entry_pc_ = true;
+
die.attribute (DW_AT_linkage_name, linkage_name_, false);
+ die.attribute (DW_AT_call_file, decl_file_, false);
+ die.attribute (DW_AT_call_line, decl_line_, false);
+ die.attribute (DW_AT_call_file, call_file_, false);
+ die.attribute (DW_AT_call_line, call_line_, false);
if (!die.attribute (DW_AT_inline, inline_, false))
inline_ = DW_INL_not_inlined;
- if (inline_ == DW_INL_declared_inlined)
- {
- die_dump_children (die, " +");
- }
-
/*
* If ranges are not found see if the PC low and PC high attributes
* can be found.
@@ -653,7 +663,17 @@ namespace rld
{
debug_info_entry abst_at_die (debug, abst_at_die_offset);
if (abst_at_die.attribute (DW_AT_name, name_, false))
+ {
found = true;
+ abst_at_die.attribute (DW_AT_inline, inline_, false);
+ if (abst_at_die.attribute (DW_AT_external, db, false))
+ external_ = db ? true : false;
+ if (abst_at_die.attribute (DW_AT_declaration, db, false))
+ declaration_ = db ? true : false;
+ abst_at_die.attribute (DW_AT_linkage_name, linkage_name_, false);
+ abst_at_die.attribute (DW_AT_decl_file, decl_file_, false);
+ abst_at_die.attribute (DW_AT_decl_line, decl_line_, false);
+ }
}
}
@@ -675,36 +695,48 @@ namespace rld
{
debug_info_entry spec_die (debug, spec_die_offset);
if (spec_die.attribute (DW_AT_name, name_, false))
+ {
found = true;
+ if (spec_die.attribute (DW_AT_external, db, false))
+ external_ = db ? true : false;
+ if (spec_die.attribute (DW_AT_declaration, db, false))
+ declaration_ = db ? true : false;
+ spec_die.attribute (DW_AT_linkage_name, linkage_name_, false);
+ spec_die.attribute (DW_AT_decl_file, decl_file_, false);
+ spec_die.attribute (DW_AT_decl_line, decl_line_, false);
+ }
}
}
}
}
-
- if (die.tag () == DW_TAG_inlined_subroutine)
- {
- die.attribute (DW_AT_call_file, call_file_, false);
- }
}
if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
{
std::cout << "dwarf::function: ";
- if (name_.empty ())
- std::cout << "NO NAME";
- else
- std::cout << name_;
- if (!has_machine_code ())
- std::cout << " NO MACHINE CODE";
- else
- std::cout << std::hex << std::setfill ('0')
- << " pc_low = 0x" << std::setw (8) << pc_low ()
- << " pc_high = 0x" << std::setw (8) << pc_high ()
- << std::dec << std::setfill (' ');
+ dump (std::cout);
std::cout << std::endl;
}
}
+ function::function (const function& orig)
+ : debug (orig.debug),
+ machine_code_ (orig.machine_code_),
+ external_ (orig.external_),
+ declaration_ (orig.declaration_),
+ inline_ (orig.inline_),
+ entry_pc_ (orig.entry_pc_),
+ has_entry_pc_ (orig.has_entry_pc_),
+ pc_low_ (orig.pc_low_),
+ pc_high_ (orig.pc_high_),
+ ranges_ (orig.ranges_),
+ name_ (orig.name_),
+ linkage_name_ (orig.linkage_name_),
+ call_file_ (orig.call_file_),
+ call_line_ (orig.call_line_)
+ {
+ }
+
function::~function ()
{
}
@@ -724,28 +756,36 @@ namespace rld
dwarf_unsigned
function::pc_low () const
{
- if (ranges_.empty ())
- return pc_low_;
- dwarf_address addr = ~0;
- for (auto& r : ranges_.get ())
+ dwarf_address addr = pc_low_;
+ if (!ranges_.empty ())
{
- if (!r.end () && !r.empty () && r.addr1 () < addr)
- addr = r.addr1 ();
+ addr = ~0;
+ for (auto& r : ranges_.get ())
+ {
+ if (!r.end () && !r.empty () && r.addr1 () < addr)
+ addr = r.addr1 ();
+ }
}
+ if (has_entry_pc_ && addr < entry_pc_)
+ addr += entry_pc_;
return addr;
}
dwarf_unsigned
function::pc_high () const
{
- if (ranges_.empty ())
- return pc_high_;
- dwarf_address addr = 0;
- for (auto& r : ranges_.get ())
+ dwarf_address addr = pc_high_;
+ if (!ranges_.empty ())
{
- if (!r.end () && !r.empty () && r.addr2 () > addr)
- addr = r.addr1 ();
+ addr = 0;
+ for (auto& r : ranges_.get ())
+ {
+ if (!r.end () && !r.empty () && r.addr2 () > addr)
+ addr = r.addr2 ();
+ }
}
+ if (has_entry_pc_ && addr < entry_pc_)
+ addr += entry_pc_;
return addr;
}
@@ -770,7 +810,7 @@ namespace rld
bool
function::is_inlined () const
{
- return inline_ == DW_INL_declared_inlined;
+ return inline_ == DW_INL_inlined || inline_ == DW_INL_declared_inlined;
}
std::string
@@ -786,6 +826,97 @@ namespace rld
addr >= pc_low () && addr <= pc_high ();
}
+ size_t
+ function::size () const
+ {
+ size_t s = 0;
+ if (!name_.empty () && has_machine_code ())
+ s = pc_high () - pc_low ();
+ return s;
+ }
+
+ function&
+ function::operator = (const function& rhs)
+ {
+ if (this != &rhs)
+ {
+ debug = rhs.debug;
+ machine_code_ = rhs.machine_code_;
+ external_ = rhs.external_;
+ declaration_ = rhs.declaration_;
+ inline_ = rhs.inline_;
+ entry_pc_ = rhs.entry_pc_;
+ has_entry_pc_ = rhs.has_entry_pc_;
+ pc_low_ = rhs.pc_low_;
+ pc_high_ = rhs.pc_high_;
+ ranges_ = rhs.ranges_;
+ name_ = rhs.name_;
+ linkage_name_ = rhs.linkage_name_;
+ call_file_ = rhs.call_file_;
+ }
+ return *this;
+ }
+
+ void
+ function::dump (std::ostream& out) const
+ {
+ if (name_.empty ())
+ out << "NO-NAME";
+ else
+ out << name_;
+ out << " ["
+ << (char) (machine_code_ ? 'M' : '-')
+ << (char) (external_ ? 'E' : '-')
+ << (char) (declaration_ ? 'D' : '-')
+ << (char) (is_inlined () ? 'I' : '-')
+ << (char) (has_entry_pc_ ? 'P' : '-')
+ << "] size=" << size ()
+ << std::hex << std::setfill ('0')
+ << " (0x" << size () << ')';
+ if (has_entry_pc_)
+ out << " epc=0x" << entry_pc_;
+ out << " pc_low=0x" << pc_low_
+ << " pc_high=0x" << pc_high_;
+ if (!linkage_name_.empty ())
+ out << " ln=" << linkage_name_;
+ out << std::dec << std::setfill (' ');
+ if (!call_file_.empty ())
+ out << " cf=" << call_file_ << ':' << call_line_;
+ if (!ranges_.empty ())
+ {
+ out << " ranges=";
+ ranges_.dump (out);
+ }
+ }
+
+ bool
+ function_compare::operator () (const function& a,
+ const function& b) const
+ {
+ bool r = true;
+
+ switch (by)
+ {
+ case fc_by_name:
+ default:
+ r = a.name () < b.name ();
+ break;
+ case fc_by_size:
+ r = a.size () < b.size ();
+ break;
+ case fc_by_address:
+ r = a.pc_low () < b.pc_low ();
+ break;
+ }
+
+ return r;
+ }
+
+ function_compare:: function_compare (const function_compare::sort_by by)
+ : by (by)
+ {
+ }
+
debug_info_entry::debug_info_entry (file& debug)
: debug (debug),
die (nullptr),
@@ -800,6 +931,7 @@ namespace rld
tag_ (0),
offset_ (0)
{
+ update ();
}
debug_info_entry::debug_info_entry (file& debug, dwarf_offset offset__)
@@ -808,12 +940,7 @@ namespace rld
tag_ (0),
offset_ (offset__)
{
- dwarf_die ddie;
- dwarf_error de;
- int dr;
- dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
- libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
- die = ddie;
+ update ();
}
debug_info_entry::debug_info_entry (const debug_info_entry& orig)
@@ -822,20 +949,48 @@ namespace rld
tag_ (orig.tag_),
offset_ (orig.offset_)
{
- if (offset_ != 0)
+ update ();
+ }
+
+ debug_info_entry::~debug_info_entry ()
+ {
+ dealloc ();
+ }
+
+ void
+ debug_info_entry::update ()
+ {
+ dwarf_error de;
+ int dr;
+ if (offset_ == 0 && die != nullptr)
{
- dwarf_die ddie;
- dwarf_error de;
- int dr;
+ dr = ::dwarf_dieoffset (die, &offset_, &de);
+ libdwarf_error_check ("debug_info_entry:update", dr, de);
+ }
+ if (offset_ != 0 && die == nullptr)
+ {
+ dwarf_die ddie;
dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
- libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
+ libdwarf_error_check ("debug_info_entry:update", dr, de);
die = ddie;
}
+ valid ();
}
- debug_info_entry::~debug_info_entry ()
+ bool
+ debug_info_entry::valid (bool fatal) const
{
- dealloc ();
+ bool r = die == nullptr || offset_ == 0;
+ if (r && fatal)
+ {
+ std::string what = "no DIE and offset";
+ if (offset_ != 0)
+ what = "no DIE";
+ else if (die != nullptr)
+ what = "no offset";
+ throw rld::error (what, "debug_info_entry:valid");
+ }
+ return r;
}
dwarf_die
@@ -867,6 +1022,8 @@ namespace rld
tag_ = rhs.tag_;
offset_ = rhs.offset_;
rhs.die = nullptr;
+ if (offset_ != 0 || die != nullptr)
+ update ();
}
return *this;
}
@@ -877,14 +1034,9 @@ namespace rld
dealloc ();
if (offset__ != 0)
{
- dwarf_die ddie;
- dwarf_error de;
- int dr;
offset_ = offset__;
tag_ = 0;
- dr = ::dwarf_offdie (debug, offset_, &ddie, &de);
- libdwarf_error_check ("debug_info_entry:operator=", dr, de);
- die = ddie;
+ update ();
}
return *this;
}
@@ -910,7 +1062,7 @@ namespace rld
dwarf_error de;
int dr;
dr = ::dwarf_tag (die, &tag_, &de);
- libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
+ libdwarf_error_check ("debug_info_entry:tag", dr, de);
}
return tag_;
}
@@ -923,7 +1075,7 @@ namespace rld
dwarf_error de;
int dr;
dr = ::dwarf_dieoffset (die, &offset_, &de);
- libdwarf_error_check ("debug_info_entry:debug_info_entry", dr, de);
+ libdwarf_error_check ("debug_info_entry:offset", dr, de);
}
return offset_;
}
@@ -1057,26 +1209,55 @@ namespace rld
bool
debug_info_entry::get_child (debug_info_entry& child_die)
{
+ debug_info_entry ret_die (get_debug ());
+ dwarf_error de;
+ int dr;
+ dr = ::dwarf_child (die, ret_die, &de);
+ if (dr == DW_DLV_OK)
+ {
+ ret_die.update ();
+ child_die = ret_die;
+ child_die.valid ();
+ }
+ return dr == DW_DLV_OK;
+ }
+
+ bool
+ debug_info_entry::has_child () const
+ {
+ debug_info_entry ret_die (get_debug ());
dwarf_error de;
int dr;
- dr = ::dwarf_child (die, child_die, &de);
+ dr = ::dwarf_child (die, ret_die, &de);
return dr == DW_DLV_OK;
}
bool
debug_info_entry::get_sibling (debug_info_entry& sibling_die)
{
+ debug_info_entry ret_die (get_debug ());
dwarf_error de;
int dr;
- dr = ::dwarf_siblingof (debug, die, sibling_die, &de);
+ dr = ::dwarf_siblingof (debug, die, ret_die, &de);
if (dr == DW_DLV_NO_ENTRY)
return false;
libdwarf_error_check ("compilation_unit::sibling", dr, de);
+ sibling_die = ret_die;
return true;
}
+ bool
+ debug_info_entry::has_sibling () const
+ {
+ debug_info_entry ret_die (get_debug ());
+ dwarf_error de;
+ int dr;
+ dr = ::dwarf_siblingof (debug, die, ret_die, &de);
+ return dr == DW_DLV_OK;
+ }
+
file&
- debug_info_entry::get_debug ()
+ debug_info_entry::get_debug () const
{
return debug;
}
@@ -1091,11 +1272,32 @@ namespace rld
}
void
- debug_info_entry::dump (std::string prefix, bool newline)
+ debug_info_entry::dump (std::ostream& out,
+ std::string prefix,
+ bool newline)
{
+ std::string level_prefix;
+
+ for (auto c : prefix)
+ {
+ switch (c)
+ {
+ case '+':
+ c = '|';
+ break;
+ case '-':
+ c = ' ';
+ break;
+ default:
+ break;
+ }
+ level_prefix += c;
+ }
+
const char* s;
::dwarf_get_TAG_name (tag (), &s);
- std::cout << prefix << s << std::endl;
+ out << level_prefix.substr (0, level_prefix.length () - 1)
+ << "+- " << s << std::endl;
dwarf_attribute* attributes;
dwarf_signed attr_count;
@@ -1117,8 +1319,9 @@ namespace rld
dwarf_get_FORM_name (form, &f);
dwarf_get_AT_name (attr, &s);
if (a > 0)
- std::cout << std::endl;
- std::cout << prefix << " - " << s << " (" << attr << ") [" << f << ']';
+ out << std::endl;
+ out << level_prefix << " +- "
+ << s << " (" << attr << ") [" << f << ']';
debug_info_entry v_die (debug);
address_ranges v_ranges (debug);
dwarf_unsigned v_unsigned;
@@ -1139,11 +1342,20 @@ namespace rld
case DW_FORM_udata:
dr = ::dwarf_attrval_unsigned (die, attr, &v_unsigned, &de);
libdwarf_error_check ("debug_info_entry::dump", dr, de);
- std::cout << " : "
- << std::hex << std::setfill ('0')
- << std::setw (8) << v_unsigned
- << std::dec << std::setfill (' ')
- << " (" << v_unsigned << ')';
+ s = "";
+ switch (attr)
+ {
+ case DW_AT_inline:
+ dwarf_get_INL_name(v_unsigned, &s);
+ break;
+ default:
+ break;
+ }
+ out << " : "
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << v_unsigned
+ << std::dec << std::setfill (' ')
+ << " (" << v_unsigned << ") " << s;
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
@@ -1152,18 +1364,18 @@ namespace rld
case DW_FORM_ref_udata:
dr = ::dwarf_global_formref (attributes[a], &v_offset, &de);
libdwarf_error_check ("debug_info_entry::dump", dr, de);
- std::cout << " : "
- << std::hex << std::setfill ('0')
- << std::setw (8) << v_offset
- << std::dec << std::setfill (' ')
- << " (" << v_offset << ')';
+ out << " : "
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << v_offset
+ << std::dec << std::setfill (' ')
+ << " (" << v_offset << ')';
switch (attr)
{
case DW_AT_abstract_origin:
case DW_AT_specification:
v_die = v_offset;
- std::cout << std::endl;
- v_die.dump (' ' + prefix, false);
+ out << std::endl;
+ v_die.dump (out, prefix + " | ", false);
break;
default:
break;
@@ -1175,14 +1387,14 @@ namespace rld
case DW_FORM_flag_present:
dr = ::dwarf_attrval_flag (die, attr, &v_bool, &de);
libdwarf_error_check ("debug_info_entry::dump", dr, de);
- std::cout << " : " << v_bool;
+ out << " : " << v_bool;
break;
break;
case DW_FORM_string:
case DW_FORM_strp:
dr = ::dwarf_attrval_string (die, attr, &s, &de);
libdwarf_error_check ("debug_info_entry::dump", dr, de);
- std::cout << " : " << s;
+ out << " : " << s;
break;
case DW_FORM_sec_offset:
switch (attr)
@@ -1190,9 +1402,9 @@ namespace rld
case DW_AT_ranges:
dr = ::dwarf_global_formref (attributes[a], &v_offset, &de);
libdwarf_error_check ("debug_info_entry::dump", dr, de);
- std::cout << ' ';
+ out << ' ';
v_ranges.load (v_offset);
- v_ranges.dump ();
+ v_ranges.dump (out);
break;
default:
break;
@@ -1206,38 +1418,39 @@ namespace rld
}
}
if (newline)
- std::cout << std::endl;
+ out << std::endl;
}
}
void
- die_dump_children (debug_info_entry die,
- std::string prefix,
- int nesting,
- int depth)
+ die_dump_children (debug_info_entry& die,
+ std::ostream& out,
+ std::string prefix,
+ int depth,
+ int nesting)
{
debug_info_entry child (die.get_debug ());
if (die.get_child (child))
- die_dump (child, prefix, nesting, depth);
+ die_dump (child, out, prefix, depth, nesting);
}
void
- die_dump (debug_info_entry die,
- std::string prefix,
- int nesting,
- int depth)
+ die_dump (debug_info_entry& die,
+ std::ostream& out,
+ std::string prefix,
+ int depth,
+ int nesting)
{
++nesting;
- for (int n = 0; n < nesting; ++n)
- prefix += ' ';
-
while (true)
{
- die.dump (prefix);
+ char v = die.has_sibling () || die.has_child () ? '+' : ' ';
+
+ die.dump (out, prefix + v);
if (depth < 0 || nesting < depth)
- die_dump_children (die, prefix);
+ die_dump_children (die, out, prefix + "+ ", depth, nesting);
debug_info_entry next (die.get_debug ());
@@ -1422,12 +1635,9 @@ namespace rld
compilation_unit::load_functions ()
{
debug_info_entry die (debug, die_offset);
- debug_info_entry ret_die (debug);
- dwarf_error de;
- int dr;
- dr = ::dwarf_child(die, ret_die, &de);
- if (dr == DW_DLV_OK)
- load_functions (ret_die);
+ debug_info_entry child (debug);
+ if (die.get_child (child))
+ load_functions (child);
}
void
@@ -1440,27 +1650,18 @@ namespace rld
die.tag () == DW_TAG_inlined_subroutine)
{
function func (debug, die);
- if (func.has_machine_code () &&
- func.pc_low () >= pc_low_ && func.pc_high () <= pc_high_)
- {
- functions_.push_back (func);
- }
+ functions_.push_back (func);
}
- debug_info_entry ret_die (debug);
- dwarf_error de;
- int dr;
+ debug_info_entry next (die.get_debug ());
- dr = ::dwarf_child(die, ret_die, &de);
- if (dr == DW_DLV_OK)
- load_functions (ret_die);
+ if (die.get_child (next))
+ load_functions (next);
- dr = ::dwarf_siblingof (debug, die, ret_die, &de);
- if (dr == DW_DLV_NO_ENTRY)
+ if (!die.get_sibling (next))
break;
- libdwarf_error_check ("compilation_unit:load_functions", dr, de);
- die = ret_die;
+ die = next;
}
}
@@ -1549,11 +1750,13 @@ namespace rld
}
void
- compilation_unit::dump_die ()
+ compilation_unit::dump_die (std::ostream& out,
+ const std::string prefix,
+ int depth)
{
debug_info_entry die (debug, die_offset);
- std::cout << "CU @ 0x" << std::hex << offset_ << std::dec << std::endl;
- die_dump_children (die, "");
+ out << "CU @ 0x" << std::hex << offset_ << std::dec << std::endl;
+ die_dump (die, out, prefix, depth);
}
source_flags::source_flags (const std::string& source)
@@ -1570,7 +1773,7 @@ namespace rld
return a.source < b.source;
}
- source_flags_compare:: source_flags_compare (bool by_basename)
+ source_flags_compare::source_flags_compare (bool by_basename)
: by_basename (by_basename)
{
}
@@ -1663,6 +1866,45 @@ namespace rld
}
void
+ file::dump (std::ostream& out,
+ const std::string prefix,
+ int depth)
+ {
+ dwarf_unsigned cu_offset = 0;
+
+ while (true)
+ {
+ dwarf_unsigned cu_next_offset = 0;
+ dwarf_error de;
+ int dr;
+
+ dr = ::dwarf_next_cu_header_c(debug, 1,
+ nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+ &cu_next_offset, &de);
+ if (dr != DW_DLV_OK)
+ break;
+
+ /*
+ * Find the CU DIE by asking the CU for it's first DIE.
+ */
+ debug_info_entry die (*this);
+
+ while (true)
+ {
+ debug_info_entry sibling (*this);
+ if (!die.get_sibling (sibling))
+ break;
+ if (sibling.tag () == DW_TAG_compile_unit)
+ die_dump (sibling, out, prefix, depth);
+ die = sibling;
+ }
+
+ cu_offset = cu_next_offset;
+ }
+ }
+
+ void
file::load_debug ()
{
dwarf_unsigned cu_offset = 0;
diff --git a/rtemstoolkit/rld-dwarf.h b/rtemstoolkit/rld-dwarf.h
index cfca9a6..d4e4c8a 100644
--- a/rtemstoolkit/rld-dwarf.h
+++ b/rtemstoolkit/rld-dwarf.h
@@ -25,6 +25,8 @@
#if !defined (_RLD_DWARF_H_)
#define _RLD_DWARF_H_
+#include <iostream>
+
#include <rld.h>
#include <rld-dwarf-types.h>
@@ -152,7 +154,7 @@ namespace rld
/**
* Dump the range.
*/
- void dump ();
+ void dump (std::ostream& out) const;
private:
@@ -201,7 +203,7 @@ namespace rld
/**
* Dump the address ranges.
*/
- void dump ();
+ void dump (std::ostream& out) const;
private:
@@ -281,6 +283,7 @@ namespace rld
{
public:
function (file& debug, debug_info_entry& die);
+ function (const function& orig);
~function ();
/**
@@ -339,24 +342,64 @@ namespace rld
*/
bool inside (dwarf_address addr) const;
+ /**
+ * Size of the function.
+ */
+ size_t size () const;
+
+ /**
+ * Assigment operator.
+ */
+ function& operator = (const function& rhs);
+
+ /**
+ * Dump the function.
+ */
+ void dump (std::ostream& out) const;
+
private:
file& debug;
bool machine_code_;
bool external_;
bool declaration_;
+ bool prototyped_;
dwarf_unsigned inline_;
+ dwarf_unsigned entry_pc_;
+ bool has_entry_pc_;
dwarf_unsigned pc_low_;
dwarf_unsigned pc_high_;
address_ranges ranges_;
std::string name_;
std::string linkage_name_;
+ std::string decl_file_;
+ dwarf_unsigned decl_line_;
std::string call_file_;
+ dwarf_unsigned call_line_;
};
typedef std::vector < function > functions;
/**
+ * Worker to sort the functions.
+ */
+ struct function_compare
+ {
+ enum sort_by
+ {
+ fc_by_name,
+ fc_by_size,
+ fc_by_address
+ };
+
+ const sort_by by;
+
+ bool operator () (const function& a, const function& b) const;
+
+ function_compare (sort_by by = fc_by_name);
+ };
+
+ /**
* Debug Information Element (DIE).
*
* This class clean up and deallocations a DIE when it desctructs.
@@ -378,6 +421,11 @@ namespace rld
~debug_info_entry ();
/**
+ * Is the DIE valid?
+ */
+ bool valid (bool fatal = true) const;
+
+ /**
* Get the DIE.
*/
dwarf_die get () const;
@@ -475,14 +523,24 @@ namespace rld
bool get_child (debug_info_entry& child_die);
/**
+ * Has a child?
+ */
+ bool has_child () const;
+
+ /**
* Get the silbing
*/
bool get_sibling (debug_info_entry& sibling_die);
/**
+ * Has a silbing?
+ */
+ bool has_sibling () const;
+
+ /**
* Get the debug info for this DIE.
*/
- file& get_debug ();
+ file& get_debug () const;
/**
* deallocate the DIE.
@@ -492,10 +550,17 @@ namespace rld
/**
* Dump this DIE.
*/
- void dump (std::string prefix, bool newline = true);
+ void dump (std::ostream& out,
+ std::string prefix,
+ bool newline = true);
private:
+ /**
+ * Update the internal DIE and offset values.
+ */
+ void update ();
+
file& debug;
dwarf_die die;
dwarf_tag tag_;
@@ -506,18 +571,20 @@ namespace rld
/**
* Dump the DIE and all it's children and siblings.
*/
- void die_dump_children (debug_info_entry die,
- std::string prefix,
- int nesting = 0,
- int depth = -1);
+ void die_dump_children (debug_info_entry& die,
+ std::ostream& out,
+ std::string prefix,
+ int depth = -1,
+ int nesting = 0);
/**
* Dump the DIE and all it's children and siblings.
*/
- void die_dump (debug_info_entry die,
- std::string prefix,
- int nesting = 0,
- int depth = -1);
+ void die_dump (debug_info_entry& die,
+ std::ostream& out,
+ std::string prefix,
+ int depth = -1,
+ int nesting = 0);
/**
* Compilation Unit.
@@ -588,7 +655,9 @@ namespace rld
/**
* Output the DIE tree.
*/
- void dump_die ();
+ void dump_die (std::ostream& out,
+ const std::string prefix = " ",
+ int depth = -1);
private:
@@ -703,15 +772,25 @@ namespace rld
int& source_line);
/**
- * Get the function given an address.
+ * Get the producer sources from the compilation units.
*/
- bool get_function (const unsigned int address,
- std::string& name);
+ void get_producer_sources (producer_sources& producers);
/**
- * Get the producer sources from the compilation units.
+ * Does the function exist.
*/
- void get_producer_sources (producer_sources& producers);
+ bool function_valid (std::string&name);
+
+ /**
+ * Get the function given a name. Raises an exception if not found.
+ */
+ function& get_function (std::string& name);
+
+ /**
+ * Get the function given an address.
+ */
+ bool get_function (const unsigned int address,
+ std::string& name);
/**
* Get the DWARF debug information reference.
@@ -733,6 +812,13 @@ namespace rld
*/
const std::string& name () const;
+ /**
+ * Dump the DWARF data.
+ */
+ void dump (std::ostream& out,
+ const std::string prefix = " ",
+ int depth = -1);
+
private:
/**