Acually retrieve dwarf data
Doesn't work for now: still have to take into account the memory map offsets.
This commit is contained in:
parent
67aef72302
commit
bf8864e7e6
2 changed files with 111 additions and 5 deletions
|
@ -11,6 +11,13 @@
|
||||||
#include <dwarfpp/frame.hpp>
|
#include <dwarfpp/frame.hpp>
|
||||||
#include <dwarfpp/root.hpp>
|
#include <dwarfpp/root.hpp>
|
||||||
|
|
||||||
|
#define OF_WHAT_EXCEPTION(cl_name) \
|
||||||
|
cl_name: public WhatException { \
|
||||||
|
public:\
|
||||||
|
cl_name(const std::string& what): WhatException(what) {} \
|
||||||
|
cl_name() = default; \
|
||||||
|
}
|
||||||
|
|
||||||
class DwarfInterpret {
|
class DwarfInterpret {
|
||||||
/** Singleton class holding a Dwarf interpret.
|
/** Singleton class holding a Dwarf interpret.
|
||||||
* Must be first instanciated with the path to the binary being run, with a
|
* Must be first instanciated with the path to the binary being run, with a
|
||||||
|
@ -19,11 +26,28 @@ class DwarfInterpret {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class NotInstanciated: public std::exception {};
|
class WhatException: public std::exception {
|
||||||
class AlreadyInstanciated: public std::exception {};
|
/** Base exception for other exceptions, not supposed to be thrown
|
||||||
class ValuelessRegister: public std::exception {};
|
* by itself */
|
||||||
class NotImplemented: public std::exception {};
|
|
||||||
class FailedGetContext: public std::exception {};
|
std::string what_str;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WhatException(const std::string& what): what_str(what) {}
|
||||||
|
WhatException(): what_str("") {}
|
||||||
|
|
||||||
|
const char* what() const noexcept {
|
||||||
|
return what_str.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OF_WHAT_EXCEPTION(NotInstanciated);
|
||||||
|
class OF_WHAT_EXCEPTION(AlreadyInstanciated);
|
||||||
|
class OF_WHAT_EXCEPTION(ValuelessRegister);
|
||||||
|
class OF_WHAT_EXCEPTION(NotImplemented);
|
||||||
|
class OF_WHAT_EXCEPTION(FailedGetContext);
|
||||||
|
class OF_WHAT_EXCEPTION(NotFound);
|
||||||
|
|
||||||
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
||||||
typedef std::set<std::pair<int, DwarfRegister> > DwarfRow; // FIXME
|
typedef std::set<std::pair<int, DwarfRegister> > DwarfRow; // FIXME
|
||||||
|
@ -52,12 +76,25 @@ class DwarfInterpret {
|
||||||
int reg_id
|
int reg_id
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
uintptr_t get_return_address(uintptr_t cur_pc) const;
|
||||||
|
uintptr_t get_self_return_address() const;
|
||||||
|
|
||||||
|
static uintptr_t get_current_pc();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DwarfInterpret(const std::string& elf_path);
|
DwarfInterpret(const std::string& elf_path);
|
||||||
|
|
||||||
DwarfRegister get_column(const DwarfRow& row, int column) const;
|
DwarfRegister get_column(const DwarfRow& row, int column) const;
|
||||||
reg_content_t get_cpu_register(int reg_id) const;
|
reg_content_t get_cpu_register(int reg_id) const;
|
||||||
|
|
||||||
|
const dwarf::core::FrameSection::fde_iterator fde_at(
|
||||||
|
uintptr_t pc) const;
|
||||||
|
const dwarf::core::FrameSection::cie_iterator cie_at(
|
||||||
|
uintptr_t pc) const;
|
||||||
|
const DwarfRow& dwarf_row_at(uintptr_t pc) const;
|
||||||
|
|
||||||
|
uintptr_t get_caller_pc() const;
|
||||||
|
|
||||||
|
|
||||||
private: // members
|
private: // members
|
||||||
static std::unique_ptr<DwarfInterpret> instance;
|
static std::unique_ptr<DwarfInterpret> instance;
|
||||||
|
|
|
@ -102,6 +102,36 @@ DwarfInterpret::reg_content_t DwarfInterpret::interpret_dw_register(
|
||||||
return interpret_dw_register(row, get_column(row, reg_id));
|
return interpret_dw_register(row, get_column(row, reg_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t DwarfInterpret::get_return_address(uintptr_t cur_pc) const {
|
||||||
|
const core::Cie& cie = *cie_at(cur_pc);
|
||||||
|
const DwarfRow& row = dwarf_row_at(cur_pc);
|
||||||
|
|
||||||
|
return interpret_dw_register(row, cie.get_return_address_register_rule());
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t DwarfInterpret::get_self_return_address() const {
|
||||||
|
// Aaaaand now we have to get_return_address thrice.
|
||||||
|
return get_return_address(get_caller_pc());
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t DwarfInterpret::get_current_pc() {
|
||||||
|
// Assumes the PC is stored in REG_RIP **AND** the PC we want is this
|
||||||
|
// function's return address
|
||||||
|
|
||||||
|
DwarfInterpret& dw = DwarfInterpret::acquire();
|
||||||
|
reg_content_t pc_here = dw.get_cpu_register(REG_RIP);
|
||||||
|
fprintf(stderr, "PC=%p <inside>\n", pc_here);
|
||||||
|
fprintf(stderr, "actual PC=%p <inside>\n", __builtin_return_address(0));
|
||||||
|
return dw.get_return_address(pc_here);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t DwarfInterpret::get_caller_pc() const {
|
||||||
|
// We assume we want the PC of the caller of the calling function. This
|
||||||
|
// means we have to unwind twice. `get_current_pc` unwinds once.
|
||||||
|
|
||||||
|
return get_return_address(DwarfInterpret::get_current_pc());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Key>
|
template<typename Key>
|
||||||
static typename std::set<std::pair<int, Key> >::const_iterator find_column(
|
static typename std::set<std::pair<int, Key> >::const_iterator find_column(
|
||||||
const std::set<std::pair<int, Key> >& set,
|
const std::set<std::pair<int, Key> >& set,
|
||||||
|
@ -141,3 +171,42 @@ DwarfInterpret::reg_content_t DwarfInterpret::get_cpu_register(
|
||||||
// Let the user deal with reg_id correctness
|
// Let the user deal with reg_id correctness
|
||||||
return context.uc_mcontext.gregs[reg_id];
|
return context.uc_mcontext.gregs[reg_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const core::FrameSection::fde_iterator DwarfInterpret::fde_at(
|
||||||
|
uintptr_t pc
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const core::FrameSection& fs = root_die.get_frame_section();
|
||||||
|
const auto& fde_it = fs.find_fde_for_pc(pc);
|
||||||
|
if(fde_it == fs.fde_end())
|
||||||
|
throw NotFound(std::string("FDE at pc=") + std::to_string(pc));
|
||||||
|
|
||||||
|
return fde_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const core::FrameSection::cie_iterator DwarfInterpret::cie_at(
|
||||||
|
uintptr_t pc
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const core::Fde& fde = *fde_at(pc); // let NotFound escape if it occurs
|
||||||
|
const auto& cie_it = fde.find_cie();
|
||||||
|
if(cie_it == root_die.get_frame_section().cie_end()) // Should not happen…?
|
||||||
|
throw NotFound(std::string("CIE matching FDE at pc=")
|
||||||
|
+ std::to_string(pc));
|
||||||
|
|
||||||
|
return cie_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DwarfInterpret::DwarfRow& DwarfInterpret::dwarf_row_at(
|
||||||
|
uintptr_t pc
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const core::Fde& fde = *fde_at(pc);
|
||||||
|
auto decoded = fde.decode();
|
||||||
|
const auto& row_it = decoded.rows.find(pc);
|
||||||
|
if(row_it == decoded.rows.end())
|
||||||
|
throw NotFound(std::string("Dwarf row in this FDE at pc=")
|
||||||
|
+ std::to_string(pc));
|
||||||
|
|
||||||
|
return row_it->second;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue