* 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:
@@ -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
|
||||||
|
|||||||
@@ -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'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user