More UI support for watchpointgs.

- BreakpointTableModel now encapsulates both breakpoints and watchpoints.
- Extended BreakpointView and TeamWindow to handle enable/disable/removing
  watchpoints as well.
This commit is contained in:
Rene Gollent 2012-11-07 14:50:17 +01:00
parent c1e45a1e82
commit 12c53499e7
11 changed files with 304 additions and 27 deletions

View File

@ -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',

View File

@ -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<BLocker> installLocker(fLock);
AutoLocker<Team> 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);
fTeam->NotifyWatchpointChanged(watchpoint);
}
}

View File

@ -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();

View File

@ -145,6 +145,8 @@ public:
TargetAddressRange range,
BObjectList<Watchpoint>& watchpoints)
const;
const WatchpointList& Watchpoints() const
{ return fWatchpoints; }
status_t GetStatementAtAddress(target_addr_t address,
FunctionInstance*& _function,
@ -187,7 +189,6 @@ private:
typedef BObjectList<Breakpoint> BreakpointList;
typedef DoublyLinkedList<Listener> ListenerList;
typedef BObjectList<Watchpoint> WatchpointList;
private:
void _NotifyThreadAdded(Thread* thread);

View File

@ -6,6 +6,7 @@
#define WATCHPOINT_H
#include <ObjectList.h>
#include <Referenceable.h>
#include "types/Types.h"
@ -49,4 +50,7 @@ private:
};
typedef BObjectList<Watchpoint> WatchpointList;
#endif // WATCHPOINT_H

View File

@ -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<Team> 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<UserBreakpoint> fBreakpoints;
BObjectList<Watchpoint> 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));
if (breakpoint != NULL)
fListener->BreakpointSelectionChanged(breakpoint);
else {
Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt(
selectionModel->RowAt(0));
fListener->WatchpointSelectionChanged(watchpoint);
}
}

View File

@ -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;
};

View File

@ -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)
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<Team> 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));

View File

@ -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;
};

View File

@ -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<Watchpoint> 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<Watchpoint> 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)
{

View File

@ -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);