[Haiku-commits] r31189 - in haiku/trunk/src/apps/debugger: . gui/team_window model

bonefish at BerliOS bonefish at mail.berlios.de
Mon Jun 22 23:51:33 CEST 2009


Author: bonefish
Date: 2009-06-22 23:51:32 +0200 (Mon, 22 Jun 2009)
New Revision: 31189
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31189&view=rev

Added:
   haiku/trunk/src/apps/debugger/model/Breakpoint.cpp
   haiku/trunk/src/apps/debugger/model/Breakpoint.h
Modified:
   haiku/trunk/src/apps/debugger/Jamfile
   haiku/trunk/src/apps/debugger/MessageCodes.h
   haiku/trunk/src/apps/debugger/TeamDebugger.cpp
   haiku/trunk/src/apps/debugger/TeamDebugger.h
   haiku/trunk/src/apps/debugger/gui/team_window/SourceView.cpp
   haiku/trunk/src/apps/debugger/gui/team_window/SourceView.h
   haiku/trunk/src/apps/debugger/gui/team_window/TeamWindow.cpp
   haiku/trunk/src/apps/debugger/gui/team_window/TeamWindow.h
   haiku/trunk/src/apps/debugger/model/DisassembledCode.cpp
   haiku/trunk/src/apps/debugger/model/DisassembledCode.h
   haiku/trunk/src/apps/debugger/model/SourceCode.h
   haiku/trunk/src/apps/debugger/model/Statement.cpp
   haiku/trunk/src/apps/debugger/model/Statement.h
   haiku/trunk/src/apps/debugger/model/TeamDebugModel.cpp
   haiku/trunk/src/apps/debugger/model/TeamDebugModel.h
Log:
* Added Breakpoint class and extended TeamDebugModel to manage the objects.
  Extended the event mechanism respectively.
* Added support to SourceView to display breakpoints and manipulate them.
* Extended TeamDebugger to install/uninstall breakpoints.


Modified: haiku/trunk/src/apps/debugger/Jamfile
===================================================================
--- haiku/trunk/src/apps/debugger/Jamfile	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/Jamfile	2009-06-22 21:51:32 UTC (rev 31189)
@@ -57,6 +57,7 @@
 	ThreadListView.cpp
 
 	# model
+	Breakpoint.cpp
 	DisassembledCode.cpp
 	Image.cpp
 	ImageInfo.cpp

Modified: haiku/trunk/src/apps/debugger/MessageCodes.h
===================================================================
--- haiku/trunk/src/apps/debugger/MessageCodes.h	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/MessageCodes.h	2009-06-22 21:51:32 UTC (rev 31189)
@@ -12,11 +12,14 @@
 	MSG_THREAD_STEP_OVER				= 'stov',
 	MSG_THREAD_STEP_INTO				= 'stin',
 	MSG_THREAD_STEP_OUT					= 'stou',
+	MSG_SET_BREAKPONT					= 'sbrk',
+	MSG_CLEAR_BREAKPONT					= 'cbrk',
 
 	MSG_THREAD_STATE_CHANGED			= 'tsch',
 	MSG_THREAD_CPU_STATE_CHANGED		= 'tcsc',
 	MSG_THREAD_STACK_TRACE_CHANGED		= 'tstc',
-	MSG_STACK_FRAME_SOURCE_CODE_CHANGED	= 'sfsc'
+	MSG_STACK_FRAME_SOURCE_CODE_CHANGED	= 'sfsc',
+	MSG_USER_BREAKPOINT_CHANGED			= 'ubrc'
 };
 
 

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.cpp	2009-06-22 21:51:32 UTC (rev 31189)
@@ -5,10 +5,12 @@
 
 #include "TeamDebugger.h"
 
+#include <stdarg.h>
 #include <stdio.h>
 
 #include <new>
 
+#include <Alert.h>
 #include <Message.h>
 
 #include <AutoLocker.h>
@@ -19,6 +21,7 @@
 #include "DebuggerInterface.h"
 #include "Jobs.h"
 #include "MessageCodes.h"
+#include "Statement.h"
 #include "TeamDebugModel.h"
 
 
@@ -198,6 +201,24 @@
 			break;
 		}
 
+		case MSG_SET_BREAKPONT:
+		case MSG_CLEAR_BREAKPONT:
+		{
+			uint64 address;
+			if (message->FindUInt64("address", &address) != B_OK)
+				break;
+
+			if (message->what == MSG_SET_BREAKPONT) {
+				bool enabled;
+				if (message->FindBool("enabled", &enabled) != B_OK)
+					enabled = true;
+
+				_HandleSetUserBreakpoint(address, enabled);
+			} else
+				_HandleClearUserBreakpoint(address);
+			break;
+		}
+
 		case MSG_THREAD_STATE_CHANGED:
 		{
 			int32 threadID;
@@ -267,6 +288,25 @@
 }
 
 
+void
+TeamDebugger::SetBreakpointRequested(target_addr_t address, bool enabled)
+{
+	BMessage message(MSG_SET_BREAKPONT);
+	message.AddUInt64("address", (uint64)address);
+	message.AddBool("enabled", enabled);
+	PostMessage(&message);
+}
+
+
+void
+TeamDebugger::ClearBreakpointRequested(target_addr_t address)
+{
+	BMessage message(MSG_CLEAR_BREAKPONT);
+	message.AddUInt64("address", (uint64)address);
+	PostMessage(&message);
+}
+
+
 bool
 TeamDebugger::TeamWindowQuitRequested(TeamWindow* window)
 {
@@ -569,6 +609,73 @@
 }
 
 
+status_t
+TeamDebugger::_SetUserBreakpoint(target_addr_t address, bool enabled)
+{
+	user_breakpoint_state state = enabled
+		? USER_BREAKPOINT_ENABLED : USER_BREAKPOINT_DISABLED;
+
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+	// If there already is a breakpoint, it might already have the requested
+	// state.
+	Breakpoint* breakpoint = fDebugModel->BreakpointAtAddress(address);
+	if (breakpoint != NULL && breakpoint->UserState() == state)
+		return B_OK;
+
+	// create a breakpoint, if it doesn't exist yet
+	if (breakpoint == NULL) {
+		Image* image = fTeam->ImageByAddress(address);
+		if (image == NULL)
+			return B_OK;
+
+		breakpoint = new(std::nothrow) Breakpoint(image, address);
+		if (breakpoint == NULL)
+			return B_NO_MEMORY;
+
+		if (!fDebugModel->AddBreakpoint(breakpoint))
+			return B_NO_MEMORY;
+	}
+
+	user_breakpoint_state oldState = breakpoint->UserState();
+
+	// set the breakpoint state
+	breakpoint->SetUserState(state);
+	fDebugModel->NotifyUserBreakpointChanged(breakpoint);
+
+	bool install = breakpoint->ShouldBeInstalled();
+	if (breakpoint->IsInstalled() == install)
+		return B_OK;
+
+	// The breakpoint needs to be installed/uninstalled.
+	locker.Unlock();
+
+	status_t error = install
+		? fDebuggerInterface->InstallBreakpoint(address)
+		: fDebuggerInterface->UninstallBreakpoint(address);
+
+	locker.Lock();
+
+	breakpoint = fDebugModel->BreakpointAtAddress(address);
+
+	// Mark the breakpoint installed/uninstalled, if everything went fine.
+	if (error == B_OK) {
+		breakpoint->SetInstalled(install);
+printf("-> breakpoint %sinstalled successfully!\n", install ? "" : "un");
+		return B_OK;
+	}
+
+	// revert on error
+	breakpoint->SetUserState(oldState);
+	fDebugModel->NotifyUserBreakpointChanged(breakpoint);
+
+	if (breakpoint->IsUnused())
+		fDebugModel->RemoveBreakpoint(breakpoint);
+
+	return error;
+}
+
+
 void
 TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action)
 {
@@ -620,6 +727,47 @@
 
 
 void
+TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled)
+{
+printf("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled);
+	status_t error = _SetUserBreakpoint(address, enabled);
+	if (error != B_OK) {
+		_NotifyUser("Install Breakpoint", "Failed to install breakpoint: %s",
+			strerror(error));
+	}
+}
+
+
+void
+TeamDebugger::_HandleClearUserBreakpoint(target_addr_t address)
+{
+printf("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address);
+	AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+	Breakpoint* breakpoint = fDebugModel->BreakpointAtAddress(address);
+	if (breakpoint == NULL || breakpoint->UserState() == USER_BREAKPOINT_NONE)
+		return;
+
+	// set the breakpoint state
+	breakpoint->SetUserState(USER_BREAKPOINT_NONE);
+	fDebugModel->NotifyUserBreakpointChanged(breakpoint);
+
+	// check whether the breakpoint needs to be uninstalled
+	bool uninstall = !breakpoint->ShouldBeInstalled()
+		&& breakpoint->IsInstalled();
+
+	// if unused remove it
+	if (breakpoint->IsUnused())
+		fDebugModel->RemoveBreakpoint(breakpoint);
+
+	locker.Unlock();
+
+	if (uninstall)
+		fDebuggerInterface->UninstallBreakpoint(address);
+}
+
+
+void
 TeamDebugger::_HandleThreadStateChanged(thread_id threadID)
 {
 	AutoLocker< ::Team> teamLocker(fTeam);
@@ -669,3 +817,25 @@
 {
 printf("TeamDebugger::_HandleStackTraceChanged()\n");
 }
+
+
+void
+TeamDebugger::_NotifyUser(const char* title, const char* text,...)
+{
+	// print the message
+	char buffer[1024];
+	va_list args;
+	va_start(args, text);
+	vsnprintf(buffer, sizeof(buffer), text, args);
+	va_end(args);
+
+	// show the alert
+	BAlert* alert = new(std::nothrow) BAlert(title, buffer, "OK",
+		NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
+	if (alert != NULL)
+		alert->Go(NULL);
+
+	// TODO: We need to let the alert run asynchronously, but we shouldn't just
+	// create it and don't care anymore. Maybe an error window, which can
+	// display a list of errors would be the better choice.
+}

Modified: haiku/trunk/src/apps/debugger/TeamDebugger.h
===================================================================
--- haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/TeamDebugger.h	2009-06-22 21:51:32 UTC (rev 31189)
@@ -39,6 +39,9 @@
 									TeamWindow* window, StackFrame* frame);
 	virtual	void				ThreadActionRequested(TeamWindow* window,
 									thread_id threadID, uint32 action);
+	virtual	void				SetBreakpointRequested(target_addr_t address,
+									bool enabled);
+	virtual	void				ClearBreakpointRequested(target_addr_t address);
 	virtual	bool				TeamWindowQuitRequested(TeamWindow* window);
 
 	// JobListener
@@ -88,13 +91,23 @@
 			void				_SetThreadState(::Thread* thread, uint32 state,
 									CpuState* cpuState);
 
+			status_t			_SetUserBreakpoint(target_addr_t address,
+									bool enabled);
+
 			void				_HandleThreadAction(thread_id threadID,
 									uint32 action);
+			void				_HandleSetUserBreakpoint(target_addr_t address,
+									bool enabled);
+			void				_HandleClearUserBreakpoint(
+									target_addr_t address);
 
 			void				_HandleThreadStateChanged(thread_id threadID);
 			void				_HandleCpuStateChanged(thread_id threadID);
 			void				_HandleStackTraceChanged(thread_id threadID);
 
+			void				_NotifyUser(const char* title,
+									const char* text,...);
+
 private:
 			::Team*				fTeam;
 			TeamDebugModel*		fDebugModel;

Modified: haiku/trunk/src/apps/debugger/gui/team_window/SourceView.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/gui/team_window/SourceView.cpp	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/gui/team_window/SourceView.cpp	2009-06-22 21:51:32 UTC (rev 31189)
@@ -11,12 +11,15 @@
 #include <stdio.h>
 
 #include <LayoutUtils.h>
+#include <Looper.h>
+#include <Message.h>
 #include <Polygon.h>
 #include <ScrollBar.h>
 
 #include <AutoLocker.h>
 #include <ObjectList.h>
 
+#include "Breakpoint.h"
 #include "SourceCode.h"
 #include "StackTrace.h"
 #include "Statement.h"
@@ -41,10 +44,11 @@
 
 	inline	float				TotalHeight() const;
 
+			int32				LineAtOffset(float yOffset) const;
 			void				GetLineRange(BRect rect, int32& minLine,
-									int32& maxLine);
+									int32& maxLine) const;
+			BRect				LineRect(uint32 line) const;
 
-
 protected:
 			SourceView*			fSourceView;
 			FontInfo*			fFontInfo;
@@ -55,7 +59,8 @@
 class SourceView::MarkerView : public BaseView {
 public:
 								MarkerView(SourceView* sourceView,
-									FontInfo* fontInfo);
+									TeamDebugModel* debugModel,
+									Listener* listener, FontInfo* fontInfo);
 								~MarkerView();
 
 	virtual	void				SetSourceCode(SourceCode* sourceCode);
@@ -63,25 +68,52 @@
 			void				SetStackTrace(StackTrace* stackTrace);
 			void				SetStackFrame(StackFrame* stackFrame);
 
+			void				UserBreakpointChanged(target_addr_t address);
+
 	virtual	BSize				MinSize();
 	virtual	BSize				MaxSize();
 
 	virtual	void				Draw(BRect updateRect);
 
+	virtual	void				MouseDown(BPoint where);
+
 private:
 			struct Marker;
 			struct InstructionPointerMarker;
+			struct BreakpointMarker;
 
+			template<typename MarkerType> struct MarkerByLinePredicate;
+
 			typedef BObjectList<Marker>	MarkerList;
+			typedef BObjectList<BreakpointMarker> BreakpointMarkerList;
 
 private:
-			void				_UpdateMarkers();
+			void				_InvalidateIPMarkers();
+			void				_InvalidateBreakpointMarkers();
+			void				_UpdateIPMarkers();
+			void				_UpdateBreakpointMarkers();
+			void				_GetMarkers(uint32 minLine, uint32 maxLine,
+									MarkerList& markers);
+			BreakpointMarker*	_BreakpointMarkerAtLine(uint32 line);
 
+	template<typename MarkerType>
+	static	int					_CompareMarkers(const MarkerType* a,
+									const MarkerType* b);
+
+	template<typename MarkerType>
+	static	int					_CompareLineMarker(const uint32* line,
+									const MarkerType* marker);
+
 private:
+			TeamDebugModel*		fDebugModel;
+			Listener*			fListener;
 			StackTrace*			fStackTrace;
 			StackFrame*			fStackFrame;
-			MarkerList			fMarkers;
-			bool				fMarkersValid;
+			MarkerList			fIPMarkers;
+			BreakpointMarkerList fBreakpointMarkers;
+			bool				fIPMarkersValid;
+			bool				fBreakpointMarkersValid;
+			rgb_color			fBreakpointOptionMarker;
 };
 
 
@@ -115,6 +147,40 @@
 };
 
 
+struct SourceView::MarkerView::BreakpointMarker : Marker {
+								BreakpointMarker(uint32 line,
+									target_addr_t address, bool enabled);
+
+			target_addr_t		Address() const		{ return fAddress; }
+			bool				IsEnabled() const	{ return fEnabled; }
+
+	virtual	void				Draw(MarkerView* view, BRect rect);
+
+private:
+			target_addr_t		fAddress;
+			bool				fEnabled;
+};
+
+
+template<typename MarkerType>
+struct SourceView::MarkerView::MarkerByLinePredicate
+	: UnaryPredicate<MarkerType> {
+	MarkerByLinePredicate(uint32 line)
+		:
+		fLine(line)
+	{
+	}
+
+	virtual int operator()(const MarkerType* marker) const
+	{
+		return -_CompareLineMarker<MarkerType>(&fLine, marker);
+	}
+
+private:
+	uint32	fLine;
+};
+
+
 class SourceView::TextView : public BaseView {
 public:
 								TextView(SourceView* sourceView,
@@ -181,8 +247,21 @@
 }
 
 
+int32
+SourceView::BaseView::LineAtOffset(float yOffset) const
+{
+	int32 lineCount = LineCount();
+	if (yOffset < 0 || lineCount == 0)
+		return -1;
+
+	int32 line = (int32)yOffset / (int32)fFontInfo->lineHeight;
+	return line < lineCount ? line : -1;
+}
+
+
 void
-SourceView::BaseView::GetLineRange(BRect rect, int32& minLine, int32& maxLine)
+SourceView::BaseView::GetLineRange(BRect rect, int32& minLine,
+	int32& maxLine) const
 {
 	int32 lineHeight = (int32)fFontInfo->lineHeight;
 	minLine = (int32)rect.top / lineHeight;
@@ -192,6 +271,14 @@
 }
 
 
+BRect
+SourceView::BaseView::LineRect(uint32 line) const
+{
+	float y = (float)line * fFontInfo->lineHeight;
+	return BRect(0, y, Bounds().right, y + fFontInfo->lineHeight - 1);
+}
+
+
 // #pragma mark - MarkerView::Marker
 
 
@@ -282,18 +369,52 @@
 }
 
 
+// #pragma mark - MarkerView::BreakpointMarker
+
+
+SourceView::MarkerView::BreakpointMarker::BreakpointMarker(uint32 line,
+	target_addr_t address, bool enabled)
+	:
+	Marker(line),
+	fAddress(address),
+	fEnabled(enabled)
+{
+}
+
+
+void
+SourceView::MarkerView::BreakpointMarker::Draw(MarkerView* view, BRect rect)
+{
+	float y = (rect.top + rect.bottom) / 2;
+	view->SetHighColor((rgb_color){255, 0, 0, 255});
+	if (fEnabled)
+		view->FillEllipse(BPoint(rect.right - 8, y), 4, 4);
+	else
+		view->StrokeEllipse(BPoint(rect.right - 8, y), 3.5f, 3.5f);
+}
+
+
 // #pragma mark - MarkerView
 
 
-SourceView::MarkerView::MarkerView(SourceView* sourceView, FontInfo* fontInfo)
+SourceView::MarkerView::MarkerView(SourceView* sourceView,
+	TeamDebugModel* debugModel, Listener* listener, FontInfo* fontInfo)
 	:
 	BaseView("source marker view", sourceView, fontInfo),
+	fDebugModel(debugModel),
+	fListener(listener),
 	fStackTrace(NULL),
 	fStackFrame(NULL),
-	fMarkers(20, true),
-	fMarkersValid(false)
+	fIPMarkers(10, true),
+	fBreakpointMarkers(20, true),
+	fIPMarkersValid(false),
+	fBreakpointMarkersValid(false)
+
 {
-	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+	rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
+	fBreakpointOptionMarker = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
+		B_DARKEN_1_TINT);
+	SetViewColor(background);
 }
 
 
@@ -305,8 +426,8 @@
 void
 SourceView::MarkerView::SetSourceCode(SourceCode* sourceCode)
 {
-	fMarkers.MakeEmpty();
-	fMarkersValid = false;
+	_InvalidateIPMarkers();
+	_InvalidateBreakpointMarkers();
 	BaseView::SetSourceCode(sourceCode);
 }
 
@@ -315,8 +436,7 @@
 SourceView::MarkerView::SetStackTrace(StackTrace* stackTrace)
 {
 	fStackTrace = stackTrace;
-	fMarkers.MakeEmpty();
-	fMarkersValid = false;
+	_InvalidateIPMarkers();
 	Invalidate();
 }
 
@@ -325,12 +445,19 @@
 SourceView::MarkerView::SetStackFrame(StackFrame* stackFrame)
 {
 	fStackFrame = stackFrame;
-	fMarkers.MakeEmpty();
-	fMarkersValid = false;
+	_InvalidateIPMarkers();
 	Invalidate();
 }
 
 
+void
+SourceView::MarkerView::UserBreakpointChanged(target_addr_t address)
+{
+	_InvalidateBreakpointMarkers();
+	Invalidate();
+}
+
+
 BSize
 SourceView::MarkerView::MinSize()
 {
@@ -347,40 +474,112 @@
 void
 SourceView::MarkerView::Draw(BRect updateRect)
 {
-	_UpdateMarkers();
-
-	if (fSourceCode == NULL || fMarkers.IsEmpty())
+	if (fSourceCode == NULL)
 		return;
 
 	// get the lines intersecting with the update rect
 	int32 minLine, maxLine;
 	GetLineRange(updateRect, minLine, maxLine);
+	if (minLine > maxLine)
+		return;
 
-	// draw the markers
+	// get the markers in that range
+	MarkerList markers;
+	_GetMarkers(minLine, maxLine, markers);
+
 	float width = Bounds().Width();
-	// TODO: The markers should be sorted, so we don't need to iterate over
-	// all of them.
-	for (int32 i = 0; Marker* marker = fMarkers.ItemAt(i); i++) {
-		int32 line = marker->Line();
-		if (line < minLine || line > maxLine)
+
+	int32 markerIndex = 0;
+	for (int32 line = minLine; line <= maxLine; line++) {
+		bool drawBreakpointOptionMarker = true;
+
+		Marker* marker;
+		while ((marker = markers.ItemAt(markerIndex)) != NULL
+				&& marker->Line() == (uint32)line) {
+			marker->Draw(this, LineRect(line));
+			drawBreakpointOptionMarker = false;
+			markerIndex++;
+		}
+
+		if (!drawBreakpointOptionMarker)
 			continue;
 
-		float y = (float)line * fFontInfo->lineHeight;
-		BRect rect(0, y, width, y + fFontInfo->lineHeight - 1);
-		marker->Draw(this, rect);
+		Statement* statement = fSourceCode->StatementAtLine(line);
+		if (statement == NULL
+				|| statement->StartSourceLocation().Line() != (uint32)line
+				|| !statement->BreakpointAllowed()) {
+			continue;
+		}
+
+		float y = ((float)line + 0.5f) * fFontInfo->lineHeight;
+		SetHighColor(fBreakpointOptionMarker);
+		FillEllipse(BPoint(width - 8, y), 2, 2);
 	}
+}
 
-	// TODO: Draw possible breakpoint marks!
+
+void
+SourceView::MarkerView::MouseDown(BPoint where)
+{
+	if (fSourceCode == NULL)
+		return;
+
+	int32 line = LineAtOffset(where.y);
+	if (line < 0)
+		return;
+
+	Statement* statement = fSourceCode->StatementAtLine(line);
+	if (statement == NULL
+			|| statement->StartSourceLocation().Line() != (uint32)line
+			|| !statement->BreakpointAllowed()) {
+		return;
+	}
+
+	int32 modifiers;
+	if (Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK)
+		modifiers = 0;
+
+	BreakpointMarker* marker = _BreakpointMarkerAtLine(line);
+	target_addr_t address = marker != NULL
+		? marker->Address() : statement->CoveringAddressRange().Start();
+
+	if ((modifiers & B_SHIFT_KEY) != 0) {
+		if (marker != NULL && !marker->IsEnabled())
+			fListener->ClearBreakpointRequested(address);
+		else
+			fListener->SetBreakpointRequested(address, false);
+	} else {
+		if (marker != NULL && marker->IsEnabled())
+			fListener->ClearBreakpointRequested(address);
+		else
+			fListener->SetBreakpointRequested(address, true);
+	}
 }
 
 
 void
-SourceView::MarkerView::_UpdateMarkers()
+SourceView::MarkerView::_InvalidateIPMarkers()
 {
-	if (fMarkersValid)
+	fIPMarkersValid = false;
+	fIPMarkers.MakeEmpty();
+}
+
+
+void
+SourceView::MarkerView::_InvalidateBreakpointMarkers()
+{
+	fBreakpointMarkersValid = false;
+	fBreakpointMarkers.MakeEmpty();
+}
+
+
+void
+SourceView::MarkerView::_UpdateIPMarkers()
+{
+	if (fIPMarkersValid)
 		return;
 
-	fMarkers.MakeEmpty();
+	fIPMarkers.MakeEmpty();
 
 	if (fSourceCode != NULL && fStackTrace != NULL) {
 		for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i);
@@ -395,18 +594,135 @@
 
 			Marker* marker = new(std::nothrow) InstructionPointerMarker(
 				line, i == 0, frame == fStackFrame);
-			if (marker == NULL || !fMarkers.AddItem(marker)) {
+			if (marker == NULL || !fIPMarkers.AddItem(marker)) {
 				delete marker;
 				break;
 			}
 		}
+
+		// sort by line
+		fIPMarkers.SortItems(&_CompareMarkers<Marker>);
+
+		// TODO: Filter duplicate IP markers (recursive functions)!
 	}
-	// TODO: Filter duplicate IP markers (recursive functions)!
 
-	fMarkersValid = true;
+	fIPMarkersValid = true;
 }
 
 
+void
+SourceView::MarkerView::_UpdateBreakpointMarkers()
+{
+	if (fBreakpointMarkersValid)
+		return;
+
+	fBreakpointMarkers.MakeEmpty();
+
+	if (fSourceCode != NULL) {
+		AutoLocker<TeamDebugModel> locker(fDebugModel);
+
+		// get the breakpoints in our source code range
+		BObjectList<Breakpoint> breakpoints;
+		fDebugModel->GetBreakpointsInAddressRange(
+			fSourceCode->StatementAddressRange(), breakpoints);
+
+		for (int32 i = 0; Breakpoint* breakpoint = breakpoints.ItemAt(i); i++) {
+			if (breakpoint->UserState() == USER_BREAKPOINT_NONE)
+				continue;
+
+			Statement* statement = fSourceCode->StatementAtAddress(
+				breakpoint->Address());
+			if (statement == NULL)
+				continue;
+			uint32 line = statement->StartSourceLocation().Line();
+			if (line >= (uint32)LineCount())
+				continue;
+
+			BreakpointMarker* marker = new(std::nothrow) BreakpointMarker(
+				line, breakpoint->Address(),
+				breakpoint->UserState() == USER_BREAKPOINT_ENABLED);
+			if (marker == NULL || !fBreakpointMarkers.AddItem(marker)) {
+				delete marker;
+				break;
+			}
+		}
+
+		// sort by line
+		fBreakpointMarkers.SortItems(&_CompareMarkers<BreakpointMarker>);
+	}
+
+	fBreakpointMarkersValid = true;
+}
+
+
+void
+SourceView::MarkerView::_GetMarkers(uint32 minLine, uint32 maxLine,
+	MarkerList& markers)
+{
+	_UpdateIPMarkers();
+	_UpdateBreakpointMarkers();
+
+	int32 ipIndex = fIPMarkers.FindBinaryInsertionIndex(
+		MarkerByLinePredicate<Marker>(minLine));
+	int32 breakpointIndex = fBreakpointMarkers.FindBinaryInsertionIndex(
+		MarkerByLinePredicate<BreakpointMarker>(minLine));
+
+	Marker* ipMarker = fIPMarkers.ItemAt(ipIndex);
+	Marker* breakpointMarker = fBreakpointMarkers.ItemAt(breakpointIndex);
+
+	while (ipMarker != NULL && breakpointMarker != NULL
+		&& ipMarker->Line() <= maxLine && breakpointMarker->Line() <= maxLine) {
+		if (breakpointMarker->Line() <= ipMarker->Line()) {
+			markers.AddItem(breakpointMarker);
+			breakpointMarker = fBreakpointMarkers.ItemAt(++breakpointIndex);
+		} else {
+			markers.AddItem(ipMarker);
+			ipMarker = fIPMarkers.ItemAt(++ipIndex);
+		}
+	}
+
+	while (breakpointMarker != NULL && breakpointMarker->Line() <= maxLine) {
+		markers.AddItem(breakpointMarker);
+		breakpointMarker = fBreakpointMarkers.ItemAt(++breakpointIndex);
+	}
+
+	while (ipMarker != NULL && ipMarker->Line() <= maxLine) {
+		markers.AddItem(ipMarker);
+		ipMarker = fIPMarkers.ItemAt(++ipIndex);
+	}
+}
+
+
+SourceView::MarkerView::BreakpointMarker*
+SourceView::MarkerView::_BreakpointMarkerAtLine(uint32 line)
+{
+	return fBreakpointMarkers.BinarySearchByKey(line,
+		&_CompareLineMarker<BreakpointMarker>);
+}
+
+
+template<typename MarkerType>
+/*static*/ int
+SourceView::MarkerView::_CompareMarkers(const MarkerType* a,
+	const MarkerType* b)
+{
+	if (a->Line() < b->Line())
+		return -1;
+	return a->Line() == b->Line() ? 0 : 1;
+}
+
+
+template<typename MarkerType>
+/*static*/ int
+SourceView::MarkerView::_CompareLineMarker(const uint32* line,
+	const MarkerType* marker)
+{
+	if (*line < marker->Line())
+		return -1;
+	return *line == marker->Line() ? 0 : 1;
+}
+
+
 // #pragma mark - TextView
 
 
@@ -605,6 +921,13 @@
 }
 
 
+void
+SourceView::UserBreakpointChanged(target_addr_t address)
+{
+	fMarkerView->UserBreakpointChanged(address);
+}
+
+
 bool
 SourceView::ScrollToAddress(target_addr_t address)
 {
@@ -622,7 +945,6 @@
 bool
 SourceView::ScrollToLine(uint32 line)
 {
-printf("SourceView::ScrollToLine(%lu)\n", line);
 	if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
 		return false;
 
@@ -703,7 +1025,8 @@
 void
 SourceView::_Init()
 {
-	AddChild(fMarkerView = new MarkerView(this, &fFontInfo));
+	AddChild(fMarkerView = new MarkerView(this, fDebugModel, fListener,
+		&fFontInfo));
 	AddChild(fTextView = new TextView(this, &fFontInfo));
 }
 

Modified: haiku/trunk/src/apps/debugger/gui/team_window/SourceView.h
===================================================================
--- haiku/trunk/src/apps/debugger/gui/team_window/SourceView.h	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/gui/team_window/SourceView.h	2009-06-22 21:51:32 UTC (rev 31189)
@@ -11,9 +11,11 @@
 #include "ArchitectureTypes.h"
 
 
+class Breakpoint;
 class SourceCode;
 class StackFrame;
 class StackTrace;
+class Statement;
 class TeamDebugModel;
 
 
@@ -36,6 +38,8 @@
 			void				SetStackFrame(StackFrame* stackFrame);
 			void				SetSourceCode(SourceCode* sourceCode);
 
+			void				UserBreakpointChanged(target_addr_t address);
+
 			bool				ScrollToAddress(target_addr_t address);
 			bool				ScrollToLine(uint32 line);
 
@@ -80,8 +84,10 @@
 public:
 	virtual						~Listener();
 
-//	virtual	void				StackFrameSelectionChanged(
-//									StackFrame* frame) = 0;
+	virtual	void				SetBreakpointRequested(
+									target_addr_t address, bool enabled) = 0;
+	virtual	void				ClearBreakpointRequested(
+									target_addr_t address) = 0;
 };
 
 

Modified: haiku/trunk/src/apps/debugger/gui/team_window/TeamWindow.cpp
===================================================================
--- haiku/trunk/src/apps/debugger/gui/team_window/TeamWindow.cpp	2009-06-22 21:44:09 UTC (rev 31188)
+++ haiku/trunk/src/apps/debugger/gui/team_window/TeamWindow.cpp	2009-06-22 21:51:32 UTC (rev 31189)
@@ -24,7 +24,6 @@
 #include "SourceCode.h"
 #include "StackTrace.h"
 #include "StackTraceView.h"
-#include "TeamDebugModel.h"
 
 
 // #pragma mark - TeamWindow
@@ -58,6 +57,7 @@
 		name << " (" << team->ID() << ")";
 	SetTitle(name.String());
 
+	fDebugModel->AddListener(this);
 	team->AddListener(this);
 }
 
@@ -72,6 +72,7 @@
 		fSourceView->UnsetListener();
 
 	fDebugModel->GetTeam()->RemoveListener(this);
+	fDebugModel->RemoveListener(this);
 
 	if (fActiveSourceCode != NULL)
 		fActiveSourceCode->RemoveReference();
@@ -144,9 +145,20 @@
 			break;
 		}
 
+		case MSG_USER_BREAKPOINT_CHANGED:
+		{
+			uint64 address;
+			if (message->FindUInt64("address", &address) != B_OK)
+				break;
+
+			_HandleUserBreakpointChanged(address);
+			break;
+		}
+
 		case MSG_STACK_FRAME_SOURCE_CODE_CHANGED:
 		{
 			_HandleSourceCodeChanged();
+			break;
 		}
 
 		default:
@@ -178,6 +190,20 @@
 
 
 void
+TeamWindow::SetBreakpointRequested(target_addr_t address, bool enabled)
+{
+	fListener->SetBreakpointRequested(address, enabled);
+}
+
+
+void
+TeamWindow::ClearBreakpointRequested(target_addr_t address)
+{
+	fListener->ClearBreakpointRequested(address);
+}
+
+
+void
 TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
 {
 	BMessage message(MSG_THREAD_STATE_CHANGED);
@@ -204,7 +230,17 @@
 }
 
 
+
 void
+TeamWindow::UserBreakpointChanged(const TeamDebugModel::BreakpointEvent& event)
+{
+	BMessage message(MSG_USER_BREAKPOINT_CHANGED);
+	message.AddUInt64("address", event.GetBreakpoint()->Address());
+	PostMessage(&message);
+}
+

[... truncated: 736 lines follow ...]



More information about the Haiku-commits mailing list