[Lldb-commits] [lldb] r170008 - in /lldb/trunk: include/lldb/API/SBThread.h include/lldb/Target/Thread.h include/lldb/Target/ThreadPlanStepInRange.h include/lldb/Target/ThreadPlanStepOverRange.h scripts/Python/interface/SBThread.i source/API/SBThread.cpp source/Commands/CommandObjectThread.cpp source/Target/Thread.cpp source/Target/ThreadPlanStepInRange.cpp test/lang/c/stepping/TestStepAndBreakpoints.py test/lang/c/stepping/main.c

Jim Ingham jingham at apple.com
Wed Dec 12 11:58:40 PST 2012


Author: jingham
Date: Wed Dec 12 13:58:40 2012
New Revision: 170008

URL: http://llvm.org/viewvc/llvm-project?rev=170008&view=rev
Log:
Fixed a few bugs in the "step in" thread plan logic.
Added a "step-in-target" flag to "thread step-in" so if you have something like:

Process 28464 stopped
* thread #1: tid = 0x1c03, function: main , stop reason = breakpoint 1.1
    frame #0: 0x0000000100000e08 a.out`main at main.c:62
   61         
-> 62         int A6 = complex (a(4), b(5), c(6)); // Stop here to step targetting b and hitting breakpoint.
   63             

and you want to get into "complex" skipping a, b and c, you can do:

(lldb) step -t complex
Process 28464 stopped
* thread #1: tid = 0x1c03, function: complex , stop reason = step in
    frame #0: 0x0000000100000d0d a.out`complex at main.c:44
   41     
   42     int complex (int first, int second, int third)
   43     {
-> 44         return first + second + third;  // Step in targetting complex should stop here
   45     }
   46         
   47     int main (int argc, char const *argv[])


Modified:
    lldb/trunk/include/lldb/API/SBThread.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
    lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
    lldb/trunk/scripts/Python/interface/SBThread.i
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
    lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py
    lldb/trunk/test/lang/c/stepping/main.c

Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Wed Dec 12 13:58:40 2012
@@ -99,6 +99,9 @@
     StepInto (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
 
     void
+    StepInto (const char *target_name, lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
+    
+    void
     StepOut ();
 
     void

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Wed Dec 12 13:58:40 2012
@@ -480,8 +480,8 @@
                                              bool stop_other_threads);
 
     //------------------------------------------------------------------
-    /// Queues the plan used to step through an address range, stepping into or over
-    /// function calls depending on the value of StepType.
+    /// Queues the plan used to step through an address range, stepping  over
+    /// function calls.
     ///
     /// @param[in] abort_other_plans
     ///    \b true if we discard the currently queued plans and replace them with this one.
@@ -507,10 +507,48 @@
     ///     A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
     //------------------------------------------------------------------
     virtual ThreadPlan *
-    QueueThreadPlanForStepRange (bool abort_other_plans,
-                                 StepType type,
+    QueueThreadPlanForStepOverRange (bool abort_other_plans,
                                  const AddressRange &range,
                                  const SymbolContext &addr_context,
+                                 lldb::RunMode stop_other_threads);
+
+    //------------------------------------------------------------------
+    /// Queues the plan used to step through an address range, stepping into functions.
+    ///
+    /// @param[in] abort_other_plans
+    ///    \b true if we discard the currently queued plans and replace them with this one.
+    ///    Otherwise this plan will go on the end of the plan stack.
+    ///
+    /// @param[in] type
+    ///    Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan.
+    ///
+    /// @param[in] range
+    ///    The address range to step through.
+    ///
+    /// @param[in] addr_context
+    ///    When dealing with stepping through inlined functions the current PC is not enough information to know
+    ///    what "step" means.  For instance a series of nested inline functions might start at the same address.
+    //     The \a addr_context provides the current symbol context the step
+    ///    is supposed to be out of.
+    //   FIXME: Currently unused.
+    ///
+    /// @param[in] step_in_target
+    ///    Name if function we are trying to step into.  We will step out if we don't land in that function.
+    ///
+    /// @param[in] stop_other_threads
+    ///    \b true if we will stop other threads while we single step this one.
+    ///
+    /// @param[in] avoid_code_without_debug_info
+    ///    If \b true we will step out if we step into code with no debug info.
+    ///
+    /// @return
+    ///     A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+    //------------------------------------------------------------------
+    virtual ThreadPlan *
+    QueueThreadPlanForStepInRange (bool abort_other_plans,
+                                 const AddressRange &range,
+                                 const SymbolContext &addr_context,
+                                 const char *step_in_target,
                                  lldb::RunMode stop_other_threads,
                                  bool avoid_code_without_debug_info);
 

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepInRange.h Wed Dec 12 13:58:40 2012
@@ -32,6 +32,12 @@
                            const SymbolContext &addr_context,
                            lldb::RunMode stop_others);
 
+    ThreadPlanStepInRange (Thread &thread,
+                           const AddressRange &range,
+                           const SymbolContext &addr_context,
+                           const char *step_into_function_name,
+                           lldb::RunMode stop_others);
+
     virtual
     ~ThreadPlanStepInRange ();
 
@@ -43,6 +49,11 @@
 
     void SetAvoidRegexp(const char *name);
     
+    void SetStepInTarget (const char *target)
+    {
+        m_step_into_target.SetCString(target);
+    }
+    
     static ThreadPlan *
     DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton);
 
@@ -65,10 +76,15 @@
 private:
 
     friend ThreadPlan *
-    Thread::QueueThreadPlanForStepRange (bool abort_other_plans,
-                                         StepType type,
+    Thread::QueueThreadPlanForStepOverRange (bool abort_other_plans,
                                          const AddressRange &range,
                                          const SymbolContext &addr_context,
+                                         lldb::RunMode stop_others);
+    friend ThreadPlan *
+    Thread::QueueThreadPlanForStepInRange (bool abort_other_plans,
+                                         const AddressRange &range,
+                                         const SymbolContext &addr_context,
+                                         const char *step_in_target,
                                          lldb::RunMode stop_others,
                                          bool avoid_code_without_debug_info);
 
@@ -81,7 +97,7 @@
     bool m_step_past_prologue;  // FIXME: For now hard-coded to true, we could put a switch in for this if there's
                                 // demand for that.
     bool m_virtual_step;        // true if we've just done a "virtual step", i.e. just moved the inline stack depth.
-
+    ConstString m_step_into_target;
     DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInRange);
 
 };

Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverRange.h Wed Dec 12 13:58:40 2012
@@ -41,13 +41,6 @@
 
 private:
 
-    friend ThreadPlan *
-    Thread::QueueThreadPlanForStepRange (bool abort_other_plans,
-                                         StepType type,
-                                         const AddressRange &range,
-                                         const SymbolContext &addr_context,
-                                         lldb::RunMode stop_others,
-                                         bool avoid_code_without_debug_info);
     bool m_first_resume;
 
     DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange);

Modified: lldb/trunk/scripts/Python/interface/SBThread.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBThread.i?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBThread.i (original)
+++ lldb/trunk/scripts/Python/interface/SBThread.i Wed Dec 12 13:58:40 2012
@@ -124,6 +124,9 @@
     StepInto (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
 
     void
+    StepInto (const char *target_name, lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping);
+
+    void
     StepOut ();
 
     void

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Wed Dec 12 13:58:40 2012
@@ -564,13 +564,10 @@
             if (frame_sp->HasDebugInformation ())
             {
                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
-                new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
-                                                                eStepTypeOver,
-                                                                sc.line_entry.range,
-                                                                sc,
-                                                                stop_other_threads,
-                                                                false);
-                
+                new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
+                                                                    sc.line_entry.range,
+                                                                    sc,
+                                                                    stop_other_threads);
             }
             else
             {
@@ -588,14 +585,23 @@
 void
 SBThread::StepInto (lldb::RunMode stop_other_threads)
 {
+    StepInto (NULL, stop_other_threads);
+}
+
+void
+SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
+{
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     Mutex::Locker api_locker;
     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
 
     if (log)
-        log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
+        log->Printf ("SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
+                     exe_ctx.GetThreadPtr(),
+                     target_name? target_name: "<NULL>",
                      Thread::RunModeAsCString (stop_other_threads));
+    
     if (exe_ctx.HasThreadScope())
     {
         bool abort_other_plans = false;
@@ -608,12 +614,12 @@
         {
             bool avoid_code_without_debug_info = true;
             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
-            new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
-                                                            eStepTypeInto,
-                                                            sc.line_entry.range,
-                                                            sc,
-                                                            stop_other_threads,
-                                                            avoid_code_without_debug_info);
+            new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
+                                                              sc.line_entry.range,
+                                                              sc,
+                                                              target_name,
+                                                              stop_other_threads,
+                                                              avoid_code_without_debug_info);
         }
         else
         {

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Wed Dec 12 13:58:40 2012
@@ -325,6 +325,13 @@
                 }
                 break;
 
+            case 't':
+                {
+                    m_step_in_target.clear();
+                    m_step_in_target.assign(option_arg);
+
+                }
+                break;
             default:
                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
                 break;
@@ -339,6 +346,7 @@
             m_avoid_no_debug = true;
             m_run_mode = eOnlyDuringStepping;
             m_avoid_regexp.clear();
+            m_step_in_target.clear();
         }
 
         const OptionDefinition*
@@ -355,6 +363,7 @@
         bool m_avoid_no_debug;
         RunMode m_run_mode;
         std::string m_avoid_regexp;
+        std::string m_step_in_target;
     };
 
     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
@@ -469,9 +478,10 @@
 
                 if (frame->HasDebugInformation ())
                 {
-                    new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type, 
+                    new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
-                                                                    frame->GetSymbolContext(eSymbolContextEverything), 
+                                                                    frame->GetSymbolContext(eSymbolContextEverything),
+                                                                    m_options.m_step_in_target.c_str(),
                                                                     stop_other_threads,
                                                                     m_options.m_avoid_no_debug);
                     if (new_plan && !m_options.m_avoid_regexp.empty())
@@ -489,12 +499,10 @@
                 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
 
                 if (frame->HasDebugInformation())
-                    new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 
-                                                                    m_step_type, 
-                                                                    frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
-                                                                    frame->GetSymbolContext(eSymbolContextEverything), 
-                                                                    stop_other_threads,
-                                                                    false);
+                    new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
+                                                                        frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
+                                                                        frame->GetSymbolContext(eSymbolContextEverything), 
+                                                                        stop_other_threads);
                 else
                     new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 
                                                                                 abort_other_plans, 
@@ -595,7 +603,8 @@
 {
 { LLDB_OPT_SET_1, false, "avoid-no-debug",  'a', required_argument, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether step-in will step over functions with no debug information."},
 { LLDB_OPT_SET_1, false, "run-mode",        'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
-{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to step over."},
+{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
+{ LLDB_OPT_SET_1, false, "step-in-target",  't', required_argument, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
 };
 

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Wed Dec 12 13:58:40 2012
@@ -1188,28 +1188,41 @@
 }
 
 ThreadPlan *
-Thread::QueueThreadPlanForStepRange 
+Thread::QueueThreadPlanForStepOverRange
 (
     bool abort_other_plans, 
-    StepType type, 
     const AddressRange &range, 
-    const SymbolContext &addr_context, 
+    const SymbolContext &addr_context,
+    lldb::RunMode stop_other_threads
+)
+{
+    ThreadPlanSP thread_plan_sp;
+    thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
+
+    QueueThreadPlan (thread_plan_sp, abort_other_plans);
+    return thread_plan_sp.get();
+}
+
+ThreadPlan *
+Thread::QueueThreadPlanForStepInRange
+(
+    bool abort_other_plans, 
+    const AddressRange &range, 
+    const SymbolContext &addr_context,
+    const char *step_in_target,
     lldb::RunMode stop_other_threads,
     bool avoid_code_without_debug_info
 )
 {
     ThreadPlanSP thread_plan_sp;
-    if (type == eStepTypeInto)
-    {
-        ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
-        if (avoid_code_without_debug_info)
-            plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
-        else
-            plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
-        thread_plan_sp.reset (plan);
-    }
+    ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
+    if (avoid_code_without_debug_info)
+        plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
     else
-        thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
+        plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+    if (step_in_target)
+        plan->SetStepInTarget(step_in_target);
+    thread_plan_sp.reset (plan);
 
     QueueThreadPlan (thread_plan_sp, abort_other_plans);
     return thread_plan_sp.get();

Modified: lldb/trunk/source/Target/ThreadPlanStepInRange.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepInRange.cpp?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanStepInRange.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanStepInRange.cpp Wed Dec 12 13:58:40 2012
@@ -52,6 +52,23 @@
     SetFlagsToDefault ();
 }
 
+ThreadPlanStepInRange::ThreadPlanStepInRange
+(
+    Thread &thread,
+    const AddressRange &range,
+    const SymbolContext &addr_context,
+    const char *step_into_target,
+    lldb::RunMode stop_others
+) :
+    ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
+    ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+    m_step_past_prologue (true),
+    m_virtual_step (false),
+    m_step_into_target (step_into_target)
+{
+    SetFlagsToDefault ();
+}
+
 ThreadPlanStepInRange::~ThreadPlanStepInRange ()
 {
 }
@@ -65,6 +82,7 @@
     {
         s->Printf ("Stepping through range (stepping into functions): ");
         DumpRanges(s);
+        s->Printf ("targeting %s.", m_step_into_target.AsCString());
     }
 }
 
@@ -140,6 +158,7 @@
             }
         
             SetPlanComplete();
+            m_no_more_plans = true;
             return true;
         }
         
@@ -279,15 +298,40 @@
         }
     }
     
-    if (!should_step_out)
+    if (current_plan->GetKind() == eKindStepInRange)
     {
-        if (current_plan->GetKind() == eKindStepInRange)
+        ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
+        if (step_in_range_plan->m_step_into_target)
+        {
+            SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
+            if (sc.symbol != NULL)
+            {
+                // First try an exact match, since that's cheap with ConstStrings.  Then do a strstr compare.
+                if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
+                {
+                    should_step_out = false;
+                }
+                else
+                {
+                    const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
+                    const char *function_name = sc.GetFunctionName().AsCString();
+                    
+                    if (function_name == NULL)
+                        should_step_out = true;
+                    else if (strstr (function_name, target_name) == NULL)
+                        should_step_out = true;
+                }
+            }
+        }
+        
+        if (!should_step_out)
         {
-            ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
-            should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
+                ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
+                should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
         }
     }
     
+    
     if (should_step_out)
     {
         // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
@@ -313,8 +357,12 @@
     // case we'll do our ordinary processing, or we stopped for some
     // reason that isn't handled by our sub-plans, in which case we want to just stop right
     // away.
-    // We also set ourselves complete when we stop for this sort of unintended reason, but mark
-    // success as false so we don't end up being the reason for the stop.
+    // In general, we don't want to mark the plan as complete for unexplained stops.
+    // For instance, if you step in to some code with no debug info, so you step out
+    // and in the course of that hit a breakpoint, then you want to stop & show the user
+    // the breakpoint, but not unship the step in plan, since you still may want to complete that
+    // plan when you continue.  This is particularly true when doing "step in to target function."
+    // stepping.
     //
     // The only variation is that if we are doing "step by running to next branch" in which case
     // if we hit our branch breakpoint we don't set the plan to complete.
@@ -340,8 +388,8 @@
                 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
                 if (log)
                     log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
-                SetPlanComplete(false);
             }
+            return false;
             break;
         default:
             break;

Modified: lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py (original)
+++ lldb/trunk/test/lang/c/stepping/TestStepAndBreakpoints.py Wed Dec 12 13:58:40 2012
@@ -161,6 +161,71 @@
         self.assertTrue (thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == current_line)
         self.assertTrue (thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec() == current_file)
 
+        # Now we are going to test step in targetting a function:
+
+        break_in_b.SetEnabled (False)
+
+        break_before_complex_1 = target.BreakpointCreateBySourceRegex ('// Stop here to try step in targetting b.', self.main_source_spec)
+        self.assertTrue(break_before_complex_1, VALID_BREAKPOINT)
+
+        break_before_complex_2 = target.BreakpointCreateBySourceRegex ('// Stop here to try step in targetting complex.', self.main_source_spec)
+        self.assertTrue(break_before_complex_2, VALID_BREAKPOINT)
+
+        break_before_complex_3 = target.BreakpointCreateBySourceRegex ('// Stop here to step targetting b and hitting breakpoint.', self.main_source_spec)
+        self.assertTrue(break_before_complex_3, VALID_BREAKPOINT)
+
+        break_before_complex_4 = target.BreakpointCreateBySourceRegex ('// Stop here to make sure bogus target steps over.', self.main_source_spec)
+        self.assertTrue(break_before_complex_4, VALID_BREAKPOINT)
+
+        threads = lldbutil.continue_to_breakpoint(process, break_before_complex_1)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+        break_before_complex_1.SetEnabled(False)
+
+        thread.StepInto ("b")
+        self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b")
+
+        # Now continue out and stop at the next call to complex.  This time step all the way into complex:
+        threads = lldbutil.continue_to_breakpoint (process, break_before_complex_2)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+        break_before_complex_2.SetEnabled(False)
+
+        thread.StepInto ("complex")
+        self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "complex")
+        
+        # Now continue out and stop at the next call to complex.  This time enable breakpoints in a and c and then step targetting b:
+        threads = lldbutil.continue_to_breakpoint (process, break_before_complex_3)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+        break_before_complex_3.SetEnabled(False)
+
+        break_at_start_of_a = target.BreakpointCreateByName ('a')
+        break_at_start_of_c = target.BreakpointCreateByName ('c')
+
+        thread.StepInto ("b")
+        threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonBreakpoint);
+
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+        stop_break_id = thread.GetStopReasonDataAtIndex(0)
+        self.assertTrue(stop_break_id == break_at_start_of_a.GetID() or stop_break_id == break_at_start_of_c.GetID())
+
+        break_at_start_of_a.SetEnabled(False)
+        break_at_start_of_c.SetEnabled(False)
+
+        process.Continue()
+        self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b")
+        
+        # Now continue out and stop at the next call to complex.  This time enable breakpoints in a and c and then step targetting b:
+        threads = lldbutil.continue_to_breakpoint (process, break_before_complex_4)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+        break_before_complex_4.SetEnabled(False)
+
+        thread.StepInto("NoSuchFunction")
+        self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "main")
+        
 if __name__ == '__main__':
     import atexit
     lldb.SBDebugger.Initialize()

Modified: lldb/trunk/test/lang/c/stepping/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/stepping/main.c?rev=170008&r1=170007&r2=170008&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/stepping/main.c (original)
+++ lldb/trunk/test/lang/c/stepping/main.c Wed Dec 12 13:58:40 2012
@@ -14,7 +14,7 @@
 
 int a(int val)
 {
-    int return_value = val;
+    int return_value = val;  // basic break at the start of b
 
     if (val <= 1)
     {
@@ -39,6 +39,11 @@
     return val + 3; // Find the line number of function "c" here.
 }
 
+int complex (int first, int second, int third)
+{
+    return first + second + third;  // Step in targetting complex should stop here
+}
+
 int main (int argc, char const *argv[])
 {
     int A1 = a(1); // frame select 2, thread step-out while stopped at "c(1)"
@@ -50,5 +55,13 @@
     int A3 = a(3); // frame select 1, thread step-out while stopped at "c(3)"
     printf("a(3) returns %d\n", A3);
     
+    int A4 = complex (a(1), b(2), c(3)); // Stop here to try step in targetting b.
+
+    int A5 = complex (a(2), b(3), c(4)); // Stop here to try step in targetting complex.
+
+    int A6 = complex (a(4), b(5), c(6)); // Stop here to step targetting b and hitting breakpoint.
+
+    int A7 = complex (a(5), b(6), c(7)); // Stop here to make sure bogus target steps over.
+
     return 0;
 }





More information about the lldb-commits mailing list