diff --git a/include/DwarfInterpret.hpp b/include/DwarfInterpret.hpp index 2f68908..d623d37 100644 --- a/include/DwarfInterpret.hpp +++ b/include/DwarfInterpret.hpp @@ -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); diff --git a/src/DwarfInterpret.cpp b/src/DwarfInterpret.cpp index fe2d2bd..ab50cfe 100644 --- a/src/DwarfInterpret.cpp +++ b/src/DwarfInterpret.cpp @@ -1,6 +1,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -11,6 +15,9 @@ #include #include +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 > DwarfRow; + +template +typename std::set >::const_iterator find_column( + const std::set >& 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(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 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; + } +}