139 lines
4 KiB
C++
139 lines
4 KiB
C++
#include <fstream>
|
|
#include <fileno.hpp>
|
|
#include <dwarfpp/lib.hpp>
|
|
#include <dwarfpp/attr.hpp>
|
|
#include <boost/icl/interval_map.hpp>
|
|
|
|
using std::cout;
|
|
using std::cerr;
|
|
using std::endl;
|
|
using namespace dwarf;
|
|
using namespace dwarf::lib;
|
|
using std::pair;
|
|
using std::make_pair;
|
|
using std::dynamic_pointer_cast;
|
|
using std::set;
|
|
using std::map;
|
|
|
|
int static_we_should_find;
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
assert(argc > 1);
|
|
cerr << "Opening " << argv[1] << "..." << endl;
|
|
std::ifstream in(argv[1]);
|
|
assert(in);
|
|
core::root_die root(fileno(in));
|
|
|
|
cerr << "Searching for variables..." << endl;
|
|
for (auto i = root.begin(); i != root.end(); ++i)
|
|
{
|
|
if (i.tag_here() == DW_TAG_variable
|
|
&& i.has_attribute_here(DW_AT_location))
|
|
{
|
|
/* DWARF doesn't tell us whether a variable is static or not.
|
|
* We want to rule out non-static variables. To do this, we
|
|
* rely on our existing lib:: infrastructure. */
|
|
core::Attribute a(dynamic_cast<core::Die&>(i.get_handle()), DW_AT_location);
|
|
encap::attribute_value val(a, dynamic_cast<core::Die&>(i.get_handle()), root);
|
|
auto loclist = val.get_loclist();
|
|
bool reads_register = false;
|
|
for (auto i_loc_expr = loclist.begin();
|
|
i_loc_expr != loclist.end();
|
|
++i_loc_expr)
|
|
{
|
|
for (auto i_instr = i_loc_expr->begin();
|
|
i_instr != i_loc_expr->end();
|
|
++i_instr)
|
|
{
|
|
if (spec::DEFAULT_DWARF_SPEC.op_reads_register(i_instr->lr_atom))
|
|
{
|
|
reads_register = true;
|
|
break;
|
|
}
|
|
}
|
|
if (reads_register) break;
|
|
}
|
|
if (!reads_register)
|
|
{
|
|
auto name = i.name_here();
|
|
cerr << "Found a static or global variable named "
|
|
<< (name ? *name : "(no name)") << endl;
|
|
Dwarf_Off off = i.offset_here();
|
|
//static_vars.insert(off);
|
|
|
|
auto found = root.find(off);
|
|
assert(found);
|
|
auto with_static_location
|
|
= found.as_a<core::with_static_location_die>();
|
|
if (!with_static_location)
|
|
{
|
|
cerr << "Warning: expected a with_static_location_die, got "
|
|
<< found->summary() << endl;
|
|
continue;
|
|
}
|
|
try
|
|
{
|
|
boost::icl::interval_map<Dwarf_Addr, Dwarf_Unsigned> out
|
|
= with_static_location->file_relative_intervals(root, nullptr, nullptr);
|
|
cerr << out << endl;
|
|
auto interval_count = boost::icl::interval_count(out);
|
|
if (interval_count != 1)
|
|
{
|
|
cerr << "Warning: expected a single interval, got " << interval_count
|
|
<< " of them, for " << with_static_location->summary() << endl;
|
|
continue;
|
|
}
|
|
// addr_lookup.insert(make_pair(
|
|
// out.begin()->first.lower(),
|
|
// make_pair(
|
|
// off,
|
|
// out.begin()->first.upper() - out.begin()->first.lower()
|
|
// )
|
|
// ));
|
|
/* We output to stderr ad-hoc text data in tab-separated fields as follows.
|
|
* file-relative address;
|
|
* CU offset;
|
|
* object size;
|
|
* name (free text)
|
|
*/
|
|
Dwarf_Addr file_relative_addr = out.begin()->first.lower();
|
|
Dwarf_Off cu_offset = i.enclosing_cu_offset_here();
|
|
unsigned size = out.begin()->first.upper() - out.begin()->first.lower();
|
|
cerr << std::hex
|
|
<< "0x" << file_relative_addr << '\t' // addr
|
|
<< "0x" << cu_offset << '\t' // CU offset
|
|
<< "0x" << size << '\t' // size
|
|
<< (name ? *name : "")
|
|
<< std::dec << endl;
|
|
/* We output to stdout binary data as follows.
|
|
* file-relative address (width: native);
|
|
* CU offset (64 bits);
|
|
* object size (32 bits).
|
|
*/
|
|
auto addr_size = root.find(cu_offset).as_a<core::compile_unit_die>()->get_address_size();
|
|
assert(addr_size == 4 || addr_size == 8);
|
|
assert(sizeof cu_offset == 8);
|
|
assert(sizeof size == 4);
|
|
cout.write((char*) &file_relative_addr, addr_size);
|
|
cout.write((char*) &cu_offset, 8);
|
|
cout.write((char*) &size, 4);
|
|
}
|
|
catch (dwarf::expr::Not_supported)
|
|
{
|
|
cerr << "Warning: couldn't evaluate location of DIE at 0x"
|
|
<< std::hex << off << std::dec << endl;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto name = i.name_here();
|
|
cerr << "Found a local variable named "
|
|
<< (name ? *name : "(no name)") << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|