diff --git a/include/dwarfinterpret/DwarfInterpret.hpp b/include/dwarfinterpret/DwarfInterpret.hpp index 0a46054..13122ff 100644 --- a/include/dwarfinterpret/DwarfInterpret.hpp +++ b/include/dwarfinterpret/DwarfInterpret.hpp @@ -141,16 +141,6 @@ class DwarfInterpret { const UnwindContext& ctx ) const; - /** Get the return address at a given program counter, assuming the - * correct registers are stored */ - uintptr_t get_return_address(uintptr_t cur_pc) const; - - /** Get the return address of the current program point */ - uintptr_t get_self_return_address() const; - - /// Get the current program counter - static uintptr_t get_current_pc(); - /// Get the current UnwindContext (from the caller's point of view) static UnwindContext get_current_unwind_context(); @@ -161,15 +151,12 @@ class DwarfInterpret { DwarfInterpret(const MemoryMap::MapEntry& memory_object); DwarfRegister get_column(const DwarfRow& row, int column) const; - reg_content_t get_cpu_register(int reg_id) const; const dwarf::core::FrameSection::fde_iterator fde_at( uintptr_t pc) const; const dwarf::core::FrameSection::cie_iterator cie_at( uintptr_t pc) const; - uintptr_t get_caller_pc() const; - /** Get the #DwarfInterpret instance responsible for the given PC, or * nullptr if the current instance is responsible. */ DwarfInterpret* get_responsible_instance(uintptr_t pc) const; diff --git a/src/DwarfInterpret.cpp b/src/DwarfInterpret.cpp index d312ea7..fceaa9e 100644 --- a/src/DwarfInterpret.cpp +++ b/src/DwarfInterpret.cpp @@ -24,6 +24,15 @@ using namespace std; using namespace dwarf; +#define get_cpu_register(reg_id, dest) {\ + ucontext_t context; \ + if(getcontext(&context) != 0) \ + throw DwarfInterpret::FailedGetContext(); \ + (dest) = context.uc_mcontext.gregs[(reg_id)]; \ +} + + + MemoryMap DwarfInterpret::memory_map; map > DwarfInterpret::instances; @@ -179,53 +188,18 @@ DwarfInterpret::reg_content_t DwarfInterpret::interpret_dw_register( return interpret_dw_register(row, get_column(row, reg_id), ctx); } -uintptr_t DwarfInterpret::get_return_address(uintptr_t cur_pc) const { - DwarfInterpret* responsible = get_responsible_instance(cur_pc); - if(responsible != nullptr) - return responsible->get_return_address(cur_pc); - - const core::Cie& cie = *cie_at(cur_pc); - const DwarfRow& row = dwarf_row_at(cur_pc); - - UnwindContext ctx = get_current_unwind_context(); - // FIXME ^^^ ugly patch, this should not be a thing - uintptr_t translated_ra = - interpret_dw_register(row, - cie.get_return_address_register_rule(), - ctx); - cerr << "Return address from 0x" << hex << cur_pc << ": " - << "0x" << translated_ra << endl; - return translated_ra; -} - -uintptr_t DwarfInterpret::get_self_return_address() const { - // Aaaaand now we have to get_return_address thrice. - return get_return_address(get_caller_pc()); -} - -uintptr_t DwarfInterpret::get_current_pc() { - // Assumes the PC is stored in REG_RIP **AND** the PC we want is this - // function's return address - - DwarfInterpret& dw = DwarfInterpret::acquire(); - reg_content_t pc_here = dw.get_cpu_register(REG_RIP); - fprintf(stderr, "PC=%p \n", pc_here); - fprintf(stderr, "actual PC=%p \n", __builtin_return_address(0)); - return dw.get_return_address(pc_here); -} - DwarfInterpret::UnwindContext DwarfInterpret::get_current_unwind_context() { // FIXME for now this returns SOME unwind context (actually, the unwind // context snapshot naively taken from inside this function). Unwinding // it some number of times should yield the expected context - uintptr_t rsp = DwarfInterpret::acquire().get_cpu_register(REG_RSP); + uintptr_t rsp; + get_cpu_register(REG_RSP, rsp); UnwindContext ctx(StackDump::snapshot(rsp)); - DwarfInterpret& dw = DwarfInterpret::acquire(); - ctx.rip = dw.get_cpu_register(REG_RIP); + get_cpu_register(REG_RIP, ctx.rip); ctx.rsp = rsp; - ctx.rbp = dw.get_cpu_register(REG_RBP); + get_cpu_register(REG_RBP, ctx.rbp); cerr << "CREATING CONTEXT. %rsp=0x" << hex << ctx.rsp @@ -233,7 +207,9 @@ DwarfInterpret::UnwindContext DwarfInterpret::get_current_unwind_context() { << ", %rip=0x" << ctx.rip << dec << endl; - return ctx; + DwarfInterpret& dw = DwarfInterpret::acquire(ctx.rip); + + return dw.unwind_context(ctx); } DwarfInterpret::UnwindContext DwarfInterpret::unwind_context( @@ -269,13 +245,6 @@ DwarfInterpret::UnwindContext DwarfInterpret::unwind_context( return new_context; } -uintptr_t DwarfInterpret::get_caller_pc() const { - // We assume we want the PC of the caller of the calling function. This - // means we have to unwind twice. `get_current_pc` unwinds once. - - return get_return_address(DwarfInterpret::get_current_pc()); -} - template static typename std::set >::const_iterator find_column( const std::set >& set, @@ -305,17 +274,6 @@ DwarfInterpret::DwarfRegister DwarfInterpret::get_column( return it->second; } -DwarfInterpret::reg_content_t DwarfInterpret::get_cpu_register( - int reg_id) const -{ - ucontext_t context; - if(getcontext(&context) != 0) - throw FailedGetContext(); - - // Let the user deal with reg_id correctness - return context.uc_mcontext.gregs[reg_id]; -} - const core::FrameSection::fde_iterator DwarfInterpret::fde_at( uintptr_t pc ) const diff --git a/test/Makefile b/test/Makefile index c0132a7..56c9fa0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -13,8 +13,13 @@ all: $(TARGET) %.bin: %.o $(CXX) $(CXXFLAGS) $(CXXDIRS) $(CXXLIBS) $< -o "$@" +dump_my_stack.bin: dump_my_stack.o + $(CXX) $(CXXFLAGS) $(CXXDIRS) $(CXXLIBS) -ldl -rdynamic $< -o "$@" + %.o: %.cpp $(CXX) $(CXXFLAGS) $(CXXDIRS) -c "$<" -o "$@" +.PRECIOUS: %.o + clean: rm -f $(OBJS) $(TARGET) diff --git a/test/dump_my_stack.cpp b/test/dump_my_stack.cpp index 7635f74..0c60037 100644 --- a/test/dump_my_stack.cpp +++ b/test/dump_my_stack.cpp @@ -1,4 +1,5 @@ #include +#include #include using namespace std; @@ -13,12 +14,19 @@ void dump_my_stack() { MemoryMap mmap; while(true) { + Dl_info dl_inf; + int dl_rc = dladdr((void *) unw_context.rip, &dl_inf); + printf(">> PC = %lX ", unw_context.rip); MemoryMap::MapEntry cur_map_entry = mmap[mmap.id_of_address(unw_context.rip)]; uintptr_t inelf_pc = unw_context.rip - cur_map_entry.mem_region.begin + cur_map_entry.offset; - printf("(in ELF: %lX) <<\n", inelf_pc); + + printf("(in ELF: 0x%lX, func %s, path %s) <<\n", + inelf_pc, + (dl_rc && dl_inf.dli_sname) ? dl_inf.dli_sname : "(no symbol)", + cur_map_entry.pathname.c_str()); fflush(stdout); unw_context = dw.unwind_context(unw_context); }