<div dir="ltr">Seems like kind of an obscure command.  Why not just set a one-shot breakpoint on foo by name, then continue, so that the first time the breakpoint hits it gets removed.<div><br></div><div>Also what happens if bar() calls foo()?</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Feb 9, 2016 at 7:29 PM Jim Ingham via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jingham<br>
Date: Tue Feb  9 21:25:24 2016<br>
New Revision: 260352<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=260352&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=260352&view=rev</a><br>
Log:<br>
This is an idea to make "thread step-in --target" work for the common<br>
case where you have:<br>
<br>
1 ->    foo (bar(),<br>
2            baz(),<br>
3            lala());<br>
4<br>
<br>
You are sitting on line 1, and want to step into foo, but not bar, baz & lala.  Unfortunately<br>
there are line table entries for lines 1-3, and lldb doesn't know anything about the nesting<br>
of statement in these lines.  So we'll have to use the user's intelligence...  This patch adds:<br>
<br>
(lldb) thread step-in -t foo --end-line 4<br>
<br>
That tells lldb to keep stepping in till line 4, but stop if you step into foo.  I think I would<br>
remember to use this when faced with some of the long gnarly call sequences in lldb.  But there<br>
might be ways I haven't thought of to make it more convenient.  Jason suggests having "end" as a<br>
special token for --end-line which just means keep going to the end of the function, I really want<br>
to get into this thing...<br>
<br>
There should be an SB API and tests, which will come if this seems useful.<br>
<br>
Modified:<br>
    lldb/trunk/source/Commands/CommandObjectThread.cpp<br>
<br>
Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=260352&r1=260351&r2=260352&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=260352&r1=260351&r2=260352&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)<br>
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Tue Feb  9 21:25:24 2016<br>
@@ -386,7 +386,7 @@ public:<br>
                 {<br>
                     m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);<br>
                     if (m_step_count == UINT32_MAX)<br>
-                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);<br>
+                       error.SetErrorStringWithFormat ("invalid step count '%s'", option_arg);<br>
                     break;<br>
                 }<br>
                 break;<br>
@@ -403,6 +403,16 @@ public:<br>
                 }<br>
                 break;<br>
<br>
+            case 'e':<br>
+                {<br>
+                    uint32_t tmp_end_line = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);<br>
+                    if (tmp_end_line == UINT32_MAX)<br>
+                       error.SetErrorStringWithFormat ("invalid end line number '%s'", option_arg);<br>
+                    else<br>
+                        m_end_line = tmp_end_line;<br>
+                    break;<br>
+                }<br>
+                break;<br>
             case 'r':<br>
                 {<br>
                     m_avoid_regexp.clear();<br>
@@ -441,6 +451,7 @@ public:<br>
             m_step_in_target.clear();<br>
             m_class_name.clear();<br>
             m_step_count = 1;<br>
+            m_end_line = LLDB_INVALID_LINE_NUMBER;<br>
         }<br>
<br>
         const OptionDefinition*<br>
@@ -461,6 +472,7 @@ public:<br>
         std::string m_step_in_target;<br>
         std::string m_class_name;<br>
         uint32_t m_step_count;<br>
+        uint32_t m_end_line;<br>
     };<br>
<br>
     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,<br>
@@ -559,6 +571,14 @@ protected:<br>
             }<br>
         }<br>
<br>
+        if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER<br>
+            && m_step_type != eStepTypeInto)<br>
+        {<br>
+            result.AppendErrorWithFormat("end line option is only valid for step into");<br>
+            result.SetStatus(eReturnStatusFailed);<br>
+            return false;<br>
+        }<br>
+<br>
         const bool abort_other_plans = false;<br>
         const lldb::RunMode stop_other_threads = m_options.m_run_mode;<br>
<br>
@@ -586,8 +606,70 @@ protected:<br>
<br>
             if (frame->HasDebugInformation ())<br>
             {<br>
+                AddressRange range = frame->GetSymbolContext(eSymbolContextEverything).line_entry.range;<br>
+                if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER)<br>
+                {<br>
+                    SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything);<br>
+                    if (sc.line_entry.line > m_options.m_end_line)<br>
+                    {<br>
+                        result.AppendErrorWithFormat("end line option %d must be after the current line: %d",<br>
+                                                     m_options.m_end_line,<br>
+                                                     sc.line_entry.line);<br>
+                        result.SetStatus(eReturnStatusFailed);<br>
+                        return false;<br>
+                    }<br>
+<br>
+                    CompileUnit *cu = sc.comp_unit;<br>
+                    uint32_t line_index = 0;<br>
+                    bool found = false;<br>
+                    while (1)<br>
+                    {<br>
+                        LineEntry this_line;<br>
+                        line_index = cu->FindLineEntry(line_index, sc.line_entry.line, nullptr, false, &this_line);<br>
+                        if (line_index == UINT32_MAX)<br>
+                            break;<br>
+                        if (LineEntry::Compare(this_line, sc.line_entry) == 0)<br>
+                        {<br>
+                            found = true;<br>
+                            break;<br>
+                        }<br>
+                    }<br>
+                    LineEntry end_entry;<br>
+                    if (!found)<br>
+                    {<br>
+                        // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit.<br>
+                        result.AppendErrorWithFormat("Can't find the current line entry in the CompUnit - can't process "<br>
+                                                     "the end-line option");<br>
+                        result.SetStatus(eReturnStatusFailed);<br>
+                        return false;<br>
+                    }<br>
+<br>
+                    line_index = cu->FindLineEntry(line_index, m_options.m_end_line, nullptr, false, &end_entry);<br>
+                    if (line_index == UINT32_MAX)<br>
+                    {<br>
+                        result.AppendErrorWithFormat("could not find a line table entry corresponding "<br>
+                                                     "to end line number %d",<br>
+                                                     m_options.m_end_line);<br>
+                        result.SetStatus(eReturnStatusFailed);<br>
+                        return false;<br>
+                    }<br>
+<br>
+                    Block *func_block = sc.GetFunctionBlock();<br>
+                    if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX)<br>
+                    {<br>
+                        result.AppendErrorWithFormat("end line number %d is not contained within the current function.",<br>
+                                                     m_options.m_end_line);<br>
+                        result.SetStatus(eReturnStatusFailed);<br>
+                        return false;<br>
+                    }<br>
+<br>
+                    lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress()<br>
+                                              - range.GetBaseAddress().GetFileAddress();<br>
+                    range.SetByteSize(range_size);<br>
+                }<br>
+<br>
                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,<br>
-                                                                frame->GetSymbolContext(eSymbolContextEverything).line_entry,<br>
+                                                                range,<br>
                                                                 frame->GetSymbolContext(eSymbolContextEverything),<br>
                                                                 m_options.m_step_in_target.c_str(),<br>
                                                                 stop_other_threads,<br>
@@ -737,6 +819,7 @@ CommandObjectThreadStepWithTypeAndScope:<br>
 { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether stepping into functions will step over functions with no debug information."},<br>
 { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug",  'A', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."},<br>
 { LLDB_OPT_SET_1, false, "count",                     'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},<br>
+{ LLDB_OPT_SET_1, false, "end-linenumber",            'e', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeLineNum,     "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over."},<br>
 { LLDB_OPT_SET_1, false, "run-mode",                  'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},<br>
 { LLDB_OPT_SET_1, false, "step-over-regexp",          'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},<br>
 { LLDB_OPT_SET_1, false, "step-in-target",            't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits</a><br>
</blockquote></div>