From 12c53499e76d8d0e63a94eb738bbe13f387cb0dd Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Nov 2012 14:50:17 +0100 Subject: [PATCH] More UI support for watchpointgs. - BreakpointTableModel now encapsulates both breakpoints and watchpoints. - Extended BreakpointView and TeamWindow to handle enable/disable/removing watchpoints as well. --- src/apps/debugger/MessageCodes.h | 1 + src/apps/debugger/WatchpointManager.cpp | 14 +- src/apps/debugger/model/Team.cpp | 3 + src/apps/debugger/model/Team.h | 3 +- src/apps/debugger/model/Watchpoint.h | 4 + .../gui/team_window/BreakpointListView.cpp | 136 ++++++++++++++++-- .../gui/team_window/BreakpointListView.h | 11 +- .../gui/team_window/BreakpointsView.cpp | 73 ++++++++-- .../gui/team_window/BreakpointsView.h | 18 ++- .../gui/team_window/TeamWindow.cpp | 55 ++++++- .../gui/team_window/TeamWindow.h | 13 ++ 11 files changed, 304 insertions(+), 27 deletions(-) diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 59ec092cac..b3e0f9717b 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -29,6 +29,7 @@ enum { MSG_IMAGE_FILE_CHANGED = 'ifch', MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc', MSG_USER_BREAKPOINT_CHANGED = 'ubrc', + MSG_WATCHPOINT_CHANGED = 'wapc', MSG_DEBUGGER_EVENT = 'dbge', MSG_LOAD_SETTINGS = 'ldst', diff --git a/src/apps/debugger/WatchpointManager.cpp b/src/apps/debugger/WatchpointManager.cpp index e5854a06be..9b21554c09 100644 --- a/src/apps/debugger/WatchpointManager.cpp +++ b/src/apps/debugger/WatchpointManager.cpp @@ -74,6 +74,12 @@ WatchpointManager::InstallWatchpoint(Watchpoint* watchpoint, watchpoint->SetInstalled(false); } + if (error == B_OK) { + if (fTeam->WatchpointAtAddress(watchpoint->Address()) == NULL) + fTeam->AddWatchpoint(watchpoint); + fTeam->NotifyWatchpointChanged(watchpoint); + } + return error; } @@ -84,12 +90,16 @@ WatchpointManager::UninstallWatchpoint(Watchpoint* watchpoint) AutoLocker installLocker(fLock); AutoLocker teamLocker(fTeam); + fTeam->RemoveWatchpoint(watchpoint); + if (!watchpoint->IsInstalled()) return; status_t error = fDebuggerInterface->UninstallWatchpoint( watchpoint->Address()); - if (error == B_OK) + if (error == B_OK) { watchpoint->SetInstalled(false); -} \ No newline at end of file + fTeam->NotifyWatchpointChanged(watchpoint); + } +} diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index 3a379c20e1..0f3a6a240a 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -92,6 +92,9 @@ Team::~Team() for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) breakpoint->ReleaseReference(); + for (int32 i = 0; Watchpoint* watchpoint = fWatchpoints.ItemAt(i); i++) + watchpoint->ReleaseReference(); + while (Image* image = fImages.RemoveHead()) image->ReleaseReference(); diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 03dd5f5038..d11e76728f 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -145,6 +145,8 @@ public: TargetAddressRange range, BObjectList& watchpoints) const; + const WatchpointList& Watchpoints() const + { return fWatchpoints; } status_t GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function, @@ -187,7 +189,6 @@ private: typedef BObjectList BreakpointList; typedef DoublyLinkedList ListenerList; - typedef BObjectList WatchpointList; private: void _NotifyThreadAdded(Thread* thread); diff --git a/src/apps/debugger/model/Watchpoint.h b/src/apps/debugger/model/Watchpoint.h index a9d591f829..fa1ac20f19 100644 --- a/src/apps/debugger/model/Watchpoint.h +++ b/src/apps/debugger/model/Watchpoint.h @@ -6,6 +6,7 @@ #define WATCHPOINT_H +#include #include #include "types/Types.h" @@ -49,4 +50,7 @@ private: }; +typedef BObjectList WatchpointList; + + #endif // WATCHPOINT_H diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp index a9ef8f870b..b1698c8f41 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp @@ -18,9 +18,10 @@ #include "GuiSettingsUtils.h" #include "LocatableFile.h" #include "table/TableColumns.h" +#include "TargetAddressTableColumn.h" #include "Team.h" #include "UserBreakpoint.h" -#include "TargetAddressTableColumn.h" +#include "Watchpoint.h" // #pragma mark - BreakpointsTableModel @@ -32,16 +33,18 @@ public: : fTeam(team) { - Update(NULL); + UpdateBreakpoint(NULL); + UpdateWatchpoint(NULL); } ~BreakpointsTableModel() { fTeam = NULL; - Update(NULL); + UpdateBreakpoint(NULL); + UpdateWatchpoint(NULL); } - bool Update(UserBreakpoint* changedBreakpoint) + bool UpdateBreakpoint(UserBreakpoint* changedBreakpoint) { if (fTeam == NULL) { for (int32 i = 0; @@ -93,6 +96,59 @@ public: return true; } + bool UpdateWatchpoint(Watchpoint* changedWatchpoint) + { + if (fTeam == NULL) { + for (int32 i = 0; + Watchpoint* watchpoint = fWatchpoints.ItemAt(i); + i++) { + watchpoint->ReleaseReference(); + } + fWatchpoints.MakeEmpty(); + + return true; + } + + AutoLocker locker(fTeam); + + int32 breakpointCount = fBreakpoints.CountItems(); + int32 index = 0; + int32 teamIndex = 0; + Watchpoint* newWatchpoint = fTeam->WatchpointAt(teamIndex); + // remove no longer existing breakpoints + while (Watchpoint* oldWatchpoint = fWatchpoints.ItemAt(index)) { + if (oldWatchpoint == newWatchpoint) { + if (oldWatchpoint == changedWatchpoint) + NotifyRowsChanged(index + breakpointCount, 1); + index++; + teamIndex++; + newWatchpoint = fTeam->WatchpointAt(teamIndex); + } else { + // TODO: Not particularly efficient! + fWatchpoints.RemoveItemAt(index); + oldWatchpoint->ReleaseReference(); + NotifyRowsRemoved(index + breakpointCount, 1); + } + } + + // add new breakpoints + int32 countBefore = fWatchpoints.CountItems(); + while (newWatchpoint != NULL) { + if (!fWatchpoints.AddItem(newWatchpoint)) + return false; + + newWatchpoint->AcquireReference(); + teamIndex++; + newWatchpoint = fTeam->WatchpointAt(teamIndex); + } + + int32 count = fWatchpoints.CountItems(); + if (count > countBefore) + NotifyRowsAdded(countBefore + breakpointCount, count - countBefore); + + return true; + } + virtual int32 CountColumns() const { return 5; @@ -100,10 +156,33 @@ public: virtual int32 CountRows() const { - return fBreakpoints.CountItems(); + return fBreakpoints.CountItems() + fWatchpoints.CountItems(); } virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value) + { + int32 breakpointCount = fBreakpoints.CountItems(); + if (rowIndex < breakpointCount) + return _GetBreakpointValueAt(rowIndex, columnIndex, value); + + return _GetWatchpointValueAt(rowIndex - breakpointCount, columnIndex, + value); + } + + UserBreakpoint* BreakpointAt(int32 index) const + { + return fBreakpoints.ItemAt(index); + } + + Watchpoint* WatchpointAt(int32 index) const + { + return fWatchpoints.ItemAt(index - fBreakpoints.CountItems()); + } + +private: + + bool _GetBreakpointValueAt(int32 rowIndex, int32 columnIndex, + BVariant &value) { UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex); if (breakpoint == NULL) @@ -145,14 +224,36 @@ public: } } - UserBreakpoint* BreakpointAt(int32 index) const + bool _GetWatchpointValueAt(int32 rowIndex, int32 columnIndex, + BVariant& value) { - return fBreakpoints.ItemAt(index); + Watchpoint* watchpoint = fWatchpoints.ItemAt(rowIndex); + if (watchpoint == NULL) + return false; + + switch (columnIndex) { + case 0: + value.SetTo((int32)watchpoint->IsEnabled()); + return true; + case 1: + value.SetTo("Watchpoint"); + return true; + case 2: + return false; + case 3: + return false; + case 4: + value.SetTo(watchpoint->Address()); + return true; + default: + return false; + } } private: Team* fTeam; BObjectList fBreakpoints; + BObjectList fWatchpoints; }; @@ -202,7 +303,8 @@ BreakpointListView::UnsetListener() void -BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint) +BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint, + Watchpoint* watchpoint) { if (breakpoint == fBreakpoint) return; @@ -232,7 +334,14 @@ BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint) void BreakpointListView::UserBreakpointChanged(UserBreakpoint* breakpoint) { - fBreakpointsTableModel->Update(breakpoint); + fBreakpointsTableModel->UpdateBreakpoint(breakpoint); +} + + +void +BreakpointListView::WatchpointChanged(Watchpoint* watchpoint) +{ + fBreakpointsTableModel->UpdateWatchpoint(watchpoint); } @@ -271,8 +380,13 @@ BreakpointListView::TableSelectionChanged(Table* table) TableSelectionModel* selectionModel = table->SelectionModel(); UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt( selectionModel->RowAt(0)); - - fListener->BreakpointSelectionChanged(breakpoint); + if (breakpoint != NULL) + fListener->BreakpointSelectionChanged(breakpoint); + else { + Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt( + selectionModel->RowAt(0)); + fListener->WatchpointSelectionChanged(watchpoint); + } } diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h index 73ebc0e3bf..317ca5be71 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h @@ -13,6 +13,7 @@ class Team; class UserBreakpoint; +class Watchpoint; class BreakpointListView : public BGroupView, private TableListener { @@ -29,9 +30,13 @@ public: void UnsetListener(); - void SetBreakpoint(UserBreakpoint* breakpoint); + void SetBreakpoint(UserBreakpoint* breakpoint, + Watchpoint* watchpoint); + void UserBreakpointChanged( UserBreakpoint* breakpoint); + void WatchpointChanged( + Watchpoint* breakpoint); void LoadSettings(const BMessage& settings); status_t SaveSettings(BMessage& settings); @@ -48,6 +53,7 @@ private: private: Team* fTeam; UserBreakpoint* fBreakpoint; + Watchpoint* fWatchpoint; Table* fBreakpointsTable; BreakpointsTableModel* fBreakpointsTableModel; Listener* fListener; @@ -60,6 +66,9 @@ public: virtual void BreakpointSelectionChanged( UserBreakpoint* breakpoint) = 0; + + virtual void WatchpointSelectionChanged( + Watchpoint* watchpoint) = 0; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp index 176d6cab3b..f7e58e2ba1 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp @@ -68,20 +68,26 @@ BreakpointsView::UnsetListener() void -BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint) +BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint, Watchpoint* watchpoint) { - if (breakpoint == fBreakpoint) + if (breakpoint == fBreakpoint && watchpoint == fWatchpoint) return; + if (fWatchpoint != NULL) + fWatchpoint->ReleaseReference(); + if (fBreakpoint != NULL) fBreakpoint->ReleaseReference(); + fWatchpoint = watchpoint; fBreakpoint = breakpoint; if (fBreakpoint != NULL) fBreakpoint->AcquireReference(); + else if (fWatchpoint != NULL) + fWatchpoint->AcquireReference(); - fListView->SetBreakpoint(breakpoint); + fListView->SetBreakpoint(breakpoint, watchpoint); _UpdateButtons(); } @@ -96,21 +102,49 @@ BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint) } +void +BreakpointsView::WatchpointChanged(Watchpoint* watchpoint) +{ + fListView->WatchpointChanged(watchpoint); + + _UpdateButtons(); +} + + void BreakpointsView::MessageReceived(BMessage* message) { switch (message->what) { case MSG_ENABLE_BREAKPOINT: - if (fListener != NULL && fBreakpoint != NULL) - fListener->SetBreakpointEnabledRequested(fBreakpoint, true); + if (fListener != NULL) { + if (fBreakpoint != NULL) { + fListener->SetBreakpointEnabledRequested(fBreakpoint, + true); + } else if (fWatchpoint != NULL) { + fListener->SetWatchpointEnabledRequested(fWatchpoint, + true); + } + } break; case MSG_DISABLE_BREAKPOINT: - if (fListener != NULL && fBreakpoint != NULL) - fListener->SetBreakpointEnabledRequested(fBreakpoint, false); + if (fListener != NULL) { + if (fBreakpoint != NULL) { + fListener->SetBreakpointEnabledRequested(fBreakpoint, + false); + } else if (fWatchpoint != NULL) { + fListener->SetWatchpointEnabledRequested(fWatchpoint, + false); + } + } break; case MSG_CLEAR_BREAKPOINT: - if (fListener != NULL && fBreakpoint != NULL) - fListener->ClearBreakpointRequested(fBreakpoint); + if (fListener != NULL) { + if (fBreakpoint != NULL) { + fListener->ClearBreakpointRequested(fBreakpoint); + } else if (fWatchpoint != NULL) { + fListener->ClearWatchpointRequested(fWatchpoint); + } + } break; default: BGroupView::MessageReceived(message); @@ -159,6 +193,14 @@ BreakpointsView::BreakpointSelectionChanged(UserBreakpoint* breakpoint) } +void +BreakpointsView::WatchpointSelectionChanged(Watchpoint* watchpoint) +{ + if (fListener != NULL) + fListener->WatchpointSelectionChanged(watchpoint); +} + + void BreakpointsView::_Init() { @@ -182,8 +224,19 @@ BreakpointsView::_UpdateButtons() { AutoLocker teamLocker(fTeam); + bool enabled = false; + bool valid = false; + if (fBreakpoint != NULL && fBreakpoint->IsValid()) { - if (fBreakpoint->IsEnabled()) { + valid = true; + enabled = fBreakpoint->IsEnabled(); + } else if (fWatchpoint != NULL) { + valid = true; + enabled = fWatchpoint->IsEnabled(); + } + + if (valid) { + if (enabled) { fToggleBreakpointButton->SetLabel("Disable"); fToggleBreakpointButton->SetMessage( new BMessage(MSG_DISABLE_BREAKPOINT)); diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h index 2240252ee7..02bef310b6 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h @@ -28,9 +28,13 @@ public: void UnsetListener(); - void SetBreakpoint(UserBreakpoint* breakpoint); + void SetBreakpoint(UserBreakpoint* breakpoint, + Watchpoint* watchpoint); + void UserBreakpointChanged( UserBreakpoint* breakpoint); + void WatchpointChanged( + Watchpoint* watchpoint); virtual void MessageReceived(BMessage* message); virtual void AttachedToWindow(); @@ -42,6 +46,8 @@ private: // BreakpointListView::Listener virtual void BreakpointSelectionChanged( UserBreakpoint* breakpoint); + virtual void WatchpointSelectionChanged( + Watchpoint* watchpoint); void _Init(); @@ -50,6 +56,7 @@ private: private: Team* fTeam; UserBreakpoint* fBreakpoint; + Watchpoint* fWatchpoint; BreakpointListView* fListView; BButton* fToggleBreakpointButton; BButton* fRemoveBreakpointButton; @@ -57,6 +64,7 @@ private: }; + class BreakpointsView::Listener { public: virtual ~Listener(); @@ -68,6 +76,14 @@ public: bool enabled) = 0; virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint) = 0; + + virtual void WatchpointSelectionChanged( + Watchpoint* Watchpoint) = 0; + virtual void SetWatchpointEnabledRequested( + Watchpoint* breakpoint, + bool enabled) = 0; + virtual void ClearWatchpointRequested( + Watchpoint* watchpoint) = 0; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 1fc4fd86dc..862895233b 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -356,6 +356,18 @@ TeamWindow::MessageReceived(BMessage* message) break; } + case MSG_WATCHPOINT_CHANGED: + { + Watchpoint* watchpoint; + if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK) + break; + BReference watchpointReference(watchpoint, true); + + _HandleWatchpointChanged(watchpoint); + break; + + } + case MSG_FUNCTION_SOURCE_CODE_CHANGED: { _HandleSourceCodeChanged(); @@ -584,6 +596,28 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address) } +void +TeamWindow::WatchpointSelectionChanged(Watchpoint* watchpoint) +{ + fBreakpointsView->SetBreakpoint(NULL, watchpoint); +} + + +void +TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint, + bool enabled) +{ + fListener->SetWatchpointEnabledRequested(watchpoint, enabled); +} + + +void +TeamWindow::ClearWatchpointRequested(Watchpoint* watchpoint) +{ + fListener->ClearWatchpointRequested(watchpoint); +} + + void TeamWindow::ValueNodeValueRequested(CpuState* cpuState, ValueNodeContainer* container, ValueNode* valueNode) @@ -640,6 +674,18 @@ TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event) } +void +TeamWindow::WatchpointChanged(const Team::WatchpointEvent& event) +{ + BMessage message(MSG_WATCHPOINT_CHANGED); + BReference watchpointReference(event.GetWatchpoint()); + if (message.AddPointer("watchpoint", event.GetWatchpoint()) == B_OK + && PostMessage(&message) == B_OK) { + watchpointReference.Detach(); + } +} + + void TeamWindow::FunctionSourceCodeChanged(Function* function) { @@ -923,7 +969,7 @@ TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint) _ScrollToActiveFunction(); } - fBreakpointsView->SetBreakpoint(fActiveBreakpoint); + fBreakpointsView->SetBreakpoint(fActiveBreakpoint, NULL); } @@ -1266,6 +1312,13 @@ TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint) } +void +TeamWindow::_HandleWatchpointChanged(Watchpoint* watchpoint) +{ + fBreakpointsView->WatchpointChanged(watchpoint); +} + + void TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath) { diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index 9d979723e6..d371a5b694 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -95,6 +95,15 @@ private: virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint); + virtual void WatchpointSelectionChanged( + Watchpoint* Watchpoint); + virtual void SetWatchpointEnabledRequested( + Watchpoint* breakpoint, + bool enabled); + virtual void ClearWatchpointRequested( + Watchpoint* watchpoint); + + // SourceView::Listener virtual void SetBreakpointRequested(target_addr_t address, bool enabled); @@ -116,6 +125,8 @@ private: const Team::ImageEvent& event); virtual void UserBreakpointChanged( const Team::UserBreakpointEvent& event); + virtual void WatchpointChanged( + const Team::WatchpointEvent& event); // Function::Listener virtual void FunctionSourceCodeChanged(Function* function); @@ -142,6 +153,8 @@ private: void _HandleSourceCodeChanged(); void _HandleUserBreakpointChanged( UserBreakpoint* breakpoint); + void _HandleWatchpointChanged( + Watchpoint* watchpoint); void _HandleResolveMissingSourceFile(entry_ref& locatedPath);