* 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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31189 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-06-22 21:51:32 +00:00
parent 7c439b2356
commit 6381d6cc4e
17 changed files with 1031 additions and 61 deletions
+1
View File
@@ -57,6 +57,7 @@ Application Debugger :
ThreadListView.cpp ThreadListView.cpp
# model # model
Breakpoint.cpp
DisassembledCode.cpp DisassembledCode.cpp
Image.cpp Image.cpp
ImageInfo.cpp ImageInfo.cpp
+4 -1
View File
@@ -12,11 +12,14 @@ enum {
MSG_THREAD_STEP_OVER = 'stov', MSG_THREAD_STEP_OVER = 'stov',
MSG_THREAD_STEP_INTO = 'stin', MSG_THREAD_STEP_INTO = 'stin',
MSG_THREAD_STEP_OUT = 'stou', MSG_THREAD_STEP_OUT = 'stou',
MSG_SET_BREAKPONT = 'sbrk',
MSG_CLEAR_BREAKPONT = 'cbrk',
MSG_THREAD_STATE_CHANGED = 'tsch', MSG_THREAD_STATE_CHANGED = 'tsch',
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc', MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc', 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'
}; };
+170
View File
@@ -5,10 +5,12 @@
#include "TeamDebugger.h" #include "TeamDebugger.h"
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <new> #include <new>
#include <Alert.h>
#include <Message.h> #include <Message.h>
#include <AutoLocker.h> #include <AutoLocker.h>
@@ -19,6 +21,7 @@
#include "DebuggerInterface.h" #include "DebuggerInterface.h"
#include "Jobs.h" #include "Jobs.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "Statement.h"
#include "TeamDebugModel.h" #include "TeamDebugModel.h"
@@ -198,6 +201,24 @@ TeamDebugger::MessageReceived(BMessage* message)
break; 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: case MSG_THREAD_STATE_CHANGED:
{ {
int32 threadID; int32 threadID;
@@ -267,6 +288,25 @@ TeamDebugger::ThreadActionRequested(TeamWindow* window, thread_id threadID,
} }
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 bool
TeamDebugger::TeamWindowQuitRequested(TeamWindow* window) TeamDebugger::TeamWindowQuitRequested(TeamWindow* window)
{ {
@@ -569,6 +609,73 @@ TeamDebugger::_SetThreadState(::Thread* thread, uint32 state,
} }
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 void
TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action) TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action)
{ {
@@ -619,6 +726,47 @@ printf("MSG_THREAD_STEP_OUT\n");
} }
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 void
TeamDebugger::_HandleThreadStateChanged(thread_id threadID) TeamDebugger::_HandleThreadStateChanged(thread_id threadID)
{ {
@@ -669,3 +817,25 @@ TeamDebugger::_HandleStackTraceChanged(thread_id threadID)
{ {
printf("TeamDebugger::_HandleStackTraceChanged()\n"); 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.
}
+13
View File
@@ -39,6 +39,9 @@ private:
TeamWindow* window, StackFrame* frame); TeamWindow* window, StackFrame* frame);
virtual void ThreadActionRequested(TeamWindow* window, virtual void ThreadActionRequested(TeamWindow* window,
thread_id threadID, uint32 action); 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); virtual bool TeamWindowQuitRequested(TeamWindow* window);
// JobListener // JobListener
@@ -88,13 +91,23 @@ private:
void _SetThreadState(::Thread* thread, uint32 state, void _SetThreadState(::Thread* thread, uint32 state,
CpuState* cpuState); CpuState* cpuState);
status_t _SetUserBreakpoint(target_addr_t address,
bool enabled);
void _HandleThreadAction(thread_id threadID, void _HandleThreadAction(thread_id threadID,
uint32 action); uint32 action);
void _HandleSetUserBreakpoint(target_addr_t address,
bool enabled);
void _HandleClearUserBreakpoint(
target_addr_t address);
void _HandleThreadStateChanged(thread_id threadID); void _HandleThreadStateChanged(thread_id threadID);
void _HandleCpuStateChanged(thread_id threadID); void _HandleCpuStateChanged(thread_id threadID);
void _HandleStackTraceChanged(thread_id threadID); void _HandleStackTraceChanged(thread_id threadID);
void _NotifyUser(const char* title,
const char* text,...);
private: private:
::Team* fTeam; ::Team* fTeam;
TeamDebugModel* fDebugModel; TeamDebugModel* fDebugModel;
+363 -40
View File
@@ -11,12 +11,15 @@
#include <stdio.h> #include <stdio.h>
#include <LayoutUtils.h> #include <LayoutUtils.h>
#include <Looper.h>
#include <Message.h>
#include <Polygon.h> #include <Polygon.h>
#include <ScrollBar.h> #include <ScrollBar.h>
#include <AutoLocker.h> #include <AutoLocker.h>
#include <ObjectList.h> #include <ObjectList.h>
#include "Breakpoint.h"
#include "SourceCode.h" #include "SourceCode.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "Statement.h" #include "Statement.h"
@@ -41,9 +44,10 @@ protected:
inline float TotalHeight() const; inline float TotalHeight() const;
int32 LineAtOffset(float yOffset) const;
void GetLineRange(BRect rect, int32& minLine, void GetLineRange(BRect rect, int32& minLine,
int32& maxLine); int32& maxLine) const;
BRect LineRect(uint32 line) const;
protected: protected:
SourceView* fSourceView; SourceView* fSourceView;
@@ -55,7 +59,8 @@ protected:
class SourceView::MarkerView : public BaseView { class SourceView::MarkerView : public BaseView {
public: public:
MarkerView(SourceView* sourceView, MarkerView(SourceView* sourceView,
FontInfo* fontInfo); TeamDebugModel* debugModel,
Listener* listener, FontInfo* fontInfo);
~MarkerView(); ~MarkerView();
virtual void SetSourceCode(SourceCode* sourceCode); virtual void SetSourceCode(SourceCode* sourceCode);
@@ -63,25 +68,52 @@ public:
void SetStackTrace(StackTrace* stackTrace); void SetStackTrace(StackTrace* stackTrace);
void SetStackFrame(StackFrame* stackFrame); void SetStackFrame(StackFrame* stackFrame);
void UserBreakpointChanged(target_addr_t address);
virtual BSize MinSize(); virtual BSize MinSize();
virtual BSize MaxSize(); virtual BSize MaxSize();
virtual void Draw(BRect updateRect); virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
private: private:
struct Marker; struct Marker;
struct InstructionPointerMarker; struct InstructionPointerMarker;
struct BreakpointMarker;
template<typename MarkerType> struct MarkerByLinePredicate;
typedef BObjectList<Marker> MarkerList; typedef BObjectList<Marker> MarkerList;
typedef BObjectList<BreakpointMarker> BreakpointMarkerList;
private: 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: private:
TeamDebugModel* fDebugModel;
Listener* fListener;
StackTrace* fStackTrace; StackTrace* fStackTrace;
StackFrame* fStackFrame; StackFrame* fStackFrame;
MarkerList fMarkers; MarkerList fIPMarkers;
bool fMarkersValid; BreakpointMarkerList fBreakpointMarkers;
bool fIPMarkersValid;
bool fBreakpointMarkersValid;
rgb_color fBreakpointOptionMarker;
}; };
@@ -115,6 +147,40 @@ private:
}; };
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 { class SourceView::TextView : public BaseView {
public: public:
TextView(SourceView* sourceView, TextView(SourceView* sourceView,
@@ -181,8 +247,21 @@ SourceView::BaseView::TotalHeight() const
} }
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 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; int32 lineHeight = (int32)fFontInfo->lineHeight;
minLine = (int32)rect.top / lineHeight; minLine = (int32)rect.top / lineHeight;
@@ -192,6 +271,14 @@ SourceView::BaseView::GetLineRange(BRect rect, int32& minLine, int32& maxLine)
} }
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 // #pragma mark - MarkerView::Marker
@@ -282,18 +369,52 @@ SourceView::MarkerView::InstructionPointerMarker::_DrawArrow(BView* view,
} }
// #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 // #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), BaseView("source marker view", sourceView, fontInfo),
fDebugModel(debugModel),
fListener(listener),
fStackTrace(NULL), fStackTrace(NULL),
fStackFrame(NULL), fStackFrame(NULL),
fMarkers(20, true), fIPMarkers(10, true),
fMarkersValid(false) 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 @@ SourceView::MarkerView::~MarkerView()
void void
SourceView::MarkerView::SetSourceCode(SourceCode* sourceCode) SourceView::MarkerView::SetSourceCode(SourceCode* sourceCode)
{ {
fMarkers.MakeEmpty(); _InvalidateIPMarkers();
fMarkersValid = false; _InvalidateBreakpointMarkers();
BaseView::SetSourceCode(sourceCode); BaseView::SetSourceCode(sourceCode);
} }
@@ -315,8 +436,7 @@ void
SourceView::MarkerView::SetStackTrace(StackTrace* stackTrace) SourceView::MarkerView::SetStackTrace(StackTrace* stackTrace)
{ {
fStackTrace = stackTrace; fStackTrace = stackTrace;
fMarkers.MakeEmpty(); _InvalidateIPMarkers();
fMarkersValid = false;
Invalidate(); Invalidate();
} }
@@ -325,8 +445,15 @@ void
SourceView::MarkerView::SetStackFrame(StackFrame* stackFrame) SourceView::MarkerView::SetStackFrame(StackFrame* stackFrame)
{ {
fStackFrame = stackFrame; fStackFrame = stackFrame;
fMarkers.MakeEmpty(); _InvalidateIPMarkers();
fMarkersValid = false; Invalidate();
}
void
SourceView::MarkerView::UserBreakpointChanged(target_addr_t address)
{
_InvalidateBreakpointMarkers();
Invalidate(); Invalidate();
} }
@@ -347,40 +474,112 @@ SourceView::MarkerView::MaxSize()
void void
SourceView::MarkerView::Draw(BRect updateRect) SourceView::MarkerView::Draw(BRect updateRect)
{ {
_UpdateMarkers(); if (fSourceCode == NULL)
if (fSourceCode == NULL || fMarkers.IsEmpty())
return; return;
// get the lines intersecting with the update rect // get the lines intersecting with the update rect
int32 minLine, maxLine; int32 minLine, maxLine;
GetLineRange(updateRect, minLine, maxLine); GetLineRange(updateRect, minLine, maxLine);
if (minLine > maxLine)
return;
// get the markers in that range
MarkerList markers;
_GetMarkers(minLine, maxLine, markers);
// draw the markers
float width = Bounds().Width(); float width = Bounds().Width();
// TODO: The markers should be sorted, so we don't need to iterate over
// all of them. int32 markerIndex = 0;
for (int32 i = 0; Marker* marker = fMarkers.ItemAt(i); i++) { for (int32 line = minLine; line <= maxLine; line++) {
int32 line = marker->Line(); bool drawBreakpointOptionMarker = true;
if (line < minLine || line > maxLine)
Marker* marker;
while ((marker = markers.ItemAt(markerIndex)) != NULL
&& marker->Line() == (uint32)line) {
marker->Draw(this, LineRect(line));
drawBreakpointOptionMarker = false;
markerIndex++;
}
if (!drawBreakpointOptionMarker)
continue; continue;
float y = (float)line * fFontInfo->lineHeight; Statement* statement = fSourceCode->StatementAtLine(line);
BRect rect(0, y, width, y + fFontInfo->lineHeight - 1); if (statement == NULL
marker->Draw(this, rect); || statement->StartSourceLocation().Line() != (uint32)line
} || !statement->BreakpointAllowed()) {
continue;
}
// TODO: Draw possible breakpoint marks! float y = ((float)line + 0.5f) * fFontInfo->lineHeight;
SetHighColor(fBreakpointOptionMarker);
FillEllipse(BPoint(width - 8, y), 2, 2);
}
} }
void void
SourceView::MarkerView::_UpdateMarkers() SourceView::MarkerView::MouseDown(BPoint where)
{ {
if (fMarkersValid) if (fSourceCode == NULL)
return; return;
fMarkers.MakeEmpty(); 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::_InvalidateIPMarkers()
{
fIPMarkersValid = false;
fIPMarkers.MakeEmpty();
}
void
SourceView::MarkerView::_InvalidateBreakpointMarkers()
{
fBreakpointMarkersValid = false;
fBreakpointMarkers.MakeEmpty();
}
void
SourceView::MarkerView::_UpdateIPMarkers()
{
if (fIPMarkersValid)
return;
fIPMarkers.MakeEmpty();
if (fSourceCode != NULL && fStackTrace != NULL) { if (fSourceCode != NULL && fStackTrace != NULL) {
for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i); for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i);
@@ -395,15 +594,132 @@ SourceView::MarkerView::_UpdateMarkers()
Marker* marker = new(std::nothrow) InstructionPointerMarker( Marker* marker = new(std::nothrow) InstructionPointerMarker(
line, i == 0, frame == fStackFrame); line, i == 0, frame == fStackFrame);
if (marker == NULL || !fMarkers.AddItem(marker)) { if (marker == NULL || !fIPMarkers.AddItem(marker)) {
delete marker; delete marker;
break; break;
} }
} }
}
// TODO: Filter duplicate IP markers (recursive functions)!
fMarkersValid = true; // sort by line
fIPMarkers.SortItems(&_CompareMarkers<Marker>);
// TODO: Filter duplicate IP markers (recursive functions)!
}
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;
} }
@@ -605,6 +921,13 @@ SourceView::SetSourceCode(SourceCode* sourceCode)
} }
void
SourceView::UserBreakpointChanged(target_addr_t address)
{
fMarkerView->UserBreakpointChanged(address);
}
bool bool
SourceView::ScrollToAddress(target_addr_t address) SourceView::ScrollToAddress(target_addr_t address)
{ {
@@ -622,7 +945,6 @@ SourceView::ScrollToAddress(target_addr_t address)
bool bool
SourceView::ScrollToLine(uint32 line) SourceView::ScrollToLine(uint32 line)
{ {
printf("SourceView::ScrollToLine(%lu)\n", line);
if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines()) if (fSourceCode == NULL || line >= (uint32)fSourceCode->CountLines())
return false; return false;
@@ -703,7 +1025,8 @@ SourceView::DoLayout()
void void
SourceView::_Init() SourceView::_Init()
{ {
AddChild(fMarkerView = new MarkerView(this, &fFontInfo)); AddChild(fMarkerView = new MarkerView(this, fDebugModel, fListener,
&fFontInfo));
AddChild(fTextView = new TextView(this, &fFontInfo)); AddChild(fTextView = new TextView(this, &fFontInfo));
} }
@@ -11,9 +11,11 @@
#include "ArchitectureTypes.h" #include "ArchitectureTypes.h"
class Breakpoint;
class SourceCode; class SourceCode;
class StackFrame; class StackFrame;
class StackTrace; class StackTrace;
class Statement;
class TeamDebugModel; class TeamDebugModel;
@@ -36,6 +38,8 @@ public:
void SetStackFrame(StackFrame* stackFrame); void SetStackFrame(StackFrame* stackFrame);
void SetSourceCode(SourceCode* sourceCode); void SetSourceCode(SourceCode* sourceCode);
void UserBreakpointChanged(target_addr_t address);
bool ScrollToAddress(target_addr_t address); bool ScrollToAddress(target_addr_t address);
bool ScrollToLine(uint32 line); bool ScrollToLine(uint32 line);
@@ -80,8 +84,10 @@ class SourceView::Listener {
public: public:
virtual ~Listener(); virtual ~Listener();
// virtual void StackFrameSelectionChanged( virtual void SetBreakpointRequested(
// StackFrame* frame) = 0; target_addr_t address, bool enabled) = 0;
virtual void ClearBreakpointRequested(
target_addr_t address) = 0;
}; };
@@ -24,7 +24,6 @@
#include "SourceCode.h" #include "SourceCode.h"
#include "StackTrace.h" #include "StackTrace.h"
#include "StackTraceView.h" #include "StackTraceView.h"
#include "TeamDebugModel.h"
// #pragma mark - TeamWindow // #pragma mark - TeamWindow
@@ -58,6 +57,7 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
name << " (" << team->ID() << ")"; name << " (" << team->ID() << ")";
SetTitle(name.String()); SetTitle(name.String());
fDebugModel->AddListener(this);
team->AddListener(this); team->AddListener(this);
} }
@@ -72,6 +72,7 @@ TeamWindow::~TeamWindow()
fSourceView->UnsetListener(); fSourceView->UnsetListener();
fDebugModel->GetTeam()->RemoveListener(this); fDebugModel->GetTeam()->RemoveListener(this);
fDebugModel->RemoveListener(this);
if (fActiveSourceCode != NULL) if (fActiveSourceCode != NULL)
fActiveSourceCode->RemoveReference(); fActiveSourceCode->RemoveReference();
@@ -144,9 +145,20 @@ TeamWindow::MessageReceived(BMessage* message)
break; 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: case MSG_STACK_FRAME_SOURCE_CODE_CHANGED:
{ {
_HandleSourceCodeChanged(); _HandleSourceCodeChanged();
break;
} }
default: default:
@@ -177,6 +189,20 @@ TeamWindow::StackFrameSelectionChanged(StackFrame* frame)
} }
void
TeamWindow::SetBreakpointRequested(target_addr_t address, bool enabled)
{
fListener->SetBreakpointRequested(address, enabled);
}
void
TeamWindow::ClearBreakpointRequested(target_addr_t address)
{
fListener->ClearBreakpointRequested(address);
}
void void
TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event) TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
{ {
@@ -204,6 +230,16 @@ TeamWindow::ThreadStackTraceChanged(const Team::ThreadEvent& event)
} }
void
TeamWindow::UserBreakpointChanged(const TeamDebugModel::BreakpointEvent& event)
{
BMessage message(MSG_USER_BREAKPOINT_CHANGED);
message.AddUInt64("address", event.GetBreakpoint()->Address());
PostMessage(&message);
}
void void
TeamWindow::StackFrameSourceCodeChanged(StackFrame* frame) TeamWindow::StackFrameSourceCodeChanged(StackFrame* frame)
{ {
@@ -520,6 +556,13 @@ TeamWindow::_HandleSourceCodeChanged()
} }
void
TeamWindow::_HandleUserBreakpointChanged(target_addr_t address)
{
fSourceView->UserBreakpointChanged(address);
}
// #pragma mark - Listener // #pragma mark - Listener
+17 -4
View File
@@ -12,6 +12,7 @@
#include "StackFrame.h" #include "StackFrame.h"
#include "StackTraceView.h" #include "StackTraceView.h"
#include "Team.h" #include "Team.h"
#include "TeamDebugModel.h"
#include "ThreadListView.h" #include "ThreadListView.h"
@@ -20,12 +21,11 @@ class BTabView;
class ImageListView; class ImageListView;
class RegisterView; class RegisterView;
class SourceCode; class SourceCode;
class TeamDebugModel;
class TeamWindow : public BWindow, private ThreadListView::Listener, class TeamWindow : public BWindow, private ThreadListView::Listener,
StackTraceView::Listener, SourceView::Listener, Team::Listener, StackTraceView::Listener, SourceView::Listener, Team::Listener,
StackFrame::Listener { private TeamDebugModel::Listener, StackFrame::Listener {
public: public:
class Listener; class Listener;
@@ -48,8 +48,10 @@ private:
// StackTraceView::Listener // StackTraceView::Listener
virtual void StackFrameSelectionChanged(StackFrame* frame); virtual void StackFrameSelectionChanged(StackFrame* frame);
// StackTraceView::Listener // SourceView::Listener
// nothing yet virtual void SetBreakpointRequested(target_addr_t address,
bool enabled);
virtual void ClearBreakpointRequested(target_addr_t address);
// Team::Listener // Team::Listener
virtual void ThreadStateChanged( virtual void ThreadStateChanged(
@@ -59,6 +61,11 @@ private:
virtual void ThreadStackTraceChanged( virtual void ThreadStackTraceChanged(
const Team::ThreadEvent& event); const Team::ThreadEvent& event);
// TeamDebugModel::Listener
virtual void UserBreakpointChanged(
const TeamDebugModel::BreakpointEvent&
event);
// StackFrame::Listener // StackFrame::Listener
virtual void StackFrameSourceCodeChanged(StackFrame* frame); virtual void StackFrameSourceCodeChanged(StackFrame* frame);
@@ -75,6 +82,8 @@ private:
void _HandleCpuStateChanged(thread_id threadID); void _HandleCpuStateChanged(thread_id threadID);
void _HandleStackTraceChanged(thread_id threadID); void _HandleStackTraceChanged(thread_id threadID);
void _HandleSourceCodeChanged(); void _HandleSourceCodeChanged();
void _HandleUserBreakpointChanged(
target_addr_t address);
private: private:
TeamDebugModel* fDebugModel; TeamDebugModel* fDebugModel;
@@ -105,6 +114,10 @@ public:
TeamWindow* window, StackFrame* frame) = 0; TeamWindow* window, StackFrame* frame) = 0;
virtual void ThreadActionRequested(TeamWindow* window, virtual void ThreadActionRequested(TeamWindow* window,
thread_id threadID, uint32 action) = 0; thread_id threadID, uint32 action) = 0;
virtual void SetBreakpointRequested(target_addr_t address,
bool enabled) = 0;
virtual void ClearBreakpointRequested(
target_addr_t address) = 0;
virtual bool TeamWindowQuitRequested(TeamWindow* window) = 0; virtual bool TeamWindowQuitRequested(TeamWindow* window) = 0;
}; };
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "Breakpoint.h"
// #pragma mark - BreakpointClient
BreakpointClient::~BreakpointClient()
{
}
// #pragma mark - Breakpoint
Breakpoint::Breakpoint(Image* image, target_addr_t address)
:
fAddress(address),
fImage(image),
fUserState(USER_BREAKPOINT_NONE),
fInstalled(false)
{
}
Breakpoint::~Breakpoint()
{
}
void
Breakpoint::SetUserState(user_breakpoint_state state)
{
fUserState = state;
}
void
Breakpoint::SetInstalled(bool installed)
{
fInstalled = installed;
}
bool
Breakpoint::ShouldBeInstalled() const
{
return fUserState == USER_BREAKPOINT_ENABLED || !fClients.IsEmpty();
}
bool
Breakpoint::IsUnused() const
{
return fUserState == USER_BREAKPOINT_NONE && fClients.IsEmpty();
}
bool
Breakpoint::AddClient(BreakpointClient* client)
{
return fClients.AddItem(client);
}
void
Breakpoint::RemoveClient(BreakpointClient* client)
{
fClients.RemoveItem(client);
}
/*static*/ int
Breakpoint::CompareBreakpoints(const Breakpoint* a, const Breakpoint* b)
{
if (a->Address() < b->Address())
return -1;
return a->Address() == b->Address() ? 0 : 1;
}
/*static*/ int
Breakpoint::CompareAddressBreakpoint(const target_addr_t* address,
const Breakpoint* breakpoint)
{
if (*address < breakpoint->Address())
return -1;
return *address == breakpoint->Address() ? 0 : 1;
}
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef BREAKPOINT_H
#define BREAKPOINT_H
#include <ObjectList.h>
#include <Referenceable.h>
#include "ArchitectureTypes.h"
enum user_breakpoint_state {
USER_BREAKPOINT_NONE,
USER_BREAKPOINT_ENABLED,
USER_BREAKPOINT_DISABLED
};
class Image;
class BreakpointClient {
public:
virtual ~BreakpointClient();
};
class Breakpoint : public Referenceable {
public:
Breakpoint(Image* image, target_addr_t address);
~Breakpoint();
Image* GetImage() const { return fImage; }
target_addr_t Address() const { return fAddress; }
user_breakpoint_state UserState() const { return fUserState; }
void SetUserState(user_breakpoint_state state);
bool IsInstalled() const { return fInstalled; }
void SetInstalled(bool installed);
bool ShouldBeInstalled() const;
bool IsUnused() const;
bool AddClient(BreakpointClient* client);
void RemoveClient(BreakpointClient* client);
static int CompareBreakpoints(const Breakpoint* a,
const Breakpoint* b);
static int CompareAddressBreakpoint(
const target_addr_t* address,
const Breakpoint* breakpoint);
private:
typedef BObjectList<BreakpointClient> ClientList;
private:
target_addr_t fAddress;
Image* fImage;
ClientList fClients;
user_breakpoint_state fUserState;
bool fInstalled;
};
#endif // BREAKPOINT_H
+15 -2
View File
@@ -86,6 +86,20 @@ DisassembledCode::StatementAtAddress(target_addr_t address) const
} }
TargetAddressRange
DisassembledCode::StatementAddressRange() const
{
if (fStatements.IsEmpty())
return TargetAddressRange();
ContiguousStatement* first = fStatements.ItemAt(0);
ContiguousStatement* last
= fStatements.ItemAt(fStatements.CountItems() - 1);
return TargetAddressRange(first->AddressRange().Start(),
last->AddressRange().End());
}
bool bool
DisassembledCode::AddCommentLine(const BString& line) DisassembledCode::AddCommentLine(const BString& line)
{ {
@@ -101,8 +115,7 @@ DisassembledCode::AddInstructionLine(const BString& line, target_addr_t address,
ContiguousStatement* statement = new(std::nothrow) ContiguousStatement( ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
SourceLocation(lineIndex), SourceLocation(lineIndex + 1), SourceLocation(lineIndex), SourceLocation(lineIndex + 1),
TargetAddressRange(address, size)); TargetAddressRange(address, size), breakpointAllowed);
// TODO: breakpointAllowed!
if (statement == NULL) if (statement == NULL)
return false; return false;
@@ -27,6 +27,8 @@ public:
virtual Statement* StatementAtLine(int32 index) const; virtual Statement* StatementAtLine(int32 index) const;
virtual Statement* StatementAtAddress(target_addr_t address) const; virtual Statement* StatementAtAddress(target_addr_t address) const;
virtual TargetAddressRange StatementAddressRange() const;
public: public:
bool AddCommentLine(const BString& line); bool AddCommentLine(const BString& line);
bool AddInstructionLine(const BString& line, bool AddInstructionLine(const BString& line,
+3 -1
View File
@@ -7,7 +7,7 @@
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h" #include "TargetAddressRange.h"
class Statement; class Statement;
@@ -25,6 +25,8 @@ public:
virtual Statement* StatementAtLine(int32 index) const = 0; virtual Statement* StatementAtLine(int32 index) const = 0;
virtual Statement* StatementAtAddress(target_addr_t address) virtual Statement* StatementAtAddress(target_addr_t address)
const = 0; const = 0;
virtual TargetAddressRange StatementAddressRange() const = 0;
}; };
+13 -4
View File
@@ -18,10 +18,11 @@ Statement::~Statement()
AbstractStatement::AbstractStatement(const SourceLocation& start, AbstractStatement::AbstractStatement(const SourceLocation& start,
const SourceLocation& end) const SourceLocation& end, bool breakpointAllowed)
: :
fStart(start), fStart(start),
fEnd(end) fEnd(end),
fBreakpointAllowed(breakpointAllowed)
{ {
} }
@@ -40,13 +41,21 @@ AbstractStatement::EndSourceLocation() const
} }
bool
AbstractStatement::BreakpointAllowed() const
{
return fBreakpointAllowed;
}
// #pragma mark - ContiguousStatement // #pragma mark - ContiguousStatement
ContiguousStatement::ContiguousStatement(const SourceLocation& start, ContiguousStatement::ContiguousStatement(const SourceLocation& start,
const SourceLocation& end, const TargetAddressRange& range) const SourceLocation& end, const TargetAddressRange& range,
bool breakpointAllowed)
: :
AbstractStatement(start, end), AbstractStatement(start, end, breakpointAllowed),
fRange(range) fRange(range)
{ {
} }
+9 -2
View File
@@ -26,20 +26,26 @@ public:
virtual bool ContainsAddress(target_addr_t address) virtual bool ContainsAddress(target_addr_t address)
const = 0; const = 0;
virtual bool BreakpointAllowed() const = 0;
}; };
class AbstractStatement : public Statement { class AbstractStatement : public Statement {
public: public:
AbstractStatement(const SourceLocation& start, AbstractStatement(const SourceLocation& start,
const SourceLocation& end); const SourceLocation& end,
bool breakpointAllowed);
virtual SourceLocation StartSourceLocation() const; virtual SourceLocation StartSourceLocation() const;
virtual SourceLocation EndSourceLocation() const; virtual SourceLocation EndSourceLocation() const;
virtual bool BreakpointAllowed() const;
protected: protected:
SourceLocation fStart; SourceLocation fStart;
SourceLocation fEnd; SourceLocation fEnd;
bool fBreakpointAllowed;
}; };
@@ -47,7 +53,8 @@ class ContiguousStatement : public AbstractStatement {
public: public:
ContiguousStatement(const SourceLocation& start, ContiguousStatement(const SourceLocation& start,
const SourceLocation& end, const SourceLocation& end,
const TargetAddressRange& range); const TargetAddressRange& range,
bool breakpointAllowed);
const TargetAddressRange& AddressRange() const const TargetAddressRange& AddressRange() const
{ return fRange; } { return fRange; }
+152
View File
@@ -9,6 +9,30 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include "Breakpoint.h"
// #pragma mark - BreakpointByAddressPredicate
struct TeamDebugModel::BreakpointByAddressPredicate
: UnaryPredicate<Breakpoint> {
BreakpointByAddressPredicate(target_addr_t address)
:
fAddress(address)
{
}
virtual int operator()(const Breakpoint* breakpoint) const
{
return -Breakpoint::CompareAddressBreakpoint(&fAddress, breakpoint);
}
private:
target_addr_t fAddress;
};
// #pragma mark - TeamDebugModel // #pragma mark - TeamDebugModel
@@ -25,6 +49,8 @@ TeamDebugModel::TeamDebugModel(Team* team, DebuggerInterface* debuggerInterface,
TeamDebugModel::~TeamDebugModel() TeamDebugModel::~TeamDebugModel()
{ {
for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++)
breakpoint->RemoveReference();
} }
@@ -35,6 +61,66 @@ TeamDebugModel::Init()
} }
bool
TeamDebugModel::AddBreakpoint(Breakpoint* breakpoint)
{
if (fBreakpoints.BinaryInsert(breakpoint, &Breakpoint::CompareBreakpoints))
return true;
breakpoint->RemoveReference();
return false;
}
void
TeamDebugModel::RemoveBreakpoint(Breakpoint* breakpoint)
{
int32 index = fBreakpoints.BinarySearchIndex(*breakpoint,
&Breakpoint::CompareBreakpoints);
if (index < 0)
return;
fBreakpoints.RemoveItemAt(index);
breakpoint->RemoveReference();
}
int32
TeamDebugModel::CountBreakpoints() const
{
return fBreakpoints.CountItems();
}
Breakpoint*
TeamDebugModel::BreakpointAt(int32 index) const
{
return fBreakpoints.ItemAt(index);
}
Breakpoint*
TeamDebugModel::BreakpointAtAddress(target_addr_t address) const
{
return fBreakpoints.BinarySearchByKey(address,
&Breakpoint::CompareAddressBreakpoint);
}
void
TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range,
BObjectList<Breakpoint>& breakpoints) const
{
int32 index = fBreakpoints.FindBinaryInsertionIndex(
BreakpointByAddressPredicate(range.Start()));
for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) {
if (breakpoint->Address() > range.End())
break;
breakpoints.AddItem(breakpoint);
}
}
void void
TeamDebugModel::AddListener(Listener* listener) TeamDebugModel::AddListener(Listener* listener)
{ {
@@ -51,6 +137,39 @@ TeamDebugModel::RemoveListener(Listener* listener)
} }
void
TeamDebugModel::NotifyUserBreakpointChanged(Breakpoint* breakpoint)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->UserBreakpointChanged(BreakpointEvent(
TEAM_DEBUG_MODEL_EVENT_USER_BREAKPOINT_CHANGED, this, breakpoint));
}
}
void
TeamDebugModel::_NotifyBreakpointAdded(Breakpoint* breakpoint)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->BreakpointAdded(BreakpointEvent(
TEAM_DEBUG_MODEL_EVENT_BREAKPOINT_ADDED, this, breakpoint));
}
}
void
TeamDebugModel::_NotifyBreakpointRemoved(Breakpoint* breakpoint)
{
for (ListenerList::Iterator it = fListeners.GetIterator();
Listener* listener = it.Next();) {
listener->BreakpointRemoved(BreakpointEvent(
TEAM_DEBUG_MODEL_EVENT_BREAKPOINT_REMOVED, this, breakpoint));
}
}
// #pragma mark - Event // #pragma mark - Event
@@ -62,9 +181,42 @@ TeamDebugModel::Event::Event(uint32 type, TeamDebugModel* model)
} }
// #pragma mark - ThreadEvent
TeamDebugModel::BreakpointEvent::BreakpointEvent(uint32 type,
TeamDebugModel* model, Breakpoint* breakpoint)
:
Event(type, model),
fBreakpoint(breakpoint)
{
}
// #pragma mark - Listener // #pragma mark - Listener
TeamDebugModel::Listener::~Listener() TeamDebugModel::Listener::~Listener()
{ {
} }
void
TeamDebugModel::Listener::BreakpointAdded(
const TeamDebugModel::BreakpointEvent& event)
{
}
void
TeamDebugModel::Listener::BreakpointRemoved(
const TeamDebugModel::BreakpointEvent& event)
{
}
void
TeamDebugModel::Listener::UserBreakpointChanged(
const TeamDebugModel::BreakpointEvent& event)
{
}
+56 -4
View File
@@ -5,22 +5,30 @@
#ifndef TEAM_DEBUG_MODEL_H #ifndef TEAM_DEBUG_MODEL_H
#define TEAM_DEBUG_MODEL_H #define TEAM_DEBUG_MODEL_H
#include <ObjectList.h>
#include "Breakpoint.h"
#include "TargetAddressRange.h"
#include "Team.h" #include "Team.h"
// team debug model event types // team debug model event types
//enum { enum {
// TEAM_EVENT_THREAD_ADDED TEAM_DEBUG_MODEL_EVENT_BREAKPOINT_ADDED,
//}; TEAM_DEBUG_MODEL_EVENT_BREAKPOINT_REMOVED,
TEAM_DEBUG_MODEL_EVENT_USER_BREAKPOINT_CHANGED
};
class Architecture; class Architecture;
class Breakpoint;
class DebuggerInterface; class DebuggerInterface;
class TeamDebugModel { class TeamDebugModel {
public: public:
class Event; class Event;
class BreakpointEvent;
class Listener; class Listener;
public: public:
@@ -40,16 +48,40 @@ public:
Architecture* GetArchitecture() const Architecture* GetArchitecture() const
{ return fArchitecture; } { return fArchitecture; }
bool AddBreakpoint(Breakpoint* breakpoint);
// takes over reference (also on error)
void RemoveBreakpoint(Breakpoint* breakpoint);
// releases its own reference
int32 CountBreakpoints() const;
Breakpoint* BreakpointAt(int32 index) const;
Breakpoint* BreakpointAtAddress(
target_addr_t address) const;
void GetBreakpointsInAddressRange(
TargetAddressRange range,
BObjectList<Breakpoint>& breakpoints) const;
void AddListener(Listener* listener); void AddListener(Listener* listener);
void RemoveListener(Listener* listener); void RemoveListener(Listener* listener);
void NotifyUserBreakpointChanged(
Breakpoint* breakpoint);
private: private:
struct BreakpointByAddressPredicate;
typedef BObjectList<Breakpoint> BreakpointList;
typedef DoublyLinkedList<Listener> ListenerList; typedef DoublyLinkedList<Listener> ListenerList;
private:
void _NotifyBreakpointAdded(Breakpoint* breakpoint);
void _NotifyBreakpointRemoved(
Breakpoint* breakpoint);
private: private:
Team* fTeam; Team* fTeam;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture; Architecture* fArchitecture;
BreakpointList fBreakpoints;
ListenerList fListeners; ListenerList fListeners;
}; };
@@ -67,13 +99,33 @@ protected:
}; };
class TeamDebugModel::BreakpointEvent : public Event {
public:
BreakpointEvent(uint32 type,
TeamDebugModel* model,
Breakpoint* breakpoint);
Breakpoint* GetBreakpoint() const { return fBreakpoint; }
protected:
Breakpoint* fBreakpoint;
};
class TeamDebugModel::Listener class TeamDebugModel::Listener
: public DoublyLinkedListLinkImpl<TeamDebugModel::Listener> { : public DoublyLinkedListLinkImpl<TeamDebugModel::Listener> {
public: public:
virtual ~Listener(); virtual ~Listener();
// virtual void ThreadAdded(const Team::ThreadEvent& event); virtual void BreakpointAdded(
const TeamDebugModel::BreakpointEvent&
event);
virtual void BreakpointRemoved(
const TeamDebugModel::BreakpointEvent&
event);
virtual void UserBreakpointChanged(
const TeamDebugModel::BreakpointEvent&
event);
}; };