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
|
/// Thrown when a Dwarf element is not found for a given PC
|
||||||
class OF_WHAT_EXCEPTION(NotFound);
|
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
|
/// A Dwarf register
|
||||||
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
||||||
|
@ -172,7 +174,10 @@ class DwarfInterpret {
|
||||||
*/
|
*/
|
||||||
static UnwindContext get_current_unwind_context();
|
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);
|
UnwindContext unwind_context(const UnwindContext& ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -220,15 +220,24 @@ DwarfInterpret::UnwindContext DwarfInterpret::unwind_context(
|
||||||
<< cie.get_return_address_register_rule()
|
<< cie.get_return_address_register_rule()
|
||||||
<< " at current IP = "
|
<< " at current IP = "
|
||||||
<< hex << ctx.rip << endl;
|
<< hex << ctx.rip << endl;
|
||||||
|
try {
|
||||||
new_context.rip = interpret_dw_register(
|
new_context.rip = interpret_dw_register(
|
||||||
cur_row,
|
cur_row,
|
||||||
cie.get_return_address_register_rule(),
|
cie.get_return_address_register_rule(),
|
||||||
ctx);
|
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;
|
cerr << "Yielding " << hex << new_context.rip << dec << endl;
|
||||||
new_context.rbp = interpret_dw_register(
|
new_context.rbp = interpret_dw_register(
|
||||||
cur_row,
|
cur_row,
|
||||||
lib::DWARF_X86_64_RBP,
|
lib::DWARF_X86_64_RBP,
|
||||||
ctx);
|
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(
|
new_context.rsp = interpret_dw_register(
|
||||||
cur_row,
|
cur_row,
|
||||||
|
|
|
@ -31,8 +31,8 @@ void dump_my_stack(int thread_id) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
try {
|
try {
|
||||||
unw_context = dw.unwind_context(unw_context);
|
unw_context = dw.unwind_context(unw_context);
|
||||||
} catch(...) {
|
} catch(const DwarfInterpret::FirstUnwindFrame& e) {
|
||||||
// Assume we're reached _start
|
// We're reached the end of the stack
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue