Add libdwarfpp-based DwarfReader

This commit is contained in:
Théophile Bastian 2018-04-23 15:08:27 +02:00
parent 8c2191f487
commit 13e3647629
2 changed files with 153 additions and 0 deletions

115
src/DwarfReader.cpp Normal file
View file

@ -0,0 +1,115 @@
#include "DwarfReader.hpp"
#include <fstream>
#include <fileno.hpp>
#include <set>
using namespace std;
using namespace dwarf;
typedef std::set<std::pair<int, core::FrameSection::register_def> >
dwarfpp_row_t;
DwarfReader::DwarfReader(const string& path):
root(fileno(ifstream(path)))
{}
SimpleDwarf DwarfReader::read() const {
const core::FrameSection& fs = root.get_frame_section();
SimpleDwarf output;
for(auto fde_it = fs.fde_begin(); fde_it != fs.fde_end(); ++fde_it) {
SimpleDwarf::Fde parsed_fde = read_fde(*fde_it);
output.fde_list.push_back(parsed_fde);
}
return output;
}
SimpleDwarf::Fde DwarfReader::read_fde(const core::Fde& fde) const {
SimpleDwarf::Fde output;
output.beg_ip = fde.get_low_pc();
output.end_ip = fde.get_low_pc() + fde.get_func_length();
auto rows = fde.decode().rows;
for(const auto row_pair: rows) {
SimpleDwarf::DwRow cur_row;
cur_row.ip = row_pair.first.lower();
const dwarfpp_row_t& row = row_pair.second;
for(const auto& cell: row) {
if(cell.first == DW_FRAME_CFA_COL3) {
cur_row.cfa = read_register(cell.second);
}
else {
try {
SimpleDwarf::MachineRegister reg_type =
from_dwarfpp_reg(cell.first);
cur_row.regs[reg_type] = read_register(cell.second);
}
catch(UnsupportedRegister) {} // Just ignore it.
}
}
if(cur_row.cfa.type == SimpleDwarf::DwRegister::REG_UNDEFINED
|| (cur_row.regs[SimpleDwarf::REG_RIP].type
== SimpleDwarf::DwRegister::REG_UNDEFINED)
|| (cur_row.regs[SimpleDwarf::REG_RSP].type
== SimpleDwarf::DwRegister::REG_UNDEFINED))
{
// Not set
throw InvalidDwarf();
}
}
return output;
}
SimpleDwarf::DwRegister DwarfReader::read_register(
const core::FrameSection::register_def& reg
) const
{
SimpleDwarf::DwRegister output;
switch(reg.k) {
case core::FrameSection::register_def::REGISTER:
output.type = SimpleDwarf::DwRegister::REG_REGISTER;
output.offset = reg.register_plus_offset_r().second;
output.reg = from_dwarfpp_reg(
reg.register_plus_offset_r().first);
break;
case core::FrameSection::register_def::SAVED_AT_OFFSET_FROM_CFA:
output.type = SimpleDwarf::DwRegister::REG_CFA_OFFSET;
output.offset = reg.saved_at_offset_from_cfa_r();
break;
case core::FrameSection::register_def::INDETERMINATE:
case core::FrameSection::register_def::UNDEFINED:
output.type = SimpleDwarf::DwRegister::REG_UNDEFINED;
break;
default:
output.type = SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED;
break;
}
return output;
}
SimpleDwarf::MachineRegister DwarfReader::from_dwarfpp_reg(int reg_id) const {
switch(reg_id) {
case lib::DWARF_X86_64_RIP:
return SimpleDwarf::REG_RIP;
case lib::DWARF_X86_64_RSP:
return SimpleDwarf::REG_RSP;
case lib::DWARF_X86_64_RBP:
return SimpleDwarf::REG_RBP;
default:
throw UnsupportedRegister();
}
}

38
src/DwarfReader.hpp Normal file
View file

@ -0,0 +1,38 @@
/** Use libdwarfpp to read the Dwarf data of some ELF, and output a SimpleDwarf
* structure. */
#pragma once
#include <string>
#include <dwarfpp/lib.hpp>
#include <dwarfpp/regs.hpp>
#include <dwarfpp/frame.hpp>
#include <dwarfpp/attr.hpp>
#include <dwarfpp/root.hpp>
#include "SimpleDwarf.hpp"
class DwarfReader {
public:
class InvalidDwarf: public std::exception {};
/** Read the elf file located at `path`. */
DwarfReader(const std::string& path);
/** Actually read the ELF file, generating a `SimpleDwarf` output. */
SimpleDwarf read() const;
private: //meth
SimpleDwarf::Fde read_fde(const dwarf::core::Fde& fde) const;
SimpleDwarf::DwRegister read_register(
const dwarf::core::FrameSection::register_def& reg) const;
SimpleDwarf::MachineRegister from_dwarfpp_reg(int reg_id) const;
class UnsupportedRegister: public std::exception {};
private:
dwarf::core::root_die root;
};