// [(gap, string entry)]
typedef std::vector<std::pair<gap, ::Ebl_Strent *> > str_backpatch_vec;
- struct backpatch_strp
- {
- void operator () (std::pair<gap, ::Ebl_Strent *> const &v)
- {
- v.first.patch (ebl_strtaboffset (v.second));
- }
- };
-
private:
// die offset -> file address
typedef std::map< ::Dwarf_Off, ::Dwarf_Off> die_off_map;
}
};
- class recursive_dumper;
-
public:
// Constructor for an empty file, can add to its compile_units ().
inline dwarf_output () {}
return !(*this == other);
}
- void output_debug_abbrev (section_appender &appender,
- dwarf_output_collector &dw,
- bool addr_64);
+ class writer
+ {
+ dwarf_output_collector &_m_col;
+ dwarf_output &_m_dw;
+
+ bool _m_addr_64;
+ bool _m_dwarf_64;
+ bool _m_big_endian;
- void output_debug_info (section_appender &appender,
- dwarf_output_collector &dw,
- strtab &debug_str,
- str_backpatch_vec &str_backpatch,
- bool addr_64, bool big_endian);
+ strtab &_m_debug_str;
+ str_backpatch_vec _m_str_backpatch;
- void add_shape (debug_info_entry &die, bool last_sibling);
+ // Set of shapes.
+ typedef std::tr1::unordered_map<dwarf_output::shape_type,
+ dwarf_output::shape_info,
+ dwarf_output::shape_type::hasher>
+ shape_map;
+ shape_map _m_shapes;
+
+ void add_shape (debug_info_entry &die, bool last_sibling);
+ class recursive_dumper;
+
+ public:
+ writer (dwarf_output_collector &col,
+ dwarf_output &dw,
+ bool big_endian, bool addr_64, bool dwarf_64,
+ strtab &debug_str);
+
+ void output_debug_abbrev (section_appender &appender);
+ void output_debug_info (section_appender &appender);
+ void apply_patches ();
+ };
};
+
// Explicit specializations.
template<>
std::string to_string<dwarf_output::debug_info_entry>
class dwarf_output_collector
{
friend class dwarf_output;
+ friend class dwarf_output::writer;
private:
dwarf_path_finder<dwarf_output> _m_tracker;
typedef subr::identity_map<die_type, die_info> die_map;
die_map _m_unique;
- // Set of shapes.
- typedef std::tr1::unordered_map<dwarf_output::shape_type,
- dwarf_output::shape_info,
- dwarf_output::shape_type::hasher>
- shape_map;
- shape_map _m_shapes;
-
inline die_info_pair *add_entry (int tag,
const children_type *children,
const attrs_type *attrs)
public:
inline dwarf_output_collector ()
: _m_total (0)
- , _m_output_built (false)
{}
static void die_stats (const die_map::value_type &elt)
std::for_each (_m_unique.begin (), _m_unique.end (), die_stats);
}
- bool _m_output_built;
void build_output (bool addr_64, bool dwarf_64);
};
*inserter++ = 0;
}
-void
-dwarf_output_collector::build_output (bool addr_64, bool dwarf_64)
+dwarf_output::writer::writer (dwarf_output_collector &col,
+ dwarf_output &dw,
+ bool big_endian, bool addr_64, bool dwarf_64,
+ strtab &debug_str)
+ : _m_col (col)
+ , _m_dw (dw)
+ , _m_addr_64 (addr_64)
+ , _m_dwarf_64 (dwarf_64)
+ , _m_big_endian (big_endian)
+ , _m_debug_str (debug_str)
{
size_t code = 0;
- for (die_map::const_iterator it = _m_unique.begin ();
- it != _m_unique.end (); ++it)
+ for (dwarf_output_collector::die_map::const_iterator it
+ = col._m_unique.begin ();
+ it != col._m_unique.end (); ++it)
{
dwarf_output::shape_type shape (it->first, it->second);
- dwarf_output_collector::shape_map::iterator st
- = _m_shapes.find (shape);
+ shape_map::iterator st = _m_shapes.find (shape);
if (st != _m_shapes.end ())
st->second.add_user (it->first);
else
for (shape_map::iterator it = _m_shapes.begin ();
it != _m_shapes.end (); ++it)
{
- it->second.instantiate (it->first, *this, addr_64, dwarf_64);
+ it->second.instantiate (it->first, col, addr_64, dwarf_64);
for (dwarf_output::shape_info::instance_vec::iterator jt
= it->second._m_instances.begin ();
jt != it->second._m_instances.end (); ++jt)
jt->code = ++code;
}
-
- _m_output_built = true;
}
void
-dwarf_output::output_debug_abbrev (section_appender &appender,
- dwarf_output_collector &c,
- bool addr_64)
+dwarf_output::writer::output_debug_abbrev (section_appender &appender)
{
- if (!c._m_output_built)
- c.build_output (addr_64, false /* xxx dwarf_64 */);
-
- for (dwarf_output_collector::shape_map::iterator it = c._m_shapes.begin ();
- it != c._m_shapes.end (); ++it)
+ for (shape_map::iterator it = _m_shapes.begin ();
+ it != _m_shapes.end (); ++it)
for (dwarf_output::shape_info::instance_vec::const_iterator jt
= it->second._m_instances.begin ();
jt != it->second._m_instances.end (); ++jt)
}
};
-class dwarf_output::recursive_dumper
+class dwarf_output::writer::recursive_dumper
{
- dwarf_output &c;
+ dwarf_output::writer &_m_parent;
section_appender &appender;
- strtab &debug_str;
- bool addr_64;
die_off_map &die_off;
die_backpatch_vec &die_backpatch;
- str_backpatch_vec &str_backpatch;
- bool big_endian;
gap::recomputer::ptr cu_local_recomputer;
recursive_dumper (recursive_dumper const ©); // nocopy
public:
- recursive_dumper (dwarf_output &a_c,
+ recursive_dumper (dwarf_output::writer &writer,
section_appender &a_appender,
- strtab &a_debug_str,
- bool a_addr_64,
die_off_map &a_die_off,
die_backpatch_vec &a_die_backpatch,
- str_backpatch_vec &a_str_backpatch,
- bool a_big_endian,
uint64_t cu_start)
- : c (a_c),
+ : _m_parent (writer),
appender (a_appender),
- debug_str (a_debug_str),
- addr_64 (a_addr_64),
die_off (a_die_off),
die_backpatch (a_die_backpatch),
- str_backpatch (a_str_backpatch),
- big_endian (a_big_endian),
cu_local_recomputer (new local_ref_recomputer (cu_start))
{}
// other CU-local reference. So also use this below (or
// better reuse single piece of code for reference
// handling).
- size_t gap_size
- = ::form_width (form, addr_64, false /* xxx dwarf_64 */);
+ size_t gap_size = ::form_width (form,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
sibling_gap = gap (appender, gap_size,
- big_endian, cu_local_recomputer);
+ _m_parent._m_big_endian, cu_local_recomputer);
continue;
}
case dwarf::VS_rangelistptr:
case dwarf::VS_lineptr:
case dwarf::VS_macptr:
- ::dw_write_form (appender, form, 0 /*xxx*/, big_endian,
- addr_64, false /* dwarf_64 */);
+ ::dw_write_form (appender, form, 0 /*xxx*/,
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
break;
case dwarf::VS_constant:
if (value.constant_is_integer ())
- ::dw_write_form (appender, form, value.constant (), big_endian,
- addr_64, false /* dwarf_64 */);
+ ::dw_write_form (appender, form, value.constant (),
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
else
{
const std::vector<uint8_t> &block = value.constant_block ();
- ::dw_write_form (appender, form, block.size (), big_endian,
- addr_64, false /* dwarf_64 */);
+ ::dw_write_form (appender, form, block.size (),
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
std::copy (block.begin (), block.end (), inserter);
}
break;
case dwarf::VS_dwarf_constant:
::dw_write_form (appender, form, value.dwarf_constant (),
- big_endian, addr_64, false /* dwarf_64 */);
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
break;
case dwarf::VS_source_line:
::dw_write_form (appender, form, value.source_line (),
- big_endian, addr_64, false /* dwarf_64 */);
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
break;
case dwarf::VS_source_column:
::dw_write_form (appender, form, value.source_column (),
- big_endian, addr_64, false /* dwarf_64 */);
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
break;
case dwarf::VS_string:
::dw_write_string (value.string (), form, appender,
- debug_str, str_backpatch, big_endian);
+ _m_parent._m_debug_str,
+ _m_parent._m_str_backpatch,
+ _m_parent._m_big_endian);
break;
case dwarf::VS_identifier:
::dw_write_string (value.identifier (), form, appender,
- debug_str, str_backpatch, big_endian);
+ _m_parent._m_debug_str,
+ _m_parent._m_str_backpatch,
+ _m_parent._m_big_endian);
break;
case dwarf::VS_source_file:
{
::dw_write_string (value.source_file ().name (),
form, appender,
- debug_str, str_backpatch, big_endian);
+ _m_parent._m_debug_str,
+ _m_parent._m_str_backpatch,
+ _m_parent._m_big_endian);
break;
}
else
- ::dw_write_form (appender, form, 0 /*xxx*/, big_endian,
- addr_64, false /* dwarf_64 */);
+ ::dw_write_form (appender, form, 0 /*xxx*/,
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
break;
case dwarf::VS_address:
{
assert (form == DW_FORM_addr);
- size_t w = addr_64 ? 8 : 4;
+ size_t w = _m_parent._m_addr_64 ? 8 : 4;
::dw_write_var (appender.alloc (w), w,
- value.address (), big_endian);
+ value.address (),
+ _m_parent._m_big_endian);
}
break;
assert (form == DW_FORM_ref_addr);
// XXX dwarf64
die_backpatch.push_back
- (std::make_pair (gap (appender, 4, big_endian),
+ (std::make_pair (gap (appender, 4, _m_parent._m_big_endian),
value.reference ()->offset ()));
}
break;
if (form == DW_FORM_block)
::dw_write_uleb128 (inserter, 0);
else
- ::dw_write_form (appender, form, 0 /*xxx*/, big_endian,
- addr_64, false /* dwarf_64 */);
+ ::dw_write_form (appender, form, 0 /*xxx*/,
+ _m_parent._m_big_endian,
+ _m_parent._m_addr_64,
+ _m_parent._m_dwarf_64);
break;
case dwarf::VS_discr_list:
}
};
- void
- dwarf_output::output_debug_info (section_appender &appender,
- dwarf_output_collector &c,
- strtab &debug_str,
- str_backpatch_vec &str_backpatch,
- bool addr_64, bool big_endian)
- {
- /* We request appender directly, because we depend on .alloc method
- being implemented: we need continuous chunks of memory for
- back-patching. While it would be possible to implement this
- purely on iterators, it's not really useful. */
-
- if (!c._m_output_built)
- c.build_output (addr_64, false /* dwarf_64 */);
-
- std::back_insert_iterator <section_appender> inserter
- = std::back_inserter (appender);
-
- for (compile_units::const_iterator it = _m_units.begin ();
- it != _m_units.end (); ++it)
- {
- // Remember where the unit started for back-patching of size.
- size_t cu_start = appender.size ();
-
- // Unit length.
- gap length_gap (appender, 4 /*XXX dwarf64*/, big_endian);
-
- // Version.
- ::dw_write<2> (appender.alloc (2), 3, big_endian);
-
- // Debug abbrev offset. Use the single abbrev table that we
- // emit at offset 0.
- ::dw_write<4> (appender.alloc (4), 0, big_endian);
-
- // Size in bytes of an address on the target architecture.
- *inserter++ = addr_64 ? 8 : 4;
-
- die_off_map die_off;
- die_backpatch_vec die_backpatch;
-
- //std::cout << "UNIT " << it->_m_cu_die << std::endl;
- gap fake_gap;
- recursive_dumper (*this, appender, debug_str, addr_64,
- die_off, die_backpatch, str_backpatch,
- big_endian, cu_start)
- .dump (*c._m_unique.find (*it), fake_gap, 0);
+void
+dwarf_output::writer::output_debug_info (section_appender &appender)
+{
+ std::back_insert_iterator <section_appender> inserter
+ = std::back_inserter (appender);
+
+ for (compile_units::const_iterator it = _m_dw._m_units.begin ();
+ it != _m_dw._m_units.end (); ++it)
+ {
+ // Remember where the unit started for back-patching of size.
+ size_t cu_start = appender.size ();
+
+ // Unit length.
+ dwarf_output::gap length_gap (appender,
+ _m_dwarf_64 ? 8 : 4,
+ _m_big_endian);
+
+ // Version.
+ ::dw_write<2> (appender.alloc (2), 3, _m_big_endian);
+
+ // Debug abbrev offset. Use the single abbrev table that we
+ // emit at offset 0.
+ ::dw_write<4> (appender.alloc (4), 0, _m_big_endian);
+
+ // Size in bytes of an address on the target architecture.
+ *inserter++ = _m_addr_64 ? 8 : 4;
+
+ die_off_map die_off;
+ die_backpatch_vec die_backpatch;
+
+ gap fake_gap;
+ recursive_dumper (*this, appender, die_off, die_backpatch, cu_start)
+ .dump (*_m_col._m_unique.find (*it), fake_gap, 0);
assert (!fake_gap.valid ());
std::for_each (die_backpatch.begin (), die_backpatch.end (),
length_gap.patch (length);
}
}
+
+void
+dwarf_output::writer::apply_patches ()
+{
+ for (dwarf_output::str_backpatch_vec::const_iterator it
+ = _m_str_backpatch.begin ();
+ it != _m_str_backpatch.end (); ++it)
+ it->first.patch (ebl_strtaboffset (it->second));
+}