blob: 5df223d3ac00542c1de1e3ee157214c8017b1bb2 [file] [edit]
/* elfutils::dwarf_ref_maker -- -*- C++ -*- template type specification
Copyright (C) 2009-2010 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
it under the terms of either
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at
your option) any later version
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at
your option) any later version
or both in parallel, as here.
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 copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see <http://www.gnu.org/licenses/>. */
#ifndef _ELFUTILS_DWARF_REF_MAKER
#define _ELFUTILS_DWARF_REF_MAKER 1
#include "dwarf"
#include <tr1/unordered_map>
#include <vector>
namespace elfutils
{
// Prototypical stub for reference maker object.
// This keeps no state and can't really be used.
template<class output, class input>
struct dwarf_ref_maker_base
{
typedef typename input::debug_info_entry input_entry;
typedef typename input_entry::children_type::const_iterator input_ref;
typedef typename output::debug_info_entry::pointer output_ref;
// These are called around a whole-file construction.
inline void start () {}
// If called, all pointers passed in since start () before are bogus.
inline void abort () {}
// Construction is complete: now snap in all recorded references.
inline void finish (output &file) {}
// The referenced output DIE has been constructed to match the input DIE.
inline void equivalence (const output_ref &to, const input_ref &from)
{
}
// *REF is an uninitialized attr_value.reference ().
// It's meant to refer to the output DIE equivalent to the given input DIE.
inline void refer (output_ref *ref, const input_ref &target)
{
throw std::logic_error ("dwarf_ref_maker_base cannot make references");
}
};
// Simple maker used for a single copy-construction.
template<class output, class input>
class dwarf_ref_maker : public dwarf_ref_maker_base<output, input>
{
public:
typedef typename input::debug_info_entry input_entry;
typedef typename output::debug_info_entry output_entry;
typedef typename input_entry::children_type::const_iterator input_ref;
typedef typename output_entry::children_type::iterator output_ref;
private:
struct seen
{
bool _m_known;
output_ref _m_out;
std::vector<output_ref *> _m_refs;
inline seen ()
: _m_known (false), _m_out (), _m_refs ()
{}
// Copy construction only valid for initial state.
inline seen (const seen &other)
: _m_known (false), _m_out (), _m_refs ()
{
if (unlikely (other._m_known) || unlikely (!other._m_refs.empty ()))
throw std::logic_error
("seen copy constructs only from default-constructed");
}
inline void resolve ()
{
for (; !_m_refs.empty (); _m_refs.pop_back ())
*_m_refs.back () = _m_out;
}
inline void resolve (const output_ref &to)
{
_m_out = to;
_m_known = true;
resolve ();
}
inline void refer (output_ref *out)
{
_m_refs.push_back (out);
if (_m_known)
resolve ();
}
};
std::tr1::unordered_map<dwarf::debug_info_entry::identity_type,
seen> _m_map;
public:
inline dwarf_ref_maker ()
: _m_map ()
{}
inline dwarf_ref_maker (const dwarf_ref_maker &other)
: _m_map ()
{
if (unlikely (!other._m_map.empty ()))
throw std::logic_error
("dwarf_ref_maker copy constructs only from default-constructed");
}
inline ~dwarf_ref_maker ()
{}
inline void abort ()
{
_m_map.clear ();
}
inline void equivalence (const output_ref &out, const input_ref &in)
{
_m_map[in->identity ()].resolve (out);
}
inline void refer (output_ref *out, const input_ref &in)
{
_m_map[in->identity ()].refer (out);
}
inline void finish (output &file)
{
while (_m_map.begin () != _m_map.end ())
if (_m_map.begin ()->second._m_known)
_m_map.erase (_m_map.begin ());
else
throw std::logic_error ("construction finished with unresolved refs");
}
};
};
#endif // <elfutils/dwarf_ref_maker>