void Debugger::pauseIfNeeded(CallFrame* callFrame) { if (m_isPaused) return; if (m_suppressAllPauses) return; JSGlobalObject* vmEntryGlobalObject = callFrame->vmEntryGlobalObject(); if (!needPauseHandling(vmEntryGlobalObject)) return; Breakpoint breakpoint; bool didHitBreakpoint = false; bool pauseNow = m_pauseOnNextStatement; pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame); DebuggerPausedScope debuggerPausedScope(*this); intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame); TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame); pauseNow |= didHitBreakpoint = hasBreakpoint(sourceID, position, &breakpoint); m_lastExecutedLine = position.m_line.zeroBasedInt(); if (!pauseNow) return; // Make sure we are not going to pause again on breakpoint actions by // reseting the pause state before executing any breakpoint actions. TemporaryPausedState pausedState(*this); m_pauseOnCallFrame = 0; m_pauseOnNextStatement = false; if (didHitBreakpoint) { handleBreakpointHit(vmEntryGlobalObject, breakpoint); // Note that the actions can potentially stop the debugger, so we need to check that // we still have a current call frame when we get back. if (breakpoint.autoContinue || !m_currentCallFrame) return; m_pausingBreakpointID = breakpoint.id; } { PauseReasonDeclaration reason(*this, didHitBreakpoint ? PausedForBreakpoint : m_reasonForPause); handlePause(vmEntryGlobalObject, m_reasonForPause); RELEASE_ASSERT(!callFrame->hadException()); } m_pausingBreakpointID = noBreakpointID; if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) { setSteppingMode(SteppingModeDisabled); m_currentCallFrame = nullptr; } }
NaviError GdbSystem::processBreakpointMessage(const std::string& msg) { // If the received message is a breakpoint message, it // is necessary to find out where the breakpoint exception // occurred. // TODO: Not all require this cpu->sendAck(); CPUADDRESS address = 0; NaviError getProgramCounterError = getInstructionPointerFromStopMessage( msg, cpu->getInstructionPointerIndex(), address); if (getProgramCounterError) { msglog->log( LOG_VERBOSE, "Error: Couldn't read the value of the instruction pointer (Code %d)", getProgramCounterError); return getProgramCounterError; } synchronizeThreadState(); unsigned int threadId = threadFromBreakpointMessage(msg); NaviError eipResult = getInstructionPointer(threadId, address); address = cpu->correctBreakpointAddress(address); if (hasBreakpoint(address, BPX_simple) || hasBreakpoint(address, BPX_echo) || hasBreakpoint(address, BPX_stepping)) { handleBreakpointHit(address); } else if (cpu->getDebuggerOptions().canHalt) { // Some other reason caused the process to stop // If the target CPU can halt arbitrarily, let's hope // that the halt was caused by the user. } else { // None of our breakpoints and the target CPU can not // halt arbitrarily => Handle the issue farther up in the chain. handleBreakpointHit(address); } return NaviErrors::SUCCESS; }