bool ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) { // in any case uninstall the temporary breakpoint _UninstallTemporaryBreakpoint(); switch (fStepMode) { case STEP_OVER: // If we're still in the statement, we continue single-stepping, // otherwise we're done. if (fStepStatement->ContainsAddress( cpuState->InstructionPointer())) { if (!_DoStepOver(cpuState)) _StepFallback(); return true; } return false; case STEP_INTO: // Should never happen -- we don't set a breakpoint in this case. case STEP_OUT: // That's the return address, so we're done. default: return false; } }
void ThreadHandler::_ClearContinuationState() { _UninstallTemporaryBreakpoint(); if (fStepStatement != NULL) { fStepStatement->ReleaseReference(); fStepStatement = NULL; } fStepMode = STEP_NONE; fSingleStepping = false; }
status_t ThreadHandler::_InstallTemporaryBreakpoint(target_addr_t address) { _UninstallTemporaryBreakpoint(); status_t error = fBreakpointManager->InstallTemporaryBreakpoint(address, this); if (error != B_OK) return error; fBreakpointAddress = address; return B_OK; }
bool ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) { // in any case uninstall the temporary breakpoint _UninstallTemporaryBreakpoint(); switch (fStepMode) { case STEP_OVER: { StackTrace* stackTrace = fThread->GetStackTrace(); BReference<StackTrace> stackTraceReference(stackTrace); if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( fThread->GetTeam(), this, cpuState, stackTrace, NULL, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } if (stackTrace != NULL) { StackFrame* frame = stackTrace->FrameAt(0); // If we're not in the same frame we started in, // keep executing. if (frame != NULL && fPreviousFrameAddress != frame->FrameAddress()) { status_t error = _InstallTemporaryBreakpoint( cpuState->InstructionPointer()); if (error != B_OK) _StepFallback(); else _RunThread(cpuState->InstructionPointer()); return true; } } if (fPreviousFrameAddress != 0 && fSteppedOverFunctionAddress != cpuState->InstructionPointer()) { TRACE_CONTROL("STEP_OVER: called function address %#" B_PRIx64 ", previous frame address: %#" B_PRIx64 ", frame address: %#" B_PRIx64 ", adding return info\n", fSteppedOverFunctionAddress, fPreviousFrameAddress, stackTrace->FrameAt(0)->FrameAddress()); ReturnValueInfo* returnInfo = new(std::nothrow) ReturnValueInfo( fSteppedOverFunctionAddress, cpuState); if (returnInfo == NULL) return false; BReference<ReturnValueInfo> returnInfoReference(returnInfo, true); if (fThread->AddReturnValueInfo(returnInfo) != B_OK) return false; returnInfoReference.Detach(); fSteppedOverFunctionAddress = 0; } // If we're still in the statement, we continue single-stepping, // otherwise we're done. if (fStepStatement->ContainsAddress( cpuState->InstructionPointer())) { if (!_DoStepOver(cpuState)) _StepFallback(); return true; } fPreviousFrameAddress = 0; return false; } case STEP_INTO: // Should never happen -- we don't set a breakpoint in this case. return false; case STEP_OUT: { // That's the return address, so we're done in theory, // unless we're a recursive function. Check if we've actually // exited the previous stack frame or not if (!_HasExitedFrame(cpuState->StackFramePointer())) { status_t error = _InstallTemporaryBreakpoint( cpuState->InstructionPointer()); if (error != B_OK) _StepFallback(); else _RunThread(cpuState->InstructionPointer()); return true; } if (fPreviousFrameAddress == 0) return false; TRACE_CONTROL("ThreadHandler::_HandleBreakpointHitStep() - " "frame pointer 0x%#" B_PRIx64 ", previous: 0x%#" B_PRIx64 " - step out adding return value\n", cpuState ->StackFramePointer(), fPreviousFrameAddress); ReturnValueInfo* info = new(std::nothrow) ReturnValueInfo( fPreviousInstructionPointer, cpuState); if (info == NULL) return false; BReference<ReturnValueInfo> infoReference(info, true); if (fThread->AddReturnValueInfo(info) != B_OK) return false; infoReference.Detach(); fPreviousFrameAddress = 0; } default: return false; } }
bool ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) { // in any case uninstall the temporary breakpoint _UninstallTemporaryBreakpoint(); switch (fStepMode) { case STEP_OVER: { StackTrace* stackTrace = fThread->GetStackTrace(); BReference<StackTrace> stackTraceReference(stackTrace); if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } if (stackTrace != NULL) { StackFrame* frame = stackTrace->FrameAt(0); // If we're not in the same frame we started in, // keep executing. if (frame != NULL && fPreviousFrameAddress != frame->FrameAddress()) { status_t error = _InstallTemporaryBreakpoint( cpuState->InstructionPointer()); if (error != B_OK) _StepFallback(); else _RunThread(cpuState->InstructionPointer()); return true; } } // If we're still in the statement, we continue single-stepping, // otherwise we're done. if (fStepStatement->ContainsAddress( cpuState->InstructionPointer())) { if (!_DoStepOver(cpuState)) _StepFallback(); return true; } fPreviousFrameAddress = 0; return false; } case STEP_INTO: // Should never happen -- we don't set a breakpoint in this case. return false; case STEP_OUT: { // That's the return address, so we're done in theory, // unless we're a recursive function. Check if we've actually // exited the previous stack frame or not. fThread->SetExecutedSubroutine(cpuState->InstructionPointer()); target_addr_t framePointer = cpuState->StackFramePointer(); bool hasExitedFrame = fDebuggerInterface->GetArchitecture() ->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE ? framePointer < fPreviousFrameAddress : framePointer > fPreviousFrameAddress; if (!hasExitedFrame) { status_t error = _InstallTemporaryBreakpoint( cpuState->InstructionPointer()); if (error != B_OK) _StepFallback(); else _RunThread(cpuState->InstructionPointer()); return true; } fPreviousFrameAddress = 0; } default: return false; } }