diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index fbe38d7eba..1f3e3c0a81 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -536,11 +536,15 @@ TeamDebugger::MessageReceived(BMessage* message) case MSG_THREAD_STEP_OUT: { int32 threadID; + target_addr_t address; if (message->FindInt32("thread", &threadID) != B_OK) break; + if (message->FindUInt64("address", &address) != B_OK) + address = 0; + if (ThreadHandler* handler = _GetThreadHandler(threadID)) { - handler->HandleThreadAction(message->what); + handler->HandleThreadAction(message->what, address); handler->ReleaseReference(); } break; @@ -801,10 +805,11 @@ TeamDebugger::ValueNodeValueRequested(CpuState* cpuState, void TeamDebugger::ThreadActionRequested(thread_id threadID, - uint32 action) + uint32 action, target_addr_t address) { BMessage message(action); message.AddInt32("thread", threadID); + message.AddUInt64("address", address); PostMessage(&message); } diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 700c01a430..6b5e33b010 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -60,7 +60,7 @@ private: ValueNodeContainer* container, ValueNode* valueNode); virtual void ThreadActionRequested(thread_id threadID, - uint32 action); + uint32 action, target_addr_t address); virtual void SetBreakpointRequested(target_addr_t address, bool enabled); virtual void SetBreakpointEnabledRequested( diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index 5b79d148a5..d5fe3a9d1c 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -37,7 +37,8 @@ enum { STEP_NONE, STEP_OVER, STEP_INTO, - STEP_OUT + STEP_OUT, + STEP_UNTIL }; @@ -124,7 +125,7 @@ ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* event) // check whether this is a temporary breakpoint we're waiting for if (fBreakpointAddress != 0 && instructionPointer == fBreakpointAddress && fStepMode != STEP_NONE) { - if (_HandleBreakpointHitStep(cpuState)) + if (fStepMode != STEP_UNTIL && _HandleBreakpointHitStep(cpuState)) return true; } else { // Might be a user breakpoint, but could as well be a temporary @@ -199,7 +200,7 @@ ThreadHandler::HandleExceptionOccurred(ExceptionOccurredEvent* event) void -ThreadHandler::HandleThreadAction(uint32 action) +ThreadHandler::HandleThreadAction(uint32 action, target_addr_t address) { AutoLocker locker(fThread->GetTeam()); @@ -230,7 +231,9 @@ ThreadHandler::HandleThreadAction(uint32 action) switch (action) { case MSG_THREAD_RUN: - fStepMode = STEP_NONE; + fStepMode = address != 0 ? STEP_UNTIL : STEP_NONE; + if (address != 0) + _InstallTemporaryBreakpoint(address); _RunThread(0); return; case MSG_THREAD_STOP: diff --git a/src/apps/debugger/controllers/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h index 4fd078565a..e1c6b1c322 100644 --- a/src/apps/debugger/controllers/ThreadHandler.h +++ b/src/apps/debugger/controllers/ThreadHandler.h @@ -53,7 +53,8 @@ public: bool HandleExceptionOccurred( ExceptionOccurredEvent* event); - void HandleThreadAction(uint32 action); + void HandleThreadAction(uint32 action, + target_addr_t address); void HandleThreadStateChanged(); void HandleCpuStateChanged(); diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 9ed4657440..96d1926ab8 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -90,7 +90,8 @@ public: ValueNodeContainer* container, ValueNode* valueNode) = 0; virtual void ThreadActionRequested(thread_id threadID, - uint32 action) = 0; + uint32 action, + target_addr_t address = 0) = 0; virtual void SetBreakpointRequested(target_addr_t address, bool enabled) = 0; diff --git a/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp b/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp index fad29e172c..c43e084936 100644 --- a/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/SourceView.cpp @@ -16,9 +16,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -27,6 +29,7 @@ #include #include +#include "AutoDeleter.h" #include "Breakpoint.h" #include "DisassembledCode.h" #include "Function.h" @@ -918,18 +921,11 @@ SourceView::MarkerView::MouseDown(BPoint where) return; int32 line = LineAtOffset(where.y); - if (line < 0) - return; - AutoLocker locker(fTeam); Statement* statement; - if (fTeam->GetStatementAtSourceLocation(fSourceCode, - SourceLocation(line), statement) != B_OK) { + if (!fSourceView->GetStatementForLine(line, statement)) return; - } BReference statementReference(statement, true); - if (statement->StartSourceLocation().Line() != line) - return; int32 modifiers; if (Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK) @@ -1193,7 +1189,15 @@ SourceView::TextView::MessageReceived(BMessage* message) void SourceView::TextView::MouseDown(BPoint where) { - if (fSourceCode != NULL) { + if (fSourceCode == NULL) + return; + + int32 buttons; + if (Looper()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) + buttons = B_PRIMARY_MOUSE_BUTTON; + + + if (buttons == B_PRIMARY_MOUSE_BUTTON) { if (!IsFocus()) MakeFocus(true); fTrackState = kTracking; @@ -1233,6 +1237,57 @@ SourceView::TextView::MouseDown(BPoint where) Invalidate(); SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); } + } else if (buttons == B_SECONDARY_MOUSE_BUTTON) { + int32 line = LineAtOffset(where.y); + if (line < 0) + return; + + ::Team* team = fSourceView->fTeam; + AutoLocker locker(team); + ::Thread* activeThread = fSourceView->fActiveThread; + + if (activeThread == NULL) + return; + else if (activeThread->State() != THREAD_STATE_STOPPED) + return; + + Statement* statement; + if (!fSourceView->GetStatementForLine(line, statement)) + return; + BReference statementReference(statement, true); + + BPopUpMenu* menu = new(std::nothrow) BPopUpMenu(""); + if (menu == NULL) + return; + ObjectDeleter menuDeleter(menu); + + BMessage* message = new(std::nothrow) BMessage(MSG_THREAD_RUN); + if (message == NULL) + return; + ObjectDeleter messageDeleter(message); + + message->AddUInt64("address", statement->CoveringAddressRange() + .Start()); + BMenuItem* item = new(std::nothrow) BMenuItem("Run to cursor", + message); + if (item == NULL) + return; + ObjectDeleter itemDeleter(item); + messageDeleter.Detach(); + + if (!menu->AddItem(item)) + return; + + itemDeleter.Detach(); + messageDeleter.Detach(); + menuDeleter.Detach(); + + BPoint screenWhere(where); + ConvertToScreen(&screenWhere); + menu->SetTargetForItems(fSourceView); + BRect mouseRect(screenWhere, screenWhere); + mouseRect.InsetBy(-4.0, -4.0); + menu->Go(screenWhere, true, false, mouseRect, true); } } @@ -1695,6 +1750,7 @@ SourceView::SourceView(Team* team, Listener* listener) : BView("source view", 0), fTeam(team), + fActiveThread(NULL), fStackTrace(NULL), fStackFrame(NULL), fSourceCode(NULL), @@ -1713,7 +1769,7 @@ SourceView::SourceView(Team* team, Listener* listener) SourceView::~SourceView() { SetStackFrame(NULL); - SetStackTrace(NULL); + SetStackTrace(NULL, NULL); SetSourceCode(NULL); } @@ -1734,6 +1790,27 @@ SourceView::Create(Team* team, Listener* listener) } +void +SourceView::MessageReceived(BMessage* message) +{ + switch(message->what) { + case MSG_THREAD_RUN: + { + target_addr_t address; + if (message->FindUInt64("address", &address) != B_OK) + break; + fListener->ThreadActionRequested(fActiveThread, message->what, + address); + break; + } + + default: + BView::MessageReceived(message); + break; + } +} + + void SourceView::UnsetListener() { @@ -1742,13 +1819,21 @@ SourceView::UnsetListener() void -SourceView::SetStackTrace(StackTrace* stackTrace) +SourceView::SetStackTrace(StackTrace* stackTrace, Thread* activeThread) { TRACE_GUI("SourceView::SetStackTrace(%p)\n", stackTrace); if (stackTrace == fStackTrace) return; + if (fActiveThread != NULL) + fActiveThread->ReleaseReference(); + + fActiveThread = activeThread; + + if (fActiveThread != NULL) + fActiveThread->AcquireReference(); + if (fStackTrace != NULL) { fMarkerManager->SetStackTrace(NULL); fMarkerView->SetStackTrace(NULL); @@ -1949,6 +2034,29 @@ SourceView::DoLayout() } +bool +SourceView::GetStatementForLine(int32 line, Statement*& _statement) +{ + if (line < 0) + return false; + + AutoLocker locker(fTeam); + Statement* statement; + if (fTeam->GetStatementAtSourceLocation(fSourceCode, SourceLocation(line), + statement) != B_OK) { + return false; + } + BReference statementReference(statement, true); + if (statement->StartSourceLocation().Line() != line) + return false; + + _statement = statement; + statementReference.Detach(); + + return true; +} + + void SourceView::_Init() { diff --git a/src/apps/debugger/user_interface/gui/team_window/SourceView.h b/src/apps/debugger/user_interface/gui/team_window/SourceView.h index bf12eefb2d..9acd586356 100644 --- a/src/apps/debugger/user_interface/gui/team_window/SourceView.h +++ b/src/apps/debugger/user_interface/gui/team_window/SourceView.h @@ -18,6 +18,7 @@ class StackFrame; class StackTrace; class Statement; class Team; +class Thread; class UserBreakpoint; @@ -32,9 +33,12 @@ public: static SourceView* Create(Team* team, Listener* listener); // throws + virtual void MessageReceived(BMessage* message); + void UnsetListener(); - void SetStackTrace(StackTrace* stackTrace); + void SetStackTrace(StackTrace* stackTrace, + Thread* thread); void SetStackFrame(StackFrame* stackFrame); void SetSourceCode(SourceCode* sourceCode); @@ -65,6 +69,10 @@ private: float lineHeight; }; +protected: + bool GetStatementForLine(int32 line, + Statement*& _statement); + private: void _Init(); void _UpdateScrollBars(); @@ -72,6 +80,7 @@ private: private: Team* fTeam; + Thread* fActiveThread; StackTrace* fStackTrace; StackFrame* fStackFrame; SourceCode* fSourceCode; @@ -91,6 +100,8 @@ public: target_addr_t address, bool enabled) = 0; virtual void ClearBreakpointRequested( target_addr_t address) = 0; + virtual void ThreadActionRequested(Thread* thread, + uint32 action, target_addr_t address) = 0; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 0f2e594e12..e7f52a7055 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -645,6 +645,14 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address) } +void +TeamWindow::ThreadActionRequested(::Thread* thread, uint32 action, + target_addr_t address) +{ + fListener->ThreadActionRequested(thread->ID(), action, address); +} + + void TeamWindow::WatchpointSelectionChanged(Watchpoint* watchpoint) { @@ -953,7 +961,7 @@ TeamWindow::_SetActiveStackTrace(StackTrace* stackTrace) fActiveStackTrace->AcquireReference(); fStackTraceView->SetStackTrace(fActiveStackTrace); - fSourceView->SetStackTrace(fActiveStackTrace); + fSourceView->SetStackTrace(fActiveStackTrace, fActiveThread); if (fActiveStackTrace != NULL) _SetActiveStackFrame(fActiveStackTrace->FrameAt(0)); diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index 2e8e8d487f..4abf4d8a05 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -107,7 +107,11 @@ private: // SourceView::Listener virtual void SetBreakpointRequested(target_addr_t address, bool enabled); - virtual void ClearBreakpointRequested(target_addr_t address); + virtual void ClearBreakpointRequested( + target_addr_t address); + virtual void ThreadActionRequested(::Thread* thread, + uint32 action, target_addr_t address); + // VariablesView::Listener virtual void ValueNodeValueRequested(CpuState* cpuState,