Add debug code to print return address
This commit is contained in:
parent
3932ee09e6
commit
c4a0a38b34
2 changed files with 150 additions and 0 deletions
|
@ -22,6 +22,11 @@ class DwarfInterpret {
|
|||
static DwarfInterpret& acquire();
|
||||
static DwarfInterpret& instanciate(const std::string& elf_path);
|
||||
|
||||
int get_elf_machine() const { return elf_machine; }
|
||||
|
||||
// FIXME DEBUG vvv
|
||||
void dbg_dump_ra();
|
||||
|
||||
private:
|
||||
DwarfInterpret(const std::string& elf_path);
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include <DwarfInterpret.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <fileno.hpp>
|
||||
#include <dwarfpp/lib.hpp>
|
||||
|
@ -11,6 +15,9 @@
|
|||
#include <dwarfpp/root.hpp>
|
||||
#include <gelf.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace dwarf;
|
||||
|
||||
DwarfInterpret::DwarfInterpret(const std::string& elf_path)
|
||||
: root_die(fileno(std::ifstream(elf_path)))
|
||||
{
|
||||
|
@ -37,3 +44,141 @@ DwarfInterpret& DwarfInterpret::instanciate(const std::string& elf_path) {
|
|||
new DwarfInterpret(elf_path));
|
||||
return *(DwarfInterpret::instance);
|
||||
}
|
||||
|
||||
// BEGIN DEBUG
|
||||
using core::FrameSection;
|
||||
typedef FrameSection::register_def register_def;
|
||||
|
||||
typedef std::set<std::pair<int, register_def> > DwarfRow;
|
||||
|
||||
template<typename Key>
|
||||
typename std::set<std::pair<int, Key> >::const_iterator find_column(
|
||||
const std::set<std::pair<int, Key> >& set,
|
||||
int key)
|
||||
{
|
||||
if(set.empty())
|
||||
return set.end();
|
||||
Key some_key_val = set.begin()->second;
|
||||
auto it = set.upper_bound(make_pair(key - 1, some_key_val));
|
||||
if(it == set.end())
|
||||
return set.end();
|
||||
while(it != set.end() && it->first != key)
|
||||
++it;
|
||||
if(it == set.end() || it->first != key)
|
||||
return set.end();
|
||||
return it;
|
||||
}
|
||||
|
||||
register_def get_column(const DwarfRow& row, int column) {
|
||||
auto it = find_column<register_def>(row, column);
|
||||
if(it == row.end())
|
||||
throw std::out_of_range("No such column");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
struct ColumnQuery {
|
||||
const DwarfRow& row;
|
||||
int column;
|
||||
ColumnQuery(const DwarfRow& row, int column):
|
||||
row(row), column(column) {}
|
||||
};
|
||||
|
||||
ostream& operator<<(ostream& os, const register_def& reg) {
|
||||
switch(reg.k) {
|
||||
case FrameSection::register_def::INDETERMINATE:
|
||||
case FrameSection::register_def::UNDEFINED:
|
||||
return os << "u";
|
||||
|
||||
case FrameSection::register_def::REGISTER: {
|
||||
ostringstream exprs;
|
||||
int regnum = reg.register_plus_offset_r().first;
|
||||
string regname;
|
||||
if (regnum == DW_FRAME_CFA_COL3) regname = "X";
|
||||
// DON'T confuse this case with 'c', which means
|
||||
// SAVED_AT_OFFSET_FROM_CFA
|
||||
else
|
||||
regname = dwarf::lib::dwarf_regnames_for_elf_machine(
|
||||
DwarfInterpret::acquire().get_elf_machine())[regnum];
|
||||
exprs << regname << std::showpos << std::dec << setw(0)
|
||||
<< (int) reg.register_plus_offset_r().second;
|
||||
|
||||
return os << exprs.str();
|
||||
} break;
|
||||
|
||||
case FrameSection::register_def::SAVED_AT_OFFSET_FROM_CFA: {
|
||||
ostringstream exprs;
|
||||
exprs << "c" << std::showpos << std::dec
|
||||
<< reg.saved_at_offset_from_cfa_r();
|
||||
return os << exprs.str();
|
||||
} break;
|
||||
case FrameSection::register_def::SAVED_AT_EXPR:
|
||||
return os << "exp";
|
||||
break;
|
||||
case FrameSection::register_def::VAL_IS_OFFSET_FROM_CFA:
|
||||
case FrameSection::register_def::VAL_OF_EXPR:
|
||||
default:
|
||||
return os << "BLAH";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream& os, const ColumnQuery& query) {
|
||||
try {
|
||||
register_def regdef = get_column(query.row, query.column);
|
||||
return os << regdef;
|
||||
} catch(const std::out_of_range&) {
|
||||
return os << "u";
|
||||
}
|
||||
}
|
||||
|
||||
void extract_ra_of_fde(const core::FrameSection& fs, const core::Fde& fde) {
|
||||
auto decoded = fde.decode();
|
||||
const core::Cie& cie = *(fde.find_cie());
|
||||
|
||||
int ra_col = cie.get_return_address_register_rule();
|
||||
int cfa_col = DW_FRAME_CFA_COL3;
|
||||
|
||||
for(const auto& row: decoded.rows) {
|
||||
cout
|
||||
<< std::hex << std::setfill('0')
|
||||
<< std::setw(2 * cie.get_address_size())
|
||||
<< row.first.lower() << ' '
|
||||
<< setfill(' ')
|
||||
<< setw(8) << ColumnQuery(row.second, cfa_col) << ' '
|
||||
<< setw(6) << ColumnQuery(row.second, ra_col)
|
||||
<< endl
|
||||
<< std::dec;
|
||||
}
|
||||
}
|
||||
// END DEBUG
|
||||
|
||||
void DwarfInterpret::dbg_dump_ra() {
|
||||
dwarf::core::FrameSection& frame_section =
|
||||
root_die.get_frame_section();
|
||||
std::vector<FrameSection::fde_iterator> fdes;
|
||||
for(auto fde_it = frame_section.fde_begin();
|
||||
fde_it != frame_section.fde_end();
|
||||
++fde_it)
|
||||
{
|
||||
fdes.push_back(fde_it);
|
||||
}
|
||||
|
||||
std::sort(fdes.begin(), fdes.end(),
|
||||
[&frame_section]
|
||||
(const FrameSection::fde_iterator& f1,
|
||||
const FrameSection::fde_iterator& f2)
|
||||
{
|
||||
assert(f1 != frame_section.end());
|
||||
assert(f2 != frame_section.end());
|
||||
return f1->get_offset() < f2->get_offset();
|
||||
});
|
||||
|
||||
// FDEs are sorted, now we can extract RAs for each of them
|
||||
for(const auto& fde: fdes) {
|
||||
cout << "==== FDE at offset "
|
||||
<< std::hex << fde->get_fde_offset() << std::dec
|
||||
<< " ====" << endl;
|
||||
extract_ra_of_fde(frame_section, *fde);
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue