From 1325ad5fe84c9aa5e3300eeef5098cb89d0b7e72 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 16 Dec 2012 21:56:22 -0500 Subject: [PATCH] Various improvements to CliContext. - CliContext now tracks the current stack trace and frame if applicable. - CliContext now carries a value node manager. This allows it to track the variables in the currently active frame. --- .../user_interface/cli/CliContext.cpp | 77 ++++++++++++++++++- .../debugger/user_interface/cli/CliContext.h | 27 +++++-- 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 6623300ea1..7b430dc19d 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2012, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -9,8 +10,9 @@ #include #include +#include "StackTrace.h" #include "UserInterface.h" - +#include "ValueNodeManager.h" // NOTE: This is a simple work-around for EditLine not having any kind of user // data field. Hence in _GetPrompt() we don't have access to the context object. @@ -55,6 +57,7 @@ CliContext::CliContext() fLock("CliContext"), fTeam(NULL), fListener(NULL), + fNodeManager(NULL), fEditLine(NULL), fHistory(NULL), fPrompt(NULL), @@ -63,7 +66,9 @@ CliContext::CliContext() fEventsOccurred(0), fInputLoopWaiting(false), fTerminating(false), - fCurrentThread(NULL) + fCurrentThread(NULL), + fCurrentStackTrace(NULL), + fCurrentStackFrameIndex(-1) { sCurrentContext = this; } @@ -110,6 +115,10 @@ CliContext::Init(Team* team, UserInterfaceListener* listener) el_set(fEditLine, EL_EDITOR, "emacs"); el_set(fEditLine, EL_PROMPT, &_GetPrompt); + fNodeManager = new(std::nothrow) ValueNodeManager(); + if (fNodeManager == NULL) + return B_NO_MEMORY; + return B_OK; } @@ -136,6 +145,11 @@ CliContext::Cleanup() fTeam->RemoveListener(this); fTeam = NULL; } + + if (fNodeManager != NULL) { + fNodeManager->ReleaseReference(); + fNodeManager = NULL; + } } @@ -168,8 +182,25 @@ CliContext::SetCurrentThread(Thread* thread) fCurrentThread = thread; - if (fCurrentThread != NULL) + if (fCurrentStackTrace != NULL) { + fCurrentStackTrace->ReleaseReference(); + fCurrentStackTrace = NULL; + fCurrentStackFrameIndex = -1; + fNodeManager->SetStackFrame(NULL, NULL); + } + + if (fCurrentThread != NULL) { fCurrentThread->AcquireReference(); + StackTrace* stackTrace = fCurrentThread->GetStackTrace(); + // if the thread's stack trace has already been loaded, + // set it, otherwise we'll set it when we process the thread's + // stack trace changed event. + if (stackTrace != NULL) { + fCurrentStackTrace = stackTrace; + fCurrentStackTrace->AcquireReference(); + SetCurrentStackFrameIndex(0); + } + } } @@ -186,6 +217,24 @@ CliContext::PrintCurrentThread() } +void +CliContext::SetCurrentStackFrameIndex(int32 index) +{ + AutoLocker locker(fLock); + + if (fCurrentStackTrace == NULL) + return; + else if (index < 0 || index >= fCurrentStackTrace->CountFrames()) + return; + + fCurrentStackFrameIndex = index; + + StackFrame* frame = fCurrentStackTrace->FrameAt(index); + if (frame != NULL) + fNodeManager->SetStackFrame(fCurrentThread, frame); +} + + const char* CliContext::PromptUser(const char* prompt) { @@ -253,7 +302,7 @@ CliContext::WaitForThreadOrUser() if (stoppedThread != NULL) { if (fCurrentThread == NULL) - fCurrentThread = stoppedThread; + SetCurrentThread(stoppedThread); _SignalInputLoop(EVENT_THREAD_STOPPED); } @@ -300,6 +349,13 @@ CliContext::ProcessPendingEvents() printf("[thread stopped: %" B_PRId32 " \"%s\"]\n", thread->ID(), thread->Name()); break; + case EVENT_THREAD_STACK_TRACE_CHANGED: + if (thread == fCurrentThread) { + fCurrentStackTrace = thread->GetStackTrace(); + fCurrentStackTrace->AcquireReference(); + SetCurrentStackFrameIndex(0); + } + break; } } } @@ -335,6 +391,19 @@ CliContext::ThreadStateChanged(const Team::ThreadEvent& threadEvent) } +void +CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent) +{ + if (threadEvent.GetThread()->State() != THREAD_STATE_STOPPED) + return; + + _QueueEvent( + new(std::nothrow) Event(EVENT_THREAD_STACK_TRACE_CHANGED, + threadEvent.GetThread())); + _SignalInputLoop(EVENT_THREAD_STACK_TRACE_CHANGED); +} + + void CliContext::_QueueEvent(Event* event) { diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index 3a7c98d879..faf6bfa3ae 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -15,18 +15,22 @@ #include "Team.h" +class StackFrame; +class StackTrace; class Team; class UserInterfaceListener; +class ValueNodeManager; class CliContext : private Team::Listener { public: enum { - EVENT_QUIT = 0x01, - EVENT_USER_INTERRUPT = 0x02, - EVENT_THREAD_ADDED = 0x04, - EVENT_THREAD_REMOVED = 0x08, - EVENT_THREAD_STOPPED = 0x10, + EVENT_QUIT = 0x01, + EVENT_USER_INTERRUPT = 0x02, + EVENT_THREAD_ADDED = 0x04, + EVENT_THREAD_REMOVED = 0x08, + EVENT_THREAD_STOPPED = 0x10, + EVENT_THREAD_STACK_TRACE_CHANGED = 0x20 }; public: @@ -46,12 +50,20 @@ public: Team* GetTeam() const { return fTeam; } UserInterfaceListener* GetUserInterfaceListener() const { return fListener; } + ValueNodeManager* GetValueNodeManager() const + { return fNodeManager; } + StackTrace* GetStackTrace() const + { return fCurrentStackTrace; } Thread* CurrentThread() const { return fCurrentThread; } thread_id CurrentThreadID() const; void SetCurrentThread(Thread* thread); void PrintCurrentThread(); + int32 CurrentStackFrameIndex() const + { return fCurrentStackFrameIndex; } + void SetCurrentStackFrameIndex(int32 index); + const char* PromptUser(const char* prompt); void AddLineToInputHistory(const char* line); @@ -72,6 +84,8 @@ private: virtual void ThreadStateChanged( const Team::ThreadEvent& event); + virtual void ThreadStackTraceChanged( + const Team::ThreadEvent& event); private: void _QueueEvent(Event* event); @@ -86,6 +100,7 @@ private: BLocker fLock; Team* fTeam; UserInterfaceListener* fListener; + ValueNodeManager* fNodeManager; EditLine* fEditLine; History* fHistory; const char* fPrompt; @@ -96,6 +111,8 @@ private: volatile bool fTerminating; Thread* fCurrentThread; + StackTrace* fCurrentStackTrace; + int32 fCurrentStackFrameIndex; EventList fPendingEvents; };