diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index b0b0ce74c9..6c21ce91e8 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -7,10 +7,15 @@ enum { - MSG_THREAD_RUN = 'run_', - MSG_THREAD_STEP_OVER = 'stov', - MSG_THREAD_STEP_INTO = 'stin', - MSG_THREAD_STEP_OUT = 'stou' + MSG_THREAD_RUN = 'run_', + MSG_THREAD_STOP = 'stop', + MSG_THREAD_STEP_OVER = 'stov', + MSG_THREAD_STEP_INTO = 'stin', + MSG_THREAD_STEP_OUT = 'stou', + + MSG_THREAD_STATE_CHANGED = 'tsch', + MSG_THREAD_CPU_STATE_CHANGED = 'tcsc', + MSG_THREAD_STACK_TRACE_CHANGED = 'tstc' }; diff --git a/src/apps/debugger/Team.cpp b/src/apps/debugger/Team.cpp index bbb73bcf6b..196bb937e0 100644 --- a/src/apps/debugger/Team.cpp +++ b/src/apps/debugger/Team.cpp @@ -204,6 +204,39 @@ Team::RemoveListener(Listener* listener) } +void +Team::NotifyThreadStateChanged(Thread* thread) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->ThreadStateChanged( + ThreadEvent(TEAM_EVENT_THREAD_STATE_CHANGED, thread)); + } +} + + +void +Team::NotifyThreadCpuStateChanged(Thread* thread) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->ThreadCpuStateChanged( + ThreadEvent(TEAM_EVENT_THREAD_CPU_STATE_CHANGED, thread)); + } +} + + +void +Team::NotifyThreadStackTraceChanged(Thread* thread) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->ThreadStackTraceChanged( + ThreadEvent(TEAM_EVENT_THREAD_STACK_TRACE_CHANGED, thread)); + } +} + + void Team::_NotifyThreadAdded(Thread* thread) { @@ -307,3 +340,21 @@ void Team::Listener::ImageRemoved(const Team::ImageEvent& event) { } + + +void +Team::Listener::ThreadStateChanged(const Team::ThreadEvent& event) +{ +} + + +void +Team::Listener::ThreadCpuStateChanged(const Team::ThreadEvent& event) +{ +} + + +void +Team::Listener::ThreadStackTraceChanged(const Team::ThreadEvent& event) +{ +} diff --git a/src/apps/debugger/Team.h b/src/apps/debugger/Team.h index 568177ecba..c285c232e9 100644 --- a/src/apps/debugger/Team.h +++ b/src/apps/debugger/Team.h @@ -18,7 +18,11 @@ enum { TEAM_EVENT_THREAD_ADDED, TEAM_EVENT_THREAD_REMOVED, TEAM_EVENT_IMAGE_ADDED, - TEAM_EVENT_IMAGE_REMOVED + TEAM_EVENT_IMAGE_REMOVED, + + TEAM_EVENT_THREAD_STATE_CHANGED, + TEAM_EVENT_THREAD_CPU_STATE_CHANGED, + TEAM_EVENT_THREAD_STACK_TRACE_CHANGED }; @@ -59,6 +63,11 @@ public: void AddListener(Listener* listener); void RemoveListener(Listener* listener); + // service methods for Thread + void NotifyThreadStateChanged(Thread* thread); + void NotifyThreadCpuStateChanged(Thread* thread); + void NotifyThreadStackTraceChanged(Thread* thread); + private: typedef DoublyLinkedList ListenerList; @@ -121,6 +130,13 @@ public: virtual void ImageAdded(const Team::ImageEvent& event); virtual void ImageRemoved(const Team::ImageEvent& event); + + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); + virtual void ThreadCpuStateChanged( + const Team::ThreadEvent& event); + virtual void ThreadStackTraceChanged( + const Team::ThreadEvent& event); }; diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index 831c41cc94..1b5c37b77c 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -17,6 +17,7 @@ #include "CpuState.h" #include "DebuggerInterface.h" +#include "MessageCodes.h" #include "Team.h" #include "TeamDebugModel.h" @@ -168,6 +169,19 @@ void TeamDebugger::MessageReceived(BMessage* message) { switch (message->what) { + case MSG_THREAD_RUN: + case MSG_THREAD_STOP: + case MSG_THREAD_STEP_OVER: + case MSG_THREAD_STEP_INTO: + case MSG_THREAD_STEP_OUT: + { + int32 threadID; + if (message->FindInt32("thread", &threadID) != B_OK) + break; + + _HandleThreadAction(threadID, message->what); + break; + } default: BLooper::MessageReceived(message); break; @@ -175,6 +189,24 @@ TeamDebugger::MessageReceived(BMessage* message) } +void +TeamDebugger::ThreadActionRequested(TeamWindow* window, thread_id threadID, + uint32 action) +{ + BMessage message(action); + message.AddInt32("thread", threadID); + PostMessage(&message); +} + + +bool +TeamDebugger::TeamWindowQuitRequested(TeamWindow* window) +{ + // TODO:... + return true; +} + + /*static*/ status_t TeamDebugger::_DebugEventListenerEntry(void* data) { @@ -222,30 +254,43 @@ printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType()); switch (event->EventType()) { case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread()); + handled = _HandleThreadDebugged( + dynamic_cast(event)); break; case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread()); + handled = _HandleDebuggerCall( + dynamic_cast(event)); break; case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread()); + handled = _HandleBreakpointHit( + dynamic_cast(event)); break; case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread()); + handled = _HandleWatchpointHit( + dynamic_cast(event)); break; case B_DEBUGGER_MESSAGE_SINGLE_STEP: printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread()); + handled = _HandleSingleStep(dynamic_cast(event)); break; case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread()); + handled = _HandleExceptionOccurred( + dynamic_cast(event)); break; // case B_DEBUGGER_MESSAGE_TEAM_CREATED: //printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team); // break; case B_DEBUGGER_MESSAGE_TEAM_DELETED: + // TODO: Handle! printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n", event->Team()); break; case B_DEBUGGER_MESSAGE_TEAM_EXEC: printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team()); + // TODO: Handle! break; case B_DEBUGGER_MESSAGE_THREAD_CREATED: handled = _HandleThreadCreated( @@ -281,6 +326,70 @@ printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team()); } +bool +TeamDebugger::_HandleThreadStopped(thread_id threadID, CpuState* cpuState) +{ + // get the thread + AutoLocker< ::Team> locker(fTeam); + ::Thread* thread = fTeam->ThreadByID(threadID); + if (thread == NULL) + return false; + + // update the thread state + thread->SetState(THREAD_STATE_STOPPED); + + if (cpuState != NULL) { + thread->SetCpuState(cpuState); + } else { + // TODO: Trigger updating the CPU state! + } + + return true; +} + + +bool +TeamDebugger::_HandleThreadDebugged(ThreadDebuggedEvent* event) +{ + return _HandleThreadStopped(event->Thread(), NULL); +} + + +bool +TeamDebugger::_HandleDebuggerCall(DebuggerCallEvent* event) +{ + return _HandleThreadStopped(event->Thread(), NULL); +} + + +bool +TeamDebugger::_HandleBreakpointHit(BreakpointHitEvent* event) +{ + return _HandleThreadStopped(event->Thread(), event->GetCpuState()); +} + + +bool +TeamDebugger::_HandleWatchpointHit(WatchpointHitEvent* event) +{ + return _HandleThreadStopped(event->Thread(), event->GetCpuState()); +} + + +bool +TeamDebugger::_HandleSingleStep(SingleStepEvent* event) +{ + return _HandleThreadStopped(event->Thread(), event->GetCpuState()); +} + + +bool +TeamDebugger::_HandleExceptionOccurred(ExceptionOccurredEvent* event) +{ + return _HandleThreadStopped(event->Thread(), NULL); +} + + bool TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event) { @@ -339,3 +448,53 @@ TeamDebugger::_UpdateThreadState(::Thread* thread) thread->SetState(newState); thread->SetCpuState(state); } + + +void +TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action) +{ + AutoLocker< ::Team> locker(fTeam); + + ::Thread* thread = fTeam->ThreadByID(threadID); + if (thread == NULL || thread->State() == THREAD_STATE_UNKNOWN) + return; + + // When stop is requested, thread must be running, otherwise stopped. + if (action == MSG_THREAD_STOP + ? thread->State() != THREAD_STATE_RUNNING + : thread->State() != THREAD_STATE_STOPPED) { + return; + } + + // When continuing the thread update thread state before actually issuing + // the command, since we need to unlock. + if (action != MSG_THREAD_STOP) + thread->SetState(THREAD_STATE_RUNNING); + + locker.Unlock(); + + switch (action) { + case MSG_THREAD_RUN: +printf("MSG_THREAD_RUN\n"); + fDebuggerInterface->ContinueThread(threadID); + break; + case MSG_THREAD_STOP: +printf("MSG_THREAD_STOP\n"); + fDebuggerInterface->StopThread(threadID); + break; + case MSG_THREAD_STEP_OVER: +printf("MSG_THREAD_STEP_OVER\n"); + fDebuggerInterface->SingleStepThread(threadID); + break; + case MSG_THREAD_STEP_INTO: +printf("MSG_THREAD_STEP_INTO\n"); + fDebuggerInterface->SingleStepThread(threadID); + break; + case MSG_THREAD_STEP_OUT: +printf("MSG_THREAD_STEP_OUT\n"); + fDebuggerInterface->SingleStepThread(threadID); + break; + +// TODO: Handle stepping correctly! + } +} diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h index c824f73c57..c758d92195 100644 --- a/src/apps/debugger/TeamDebugger.h +++ b/src/apps/debugger/TeamDebugger.h @@ -34,12 +34,32 @@ public: private: virtual void MessageReceived(BMessage* message); + // TeamWindow::Listener + virtual void ThreadActionRequested(TeamWindow* window, + thread_id threadID, uint32 action); + virtual bool TeamWindowQuitRequested(TeamWindow* window); + private: static status_t _DebugEventListenerEntry(void* data); status_t _DebugEventListener(); void _HandleDebuggerMessage(DebugEvent* event); + bool _HandleThreadStopped(thread_id threadID, + CpuState* cpuState); + + bool _HandleThreadDebugged( + ThreadDebuggedEvent* event); + bool _HandleDebuggerCall( + DebuggerCallEvent* event); + bool _HandleBreakpointHit( + BreakpointHitEvent* event); + bool _HandleWatchpointHit( + WatchpointHitEvent* event); + bool _HandleSingleStep( + SingleStepEvent* event); + bool _HandleExceptionOccurred( + ExceptionOccurredEvent* event); bool _HandleThreadCreated( ThreadCreatedEvent* event); bool _HandleThreadDeleted( @@ -51,6 +71,9 @@ private: void _UpdateThreadState(::Thread* thread); + void _HandleThreadAction(thread_id threadID, + uint32 action); + private: ::Team* fTeam; TeamDebugModel* fDebugModel; diff --git a/src/apps/debugger/Thread.cpp b/src/apps/debugger/Thread.cpp index 64c7072bb3..d456b10608 100644 --- a/src/apps/debugger/Thread.cpp +++ b/src/apps/debugger/Thread.cpp @@ -7,6 +7,7 @@ #include "CpuState.h" #include "StackTrace.h" +#include "Team.h" Thread::Thread(Team* team, thread_id threadID) @@ -56,6 +57,8 @@ Thread::SetState(uint32 state) SetCpuState(NULL); SetStackTrace(NULL); } + + fTeam->NotifyThreadStateChanged(this); } @@ -72,8 +75,11 @@ Thread::SetCpuState(CpuState* state) if (fCpuState != NULL) fCpuState->AddReference(); + + fTeam->NotifyThreadCpuStateChanged(this); } + void Thread::SetStackTrace(StackTrace* trace) { @@ -87,4 +93,6 @@ Thread::SetStackTrace(StackTrace* trace) if (fStackTrace != NULL) fStackTrace->AddReference(); + + fTeam->NotifyThreadStackTraceChanged(this); } diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp index df3d8b2192..70fa123a13 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp @@ -131,6 +131,26 @@ DebuggerInterface::ContinueThread(thread_id thread) } +status_t +DebuggerInterface::StopThread(thread_id thread) +{ + return debug_thread(thread); +} + + +status_t +DebuggerInterface::SingleStepThread(thread_id thread) +{ + debug_nub_continue_thread continueMessage; + continueMessage.thread = thread; + continueMessage.handle_event = B_THREAD_DEBUG_HANDLE_EVENT; + continueMessage.single_step = true; + + return write_port(fNubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD, + &continueMessage, sizeof(continueMessage)); +} + + status_t DebuggerInterface::GetThreadInfos(BObjectList& infos) { diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.h b/src/apps/debugger/debugger_interface/DebuggerInterface.h index ec830a42c7..99d5e520bf 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.h +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.h @@ -34,6 +34,8 @@ public: virtual status_t SetTeamDebuggingFlags(uint32 flags); virtual status_t ContinueThread(thread_id thread); + virtual status_t StopThread(thread_id thread); + virtual status_t SingleStepThread(thread_id thread); virtual status_t GetThreadInfos(BObjectList& infos); virtual status_t GetImageInfos(BObjectList& infos); diff --git a/src/apps/debugger/gui/team_window/TeamWindow.cpp b/src/apps/debugger/gui/team_window/TeamWindow.cpp index f7574b9a79..94007e5297 100644 --- a/src/apps/debugger/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/gui/team_window/TeamWindow.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include "ImageListView.h" #include "MessageCodes.h" #include "TeamDebugModel.h" @@ -42,11 +44,14 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener) if (team->ID() >= 0) name << " (" << team->ID() << ")"; SetTitle(name.String()); + + team->AddListener(this); } TeamWindow::~TeamWindow() { + fDebugModel->GetTeam()->RemoveListener(this); } @@ -71,17 +76,28 @@ TeamWindow::MessageReceived(BMessage* message) { switch (message->what) { case MSG_THREAD_RUN: -printf("MSG_THREAD_RUN\n"); - break; + case MSG_THREAD_STOP: case MSG_THREAD_STEP_OVER: -printf("MSG_THREAD_STEP_OVER\n"); - break; case MSG_THREAD_STEP_INTO: -printf("MSG_THREAD_STEP_INTO\n"); - break; case MSG_THREAD_STEP_OUT: -printf("MSG_THREAD_STEP_OUT\n"); + if (fActiveThread != NULL) { + fListener->ThreadActionRequested(this, fActiveThread->ID(), + message->what); + } break; + + case MSG_THREAD_STATE_CHANGED: + { + int32 threadID; + if (message->FindInt32("thread", &threadID) != B_OK) + break; + + _HandleThreadStateChanged(threadID); + break; + } +// case MSG_THREAD_CPU_STATE_CHANGED: +// case MSG_THREAD_STACK_TRACE_CHANGED: + default: BWindow::MessageReceived(message); break; @@ -103,6 +119,33 @@ TeamWindow::ThreadSelectionChanged(::Thread* thread) } +void +TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event) +{ + BMessage message(MSG_THREAD_STATE_CHANGED); + message.AddInt32("thread", event.GetThread()->ID()); + PostMessage(&message); +} + + +void +TeamWindow::ThreadCpuStateChanged(const Team::ThreadEvent& event) +{ +// BMessage message(MSG_THREAD_CPU_STATE_CHANGED); +// message.AddInt32("thread", event.GetThread()->ID()); +// PostMessage(&message); +} + + +void +TeamWindow::ThreadStackTraceChanged(const Team::ThreadEvent& event) +{ +// BMessage message(MSG_THREAD_STACK_TRACE_CHANGED); +// message.AddInt32("thread", event.GetThread()->ID()); +// PostMessage(&message); +} + + void TeamWindow::_Init() { @@ -155,6 +198,7 @@ TeamWindow::_Init() fRunButton->SetTarget(this); fStepOutButton->SetTarget(this); + AutoLocker locker(fDebugModel); _UpdateRunButtons(); } @@ -167,6 +211,7 @@ TeamWindow::_SetActiveThread(::Thread* thread) fActiveThread = thread; + AutoLocker locker(fDebugModel); _UpdateRunButtons(); } @@ -186,6 +231,7 @@ TeamWindow::_UpdateRunButtons() break; case THREAD_STATE_RUNNING: fRunButton->SetLabel("Stop"); + fRunButton->SetMessage(new BMessage(MSG_THREAD_STOP)); fRunButton->SetEnabled(true); fStepOverButton->SetEnabled(false); fStepIntoButton->SetEnabled(false); @@ -193,6 +239,7 @@ TeamWindow::_UpdateRunButtons() break; case THREAD_STATE_STOPPED: fRunButton->SetLabel("Run"); + fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN)); fRunButton->SetEnabled(true); fStepOverButton->SetEnabled(true); fStepIntoButton->SetEnabled(true); @@ -202,16 +249,21 @@ TeamWindow::_UpdateRunButtons() } +void +TeamWindow::_HandleThreadStateChanged(thread_id threadID) +{ + // ATM we're only interested in the currently selected thread + if (fActiveThread == NULL || threadID != fActiveThread->ID()) + return; + + AutoLocker locker(fDebugModel); + _UpdateRunButtons(); +} + + // #pragma mark - Listener TeamWindow::Listener::~Listener() { } - - -bool -TeamWindow::Listener::TeamWindowQuitRequested(TeamWindow* window) -{ - return true; -} diff --git a/src/apps/debugger/gui/team_window/TeamWindow.h b/src/apps/debugger/gui/team_window/TeamWindow.h index 265bbca9ee..ea1661c829 100644 --- a/src/apps/debugger/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/gui/team_window/TeamWindow.h @@ -8,17 +8,18 @@ #include #include +#include "Team.h" #include "ThreadListView.h" class BButton; class BTabView; class ImageListView; -class Team; class TeamDebugModel; -class TeamWindow : public BWindow, private ThreadListView::Listener { +class TeamWindow : public BWindow, private ThreadListView::Listener, + Team::Listener { public: class Listener; @@ -38,11 +39,21 @@ private: // ThreadListView::Listener virtual void ThreadSelectionChanged(::Thread* thread); + // Team::Listener + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); + virtual void ThreadCpuStateChanged( + const Team::ThreadEvent& event); + virtual void ThreadStackTraceChanged( + const Team::ThreadEvent& event); + void _Init(); void _SetActiveThread(::Thread* thread); void _UpdateRunButtons(); + void _HandleThreadStateChanged(thread_id threadID); + private: TeamDebugModel* fDebugModel; ::Thread* fActiveThread; @@ -61,7 +72,9 @@ class TeamWindow::Listener { public: virtual ~Listener(); - virtual bool TeamWindowQuitRequested(TeamWindow* window); + virtual void ThreadActionRequested(TeamWindow* window, + thread_id threadID, uint32 action) = 0; + virtual bool TeamWindowQuitRequested(TeamWindow* window) = 0; };