diff --git a/frame-machine.cc b/frame-machine.cc index 5827522..4b7a582 100644 --- a/frame-machine.cc +++ b/frame-machine.cc @@ -10,6 +10,9 @@ #include #include +// Cf. https://git.tobast.fr/m2-internship/dwarfinterpret +#include + /* 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 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 + 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 + static + //std::function + 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 + 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); }