[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