⛏️ index : haiku.git

author Rene Gollent <anevilyak@gmail.com> 2012-11-06 11:45:26.0 +01:00:00
committer Alexander von Gluck IV <kallisti5@unixzen.com> 2012-11-06 8:08:41.0 -06:00:00
commit
601538f2afd1408ce09e1abaed5a5d99cdee9cd9 [patch]
tree
7c1ab3e06ba05a0cc430bbf48954ff2ea3eb0b09
parent
cb51c20c26a95e341cb56ceaa7cc4402c21464a6
download
601538f2afd1408ce09e1abaed5a5d99cdee9cd9.tar.gz

Start adding the underlying infrastructure for watchpoint support.



Diff

 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<Watchpoint> 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<Watchpoint> 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<Watchpoint> 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<Watchpoint> 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<Watchpoint> 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<Watchpoint> 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 <stdio.h>

#include <new>

#include <AutoLocker.h>

#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<BLocker> installLocker(fLock);
	AutoLocker<Team> 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<BLocker> installLocker(fLock);
	AutoLocker<Team> 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 <Locker.h>

#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<Watchpoint> {
	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<Watchpoint>& 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<Watchpoint>& 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<Breakpoint> BreakpointList;
			typedef DoublyLinkedList<Listener> ListenerList;
			typedef BObjectList<Watchpoint> 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 <Referenceable.h>

#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<BreakpointSetting> BreakpointList;
			typedef BObjectList<TeamUiSettings> UiSettingsList;
			typedef BObjectList<WatchpointSetting> 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 <Message.h>

#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 <String.h>

#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,