//------------------------------------------------------------------------------ // 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)); } } } } }
//------------------------------------------------------------------------------ // 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: resumes this thread , passing the signal that stopped it // (unless the signal was SIGSTOP, or the passed status != DEBUG_EXCEPTION_NOT_HANDLED) //------------------------------------------------------------------------------ void PlatformThread::resume(edb::EVENT_STATUS status) { const int code = (status == edb::DEBUG_EXCEPTION_NOT_HANDLED) ? resume_code(status_) : 0; core_->ptrace_continue(tid_, code); }
//------------------------------------------------------------------------------ // Name: resume // Desc: resumes this thread, passing the signal that stopped it // (unless the signal was SIGSTOP) //------------------------------------------------------------------------------ void PlatformThread::resume() { core_->ptrace_continue(tid_, resume_code(status_)); }
//------------------------------------------------------------------------------ // Name: step // Desc: steps this thread one instruction, passing the signal that stopped it // (unless the signal was SIGSTOP) //------------------------------------------------------------------------------ void PlatformThread::step() { core_->ptrace_step(tid_, resume_code(status_)); }
//------------------------------------------------------------------------------ // Name: handle_event // Desc: //------------------------------------------------------------------------------ IDebugEvent::const_pointer DebuggerCore::handle_event(edb::tid_t tid, int status) { // note that we have waited on this thread waited_threads_.insert(tid); // was it a thread exit event? if(WIFEXITED(status)) { threads_.remove(tid); waited_threads_.remove(tid); // if this was the last thread, return true // so we report it to the user. // if this wasn't, then we should silently // procceed. if(!threads_.empty()) { return nullptr; } } // was it a thread create event? if(is_clone_event(status)) { unsigned long new_tid; if(ptrace_get_event_message(tid, &new_tid) != -1) { const thread_info info = { 0, thread_info::THREAD_STOPPED }; threads_.insert(new_tid, info); int thread_status = 0; if(!waited_threads_.contains(new_tid)) { if(native::waitpid(new_tid, &thread_status, __WALL) > 0) { waited_threads_.insert(new_tid); } } if(!WIFSTOPPED(thread_status) || WSTOPSIG(thread_status) != SIGSTOP) { qDebug("[warning] new thread [%d] received an event besides SIGSTOP", static_cast<int>(new_tid)); } // TODO: what the heck do we do if this isn't a SIGSTOP? ptrace_continue(new_tid, resume_code(thread_status)); } ptrace_continue(tid, 0); return nullptr; } // normal event auto e = std::make_shared<PlatformEvent>(); e->pid_ = pid(); e->tid_ = tid; e->status_ = status; if(ptrace_getsiginfo(tid, &e->siginfo_) == -1) { // TODO: handle no info? } active_thread_ = tid; event_thread_ = tid; threads_[tid].status = status; stop_threads(); return e; }