2018-04-23 15:02:59 +02:00
|
|
|
/** SimpleDwarf - a simplified representation of Dwarf rules and table
|
|
|
|
*
|
|
|
|
* This class is made to handle a simple subset of the Dwarf table - the subset
|
|
|
|
* that is the most ubiquitous. It should cover most of the real-life cases.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <vector> // We only need linear swipes, no need for anything fancier
|
2018-04-23 15:59:10 +02:00
|
|
|
#include <ostream>
|
2018-04-23 15:02:59 +02:00
|
|
|
|
|
|
|
struct SimpleDwarf {
|
|
|
|
/** A machine register (eg. %rip) among the supported ones (x86_64 only
|
|
|
|
* for now) */
|
2018-04-23 15:59:10 +02:00
|
|
|
static const std::size_t HANDLED_REGISTERS_COUNT = 4;
|
2018-04-23 15:02:59 +02:00
|
|
|
enum MachineRegister {
|
2018-04-23 15:59:10 +02:00
|
|
|
REG_RIP, REG_RSP, REG_RBP,
|
|
|
|
REG_RA ///< A bit of cheating: not a machine register
|
2018-04-23 15:02:59 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct DwRegister {
|
|
|
|
/** Holds a single Dwarf register value */
|
|
|
|
|
|
|
|
DwRegister(): type(REG_UNDEFINED), offset(0), reg(REG_RIP /* 0 */) {}
|
|
|
|
|
|
|
|
/// Type of register (what does the expression mean?)
|
|
|
|
enum Type {
|
|
|
|
REG_UNDEFINED, /**< Undefined register (the value will be
|
|
|
|
defined at some later IP in the same DIE) */
|
|
|
|
REG_REGISTER, ///< Value of a machine register plus offset
|
|
|
|
REG_CFA_OFFSET, ///< Value stored at some offset from CFA
|
|
|
|
REG_NOT_IMPLEMENTED ///< This type of register is not supported
|
|
|
|
};
|
|
|
|
|
|
|
|
Type type; ///< Type of this register
|
2018-04-23 16:12:10 +02:00
|
|
|
int offset; ///< Offset from the expression, if applicable
|
2018-04-23 15:02:59 +02:00
|
|
|
MachineRegister reg; ///< Machine register implied, if applicable
|
2018-04-23 15:59:10 +02:00
|
|
|
|
|
|
|
friend std::ostream& operator<<(std::ostream &, const DwRegister&);
|
2018-04-23 15:02:59 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct DwRow {
|
2018-04-23 15:59:10 +02:00
|
|
|
uintptr_t ip; ///< Instruction pointer
|
|
|
|
DwRegister cfa; ///< Canonical Frame Address
|
2018-04-23 16:46:03 +02:00
|
|
|
DwRegister rbp; ///< Base pointer register
|
|
|
|
DwRegister ra; ///< Return address
|
2018-04-23 15:59:10 +02:00
|
|
|
|
|
|
|
friend std::ostream& operator<<(std::ostream &, const DwRow&);
|
2018-04-23 15:02:59 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Fde {
|
2018-04-30 13:23:48 +02:00
|
|
|
uintptr_t fde_offset; ///< This FDE's offset in the original DWARF
|
2018-04-23 15:59:10 +02:00
|
|
|
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&);
|
2018-04-23 15:02:59 +02:00
|
|
|
};
|
|
|
|
|
2018-04-23 15:59:10 +02:00
|
|
|
std::vector<Fde> fde_list; ///< List of FDEs in this Dwarf
|
|
|
|
|
|
|
|
friend std::ostream& operator<<(std::ostream &, const SimpleDwarf&);
|
2018-04-23 15:02:59 +02:00
|
|
|
};
|
2018-04-23 15:59:10 +02:00
|
|
|
|
|
|
|
/// 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);
|