[haiku-commits] haiku: hrev48170 - in src/apps/debugger: user_interface/gui/team_window controllers settings model jobs

  • From: anevilyak@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 30 Oct 2014 21:54:53 +0100 (CET)

hrev48170 adds 6 changesets to branch 'master'
old head: a13654e0894836c7e215d2a64c5c76072485832d
new head: a5ce4678c054489520b8e2a7c0910da48a5d1521
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=a5ce467+%5Ea13654e

----------------------------------------------------------------------------

854b341: Debugger: Minor tweak to expression window.
  
  - If the expression result is an integer, display it in both hex and decimal
    format.

65a10b5: Debugger: Add condition expression member to UserBreakpoint.
  
  - UserBreakpoint and its corresponding settings classes now
    store/recall an optional condition expression.

3dfdc98: Debugger: Show breakpoint conditions in list view.
  
  - Adjust breakpoint table and model to also show breakpoint conditions,
    if set.

942226c: Debugger: Add UI for configuring breakpoint conditions.
  
  General:
  - Add message codes for requesting breakpoint configuration.
  
  UserInterfaceListener/TeamDebugger:
  - Add/implement hooks for requesting breakpoint condition changes.
  
  BreakpointsView:
  - Add button to request editing the currently selected breakpoint's
    condition.
  
  TeamWindow:
  - Handle request to show breakpoint edit window.
  
  BreakpointEditWindow:
  - Implement simple radio-based UI for modifying the current breakpoint's
    condition.
  
  Still missing: Actually handling/evaluating the breakpoint conditions in
  the ThreadHandler when the breakpoint is hit.

43060a5: Debugger: Minor tweak to ExpressionEvaluationJob.
  
  - ExpressionEvaluationJob now stores the final result value,
    and provides an accessor to it.

a5ce467: Debugger: Implement conditional breakpoints.
  
  ThreadHandler:
  - When a breakpoint event is hit, we now check if there is an
    associated UserBreakpoint with a condition attached. If so,
    we schedule an evaluation request, and only stop the thread if
    that one evaluates to true (or if evaluation fails in some way).
  
  This implements #9713.

                                         [ Rene Gollent <rene@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

22 files changed, 601 insertions(+), 26 deletions(-)
src/apps/debugger/Jamfile                        |   1 +
src/apps/debugger/MessageCodes.h                 |   4 +
src/apps/debugger/controllers/TeamDebugger.cpp   |  71 +++++++-
src/apps/debugger/controllers/TeamDebugger.h     |   5 +
src/apps/debugger/controllers/ThreadHandler.cpp  | 168 ++++++++++++++++++-
src/apps/debugger/controllers/ThreadHandler.h    |  11 ++
.../debugger/jobs/ExpressionEvaluationJob.cpp    |  14 +-
src/apps/debugger/jobs/Jobs.h                    |   3 +
src/apps/debugger/model/UserBreakpoint.cpp       |  12 +-
src/apps/debugger/model/UserBreakpoint.h         |  11 +-
src/apps/debugger/settings/BreakpointSetting.cpp |  20 ++-
src/apps/debugger/settings/BreakpointSetting.h   |   9 +-
src/apps/debugger/settings/TeamSettings.cpp      |   3 +-
src/apps/debugger/user_interface/UserInterface.h |   5 +
.../gui/team_window/BreakpointEditWindow.cpp     | 144 ++++++++++++++++
.../gui/team_window/BreakpointEditWindow.h       |  61 +++++++
.../gui/team_window/BreakpointListView.cpp       |  10 +-
.../gui/team_window/BreakpointsView.cpp          |  24 +++
.../gui/team_window/BreakpointsView.h            |   1 +
.../team_window/ExpressionEvaluationWindow.cpp   |  13 +-
.../gui/team_window/TeamWindow.cpp               |  35 +++-
.../user_interface/gui/team_window/TeamWindow.h  |   2 +

############################################################################

Commit:      854b341612a905567ed990e5752f66d5b5a158ce
URL:         http://cgit.haiku-os.org/haiku/commit/?id=854b341
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Thu Oct 30 15:28:23 2014 UTC

Debugger: Minor tweak to expression window.

- If the expression result is an integer, display it in both hex and decimal
  format.

----------------------------------------------------------------------------

diff --git 
a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp
 
b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp
index 8236450..b9724e8 100644
--- 
a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp
+++ 
b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp
@@ -254,9 +254,16 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* 
message)
                        }
 
                        BString outputText;
-                       if (value != NULL)
-                               value->ToString(outputText);
-                       else {
+                       if (value != NULL) {
+                               BVariant variantValue;
+                               value->ToVariant(variantValue);
+                               if 
(variantValue.TypeIsInteger(variantValue.Type())) {
+                                       value->ToString(outputText);
+                                       outputText.SetToFormat("%#" B_PRIx64 " 
(%s)",
+                                               variantValue.ToUInt64(), 
outputText.String());
+                               } else
+                                       value->ToString(outputText);
+                       } else {
                                status_t result;
                                if (message->FindInt32("result", &result) != 
B_OK)
                                        result = B_ERROR;

############################################################################

Commit:      65a10b5000e34eab3c066965642b3fec95781c16
URL:         http://cgit.haiku-os.org/haiku/commit/?id=65a10b5
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Thu Oct 30 14:12:21 2014 UTC

Debugger: Add condition expression member to UserBreakpoint.

- UserBreakpoint and its corresponding settings classes now
  store/recall an optional condition expression.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp 
b/src/apps/debugger/controllers/TeamDebugger.cpp
index 133a395..620eca5 100644
--- a/src/apps/debugger/controllers/TeamDebugger.cpp
+++ b/src/apps/debugger/controllers/TeamDebugger.cpp
@@ -2122,6 +2122,7 @@ TeamDebugger::_LoadSettings()
                BReference<UserBreakpoint> breakpointReference(breakpoint, 
true);
 
                breakpoint->SetHidden(breakpointSetting->IsHidden());
+               breakpoint->SetCondition(breakpointSetting->Condition());
 
                // install it
                fBreakpointManager->InstallUserBreakpoint(breakpoint,
diff --git a/src/apps/debugger/model/UserBreakpoint.cpp 
b/src/apps/debugger/model/UserBreakpoint.cpp
index 996eb6e..c2c288e 100644
--- a/src/apps/debugger/model/UserBreakpoint.cpp
+++ b/src/apps/debugger/model/UserBreakpoint.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -101,7 +101,8 @@ UserBreakpoint::UserBreakpoint(const 
UserBreakpointLocation& location)
        fLocation(location),
        fValid(false),
        fEnabled(false),
-       fHidden(false)
+       fHidden(false),
+       fConditionExpression()
 {
 }
 
@@ -169,3 +170,10 @@ UserBreakpoint::SetHidden(bool hidden)
 {
        fHidden = hidden;
 }
+
+
+void
+UserBreakpoint::SetCondition(const BString& conditionExpression)
+{
+       fConditionExpression = conditionExpression;
+}
diff --git a/src/apps/debugger/model/UserBreakpoint.h 
b/src/apps/debugger/model/UserBreakpoint.h
index cf4cfe3..84969b6 100644
--- a/src/apps/debugger/model/UserBreakpoint.h
+++ b/src/apps/debugger/model/UserBreakpoint.h
@@ -1,6 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef USER_BREAKPOINT_H
@@ -12,6 +12,7 @@
 #include <util/DoublyLinkedList.h>
 
 #include "SourceLocation.h"
+#include "String.h"
 #include "Types.h"
 
 
@@ -104,6 +105,13 @@ public:
                        bool                            IsHidden() const        
{ return fHidden; }
                        void                            SetHidden(bool hidden);
 
+                       bool                            HasCondition() const
+                                                                       { 
return !fConditionExpression.IsEmpty(); }
+                       const BString&          Condition() const
+                                                                       { 
return fConditionExpression; }
+                       void                            SetCondition(
+                                                                       const 
BString& conditionExpression);
+
 private:
                        typedef BObjectList<UserBreakpointInstance> 
InstanceList;
 
@@ -113,6 +121,7 @@ private:
                        bool                            fValid;
                        bool                            fEnabled;
                        bool                            fHidden;
+                       BString                         fConditionExpression;
 };
 
 
diff --git a/src/apps/debugger/settings/BreakpointSetting.cpp 
b/src/apps/debugger/settings/BreakpointSetting.cpp
index 03ade77..6ad3db1 100644
--- a/src/apps/debugger/settings/BreakpointSetting.cpp
+++ b/src/apps/debugger/settings/BreakpointSetting.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 
@@ -22,7 +22,8 @@ BreakpointSetting::BreakpointSetting()
        fSourceLocation(),
        fRelativeAddress(0),
        fEnabled(false),
-       fHidden(false)
+       fHidden(false),
+       fConditionExpression()
 {
 }
 
@@ -34,7 +35,8 @@ BreakpointSetting::BreakpointSetting(const BreakpointSetting& 
other)
        fSourceLocation(other.fSourceLocation),
        fRelativeAddress(other.fRelativeAddress),
        fEnabled(other.fEnabled),
-       fHidden(other.fHidden)
+       fHidden(other.fHidden),
+       fConditionExpression(other.fConditionExpression)
 {
        if (fFunctionID != NULL)
                fFunctionID->AcquireReference();
@@ -49,7 +51,7 @@ BreakpointSetting::~BreakpointSetting()
 
 status_t
 BreakpointSetting::SetTo(const UserBreakpointLocation& location, bool enabled,
-       bool hidden)
+       bool hidden, const BString& conditionExpression)
 {
        _Unset();
 
@@ -64,6 +66,7 @@ BreakpointSetting::SetTo(const UserBreakpointLocation& 
location, bool enabled,
        fRelativeAddress = location.RelativeAddress();
        fEnabled = enabled;
        fHidden = hidden;
+       fConditionExpression = conditionExpression;
 
        return B_OK;
 }
@@ -100,6 +103,9 @@ BreakpointSetting::SetTo(const BMessage& archive)
        if (archive.FindBool("hidden", &fHidden) != B_OK)
                fHidden = false;
 
+       if (archive.FindString("condition", &fConditionExpression) != B_OK)
+               fConditionExpression.Truncate(0);
+
        return B_OK;
 }
 
@@ -122,7 +128,9 @@ BreakpointSetting::WriteTo(BMessage& archive) const
                || (error = archive.AddUInt64("relativeAddress", 
fRelativeAddress))
                        != B_OK
                || (error = archive.AddBool("enabled", fEnabled)) != B_OK
-               || (error = archive.AddBool("hidden", fHidden)) != B_OK) {
+               || (error = archive.AddBool("hidden", fHidden)) != B_OK
+               || (error = archive.AddString("condition", 
fConditionExpression))
+                       != B_OK) {
                return error;
        }
 
@@ -147,6 +155,7 @@ BreakpointSetting::operator=(const BreakpointSetting& other)
        fRelativeAddress = other.fRelativeAddress;
        fEnabled = other.fEnabled;
        fHidden = other.fHidden;
+       fConditionExpression = other.fConditionExpression;
 
        return *this;
 }
@@ -164,4 +173,5 @@ BreakpointSetting::_Unset()
        fSourceLocation = SourceLocation();
        fRelativeAddress = 0;
        fEnabled = false;
+       fConditionExpression.Truncate(0);
 }
diff --git a/src/apps/debugger/settings/BreakpointSetting.h 
b/src/apps/debugger/settings/BreakpointSetting.h
index 90d0a03..9ea54d2 100644
--- a/src/apps/debugger/settings/BreakpointSetting.h
+++ b/src/apps/debugger/settings/BreakpointSetting.h
@@ -1,6 +1,6 @@
 /*
  * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2013, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2014, Rene Gollent, rene@xxxxxxxxxxx.
  * Distributed under the terms of the MIT License.
  */
 #ifndef BREAKPOINT_SETTING_H
@@ -28,7 +28,8 @@ public:
                                                                
~BreakpointSetting();
 
                        status_t                        SetTo(const 
UserBreakpointLocation& location,
-                                                                       bool 
enabled, bool hidden);
+                                                                       bool 
enabled, bool hidden,
+                                                                       const 
BString& conditionExpression);
                        status_t                        SetTo(const BMessage& 
archive);
                        status_t                        WriteTo(BMessage& 
archive) const;
 
@@ -42,6 +43,9 @@ public:
                        bool                            IsEnabled() const       
{ return fEnabled; }
                        bool                            IsHidden() const        
{ return fHidden; }
 
+                       const BString&          Condition() const
+                                                                       { 
return fConditionExpression; }
+
                        BreakpointSetting&      operator=(const 
BreakpointSetting& other);
 
 private:
@@ -54,6 +58,7 @@ private:
                        target_addr_t           fRelativeAddress;
                        bool                            fEnabled;
                        bool                            fHidden;
+                       BString                         fConditionExpression;
 };
 
 
diff --git a/src/apps/debugger/settings/TeamSettings.cpp 
b/src/apps/debugger/settings/TeamSettings.cpp
index 99c38a0..b77224f 100644
--- a/src/apps/debugger/settings/TeamSettings.cpp
+++ b/src/apps/debugger/settings/TeamSettings.cpp
@@ -64,7 +64,8 @@ TeamSettings::SetTo(Team* team)
                        return B_NO_MEMORY;
 
                status_t error = 
breakpointSetting->SetTo(breakpoint->Location(),
-                       breakpoint->IsEnabled(), breakpoint->IsHidden());
+                       breakpoint->IsEnabled(), breakpoint->IsHidden(),
+                       breakpoint->Condition());
                if (error == B_OK && !fBreakpoints.AddItem(breakpointSetting))
                        error = B_NO_MEMORY;
                if (error != B_OK) {

############################################################################

Commit:      3dfdc98cd1ee9c6ad6619ae4c0f94ead5ede0ee1
URL:         http://cgit.haiku-os.org/haiku/commit/?id=3dfdc98
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Thu Oct 30 15:38:06 2014 UTC

Debugger: Show breakpoint conditions in list view.

- Adjust breakpoint table and model to also show breakpoint conditions,
  if set.

----------------------------------------------------------------------------

diff --git 
a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp 
b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp
index 6b88b63..a3742d8 100644
--- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp
+++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp
@@ -217,7 +217,7 @@ public:
 
        virtual int32 CountColumns() const
        {
-               return 3;
+               return 4;
        }
 
        virtual int32 CountRows() const
@@ -277,6 +277,12 @@ private:
                                value.SetTo(data);
                                return true;
                        }
+                       case 3:
+                       {
+                               value.SetTo(breakpoint->Condition(),
+                                       B_VARIANT_DONT_COPY_DATA);
+                               return true;
+                       }
                        default:
                                return false;
                }
@@ -456,6 +462,8 @@ BreakpointListView::_Init(BView* filterTarget)
                1000, B_TRUNCATE_END, B_ALIGN_LEFT));
        fBreakpointsTable->AddColumn(new StringTableColumn(2, 
"File:Line/Address",
                250, 40, 1000, B_TRUNCATE_END, B_ALIGN_LEFT));
+       fBreakpointsTable->AddColumn(new StringTableColumn(3, "Condition",
+               250, 40, 1000, B_TRUNCATE_END, B_ALIGN_LEFT));
 
        fBreakpointsTable->SetSelectionMode(B_MULTIPLE_SELECTION_LIST);
        fBreakpointsTable->AddTableListener(this);

############################################################################

Commit:      942226c711ca32e4c9b18e7c1e3a76fd546b3082
URL:         http://cgit.haiku-os.org/haiku/commit/?id=942226c
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Thu Oct 30 18:23:26 2014 UTC

Debugger: Add UI for configuring breakpoint conditions.

General:
- Add message codes for requesting breakpoint configuration.

UserInterfaceListener/TeamDebugger:
- Add/implement hooks for requesting breakpoint condition changes.

BreakpointsView:
- Add button to request editing the currently selected breakpoint's
  condition.

TeamWindow:
- Handle request to show breakpoint edit window.

BreakpointEditWindow:
- Implement simple radio-based UI for modifying the current breakpoint's
  condition.

Still missing: Actually handling/evaluating the breakpoint conditions in
the ThreadHandler when the breakpoint is hit.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
index 43ad313..ad85396c 100644
--- a/src/apps/debugger/Jamfile
+++ b/src/apps/debugger/Jamfile
@@ -262,6 +262,7 @@ Application Debugger :
 
        # user_interface/gui/team_window
        BreakConditionConfigWindow.cpp
+       BreakpointEditWindow.cpp
        BreakpointListView.cpp
        BreakpointsView.cpp
        ConsoleOutputView.cpp
diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h
index 42d9966..fdf07db 100644
--- a/src/apps/debugger/MessageCodes.h
+++ b/src/apps/debugger/MessageCodes.h
@@ -18,6 +18,8 @@ enum {
        MSG_CLEAR_BREAKPOINT                                            = 
'cbrk',
        MSG_ENABLE_BREAKPOINT                                           = 
'ebrk',
        MSG_DISABLE_BREAKPOINT                                          = 
'dbrk',
+       MSG_SET_BREAKPOINT_CONDITION                            = 'sbpc',
+       MSG_CLEAR_BREAKPOINT_CONDITION                          = 'cbpc',
        MSG_SET_WATCHPOINT                                                      
= 'swpt',
        MSG_CLEAR_WATCHPOINT                                            = 
'cwpt',
        MSG_ENABLE_WATCHPOINT                                           = 
'ewpt',
@@ -61,6 +63,8 @@ enum {
        MSG_TEAMS_WINDOW_CLOSED                                         = 
'tswc',
        MSG_SHOW_BREAK_CONDITION_CONFIG_WINDOW          = 'sbcc',
        MSG_BREAK_CONDITION_CONFIG_WINDOW_CLOSED        = 'bccw',
+       MSG_SHOW_BREAKPOINT_EDIT_WINDOW                         = 'sbew',
+       MSG_BREAKPOINT_EDIT_WINDOW_CLOSED                       = 'bewc',
        MSG_START_NEW_TEAM                                                      
= 'sttt',
        MSG_DEBUG_THIS_TEAM                                                     
= 'dbtt',
        MSG_SHOW_INSPECTOR_WINDOW                                       = 
'sirw',
diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp 
b/src/apps/debugger/controllers/TeamDebugger.cpp
index 620eca5..eec3593 100644
--- a/src/apps/debugger/controllers/TeamDebugger.cpp
+++ b/src/apps/debugger/controllers/TeamDebugger.cpp
@@ -582,9 +582,10 @@ TeamDebugger::MessageReceived(BMessage* message)
                        BReference<UserBreakpoint> breakpointReference;
                        uint64 address = 0;
 
-                       if (message->FindPointer("breakpoint", 
(void**)&breakpoint) == B_OK)
+                       if (message->FindPointer("breakpoint", 
(void**)&breakpoint)
+                               == B_OK) {
                                breakpointReference.SetTo(breakpoint, true);
-                       else if (message->FindUInt64("address", &address) != 
B_OK)
+                       } else if (message->FindUInt64("address", &address) != 
B_OK)
                                break;
 
                        if (message->what == MSG_SET_BREAKPOINT) {
@@ -610,6 +611,45 @@ TeamDebugger::MessageReceived(BMessage* message)
                        break;
                }
 
+               case MSG_SET_BREAKPOINT_CONDITION:
+               {
+                       UserBreakpoint* breakpoint = NULL;
+                       BReference<UserBreakpoint> breakpointReference;
+                       if (message->FindPointer("breakpoint", 
(void**)&breakpoint)
+                               != B_OK) {
+                               break;
+                       }
+
+                       breakpointReference.SetTo(breakpoint, true);
+
+                       const char* condition;
+                       if (message->FindString("condition", &condition) != 
B_OK)
+                               break;
+
+                       AutoLocker< ::Team> teamLocker(fTeam);
+                       breakpoint->SetCondition(condition);
+                       fTeam->NotifyUserBreakpointChanged(breakpoint);
+
+                       break;
+               }
+
+               case MSG_CLEAR_BREAKPOINT_CONDITION:
+               {
+                       UserBreakpoint* breakpoint = NULL;
+                       BReference<UserBreakpoint> breakpointReference;
+                       if (message->FindPointer("breakpoint", 
(void**)&breakpoint)
+                               != B_OK)
+                               break;
+
+                       breakpointReference.SetTo(breakpoint, true);
+
+                       AutoLocker< ::Team> teamLocker(fTeam);
+                       breakpoint->SetCondition(NULL);
+                       fTeam->NotifyUserBreakpointChanged(breakpoint);
+
+                       break;
+               }
+
                case MSG_STOP_ON_IMAGE_LOAD:
                {
                        bool enabled;
@@ -987,6 +1027,32 @@ 
TeamDebugger::SetBreakpointEnabledRequested(UserBreakpoint* breakpoint,
 
 
 void
+TeamDebugger::SetBreakpointConditionRequested(UserBreakpoint* breakpoint,
+       const char* condition)
+{
+       BMessage message(MSG_SET_BREAKPOINT_CONDITION);
+       BReference<UserBreakpoint> breakpointReference(breakpoint);
+       if (message.AddPointer("breakpoint", breakpoint) == B_OK
+               && message.AddString("condition", condition) == B_OK
+               && PostMessage(&message) == B_OK) {
+               breakpointReference.Detach();
+       }
+}
+
+
+void
+TeamDebugger::ClearBreakpointConditionRequested(UserBreakpoint* breakpoint)
+{
+       BMessage message(MSG_CLEAR_BREAKPOINT_CONDITION);
+       BReference<UserBreakpoint> breakpointReference(breakpoint);
+       if (message.AddPointer("breakpoint", breakpoint) == B_OK
+               && PostMessage(&message) == B_OK) {
+               breakpointReference.Detach();
+       }
+}
+
+
+void
 TeamDebugger::ClearBreakpointRequested(target_addr_t address)
 {
        BMessage message(MSG_CLEAR_BREAKPOINT);
diff --git a/src/apps/debugger/controllers/TeamDebugger.h 
b/src/apps/debugger/controllers/TeamDebugger.h
index ef5a9f2..10e0447 100644
--- a/src/apps/debugger/controllers/TeamDebugger.h
+++ b/src/apps/debugger/controllers/TeamDebugger.h
@@ -81,6 +81,11 @@ private:
        virtual void                            SetBreakpointEnabledRequested(
                                                                        
UserBreakpoint* breakpoint,
                                                                        bool 
enabled);
+       virtual void                            SetBreakpointConditionRequested(
+                                                                       
UserBreakpoint* breakpoint,
+                                                                       const 
char* condition);
+       virtual void                            
ClearBreakpointConditionRequested(
+                                                                       
UserBreakpoint* breakpoint);
        virtual void                            
ClearBreakpointRequested(target_addr_t address);
        virtual void                            ClearBreakpointRequested(
                                                                        
UserBreakpoint* breakpoint);
diff --git a/src/apps/debugger/user_interface/UserInterface.h 
b/src/apps/debugger/user_interface/UserInterface.h
index 565f0b9..e6abffb 100644
--- a/src/apps/debugger/user_interface/UserInterface.h
+++ b/src/apps/debugger/user_interface/UserInterface.h
@@ -109,6 +109,11 @@ public:
        virtual void                            SetBreakpointEnabledRequested(
                                                                        
UserBreakpoint* breakpoint,
                                                                        bool 
enabled) = 0;
+       virtual void                            SetBreakpointConditionRequested(
+                                                                       
UserBreakpoint* breakpoint,
+                                                                       const 
char* condition) = 0;
+       virtual void                            
ClearBreakpointConditionRequested(
+                                                                       
UserBreakpoint* breakpoint) = 0;
        virtual void                            ClearBreakpointRequested(
                                                                        
target_addr_t address) = 0;
        virtual void                            ClearBreakpointRequested(
diff --git 
a/src/apps/debugger/user_interface/gui/team_window/BreakpointEditWindow.cpp 
b/src/apps/debugger/user_interface/gui/team_window/BreakpointEditWindow.cpp
new file mode 100644
index 0000000..a5f5abe
--- /dev/null
+++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointEditWindow.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#include "BreakpointEditWindow.h"
+
+#include <Button.h>
+#include <LayoutBuilder.h>
+#include <RadioButton.h>
+#include <StringView.h>
+#include <TextControl.h>
+
+#include <AutoDeleter.h>
+#include <AutoLocker.h>
+
+#include "MessageCodes.h"
+#include "UserBreakpoint.h"
+#include "UserInterface.h"
+#include "Team.h"
+
+
+enum {
+       MSG_SET_BREAK_ALWAYS                    = 'sbal',
+       MSG_SET_BREAK_ON_CONDITION              = 'sboc',
+       MSG_SAVE_BREAKPOINT_SETTINGS    = 'sbps'
+};
+
+
+BreakpointEditWindow::BreakpointEditWindow(::Team* team,
+       UserBreakpoint* breakpoint, UserInterfaceListener* listener,
+       BHandler* target)
+       :
+       BWindow(BRect(), "Edit breakpoint", B_FLOATING_WINDOW,
+               B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
+       fTeam(team),
+       fListener(listener),
+       fTargetBreakpoint(breakpoint),
+       fSaveButton(NULL),
+       fCancelButton(NULL),
+       fTarget(target)
+{
+       fTargetBreakpoint->AcquireReference();
+}
+
+
+BreakpointEditWindow::~BreakpointEditWindow()
+{
+       fTargetBreakpoint->ReleaseReference();
+       BMessenger(fTarget).SendMessage(MSG_BREAKPOINT_EDIT_WINDOW_CLOSED);
+}
+
+
+BreakpointEditWindow*
+BreakpointEditWindow::Create(::Team* team, UserBreakpoint* breakpoint,
+       UserInterfaceListener* listener, BHandler* target)
+{
+       BreakpointEditWindow* self = new BreakpointEditWindow(
+               team, breakpoint, listener, target);
+
+       try {
+               self->_Init();
+       } catch (...) {
+               delete self;
+               throw;
+       }
+
+       return self;
+
+}
+
+void
+BreakpointEditWindow::MessageReceived(BMessage* message)
+{
+       switch (message->what) {
+               case MSG_SET_BREAK_ALWAYS:
+                       fConditionInput->SetEnabled(false);
+                       break;
+               case MSG_SET_BREAK_ON_CONDITION:
+                       fConditionInput->SetEnabled(true);
+                       break;
+               case MSG_SAVE_BREAKPOINT_SETTINGS:
+               {
+                       if (fConditionRadio->Value() == B_CONTROL_ON) {
+                               fListener->SetBreakpointConditionRequested(
+                                       fTargetBreakpoint, 
fConditionInput->Text());
+                       } else {
+                               fListener->ClearBreakpointConditionRequested(
+                                       fTargetBreakpoint);
+                       }
+                       // fall through
+               }
+               case B_CANCEL:
+                       Quit();
+                       break;
+
+               default:
+                       BWindow::MessageReceived(message);
+                       break;
+       }
+
+}
+
+
+void
+BreakpointEditWindow::Show()
+{
+       CenterOnScreen();
+       BWindow::Show();
+}
+
+
+void
+BreakpointEditWindow::_Init()
+{
+       fConditionInput = new BTextControl(NULL, NULL, NULL);
+       BLayoutItem* textLayoutItem = 
fConditionInput->CreateTextViewLayoutItem();
+       textLayoutItem->SetExplicitMinSize(BSize(200.0, B_SIZE_UNSET));
+       BLayoutBuilder::Group<>(this, B_VERTICAL)
+               .SetInsets(B_USE_DEFAULT_SPACING)
+               .Add((fAlwaysRadio = new BRadioButton("Break always",
+                               new BMessage(MSG_SET_BREAK_ALWAYS))))
+               .AddGroup(B_HORIZONTAL)
+                       .Add((fConditionRadio = new BRadioButton("Break on 
condition: ",
+                               new BMessage(MSG_SET_BREAK_ON_CONDITION))))
+                       .Add(textLayoutItem)
+               .End()
+               .AddGroup(B_HORIZONTAL)
+                       .AddGlue()
+                       .Add((fSaveButton = new BButton("Save",
+                               new BMessage(MSG_SAVE_BREAKPOINT_SETTINGS))))
+                       .Add((fCancelButton = new BButton("Cancel",
+                               new BMessage(B_CANCEL))))
+               .End()
+       .End();
+
+       AutoLocker< ::Team> teamLocker(fTeam);
+       if (fTargetBreakpoint->HasCondition()) {
+               fConditionRadio->SetValue(B_CONTROL_ON);
+               fConditionInput->SetText(fTargetBreakpoint->Condition());
+       } else {
+               fAlwaysRadio->SetValue(B_CONTROL_ON);
+               fConditionInput->SetEnabled(false);
+       }
+}
diff --git 
a/src/apps/debugger/user_interface/gui/team_window/BreakpointEditWindow.h 
b/src/apps/debugger/user_interface/gui/team_window/BreakpointEditWindow.h
new file mode 100644
index 0000000..a733fd4
--- /dev/null
+++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointEditWindow.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef BREAKPOINT_EDIT_WINDOW_H
+#define BREAKPOINT_EDIT_WINDOW_H
+
+
+#include <Window.h>
+
+#include "Team.h"
+
+#include "types/Types.h"
+
+
+class BButton;
+class BRadioButton;
+class BTextControl;
+class Team;
+class UserBreakpoint;
+class UserInterfaceListener;
+
+
+class BreakpointEditWindow : public BWindow {
+public:
+                                                               
BreakpointEditWindow(
+                                                                       ::Team* 
team,
+                                                                       
UserBreakpoint* breakpoint,
+                                                                       
UserInterfaceListener* listener,
+                                                                       
BHandler* target);
+
+                                                               
~BreakpointEditWindow();
+
+       static  BreakpointEditWindow* Create(::Team* team,
+                                                                       
UserBreakpoint* breakpoint,
+                                                                       
UserInterfaceListener* listener,
+                                                                       
BHandler* target);
+                                                                       // 
throws
+
+       virtual void                            MessageReceived(BMessage* 
message);
+
+       virtual void                            Show();
+
+private:
+                       void                            _Init();
+                       void                            _UpdateState();
+
+private:
+                       ::Team*                         fTeam;
+                       UserInterfaceListener* fListener;
+                       UserBreakpoint*         fTargetBreakpoint;
+                       BTextControl*           fConditionInput;
+                       BButton*                        fSaveButton;
+                       BButton*                        fCancelButton;
+                       BRadioButton*           fAlwaysRadio;
+                       BRadioButton*           fConditionRadio;
+                       BHandler*                       fTarget;
+};
+
+
+#endif // BREAKPOINT_EDIT_WINDOW
diff --git 
a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp 
b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp
index baf5a96..acd7888 100644
--- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp
+++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp
@@ -31,6 +31,7 @@ BreakpointsView::BreakpointsView(Team* team, Listener* 
listener)
        fListView(NULL),
        fConfigureExceptionsButton(NULL),
        fToggleBreakpointButton(NULL),
+       fEditBreakpointButton(NULL),
        fRemoveBreakpointButton(NULL),
        fListener(listener)
 {
@@ -96,6 +97,12 @@ BreakpointsView::MessageReceived(BMessage* message)
                        _HandleBreakpointAction(message->what);
                        break;
 
+               case MSG_SHOW_BREAKPOINT_EDIT_WINDOW:
+                       message->AddPointer("breakpoint",
+                               
fSelectedBreakpoints.ItemAt(0)->GetBreakpoint());
+                       Window()->PostMessage(message);
+                       break;
+
                default:
                        BGroupView::MessageReceived(message);
                        break;
@@ -107,6 +114,7 @@ void
 BreakpointsView::AttachedToWindow()
 {
        fConfigureExceptionsButton->SetTarget(Window());
+       fEditBreakpointButton->SetTarget(this);
        fToggleBreakpointButton->SetTarget(this);
        fRemoveBreakpointButton->SetTarget(this);
 }
@@ -157,6 +165,7 @@ BreakpointsView::_Init()
                        .Add(fConfigureExceptionsButton = new BButton(
                                "Configure break conditions" B_UTF8_ELLIPSIS))
                        .Add(fRemoveBreakpointButton = new BButton("Remove"))
+                       .Add(fEditBreakpointButton = new BButton("Edit" 
B_UTF8_ELLIPSIS))
                        .Add(fToggleBreakpointButton = new BButton("Toggle"))
                .End();
 
@@ -164,6 +173,8 @@ BreakpointsView::_Init()
                new BMessage(MSG_SHOW_BREAK_CONDITION_CONFIG_WINDOW));
        fToggleBreakpointButton->SetMessage(new 
BMessage(MSG_ENABLE_BREAKPOINT));
        fRemoveBreakpointButton->SetMessage(new BMessage(MSG_CLEAR_BREAKPOINT));
+       fEditBreakpointButton->SetMessage(
+               new BMessage(MSG_SHOW_BREAKPOINT_EDIT_WINDOW));
 
        _UpdateButtons();
 }
@@ -190,6 +201,7 @@ BreakpointsView::_UpdateButtons()
                                                hasEnabled = true;
                                        else
                                                hasDisabled = true;
+
                                }
                                break;
                        }
@@ -209,6 +221,17 @@ BreakpointsView::_UpdateButtons()
        }
 
        if (valid) {
+               // only allow condition editing if we have a single
+               // actual breakpoint selected.
+               // TODO: allow using this to modify watchpoints as
+               // well.
+               if (fSelectedBreakpoints.CountItems() == 1
+                       && fSelectedBreakpoints.ItemAt(0)->Type()
+                               == BREAKPOINT_PROXY_TYPE_BREAKPOINT) {
+                       fEditBreakpointButton->SetEnabled(true);
+               } else
+                       fEditBreakpointButton->SetEnabled(false);
+
                // if we have at least one disabled breakpoint in the
                // selection, we leave the button as an Enable button
                if (hasEnabled && !hasDisabled) {
@@ -226,6 +249,7 @@ BreakpointsView::_UpdateButtons()
        } else {
                fToggleBreakpointButton->SetLabel("Enable");
                fToggleBreakpointButton->SetEnabled(false);
+               fEditBreakpointButton->SetEnabled(false);
                fRemoveBreakpointButton->SetEnabled(false);
        }
 }
diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h 
b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h
index ea10f93..4946b46 100644
--- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h
+++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h
@@ -57,6 +57,7 @@ private:
                        BreakpointProxyList     fSelectedBreakpoints;
                        BButton*                        
fConfigureExceptionsButton;
                        BButton*                        fToggleBreakpointButton;
+                       BButton*                        fEditBreakpointButton;
                        BButton*                        fRemoveBreakpointButton;
                        Listener*                       fListener;
 };
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 32c1543..d820398 100644
--- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp
+++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp
@@ -33,12 +33,14 @@
 #include <AutoDeleter.h>
 #include <AutoLocker.h>
 
+#include "BreakConditionConfigWindow.h"
 #include "Breakpoint.h"
+#include "BreakpointEditWindow.h"
 #include "ConsoleOutputView.h"
 #include "CppLanguage.h"
 #include "CpuState.h"
 #include "DisassembledCode.h"
-#include "BreakConditionConfigWindow.h"
+#include "BreakpointEditWindow.h"
 #include "ExpressionEvaluationWindow.h"
 #include "FileSourceCode.h"
 #include "GuiSettingsUtils.h"
@@ -136,6 +138,7 @@ TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* 
listener)
        fThreadSplitView(NULL),
        fConsoleSplitView(NULL),
        fBreakConditionConfigWindow(NULL),
+       fBreakpointEditWindow(NULL),
        fInspectorWindow(NULL),
        fExpressionWindow(NULL),
        fFilePanel(NULL),
@@ -395,6 +398,36 @@ TeamWindow::MessageReceived(BMessage* message)
                        fBreakConditionConfigWindow = NULL;
                        break;
                }
+               case MSG_SHOW_BREAKPOINT_EDIT_WINDOW:
+               {
+                       if (fBreakpointEditWindow != NULL) {
+                               AutoLocker<BWindow> lock(fBreakpointEditWindow);
+                               if (lock.IsLocked())
+                                       fBreakpointEditWindow->Activate(true);
+                       } else {
+                               UserBreakpoint* breakpoint;
+                               if (message->FindPointer("breakpoint",
+                                       reinterpret_cast<void**>(&breakpoint)) 
!= B_OK) {
+                                       break;
+                               }
+
+                               try {
+                                       fBreakpointEditWindow
+                                               = BreakpointEditWindow::Create(
+                                               fTeam, breakpoint, fListener, 
this);
+                                       if (fBreakpointEditWindow != NULL)
+                                               fBreakpointEditWindow->Show();
+                       } catch (...) {
+                               // TODO: notify user
+                       }
+                       }
+                       break;
+               }
+               case MSG_BREAKPOINT_EDIT_WINDOW_CLOSED:
+               {
+                       fBreakpointEditWindow = NULL;
+                       break;
+               }
                case MSG_SHOW_WATCH_VARIABLE_PROMPT:
                {
                        target_addr_t address;
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 91a414e..ec0cd5c 100644
--- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h
+++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h
@@ -33,6 +33,7 @@ class BStringView;
 class BTabView;
 class ConsoleOutputView;
 class BreakConditionConfigWindow;
+class BreakpointEditWindow;
 class ExpressionEvaluationWindow;
 class Image;
 class InspectorWindow;
@@ -220,6 +221,7 @@ private:
                        BSplitView*                     fThreadSplitView;
                        BSplitView*                     fConsoleSplitView;
                        BreakConditionConfigWindow* fBreakConditionConfigWindow;
+                       BreakpointEditWindow* fBreakpointEditWindow;
                        InspectorWindow*        fInspectorWindow;
                        ExpressionEvaluationWindow* fExpressionWindow;
                        GuiTeamUiSettings       fUiSettings;

############################################################################

Commit:      43060a58fa461430c98c7d24c3e71179e160a5ab
URL:         http://cgit.haiku-os.org/haiku/commit/?id=43060a5
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Thu Oct 30 20:48:00 2014 UTC

Debugger: Minor tweak to ExpressionEvaluationJob.

- ExpressionEvaluationJob now stores the final result value,
  and provides an accessor to it.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp 
b/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp
index b98f783..22bd03e 100644
--- a/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp
+++ b/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp
@@ -34,7 +34,8 @@ ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team,
        fResultType(resultType),
        fFrame(frame),
        fThread(thread),
-       fManager(NULL)
+       fManager(NULL),
+       fResultValue(NULL)
 {
        fLanguage->AcquireReference();
        if (fFrame != NULL)
@@ -53,6 +54,8 @@ ExpressionEvaluationJob::~ExpressionEvaluationJob()
                fThread->ReleaseReference();
        if (fManager != NULL)
                fManager->ReleaseReference();
+       if (fResultValue != NULL)
+               fResultValue->ReleaseReference();
 }
 
 
@@ -66,8 +69,6 @@ ExpressionEvaluationJob::Key() const
 status_t
 ExpressionEvaluationJob::Do()
 {
-
-       Value* value = NULL;
        BReference<Value> reference;
        status_t result = B_OK;
        if (fFrame != NULL && fManager == NULL) {
@@ -85,18 +86,17 @@ ExpressionEvaluationJob::Do()
 
        ValueNode* neededNode = NULL;
        result = fLanguage->EvaluateExpression(fExpression,
-               fResultType, fManager, value, neededNode);
+               fResultType, fManager, fResultValue, neededNode);
        if (neededNode != NULL) {
                result = ResolveNodeValue(neededNode);
                if (State() == JOB_STATE_WAITING)
                        return B_OK;
-               else if (value != NULL)
-                       reference.SetTo(value, true);
                // if result != B_OK, fall through
        }
 
        AutoLocker<Team> teamLocker(fTeam);
-       fTeam->NotifyExpressionEvaluated(fExpression.String(), result, value);
+       fTeam->NotifyExpressionEvaluated(fExpression.String(), result,
+               fResultValue);
 
        return B_OK;
 }
diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h
index 6ae378e..c94c091 100644
--- a/src/apps/debugger/jobs/Jobs.h
+++ b/src/apps/debugger/jobs/Jobs.h
@@ -245,6 +245,8 @@ public:
        virtual const JobKey&           Key() const;
        virtual status_t                        Do();
 
+                       Value*                          GetResultValue() const 
{ return fResultValue; }
+
 private:
                        status_t                        
ResolveNodeValue(ValueNode* node);
 
@@ -260,6 +262,7 @@ private:
                        StackFrame*                     fFrame;
                        Thread*                         fThread;
                        ValueNodeManager*       fManager;
+                       Value*                          fResultValue;
 };
 
 

############################################################################

Revision:    hrev48170
Commit:      a5ce4678c054489520b8e2a7c0910da48a5d1521
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a5ce467
Author:      Rene Gollent <rene@xxxxxxxxxxx>
Date:        Thu Oct 30 20:49:16 2014 UTC

Ticket:      https://dev.haiku-os.org/ticket/9713

Debugger: Implement conditional breakpoints.

ThreadHandler:
- When a breakpoint event is hit, we now check if there is an
  associated UserBreakpoint with a condition attached. If so,
  we schedule an evaluation request, and only stop the thread if
  that one evaluates to true (or if evaluation fails in some way).

This implements #9713.

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp 
b/src/apps/debugger/controllers/ThreadHandler.cpp
index a9653c2..e44bbbb 100644
--- a/src/apps/debugger/controllers/ThreadHandler.cpp
+++ b/src/apps/debugger/controllers/ThreadHandler.cpp
@@ -11,7 +11,9 @@
 
 #include <new>
 
+#include <AutoDeleter.h>
 #include <AutoLocker.h>
+#include <Variant.h>
 
 #include "Architecture.h"
 #include "BreakpointManager.h"
@@ -24,11 +26,13 @@
 #include "MessageCodes.h"
 #include "Register.h"
 #include "SourceCode.h"
+#include "SourceLanguage.h"
 #include "SpecificImageDebugInfo.h"
 #include "StackTrace.h"
 #include "Statement.h"
 #include "Team.h"
 #include "Tracing.h"
+#include "Value.h"
 #include "Worker.h"
 
 
@@ -42,6 +46,43 @@ enum {
 };
 
 
+class ExpressionJobListener : public JobListener {
+public:
+       ExpressionJobListener(ThreadHandler* handler)
+       :
+       JobListener(),
+       fHandler(handler)
+       {
+               fHandler->AcquireReference();
+       }
+
+       ~ExpressionJobListener()
+       {
+               fHandler->ReleaseReference();
+       }
+
+       virtual void JobDone(Job* job)
+       {
+               Value* resultValue = dynamic_cast<ExpressionEvaluationJob*>(job)
+                       ->GetResultValue();
+
+               fHandler->_HandleBreakpointConditionEvaluated(resultValue);
+       }
+
+       virtual void JobFailed(Job* job)
+       {
+               fHandler->_HandleBreakpointConditionEvaluated(NULL);
+       }
+
+       virtual void JobAborted(Job* job)
+       {
+               fHandler->_HandleBreakpointConditionEvaluated(NULL);
+       }
+private:
+       ThreadHandler* fHandler;
+};
+
+
 ThreadHandler::ThreadHandler(Thread* thread, Worker* worker,
        DebuggerInterface* debuggerInterface,
        ImageDebugInfoJobListener* listener,
@@ -58,7 +99,10 @@ ThreadHandler::ThreadHandler(Thread* thread, Worker* worker,
        fSteppedOverFunctionAddress(0),
        fPreviousInstructionPointer(0),
        fPreviousFrameAddress(0),
-       fSingleStepping(false)
+       fSingleStepping(false),
+       fHasPendingConditionEvaluation(false),
+       fConditionWaitSem(-1),
+       fConditionResult(NULL)
 {
        fDebuggerInterface->AcquireReference();
 }
@@ -68,6 +112,9 @@ ThreadHandler::~ThreadHandler()
 {
        _ClearContinuationState();
        fDebuggerInterface->ReleaseReference();
+
+       if (fConditionWaitSem > 0)
+               delete_sem(fConditionWaitSem);
 }
 
 
@@ -76,6 +123,7 @@ ThreadHandler::Init()
 {
        fWorker->ScheduleJob(new(std::nothrow) 
GetThreadStateJob(fDebuggerInterface,
                fThread));
+       fConditionWaitSem = create_sem(0, "breakpoint condition waiter");
 }
 
 
@@ -164,6 +212,12 @@ ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* 
event)
                        }
 
                        return false;
+               } else {
+                       locker.Unlock();
+                       if (_HandleBreakpointConditionIfNeeded(cpuState))
+                               return true;
+
+                       locker.Lock();
                }
        }
 
@@ -387,6 +441,13 @@ ThreadHandler::HandleCpuStateChanged()
 void
 ThreadHandler::HandleStackTraceChanged()
 {
+       AutoLocker< ::Team> teamLocker(fThread->GetTeam());
+       if (fHasPendingConditionEvaluation && fThread->GetStackTrace() != NULL) 
{
+               fHasPendingConditionEvaluation = false;
+               teamLocker.Unlock();
+
+               _HandleBreakpointConditionIfNeeded(fThread->GetCpuState());
+       }
 }
 
 
@@ -789,6 +850,111 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
 
 
 bool
+ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState)
+{
+       AutoLocker< ::Team> teamLocker(fThread->GetTeam());
+       Breakpoint* breakpoint = fThread->GetTeam()->BreakpointAtAddress(
+               cpuState->InstructionPointer());
+
+       if (breakpoint == NULL)
+               return false;
+
+       if (!breakpoint->HasEnabledUserBreakpoint())
+               return false;
+
+       const UserBreakpointInstanceList& breakpoints
+               = breakpoint->UserBreakpoints();
+
+       for (UserBreakpointInstanceList::ConstIterator it
+                       = breakpoints.GetIterator(); it.HasNext();) {
+               UserBreakpoint* userBreakpoint = it.Next()->GetUserBreakpoint();
+               if (!userBreakpoint->IsValid())
+                       continue;
+               if (!userBreakpoint->IsEnabled())
+                       continue;
+               if (!userBreakpoint->HasCondition())
+                       continue;
+
+               StackTrace* stackTrace = fThread->GetStackTrace();
+               if (stackTrace == NULL) {
+                       fThread->SetCpuState(cpuState);
+                       fHasPendingConditionEvaluation = true;
+                       return true;
+               }
+
+               StackFrame* frame = stackTrace->FrameAt(0);
+               FunctionDebugInfo* info = 
frame->Function()->GetFunctionDebugInfo();
+               if (info == NULL)
+                       return false;
+
+               SpecificImageDebugInfo* specificInfo
+                       = info->GetSpecificImageDebugInfo();
+               if (specificInfo == NULL)
+                       return false;
+
+               SourceLanguage* language;
+               if (specificInfo->GetSourceLanguage(info, language) != B_OK)
+                       return false;
+
+               BReference<SourceLanguage> reference(language, true);
+               ExpressionJobListener* listener
+                       = new(std::nothrow) ExpressionJobListener(this);
+               if (listener == NULL)
+                       return false;
+
+               status_t error = fWorker->ScheduleJob(
+                       new(std::nothrow) 
ExpressionEvaluationJob(fThread->GetTeam(),
+                               fDebuggerInterface, language, 
userBreakpoint->Condition(),
+                               B_UINT64_TYPE, frame, fThread), listener);
+
+               BPrivate::ObjectDeleter<ExpressionJobListener> 
deleter(listener);
+               if (error == B_OK) {
+                       teamLocker.Unlock();
+
+                       do {
+                               error = acquire_sem(fConditionWaitSem);
+                       } while (error == B_INTERRUPTED);
+
+                       teamLocker.Lock();
+
+                       bool stop = false;
+                       if (fConditionResult == NULL)
+                               stop = true;
+                       else {
+                               BVariant value;
+                               if (!fConditionResult->ToVariant(value))
+                                       stop = true;
+                               if (!value.TypeIsInteger(value.Type()))
+                                       stop = true;
+                               stop = value.ToBool();
+                               fConditionResult->ReleaseReference();
+                               fConditionResult = NULL;
+                       }
+
+                       if (stop)
+                               return false;
+                       else {
+                               
fDebuggerInterface->ContinueThread(fThread->ID());
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+
+void
+ThreadHandler::_HandleBreakpointConditionEvaluated(Value* value)
+{
+       fConditionResult = value;
+       if (fConditionResult != NULL)
+               fConditionResult->AcquireReference();
+       release_sem(fConditionWaitSem);
+}
+
+
+bool
 ThreadHandler::_HasExitedFrame(target_addr_t framePointer) const
 {
        return fDebuggerInterface->GetArchitecture()->StackGrowthDirection()
diff --git a/src/apps/debugger/controllers/ThreadHandler.h 
b/src/apps/debugger/controllers/ThreadHandler.h
index eb80905..f29f539 100644
--- a/src/apps/debugger/controllers/ThreadHandler.h
+++ b/src/apps/debugger/controllers/ThreadHandler.h
@@ -21,6 +21,7 @@ class DebuggerInterface;
 class ImageDebugInfoJobListener;
 class StackFrame;
 class Statement;
+class Value;
 class Worker;
 
 
@@ -65,6 +66,9 @@ public:
                        void                            
HandleStackTraceChanged();
 
 private:
+                       friend class ExpressionJobListener;
+
+private:
        // ImageDebugInfoProvider
        virtual status_t                        GetImageDebugInfo(Image* image,
                                                                        
ImageDebugInfo*& _info);
@@ -95,6 +99,10 @@ private:
                        void                            _SingleStepThread(
                                                                        
target_addr_t instructionPointer);
 
+                       bool                            
_HandleBreakpointConditionIfNeeded(
+                                                                       
CpuState* cpuState);
+                       void                            
_HandleBreakpointConditionEvaluated(
+                                                                       Value* 
value);
 
                        bool                            
_HandleBreakpointHitStep(CpuState* cpuState);
                        bool                            
_HandleSingleStepStep(CpuState* cpuState);
@@ -115,6 +123,9 @@ private:
                        target_addr_t           fPreviousInstructionPointer;
                        target_addr_t           fPreviousFrameAddress;
                        bool                            fSingleStepping;
+                       bool                            
fHasPendingConditionEvaluation;
+                       sem_id                          fConditionWaitSem;
+                       Value*                          fConditionResult;
 
 public:
                        ThreadHandler*          fNext;


Other related posts:

  • » [haiku-commits] haiku: hrev48170 - in src/apps/debugger: user_interface/gui/team_window controllers settings model jobs - anevilyak