Adapt to use DwarfInterpret as unwinder

This commit is contained in:
Théophile Bastian 2018-04-12 13:31:30 +02:00
parent 77bd72cbf8
commit 48e08d0eda
1 changed files with 68 additions and 7 deletions

View File

@ -10,6 +10,9 @@
#include <cassert>
#include <functional>
// Cf. https://git.tobast.fr/m2-internship/dwarfinterpret
#include <DwarfInterpret.hpp>
/* How can we "compile" the DWARF CFA instructions into C++ code?
* Perhaps the right thing to do is expand into "table" form first.
* Compiled code just needs to
@ -212,6 +215,17 @@ struct mcursor
long long int& rbp() { return state.gregs[REG_RBP]; }
};
struct UnwContext {
UnwContext(): valid(true) {}
bool valid;
DwarfInterpret::UnwindContext ctx;
long long int rip() { return ctx.rip; }
long long int rsp() { return ctx.rsp; }
long long int rbp() { return ctx.rbp; }
};
template <unsigned CacheSize, typename Cursor, typename StepRoutine, typename ValidityCheck, typename Dispatcher, typename Action>
struct caching_stack_walker
{
@ -306,6 +320,10 @@ struct blind_frame_pointer_validity_checker
static bool check(mcursor& c) { return true; }
};
struct dwarf_frame_pointer_validity_checker {
static bool check(UnwContext& c) { return c.valid; }
};
struct blind_frame_pointer_dispatcher; // see below
struct blind_frame_pointer_stepper
@ -389,6 +407,25 @@ struct blind_frame_pointer_stepper
#undef SANE_BP_OR_NULL
};
struct dwarf_frame_pointer_stepper {
template <typename Action>
static int step(const Action& a, UnwContext& c) {
DwarfInterpret& dw = DwarfInterpret::acquire();
try {
c.ctx = dw.unwind_context(c.ctx);
} catch(const DwarfInterpret::FirstUnwindFrame& e) {
c.valid = false;
return -1;
}
return 0;
}
static int initcontext(UnwContext& c) {
c.ctx = DwarfInterpret::get_current_unwind_context();
return 0;
}
};
struct blind_frame_pointer_dispatcher
{
// typedef int (*walker_fn)(Cursor&, const Action&);
@ -412,9 +449,33 @@ struct blind_frame_pointer_dispatcher
}
};
struct dwarf_frame_pointer_dispatcher
{
// typedef int (*walker_fn)(Cursor&, const Action&);
template <typename Action, typename Cursor>
static
//std::function<int(Cursor&, const Action&)>
int
(*lookup (const Action& a, Cursor &c, void **out_lower, void **out_upper))
(Cursor&, const Action&)
{
*out_lower = nullptr;
*out_upper = nullptr;
return &caching_stack_walker<
1u /* CacheSize */,
Cursor,
dwarf_frame_pointer_stepper /* StepRoutine */,
dwarf_frame_pointer_validity_checker /* ValidityCheck */,
dwarf_frame_pointer_dispatcher /* Dispatcher */,
Action
>::walk_stack;
}
};
struct print_frame_action
{
int act(mcursor& c) const
template <typename Cursor>
int act(Cursor& c) const
{
Dl_info i;
int success = dladdr((void *) c.rip(), &i);
@ -445,16 +506,16 @@ int g(int x)
// print_frame_action /* Action */
//>::walk_stack(c);
mcursor c_2;
UnwContext c_2;
ret = x;
ret = blind_frame_pointer_stepper::initcontext(c_2);
ret = dwarf_frame_pointer_stepper::initcontext(c_2);
if (ret) abort();
return
stack_walker<
mcursor,
blind_frame_pointer_stepper /* StepRoutine */,
blind_frame_pointer_validity_checker /* ValidityCheck */,
blind_frame_pointer_dispatcher /* Dispatcher */,
UnwContext,
dwarf_frame_pointer_stepper /* StepRoutine */,
dwarf_frame_pointer_validity_checker /* ValidityCheck */,
dwarf_frame_pointer_dispatcher /* Dispatcher */,
print_frame_action /* Action */
>::walk_stack(c_2);
}