hrev43504 adds 2 changesets to branch 'master' old head: d3e31951126b42f65cb57ac59eebeba003b34973 new head: 118ddee0fdddd28bb953d559713a8da1bcd0d06e ---------------------------------------------------------------------------- 16875b8: Make CreateStackTrace() more flexible. CreateStackTrace() can now optionally be asked to limit the maximum number of frames it tries to unwind. In conjunction, it can also be passed an already existing partial stack trace, and be asked to unwind more frames from it. 118ddee: Adjust ThreadHandler's usage of CreateStackTrace(). - Limit invocations of CreateStackTrace() in ThreadHandler to only unwind the topmost frame since that's all it actually cares about anyways. Also adjust Step Over to use this functionality in order to work with the correct frame addresses, since the CPU frame pointer register isn't entirely what we want here. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- 3 files changed, 57 insertions(+), 22 deletions(-) src/apps/debugger/ThreadHandler.cpp | 42 ++++++++++++++++++-------- src/apps/debugger/arch/Architecture.cpp | 33 ++++++++++++++++----- src/apps/debugger/arch/Architecture.h | 4 ++- ############################################################################ Commit: 16875b8c58c43e778fdf41b99134285052e5a5bb URL: http://cgit.haiku-os.org/haiku/commit/?id=16875b8 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Dec 15 03:00:17 2011 UTC Make CreateStackTrace() more flexible. CreateStackTrace() can now optionally be asked to limit the maximum number of frames it tries to unwind. In conjunction, it can also be passed an already existing partial stack trace, and be asked to unwind more frames from it. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index 33e5460..084b8ee 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.cpp @@ -94,18 +94,31 @@ Architecture::InitRegisterRules(CfaContext& context) const status_t Architecture::CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, - StackTrace*& _stackTrace) + StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace) { BReference<CpuState> cpuStateReference(cpuState); - // create the object - StackTrace* stackTrace = new(std::nothrow) StackTrace; - if (stackTrace == NULL) - return B_NO_MEMORY; - ObjectDeleter<StackTrace> stackTraceDeleter(stackTrace); - + StackTrace* stackTrace = NULL; + ObjectDeleter<StackTrace> stackTraceDeleter; StackFrame* frame = NULL; + if (useExistingTrace) + stackTrace = _stackTrace; + else { + // create the object + stackTrace = new(std::nothrow) StackTrace; + if (stackTrace == NULL) + return B_NO_MEMORY; + stackTraceDeleter.SetTo(stackTrace); + } + + // if we're passed an already existing partial stack trace, + // attempt to continue building it from where it left off. + if (stackTrace->CountFrames() > 0) { + frame = stackTrace->FrameAt(stackTrace->CountFrames() - 1); + cpuState = frame->GetCpuState(); + } + while (cpuState != NULL) { // get the instruction pointer target_addr_t instructionPointer = cpuState->InstructionPointer(); @@ -169,11 +182,15 @@ Architecture::CreateStackTrace(Team* team, previousFrame->SetImage(image); previousFrame->SetFunction(function); - if (!stackTrace->AddFrame(previousFrame)) + if (!stackTrace->AddFrame(previousFrame)) { + delete previousFrame; return B_NO_MEMORY; + } frame = previousFrame; cpuState = previousCpuState; + if (--maxStackDepth == 0) + break; } stackTraceDeleter.Detach(); diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index d74d652..1f0d40b 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -100,7 +100,9 @@ public: status_t CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, - StackTrace*& _stackTrace); + StackTrace*& _stackTrace, + int32 maxStackDepth = -1, + bool useExistingTrace = false); // team is not locked protected: ############################################################################ Revision: hrev43504 Commit: 118ddee0fdddd28bb953d559713a8da1bcd0d06e URL: http://cgit.haiku-os.org/haiku/commit/?id=118ddee Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Thu Dec 15 03:27:38 2011 UTC Adjust ThreadHandler's usage of CreateStackTrace(). - Limit invocations of CreateStackTrace() in ThreadHandler to only unwind the topmost frame since that's all it actually cares about anyways. Also adjust Step Over to use this functionality in order to work with the correct frame addresses, since the CPU frame pointer register isn't entirely what we want here. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/ThreadHandler.cpp b/src/apps/debugger/ThreadHandler.cpp index 19450f9..c1932f2 100644 --- a/src/apps/debugger/ThreadHandler.cpp +++ b/src/apps/debugger/ThreadHandler.cpp @@ -253,7 +253,7 @@ ThreadHandler::HandleThreadAction(uint32 action) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, 1) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -324,7 +324,7 @@ ThreadHandler::HandleThreadAction(uint32 action) fStepMode = STEP_INTO; _SingleStepThread(frame->GetCpuState()->InstructionPointer()); } else { - fPreviousFrameAddress = cpuState->StackFramePointer(); + fPreviousFrameAddress = frame->FrameAddress(); // step over fStepMode = STEP_OVER; if (!_DoStepOver(frame->GetCpuState())) @@ -559,17 +559,32 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) switch (fStepMode) { case STEP_OVER: { - // If we're not in the same frame we started in, keep executing. - if (cpuState->StackFramePointer() != fPreviousFrameAddress) - { - status_t error = _InstallTemporaryBreakpoint( - cpuState->InstructionPointer()); - if (error != B_OK) - _StepFallback(); - else - _RunThread(cpuState->InstructionPointer()); - return true; + StackTrace* stackTrace = fThread->GetStackTrace(); + BReference<StackTrace> stackTraceReference(stackTrace); + + if (stackTrace == NULL && cpuState != NULL) { + if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( + fThread->GetTeam(), this, cpuState, stackTrace, 1) + == 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 + != stackTrace->FrameAt(0)->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( @@ -635,7 +650,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, 1) + == B_OK) { stackTraceReference.SetTo(stackTrace, true); } }