bool MachThread::ShouldStop(bool &step_more) { // See if this thread is at a breakpoint? DNBBreakpoint *bp = CurrentBreakpoint(); if (bp) { // This thread is sitting at a breakpoint, ask the breakpoint // if we should be stopping here. return true; } else { if (m_arch_ap->StepNotComplete()) { step_more = true; return false; } // The thread state is used to let us know what the thread was // trying to do. MachThread::ThreadWillResume() will set the // thread state to various values depending if the thread was // the current thread and if it was to be single stepped, or // resumed. if (GetState() == eStateRunning) { // If our state is running, then we should continue as we are in // the process of stepping over a breakpoint. return false; } else { // Stop if we have any kind of valid exception for this // thread. if (GetStopException().IsValid()) return true; } } return false; }
bool MachThread::IsStepping() { // Return true if this thread is currently being stepped. // MachThread::ThreadWillResume currently determines this by looking if we // have been asked to single step, or if we are at a breakpoint instruction // and have been asked to resume. In the latter case we need to disable the // breakpoint we are at, single step, re-enable and continue. nub_state_t state = GetState(); return (state == eStateStepping) || (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint())); }
bool MachThread::ShouldStop(bool &step_more) { // See if this thread is at a breakpoint? nub_break_t breakID = CurrentBreakpoint(); if (NUB_BREAK_ID_IS_VALID(breakID)) { // This thread is sitting at a breakpoint, ask the breakpoint // if we should be stopping here. if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID)) return true; else { // The breakpoint said we shouldn't stop, but we may have gotten // a signal or the user may have requested to stop in some other // way. Stop if we have a valid exception (this thread won't if // another thread was the reason this process stopped) and that // exception, is NOT a breakpoint exception (a common case would // be a SIGINT signal). if (GetStopException().IsValid() && !GetStopException().IsBreakpoint()) return true; } } else { if (m_arch_ap->StepNotComplete()) { step_more = true; return false; } // The thread state is used to let us know what the thread was // trying to do. MachThread::ThreadWillResume() will set the // thread state to various values depending if the thread was // the current thread and if it was to be single stepped, or // resumed. if (GetState() == eStateRunning) { // If our state is running, then we should continue as we are in // the process of stepping over a breakpoint. return false; } else { // Stop if we have any kind of valid exception for this // thread. if (GetStopException().IsValid()) return true; } } return false; }
void MachThread::NotifyBreakpointChanged (const DNBBreakpoint *bp) { nub_break_t breakID = bp->GetID(); if (bp->IsEnabled()) { if (bp->Address() == GetPC()) { SetCurrentBreakpoint(breakID); } } else { if (CurrentBreakpoint() == breakID) { SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); } } }
bool MachThread::ThreadDidStop() { // This thread has existed prior to resuming under debug nub control, // and has just been stopped. Do any cleanup that needs to be done // after running. // The thread state and breakpoint will still have the same values // as they had prior to resuming the thread, so it makes it easy to check // if we were trying to step a thread, or we tried to resume while being // at a breakpoint. // When this method gets called, the process state is still in the // state it was in while running so we can act accordingly. m_arch_ap->ThreadDidStop(); // We may have suspended this thread so the primary thread could step // without worrying about race conditions, so lets restore our suspend // count. RestoreSuspendCount(); // Update the basic information for a thread MachThread::GetBasicInfo(m_tid, &m_basicInfo); #if ENABLE_AUTO_STEPPING_OVER_BP // See if we were at a breakpoint when we last resumed that we disabled, // re-enable it. nub_break_t breakID = CurrentBreakpoint(); if (NUB_BREAK_ID_IS_VALID(breakID)) { m_process->EnableBreakpoint(breakID); if (m_basicInfo.suspend_count > 0) { SetState(eStateSuspended); } else { // If we last were at a breakpoint and we single stepped, our state // will be "running" to indicate we need to continue after stepping // over the breakpoint instruction. If we step over a breakpoint // instruction, we need to stop. if (GetState() == eStateRunning) { // Leave state set to running so we will continue automatically // from this breakpoint } else { SetState(eStateStopped); } } } else { if (m_basicInfo.suspend_count > 0) { SetState(eStateSuspended); } else { SetState(eStateStopped); } } #else if (m_basicInfo.suspend_count > 0) SetState(eStateSuspended); else SetState(eStateStopped); #endif return true; }