Detect end-of-unwind
According to LibUnwind:src/x86_64/Gstep.c:85 (HEAD=c91974f30feac05055621e33ca101a371236c786), the x86_64 ABI states that the end of the call stack is determined by either a null RBP or an undefined return-address column in the DWARF.
This commit is contained in:
parent
e567039227
commit
0eb6cad1ba
3 changed files with 22 additions and 8 deletions
|
@ -81,6 +81,8 @@ class DwarfInterpret {
|
|||
/// Thrown when a Dwarf element is not found for a given PC
|
||||
class OF_WHAT_EXCEPTION(NotFound);
|
||||
|
||||
/// Thrown when trying to unwind a context with nothing more to unwind
|
||||
class FirstUnwindFrame: public std::exception {};
|
||||
|
||||
/// A Dwarf register
|
||||
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
||||
|
@ -172,7 +174,10 @@ class DwarfInterpret {
|
|||
*/
|
||||
static UnwindContext get_current_unwind_context();
|
||||
|
||||
/// Unwinds once the given context
|
||||
/** Unwinds once the given context
|
||||
*
|
||||
* \throws FirstUnwindFrame when trying to unwind the first frame.
|
||||
*/
|
||||
UnwindContext unwind_context(const UnwindContext& ctx);
|
||||
|
||||
private:
|
||||
|
|
|
@ -220,15 +220,24 @@ DwarfInterpret::UnwindContext DwarfInterpret::unwind_context(
|
|||
<< cie.get_return_address_register_rule()
|
||||
<< " at current IP = "
|
||||
<< hex << ctx.rip << endl;
|
||||
new_context.rip = interpret_dw_register(
|
||||
cur_row,
|
||||
cie.get_return_address_register_rule(),
|
||||
ctx);
|
||||
try {
|
||||
new_context.rip = interpret_dw_register(
|
||||
cur_row,
|
||||
cie.get_return_address_register_rule(),
|
||||
ctx);
|
||||
} catch(const std::out_of_range& e) {
|
||||
// An undefined RA means we've reached the end of the call stack
|
||||
throw FirstUnwindFrame();
|
||||
}
|
||||
cerr << "Yielding " << hex << new_context.rip << dec << endl;
|
||||
new_context.rbp = interpret_dw_register(
|
||||
cur_row,
|
||||
lib::DWARF_X86_64_RBP,
|
||||
ctx);
|
||||
if(new_context.rbp == 0) {
|
||||
// A null rbp means we've reached the end of the call stack
|
||||
throw FirstUnwindFrame();
|
||||
}
|
||||
|
||||
new_context.rsp = interpret_dw_register(
|
||||
cur_row,
|
||||
|
|
|
@ -30,9 +30,9 @@ void dump_my_stack(int thread_id) {
|
|||
cur_map_entry.pathname.c_str());
|
||||
fflush(stdout);
|
||||
try {
|
||||
unw_context = dw.unwind_context(unw_context);
|
||||
} catch(...) {
|
||||
// Assume we're reached _start
|
||||
unw_context = dw.unwind_context(unw_context);
|
||||
} catch(const DwarfInterpret::FirstUnwindFrame& e) {
|
||||
// We're reached the end of the stack
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue