From 601538f2afd1408ce09e1abaed5a5d99cdee9cd9 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 06 Nov 2012 11:45:26 +0100 Subject: [PATCH] Start adding the underlying infrastructure for watchpoint support. --- src/apps/debugger/Jamfile | 3 +++ src/apps/debugger/MessageCodes.h | 4 ++++ src/apps/debugger/TeamDebugger.cpp | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/apps/debugger/TeamDebugger.h | 17 +++++++++++++++++ src/apps/debugger/WatchpointManager.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/apps/debugger/WatchpointManager.h | 37 +++++++++++++++++++++++++++++++++++++ src/apps/debugger/model/Team.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/apps/debugger/model/Team.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/apps/debugger/model/Watchpoint.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/apps/debugger/model/Watchpoint.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/apps/debugger/settings/TeamSettings.cpp | 32 ++++++++++++++++++++++++++++++++ src/apps/debugger/settings/TeamSettings.h | 6 ++++++ src/apps/debugger/settings/WatchpointSetting.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/apps/debugger/settings/WatchpointSetting.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/apps/debugger/user_interface/UserInterface.h | 12 ++++++++++++ 15 files changed, 810 insertions(+), 28 deletions(-) diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index fca0a83..727155e 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -61,6 +61,7 @@ TeamMemoryBlockManager.cpp TeamDebugger.cpp ThreadHandler.cpp + WatchpointManager.cpp Worker.cpp # arch @@ -140,6 +141,7 @@ TypeComponentPath.cpp TypeLookupConstraints.cpp Variable.cpp + Watchpoint.cpp # settings BreakpointSetting.cpp @@ -148,6 +150,7 @@ TeamSettings.cpp TeamUiSettings.cpp TeamUiSettingsFactory.cpp + WatchpointSetting.cpp # settings/generic Setting.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 64af5be..75a2df8 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -16,6 +16,10 @@ MSG_CLEAR_BREAKPOINT = 'cbrk', MSG_ENABLE_BREAKPOINT = 'ebrk', MSG_DISABLE_BREAKPOINT = 'dbrk', + MSG_SET_WATCHPOINT = 'swpt', + MSG_CLEAR_WATCHPOINT = 'cwpt', + MSG_ENABLE_WATCHPOINT = 'ewpt', + MSG_DISABLE_WATCHPOINT = 'dwpt', MSG_THREAD_STATE_CHANGED = 'tsch', MSG_THREAD_CPU_STATE_CHANGED = 'tcsc', diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index 58eb10d..26378e1 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -45,6 +45,8 @@ #include "ValueNode.h" #include "ValueNodeContainer.h" #include "Variable.h" +#include "WatchpointManager.h" +#include "WatchpointSetting.h" // #pragma mark - ImageHandler @@ -142,6 +144,7 @@ fFileManager(NULL), fWorker(NULL), fBreakpointManager(NULL), + fWatchpointManager(NULL), fMemoryBlockManager(NULL), fDebugEventListener(-1), fUserInterface(userInterface), @@ -199,6 +202,7 @@ delete fImageHandlers; delete fBreakpointManager; + delete fWatchpointManager; delete fMemoryBlockManager; delete fWorker; delete fTeam; @@ -304,6 +308,16 @@ if (error != B_OK) return error; + // create the watchpoint manager + fWatchpointManager = new(std::nothrow) WatchpointManager(fTeam, + fDebuggerInterface); + if (fWatchpointManager == NULL) + return B_NO_MEMORY; + + error = fWatchpointManager->Init(); + if (error != B_OK) + return error; + // create the memory block manager fMemoryBlockManager = new(std::nothrow) TeamMemoryBlockManager(); if (fMemoryBlockManager == NULL) @@ -460,6 +474,46 @@ _HandleClearUserBreakpoint(breakpoint); else _HandleClearUserBreakpoint(address); + } + + break; + } + + case MSG_SET_WATCHPOINT: + case MSG_CLEAR_WATCHPOINT: + { + Watchpoint* watchpoint = NULL; + BReference watchpointReference; + uint64 address = 0; + uint32 type = 0; + int32 length = 0; + + if (message->FindPointer("watchpoint", (void**)&watchpoint) + == B_OK) { + watchpointReference.SetTo(watchpoint, true); + } else if (message->FindUInt64("address", &address) != B_OK) + break; + + if (message->what == MSG_SET_WATCHPOINT) { + if (watchpoint == NULL && (message->FindUInt32("type", &type) + != B_OK + || message->FindInt32("length", &length) != B_OK)) { + break; + } + + bool enabled; + if (message->FindBool("enabled", &enabled) != B_OK) + enabled = true; + + if (watchpoint != NULL) + _HandleSetWatchpoint(watchpoint, enabled); + else + _HandleSetWatchpoint(address, type, length, enabled); + } else { + if (watchpoint != NULL) + _HandleClearWatchpoint(watchpoint); + else + _HandleClearWatchpoint(address); } break; @@ -692,6 +746,54 @@ if (message.AddPointer("breakpoint", breakpoint) == B_OK && PostMessage(&message) == B_OK) { breakpointReference.Detach(); + } +} + + +void +TeamDebugger::SetWatchpointRequested(target_addr_t address, uint32 type, + int32 length, bool enabled) +{ + BMessage message(MSG_SET_WATCHPOINT); + message.AddUInt64("address", (uint64)address); + message.AddUInt32("type", type); + message.AddInt32("length", length); + message.AddBool("enabled", enabled); + PostMessage(&message); +} + + +void +TeamDebugger::SetWatchpointEnabledRequested(Watchpoint* watchpoint, + bool enabled) +{ + BMessage message(MSG_SET_WATCHPOINT); + BReference watchpointReference(watchpoint); + if (message.AddPointer("watchpoint", watchpoint) == B_OK + && message.AddBool("enabled", enabled) == B_OK + && PostMessage(&message) == B_OK) { + watchpointReference.Detach(); + } +} + + +void +TeamDebugger::ClearWatchpointRequested(target_addr_t address) +{ + BMessage message(MSG_CLEAR_WATCHPOINT); + message.AddUInt64("address", (uint64)address); + PostMessage(&message); +} + + +void +TeamDebugger::ClearWatchpointRequested(Watchpoint* watchpoint) +{ + BMessage message(MSG_CLEAR_WATCHPOINT); + BReference watchpointReference(watchpoint); + if (message.AddPointer("watchpoint", watchpoint) == B_OK + && PostMessage(&message) == B_OK) { + watchpointReference.Detach(); } } @@ -1306,6 +1408,59 @@ TeamDebugger::_HandleClearUserBreakpoint(UserBreakpoint* breakpoint) { fBreakpointManager->UninstallUserBreakpoint(breakpoint); +} + + +void +TeamDebugger::_HandleSetWatchpoint(target_addr_t address, uint32 type, + int32 length, bool enabled) +{ + Watchpoint* watchpoint = new(std::nothrow) Watchpoint(address, type, + length); + + if (watchpoint == NULL) + return; + BReference watchpointRef(watchpoint, true); + + _HandleSetWatchpoint(watchpoint, enabled); +} + + +void +TeamDebugger::_HandleSetWatchpoint(Watchpoint* watchpoint, bool enabled) +{ + status_t error = fWatchpointManager->InstallWatchpoint(watchpoint, + enabled); + if (error != B_OK) { + _NotifyUser("Install Watchpoint", "Failed to install watchpoint: %s", + strerror(error)); + } +} + + +void +TeamDebugger::_HandleClearWatchpoint(target_addr_t address) +{ + TRACE_CONTROL("TeamDebugger::_HandleClearWatchpoint(%#" B_PRIx64 ")\n", + address); + + AutoLocker< ::Team> locker(fTeam); + + Watchpoint* watchpoint = fTeam->WatchpointAtAddress(address); + if (watchpoint == NULL) + return; + BReference watchpointReference(watchpoint); + + locker.Unlock(); + + _HandleClearWatchpoint(watchpoint); +} + + +void +TeamDebugger::_HandleClearWatchpoint(Watchpoint* watchpoint) +{ + fWatchpointManager->UninstallWatchpoint(watchpoint); } @@ -1426,6 +1581,21 @@ // install it fBreakpointManager->InstallUserBreakpoint(breakpoint, breakpointSetting->IsEnabled()); + } + + // create the saved watchpoints; + for (int32 i = 0; const WatchpointSetting* watchpointSetting + = fTeamSettings.WatchpointAt(i); i++) { + Watchpoint* watchpoint = new(std::nothrow) Watchpoint( + watchpointSetting->Address(), watchpointSetting->Type(), + watchpointSetting->Length()); + if (watchpoint == NULL) + return; + BReference watchpointReference(watchpoint, true); + + // install it + fWatchpointManager->InstallWatchpoint(watchpoint, + watchpointSetting->IsEnabled()); } const TeamUiSettings* uiSettings = fTeamSettings.UiSettingFor( diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h index 189a448..b66d540 100644 --- a/src/apps/debugger/TeamDebugger.h +++ b/src/apps/debugger/TeamDebugger.h @@ -24,6 +24,7 @@ class SettingsManager; class TeamDebugInfo; class TeamMemoryBlockManager; +class WatchpointManager; class TeamDebugger : public BLooper, private UserInterfaceListener, @@ -67,6 +68,14 @@ virtual void ClearBreakpointRequested(target_addr_t address); virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint); + virtual void SetWatchpointRequested(target_addr_t address, + uint32 type, int32 length, bool enabled); + virtual void SetWatchpointEnabledRequested( + Watchpoint *watchpoint, bool enabled); + virtual void ClearWatchpointRequested(target_addr_t address); + virtual void ClearWatchpointRequested( + Watchpoint* breakpoint); + virtual void InspectRequested(target_addr_t address, TeamMemoryBlock::Listener* listener); virtual bool UserInterfaceQuitRequested( @@ -122,6 +131,13 @@ target_addr_t address); void _HandleClearUserBreakpoint( UserBreakpoint* breakpoint); + + void _HandleSetWatchpoint(target_addr_t address, + uint32 type, int32 length, bool enabled); + void _HandleSetWatchpoint( + Watchpoint* watchpoint, bool enabled); + void _HandleClearWatchpoint( target_addr_t address); + void _HandleClearWatchpoint(Watchpoint* watchpoint); void _HandleInspectAddress( target_addr_t address, @@ -151,6 +167,7 @@ FileManager* fFileManager; Worker* fWorker; BreakpointManager* fBreakpointManager; + WatchpointManager* fWatchpointManager; TeamMemoryBlockManager* fMemoryBlockManager; thread_id fDebugEventListener; diff --git a/src/apps/debugger/WatchpointManager.cpp b/src/apps/debugger/WatchpointManager.cpp new file mode 100644 index 0000000..e5854a0 100644 --- /dev/null +++ b/src/apps/debugger/WatchpointManager.cpp @@ -1,0 +1,95 @@ +/* + * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + +#include "WatchpointManager.h" + +#include + +#include + +#include + +#include "DebuggerInterface.h" +#include "Team.h" +#include "Tracing.h" + + +WatchpointManager::WatchpointManager(Team* team, + DebuggerInterface* debuggerInterface) + : + fLock("watchpoint manager"), + fTeam(team), + fDebuggerInterface(debuggerInterface) +{ + fDebuggerInterface->AcquireReference(); +} + + +WatchpointManager::~WatchpointManager() +{ + fDebuggerInterface->ReleaseReference(); +} + + +status_t +WatchpointManager::Init() +{ + return fLock.InitCheck(); +} + + +status_t +WatchpointManager::InstallWatchpoint(Watchpoint* watchpoint, + bool enabled) +{ + status_t error = B_OK; + TRACE_CONTROL("WatchpointManager::InstallUserWatchpoint(%p, %d)\n", + userWatchpoint, enabled); + + AutoLocker installLocker(fLock); + AutoLocker teamLocker(fTeam); + + bool oldEnabled = watchpoint->IsEnabled(); + if (enabled == oldEnabled) { + TRACE_CONTROL(" watchpoint already valid and with same enabled " + "state\n"); + return B_OK; + } + + watchpoint->SetEnabled(enabled); + + if (watchpoint->ShouldBeInstalled()) { + error = fDebuggerInterface->InstallWatchpoint(watchpoint->Address(), + watchpoint->Type(), watchpoint->Length()); + + if (error == B_OK) + watchpoint->SetInstalled(true); + } else { + error = fDebuggerInterface->UninstallWatchpoint(watchpoint->Address()); + + if (error == B_OK) + watchpoint->SetInstalled(false); + } + + return error; +} + + +void +WatchpointManager::UninstallWatchpoint(Watchpoint* watchpoint) +{ + AutoLocker installLocker(fLock); + AutoLocker teamLocker(fTeam); + + if (!watchpoint->IsInstalled()) + return; + + status_t error = fDebuggerInterface->UninstallWatchpoint( + watchpoint->Address()); + + if (error == B_OK) + watchpoint->SetInstalled(false); +}diff --git a/src/apps/debugger/WatchpointManager.h b/src/apps/debugger/WatchpointManager.h new file mode 100644 index 0000000..c854a6e 100644 --- /dev/null +++ b/src/apps/debugger/WatchpointManager.h @@ -1,0 +1,37 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef WATCHPOINT_MANAGER_H +#define WATCHPOINT_MANAGER_H + +#include + +#include "Watchpoint.h" + + +class DebuggerInterface; +class Team; + + +class WatchpointManager { +public: + WatchpointManager(Team* team, + DebuggerInterface* debuggerInterface); + ~WatchpointManager(); + + status_t Init(); + + status_t InstallWatchpoint(Watchpoint* watchpoint, + bool enabled); + void UninstallWatchpoint(Watchpoint* watchpoint); + +private: + BLocker fLock; // used to synchronize un-/installing + Team* fTeam; + DebuggerInterface* fDebuggerInterface; +}; + + +#endif // WATCHPOINT_MANAGER_H diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index d4868ee..3a379c2 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -22,6 +22,7 @@ #include "Statement.h" #include "TeamDebugInfo.h" #include "Tracing.h" +#include "Watchpoint.h" // #pragma mark - BreakpointByAddressPredicate @@ -45,7 +46,27 @@ }; +// #pragma mark - WatchpointByAddressPredicate + +struct Team::WatchpointByAddressPredicate + : UnaryPredicate { + WatchpointByAddressPredicate(target_addr_t address) + : + fAddress(address) + { + } + + virtual int operator()(const Watchpoint* watchpoint) const + { + return -Watchpoint::CompareAddressWatchpoint(&fAddress, watchpoint); + } + +private: + target_addr_t fAddress; +}; + + // #pragma mark - Team @@ -360,6 +381,67 @@ { fUserBreakpoints.Remove(userBreakpoint); userBreakpoint->ReleaseReference(); +} + + +bool +Team::AddWatchpoint(Watchpoint* watchpoint) +{ + if (fWatchpoints.BinaryInsert(watchpoint, &Watchpoint::CompareWatchpoints)) + return true; + + watchpoint->ReleaseReference(); + return false; +} + + +void +Team::RemoveWatchpoint(Watchpoint* watchpoint) +{ + int32 index = fWatchpoints.BinarySearchIndex(*watchpoint, + &Watchpoint::CompareWatchpoints); + if (index < 0) + return; + + fWatchpoints.RemoveItemAt(index); + watchpoint->ReleaseReference(); +} + + +int32 +Team::CountWatchpoints() const +{ + return fWatchpoints.CountItems(); +} + + +Watchpoint* +Team::WatchpointAt(int32 index) const +{ + return fWatchpoints.ItemAt(index); +} + + +Watchpoint* +Team::WatchpointAtAddress(target_addr_t address) const +{ + return fWatchpoints.BinarySearchByKey(address, + &Watchpoint::CompareAddressWatchpoint); +} + + +void +Team::GetWatchpointsInAddressRange(TargetAddressRange range, + BObjectList& watchpoints) const +{ + int32 index = fWatchpoints.FindBinaryInsertionIndex( + WatchpointByAddressPredicate(range.Start())); + for (; Watchpoint* watchpoint = fWatchpoints.ItemAt(index); index++) { + if (watchpoint->Address() > range.End()) + break; + + watchpoints.AddItem(watchpoint); + } } @@ -535,68 +617,57 @@ Listener* listener = it.Next();) { listener->UserBreakpointChanged(UserBreakpointEvent( TEAM_EVENT_USER_BREAKPOINT_CHANGED, this, breakpoint)); - } -} - - -void -Team::_NotifyThreadAdded(Thread* thread) -{ - for (ListenerList::Iterator it = fListeners.GetIterator(); - Listener* listener = it.Next();) { - listener->ThreadAdded(ThreadEvent(TEAM_EVENT_THREAD_ADDED, thread)); } } void -Team::_NotifyThreadRemoved(Thread* thread) +Team::NotifyWatchpointChanged(Watchpoint* watchpoint) { for (ListenerList::Iterator it = fListeners.GetIterator(); Listener* listener = it.Next();) { - listener->ThreadRemoved(ThreadEvent(TEAM_EVENT_THREAD_REMOVED, thread)); + listener->WatchpointChanged(WatchpointEvent( + TEAM_EVENT_WATCHPOINT_CHANGED, this, watchpoint)); } } void -Team::_NotifyImageAdded(Image* image) +Team::_NotifyThreadAdded(Thread* thread) { for (ListenerList::Iterator it = fListeners.GetIterator(); Listener* listener = it.Next();) { - listener->ImageAdded(ImageEvent(TEAM_EVENT_IMAGE_ADDED, image)); + listener->ThreadAdded(ThreadEvent(TEAM_EVENT_THREAD_ADDED, thread)); } } void -Team::_NotifyImageRemoved(Image* image) +Team::_NotifyThreadRemoved(Thread* thread) { for (ListenerList::Iterator it = fListeners.GetIterator(); Listener* listener = it.Next();) { - listener->ImageRemoved(ImageEvent(TEAM_EVENT_IMAGE_REMOVED, image)); + listener->ThreadRemoved(ThreadEvent(TEAM_EVENT_THREAD_REMOVED, thread)); } } void -Team::_NotifyBreakpointAdded(Breakpoint* breakpoint) +Team::_NotifyImageAdded(Image* image) { for (ListenerList::Iterator it = fListeners.GetIterator(); Listener* listener = it.Next();) { - listener->BreakpointAdded(BreakpointEvent( - TEAM_EVENT_BREAKPOINT_ADDED, this, breakpoint)); + listener->ImageAdded(ImageEvent(TEAM_EVENT_IMAGE_ADDED, image)); } } void -Team::_NotifyBreakpointRemoved(Breakpoint* breakpoint) +Team::_NotifyImageRemoved(Image* image) { for (ListenerList::Iterator it = fListeners.GetIterator(); Listener* listener = it.Next();) { - listener->BreakpointRemoved(BreakpointEvent( - TEAM_EVENT_BREAKPOINT_REMOVED, this, breakpoint)); + listener->ImageRemoved(ImageEvent(TEAM_EVENT_IMAGE_REMOVED, image)); } } @@ -642,6 +713,18 @@ : Event(type, team), fBreakpoint(breakpoint) +{ +} + + +// #pragma mark - WatchpointEvent + + +Team::WatchpointEvent::WatchpointEvent(uint32 type, Team* team, + Watchpoint* watchpoint) + : + Event(type, team), + fWatchpoint(watchpoint) { } @@ -728,5 +811,23 @@ void Team::Listener::UserBreakpointChanged(const Team::UserBreakpointEvent& event) +{ +} + + +void +Team::Listener::WatchpointAdded(const Team::WatchpointEvent& event) +{ +} + + +void +Team::Listener::WatchpointRemoved(const Team::WatchpointEvent& event) +{ +} + + +void +Team::Listener::WatchpointChanged(const Team::WatchpointEvent& event) { } diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 8a2f269..03dd5f5 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -16,6 +16,7 @@ #include "Thread.h" #include "ThreadInfo.h" #include "UserBreakpoint.h" +#include "Watchpoint.h" // team event types @@ -33,7 +34,11 @@ TEAM_EVENT_BREAKPOINT_ADDED, TEAM_EVENT_BREAKPOINT_REMOVED, - TEAM_EVENT_USER_BREAKPOINT_CHANGED + TEAM_EVENT_USER_BREAKPOINT_CHANGED, + + TEAM_EVENT_WATCHPOINT_ADDED, + TEAM_EVENT_WATCHPOINT_REMOVED, + TEAM_EVENT_WATCHPOINT_CHANGED }; @@ -55,10 +60,11 @@ class Team { public: class Event; - class ThreadEvent; - class ImageEvent; class BreakpointEvent; + class ImageEvent; + class ThreadEvent; class UserBreakpointEvent; + class WatchpointEvent; class Listener; public: @@ -126,6 +132,19 @@ UserBreakpoint* userBreakpoint); const UserBreakpointList& UserBreakpoints() const { return fUserBreakpoints; } + + bool AddWatchpoint(Watchpoint* watchpoint); + // takes over reference (also on error) + void RemoveWatchpoint(Watchpoint* watchpoint); + // releases its own reference + int32 CountWatchpoints() const; + Watchpoint* WatchpointAt(int32 index) const; + Watchpoint* WatchpointAtAddress( + target_addr_t address) const; + void GetWatchpointsInAddressRange( + TargetAddressRange range, + BObjectList& watchpoints) + const; status_t GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function, @@ -158,20 +177,23 @@ void NotifyUserBreakpointChanged( UserBreakpoint* breakpoint); + // watchpoint related service methods + void NotifyWatchpointChanged( + Watchpoint* watchpoint); + private: struct BreakpointByAddressPredicate; + struct WatchpointByAddressPredicate; typedef BObjectList BreakpointList; typedef DoublyLinkedList ListenerList; + typedef BObjectList WatchpointList; private: void _NotifyThreadAdded(Thread* thread); void _NotifyThreadRemoved(Thread* thread); void _NotifyImageAdded(Image* image); void _NotifyImageRemoved(Image* image); - void _NotifyBreakpointAdded(Breakpoint* breakpoint); - void _NotifyBreakpointRemoved( - Breakpoint* breakpoint); private: BLocker fLock; @@ -185,6 +207,7 @@ ThreadList fThreads; ImageList fImages; BreakpointList fBreakpoints; + WatchpointList fWatchpoints; UserBreakpointList fUserBreakpoints; ListenerList fListeners; }; @@ -234,6 +257,18 @@ protected: Breakpoint* fBreakpoint; +}; + + +class Team::WatchpointEvent : public Event { +public: + WatchpointEvent(uint32 type, Team* team, + Watchpoint* watchpoint); + + Watchpoint* GetWatchpoint() const { return fWatchpoint; } + +protected: + Watchpoint* fWatchpoint; }; @@ -275,6 +310,13 @@ const Team::BreakpointEvent& event); virtual void UserBreakpointChanged( const Team::UserBreakpointEvent& event); + + virtual void WatchpointAdded( + const Team::WatchpointEvent& event); + virtual void WatchpointRemoved( + const Team::WatchpointEvent& event); + virtual void WatchpointChanged( + const Team::WatchpointEvent& event); }; diff --git a/src/apps/debugger/model/Watchpoint.cpp b/src/apps/debugger/model/Watchpoint.cpp new file mode 100644 index 0000000..5c324d0 100644 --- /dev/null +++ b/src/apps/debugger/model/Watchpoint.cpp @@ -1,0 +1,65 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + +#include "Watchpoint.h" + + +Watchpoint::Watchpoint(target_addr_t address, uint32 type, int32 length) + : + fAddress(address), + fType(type), + fLength(length), + fInstalled(false), + fEnabled(false) +{ +} + + +Watchpoint::~Watchpoint() +{ +} + + +void +Watchpoint::SetInstalled(bool installed) +{ + fInstalled = installed; +} + + +void +Watchpoint::SetEnabled(bool enabled) +{ + fEnabled = enabled; +} + + +bool +Watchpoint::Contains(target_addr_t address) const +{ + return address >= fAddress && address <= (fAddress + fLength); +} + + +int +Watchpoint::CompareWatchpoints(const Watchpoint* a, const Watchpoint* b) +{ + if (a->Address() < b->Address()) + return -1; + return a->Address() == b->Address() ? 0 : 1; +} + + +int +Watchpoint::CompareAddressWatchpoint(const target_addr_t* address, + const Watchpoint* watchpoint) +{ + if (*address < watchpoint->Address()) + return -1; + return *address == watchpoint->Address() ? 0 : 1; +} + + + diff --git a/src/apps/debugger/model/Watchpoint.h b/src/apps/debugger/model/Watchpoint.h new file mode 100644 index 0000000..a9d591f 100644 --- /dev/null +++ b/src/apps/debugger/model/Watchpoint.h @@ -1,0 +1,52 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef WATCHPOINT_H +#define WATCHPOINT_H + + +#include + +#include "types/Types.h" + + +class Watchpoint : public BReferenceable { +public: + Watchpoint(target_addr_t address, uint32 type, + int32 length); + ~Watchpoint(); + + target_addr_t Address() const { return fAddress; } + uint32 Type() const { return fType; } + int32 Length() const { return fLength; } + + bool IsInstalled() const { return fInstalled; } + void SetInstalled(bool installed); + + bool IsEnabled() const { return fEnabled; } + void SetEnabled(bool enabled); + // WatchpointManager only + + bool ShouldBeInstalled() const + { return fEnabled && !fInstalled; } + + bool Contains(target_addr_t address) const; + + static int CompareWatchpoints(const Watchpoint* a, + const Watchpoint* b); + static int CompareAddressWatchpoint( + const target_addr_t* address, + const Watchpoint* watchpoint); + +private: + target_addr_t fAddress; + uint32 fType; + int32 fLength; + + bool fInstalled; + bool fEnabled; +}; + + +#endif // WATCHPOINT_H diff --git a/src/apps/debugger/settings/TeamSettings.cpp b/src/apps/debugger/settings/TeamSettings.cpp index 605202d..fbed4c8 100644 --- a/src/apps/debugger/settings/TeamSettings.cpp +++ b/src/apps/debugger/settings/TeamSettings.cpp @@ -18,6 +18,7 @@ #include "TeamUiSettings.h" #include "TeamUiSettingsFactory.h" #include "UserBreakpoint.h" +#include "WatchpointSetting.h" TeamSettings::TeamSettings() @@ -70,6 +71,23 @@ } } + // add watchpoints + for (int32 i = 0; Watchpoint* watchpoint = team->WatchpointAt(i); i++) { + WatchpointSetting* watchpointSetting + = new(std::nothrow) WatchpointSetting; + if (watchpointSetting == NULL) + return B_NO_MEMORY; + + status_t error = watchpointSetting->SetTo(*watchpoint, + watchpoint->IsEnabled()); + if (error == B_OK && !fWatchpoints.AddItem(watchpointSetting)) + error = B_NO_MEMORY; + if (error != B_OK) { + delete watchpointSetting; + return error; + } + } + return B_OK; } @@ -163,6 +181,20 @@ TeamSettings::BreakpointAt(int32 index) const { return fBreakpoints.ItemAt(index); +} + + +int32 +TeamSettings::CountWatchpoints() const +{ + return fWatchpoints.CountItems(); +} + + +const WatchpointSetting* +TeamSettings::WatchpointAt(int32 index) const +{ + return fWatchpoints.ItemAt(index); } diff --git a/src/apps/debugger/settings/TeamSettings.h b/src/apps/debugger/settings/TeamSettings.h index f41f2bf..3bc74e3 100644 --- a/src/apps/debugger/settings/TeamSettings.h +++ b/src/apps/debugger/settings/TeamSettings.h @@ -15,6 +15,7 @@ class Team; class BreakpointSetting; class TeamUiSettings; +class WatchpointSetting; class TeamSettings { @@ -33,6 +34,9 @@ int32 CountBreakpoints() const; const BreakpointSetting* BreakpointAt(int32 index) const; + int32 CountWatchpoints() const; + const WatchpointSetting* WatchpointAt(int32 index) const; + int32 CountUiSettings() const; const TeamUiSettings* UiSettingAt(int32 index) const; const TeamUiSettings* UiSettingFor(const char* id) const; @@ -44,12 +48,14 @@ private: typedef BObjectList BreakpointList; typedef BObjectList UiSettingsList; + typedef BObjectList WatchpointList; private: void _Unset(); private: BreakpointList fBreakpoints; + WatchpointList fWatchpoints; UiSettingsList fUiSettings; BString fTeamName; }; diff --git a/src/apps/debugger/settings/WatchpointSetting.cpp b/src/apps/debugger/settings/WatchpointSetting.cpp new file mode 100644 index 0000000..0872e14 100644 --- /dev/null +++ b/src/apps/debugger/settings/WatchpointSetting.cpp @@ -1,0 +1,100 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "WatchpointSetting.h" + +#include + +#include "Watchpoint.h" + + +WatchpointSetting::WatchpointSetting() + : + fAddress(0), + fType(0), + fLength(0), + fEnabled(false) +{ +} + + +WatchpointSetting::WatchpointSetting(const WatchpointSetting& other) + : + fAddress(other.fAddress), + fType(other.fType), + fLength(other.fLength), + fEnabled(other.fEnabled) +{ +} + + +WatchpointSetting::~WatchpointSetting() +{ +} + + +status_t +WatchpointSetting::SetTo(const Watchpoint& watchpoint, bool enabled) +{ + fAddress = watchpoint.Address(); + fType = watchpoint.Type(); + fLength = watchpoint.Length(); + fEnabled = enabled; + + return B_OK; +} + + +status_t +WatchpointSetting::SetTo(const BMessage& archive) +{ + if (archive.FindUInt64("address", &fAddress) != B_OK) + fAddress = 0; + + if (archive.FindUInt32("type", &fType) != B_OK) + fType = 0; + + if (archive.FindInt32("length", &fLength) != B_OK) + fLength = 0; + + if (archive.FindBool("enabled", &fEnabled) != B_OK) + fEnabled = false; + + return B_OK; +} + + +status_t +WatchpointSetting::WriteTo(BMessage& archive) const +{ + archive.MakeEmpty(); + + status_t error; + if ((error = archive.AddUInt64("address", fAddress)) != B_OK + || (error = archive.AddUInt32("type", fType)) != B_OK + || (error = archive.AddInt32("length", fLength)) != B_OK + || (error = archive.AddBool("enabled", fEnabled)) != B_OK) { + return error; + } + + return B_OK; +} + + +WatchpointSetting& +WatchpointSetting::operator=(const WatchpointSetting& other) +{ + if (this == &other) + return *this; + + fAddress = other.fAddress; + fType = other.fType; + fLength = other.fLength; + fEnabled = other.fEnabled; + + return *this; +} diff --git a/src/apps/debugger/settings/WatchpointSetting.h b/src/apps/debugger/settings/WatchpointSetting.h new file mode 100644 index 0000000..14fd16c 100644 --- /dev/null +++ b/src/apps/debugger/settings/WatchpointSetting.h @@ -1,0 +1,46 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef WATCHPOINT_SETTING_H +#define WATCHPOINT_SETTING_H + + +#include + +#include "types/Types.h" + +class BMessage; +class Watchpoint; + + +class WatchpointSetting { +public: + WatchpointSetting(); + WatchpointSetting( + const WatchpointSetting& other); + ~WatchpointSetting(); + + status_t SetTo(const Watchpoint& watchpoint, + bool enabled); + status_t SetTo(const BMessage& archive); + status_t WriteTo(BMessage& archive) const; + + target_addr_t Address() const { return fAddress; } + uint32 Type() const { return fType; } + int32 Length() const { return fLength; } + + bool IsEnabled() const { return fEnabled; } + + WatchpointSetting& operator=(const WatchpointSetting& other); + +private: + target_addr_t fAddress; + uint32 fType; + int32 fLength; + bool fEnabled; +}; + + +#endif // BREAKPOINT_SETTING_H diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 60ae097..a693037 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -27,6 +27,7 @@ class ValueNode; class ValueNodeContainer; class Variable; +class Watchpoint; enum user_notification_type { @@ -99,6 +100,17 @@ virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint) = 0; // TODO: Consolidate those! + + virtual void SetWatchpointRequested(target_addr_t address, + uint32 type, int32 length, + bool enabled) = 0; + virtual void SetWatchpointEnabledRequested( + Watchpoint* watchpoint, + bool enabled) = 0; + virtual void ClearWatchpointRequested( + target_addr_t address) = 0; + virtual void ClearWatchpointRequested( + Watchpoint* watchpoint) = 0; virtual void InspectRequested( target_addr_t address, -- gitore 0.2.3