Compare commits

...

3 commits

3 changed files with 32 additions and 9 deletions

View file

@ -107,6 +107,9 @@ class DwarfInterpret {
uintptr_t rip; uintptr_t rip;
uintptr_t rsp; uintptr_t rsp;
uintptr_t rbp; uintptr_t rbp;
/// This context's `RIP` minus its ELF file load offset
uintptr_t elf_local_rip() const;
}; };
public: // methods public: // methods
@ -180,6 +183,12 @@ class DwarfInterpret {
*/ */
UnwindContext unwind_context(const UnwindContext& ctx); UnwindContext unwind_context(const UnwindContext& ctx);
/** Get the offset for the instruction pointer.
*
* This offset is such that `actual_rip - pc_offset` is the ELF-local
* PC (ie. what readelf gives). */
uintptr_t get_pc_offset() const { return pc_offset; }
private: private:
DwarfInterpret(const MemoryMap::MapEntry& memory_object); DwarfInterpret(const MemoryMap::MapEntry& memory_object);

View file

@ -36,6 +36,11 @@ using namespace dwarf;
MemoryMap DwarfInterpret::memory_map; MemoryMap DwarfInterpret::memory_map;
map<int, unique_ptr<DwarfInterpret> > DwarfInterpret::instances; map<int, unique_ptr<DwarfInterpret> > DwarfInterpret::instances;
uintptr_t DwarfInterpret::UnwindContext::elf_local_rip() const {
return rip - DwarfInterpret::acquire(rip).get_pc_offset();
}
DwarfInterpret::DwarfInterpret(const MemoryMap::MapEntry& memory_object) DwarfInterpret::DwarfInterpret(const MemoryMap::MapEntry& memory_object)
: map_entry(memory_object) : map_entry(memory_object)
{ {
@ -205,13 +210,17 @@ DwarfInterpret::UnwindContext DwarfInterpret::unwind_context(
// An undefined RA means we've reached the end of the call stack // An undefined RA means we've reached the end of the call stack
throw FirstUnwindFrame(); throw FirstUnwindFrame();
} }
new_context.rbp = interpret_dw_register( try {
cur_row, new_context.rbp = interpret_dw_register(
lib::DWARF_X86_64_RBP, cur_row,
ctx); lib::DWARF_X86_64_RBP,
if(new_context.rbp == 0) { ctx);
// A null rbp means we've reached the end of the call stack if(new_context.rbp == 0) {
throw FirstUnwindFrame(); // A null rbp means we've reached the end of the call stack
throw FirstUnwindFrame();
}
} catch(const std::out_of_range& e) {
new_context.rbp = 0; // The base pointer does not exist
} }
new_context.rsp = interpret_dw_register( new_context.rsp = interpret_dw_register(

View file

@ -28,7 +28,11 @@ void dump_my_stack() {
(dl_rc && dl_inf.dli_sname) ? dl_inf.dli_sname : "(no symbol)", (dl_rc && dl_inf.dli_sname) ? dl_inf.dli_sname : "(no symbol)",
cur_map_entry.pathname.c_str()); cur_map_entry.pathname.c_str());
fflush(stdout); fflush(stdout);
unw_context = dw.unwind_context(unw_context); try {
unw_context = dw.unwind_context(unw_context);
} catch(const DwarfInterpret::FirstUnwindFrame& exn) {
return;
}
} }
} }
@ -36,7 +40,8 @@ void fill_my_stack(int stack_depth) {
if(stack_depth == 0) if(stack_depth == 0)
dump_my_stack(); dump_my_stack();
fill_my_stack(stack_depth - 1); else
fill_my_stack(stack_depth - 1);
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {