//------------------------------------------------------------------------------ // Name: get_state // Desc: //------------------------------------------------------------------------------ void DebuggerCore::get_state(State *state) { // TODO: assert that we are paused if(auto state_impl = static_cast<PlatformState *>(state->impl_)) { if(attached()) { if(ptrace(PTRACE_GETREGS, active_thread(), 0, &state_impl->regs_) != -1) { #if defined(EDB_X86) struct user_desc desc; std::memset(&desc, 0, sizeof(desc)); if(ptrace(PTRACE_GET_THREAD_AREA, active_thread(), (state_impl->regs_.xgs / LDT_ENTRY_SIZE), &desc) != -1) { state_impl->gs_base = desc.base_addr; } else { state_impl->gs_base = 0; } if(ptrace(PTRACE_GET_THREAD_AREA, active_thread(), (state_impl->regs_.xfs / LDT_ENTRY_SIZE), &desc) != -1) { state_impl->fs_base = desc.base_addr; } else { state_impl->fs_base = 0; } #elif defined(EDB_X86_64) #endif } // floating point registers if(ptrace(PTRACE_GETFPREGS, active_thread(), 0, &state_impl->fpregs_) != -1) { } // debug registers state_impl->dr_[0] = ptrace(PTRACE_PEEKUSER, active_thread(), offsetof(struct user, u_debugreg[0]), 0); state_impl->dr_[1] = ptrace(PTRACE_PEEKUSER, active_thread(), offsetof(struct user, u_debugreg[1]), 0); state_impl->dr_[2] = ptrace(PTRACE_PEEKUSER, active_thread(), offsetof(struct user, u_debugreg[2]), 0); state_impl->dr_[3] = ptrace(PTRACE_PEEKUSER, active_thread(), offsetof(struct user, u_debugreg[3]), 0); state_impl->dr_[4] = 0; state_impl->dr_[5] = 0; state_impl->dr_[6] = ptrace(PTRACE_PEEKUSER, active_thread(), offsetof(struct user, u_debugreg[6]), 0); state_impl->dr_[7] = ptrace(PTRACE_PEEKUSER, active_thread(), offsetof(struct user, u_debugreg[7]), 0); } else { state_impl->clear(); } }
//------------------------------------------------------------------------------ // Name: step // Desc: //------------------------------------------------------------------------------ void DebuggerCore::step(edb::EVENT_STATUS status) { // TODO: assert that we are paused if(attached()) { if(status != edb::DEBUG_STOP) { const edb::tid_t tid = active_thread(); const int code = (status == edb::DEBUG_EXCEPTION_NOT_HANDLED) ? resume_code(threads_[tid].status) : 0; ptrace(PT_STEP, tid, reinterpret_cast<caddr_t>(1), code); } } }
//------------------------------------------------------------------------------ // Name: resume // Desc: //------------------------------------------------------------------------------ void DebuggerCore::resume(edb::EVENT_STATUS status) { // TODO: assert that we are paused if(attached()) { if(status != edb::DEBUG_STOP) { const edb::tid_t tid = active_thread(); const int code = (status == edb::DEBUG_EXCEPTION_NOT_HANDLED) ? resume_code(threads_[tid].status) : 0; ptrace_continue(tid, code); // resume the other threads passing the signal they originally reported had for(auto it = threads_.begin(); it != threads_.end(); ++it) { if(waited_threads_.contains(it.key())) { ptrace_continue(it.key(), resume_code(it->status)); } } } } }