SimpleDwarf: add pretty-printing operator<<

This commit is contained in:
Théophile Bastian 2018-04-23 15:59:10 +02:00
parent 13e3647629
commit 8bf2e1e49d
2 changed files with 102 additions and 8 deletions

70
src/SimpleDwarf.cpp Normal file
View file

@ -0,0 +1,70 @@
#include "SimpleDwarf.hpp"
static std::ostream& operator<<(
std::ostream& out,
SimpleDwarf::MachineRegister reg)
{
switch(reg) {
case SimpleDwarf::REG_RIP:
out << "rip";
break;
case SimpleDwarf::REG_RSP:
out << "rsp";
break;
case SimpleDwarf::REG_RBP:
out << "rbp";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, const SimpleDwarf::DwRegister& reg)
{
switch(reg.type) {
case SimpleDwarf::DwRegister::REG_UNDEFINED:
out << "u";
break;
case SimpleDwarf::DwRegister::REG_REGISTER:
out << reg.reg
<< ((reg.offset >= 0) ? '+' : '-')
<< reg.offset;
break;
case SimpleDwarf::DwRegister::REG_CFA_OFFSET:
out << 'c'
<< ((reg.offset >= 0) ? '+' : '-')
<< reg.offset;
break;
case SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED:
out << 'X';
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, const SimpleDwarf::DwRow& row) {
out << std::hex << row.ip << std::dec
<< '\t' << row.cfa;
for(size_t r_id = 0; r_id < SimpleDwarf::HANDLED_REGISTERS_COUNT; ++r_id) {
out << '\t' << row.regs[r_id];
}
out << std::endl;
return out;
}
std::ostream& operator<<(std::ostream& out, const SimpleDwarf::Fde& fde) {
out << "FDE: "
<< std::hex << fde.beg_ip << "" << fde.end_ip << std::dec
<< std::endl
<< "IP\tCFA\tRIP\tRSP\tRBP\tRA"
<< std::endl;
for(const auto& row: fde.rows)
out << row;
return out;
}
std::ostream& operator<<(std::ostream& out, const SimpleDwarf& dwarf) {
for(const auto& fde: dwarf.fde_list)
out << fde << std::endl;
return out;
}

View file

@ -8,13 +8,15 @@
#include <cstdint>
#include <vector> // We only need linear swipes, no need for anything fancier
#include <ostream>
struct SimpleDwarf {
/** A machine register (eg. %rip) among the supported ones (x86_64 only
* for now) */
static const std::size_t HANDLED_REGISTERS_COUNT = 3;
static const std::size_t HANDLED_REGISTERS_COUNT = 4;
enum MachineRegister {
REG_RIP, REG_RSP, REG_RBP
REG_RIP, REG_RSP, REG_RBP,
REG_RA ///< A bit of cheating: not a machine register
};
struct DwRegister {
@ -34,18 +36,40 @@ struct SimpleDwarf {
Type type; ///< Type of this register
uintptr_t offset; ///< Offset from the expression, if applicable
MachineRegister reg; ///< Machine register implied, if applicable
friend std::ostream& operator<<(std::ostream &, const DwRegister&);
};
struct DwRow {
uintptr_t ip;
DwRegister cfa;
DwRegister regs[HANDLED_REGISTERS_COUNT];
uintptr_t ip; ///< Instruction pointer
DwRegister cfa; ///< Canonical Frame Address
DwRegister regs[HANDLED_REGISTERS_COUNT]; ///< Saved machine registers
friend std::ostream& operator<<(std::ostream &, const DwRow&);
};
struct Fde {
uintptr_t beg_ip, end_ip;
std::vector<DwRow> rows;
uintptr_t beg_ip, ///< This FDE's start instruction pointer
end_ip; ///< This FDE's end instruction pointer
std::vector<DwRow> rows; ///< Dwarf rows for this FDE
friend std::ostream& operator<<(std::ostream &, const Fde&);
};
std::vector<Fde> fde_list;
std::vector<Fde> fde_list; ///< List of FDEs in this Dwarf
friend std::ostream& operator<<(std::ostream &, const SimpleDwarf&);
};
/// Dumps this object to `out`
std::ostream& operator<<(std::ostream& out,
const SimpleDwarf::DwRegister& reg);
/// Dumps this object to `out`
std::ostream& operator<<(std::ostream& out, const SimpleDwarf::DwRow& reg);
/// Dumps this object to `out`
std::ostream& operator<<(std::ostream& out, const SimpleDwarf::Fde& reg);
/// Dumps this object to `out`
std::ostream& operator<<(std::ostream& out, const SimpleDwarf& reg);