[Lldb-commits] [lldb] r260352 - This is an idea to make "thread step-in --target" work for the common

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 9 19:25:25 PST 2016


Author: jingham
Date: Tue Feb  9 21:25:24 2016
New Revision: 260352

URL: http://llvm.org/viewvc/llvm-project?rev=260352&view=rev
Log:
This is an idea to make "thread step-in --target" work for the common
case where you have:

1 ->    foo (bar(),
2            baz(),
3            lala());
4

You are sitting on line 1, and want to step into foo, but not bar, baz & lala.  Unfortunately
there are line table entries for lines 1-3, and lldb doesn't know anything about the nesting
of statement in these lines.  So we'll have to use the user's intelligence...  This patch adds:

(lldb) thread step-in -t foo --end-line 4

That tells lldb to keep stepping in till line 4, but stop if you step into foo.  I think I would
remember to use this when faced with some of the long gnarly call sequences in lldb.  But there
might be ways I haven't thought of to make it more convenient.  Jason suggests having "end" as a
special token for --end-line which just means keep going to the end of the function, I really want
to get into this thing...

There should be an SB API and tests, which will come if this seems useful.

Modified:
    lldb/trunk/source/Commands/CommandObjectThread.cpp

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=260352&r1=260351&r2=260352&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Tue Feb  9 21:25:24 2016
@@ -386,7 +386,7 @@ public:
                 {
                     m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
                     if (m_step_count == UINT32_MAX)
-                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
+                       error.SetErrorStringWithFormat ("invalid step count '%s'", option_arg);
                     break;
                 }
                 break;
@@ -403,6 +403,16 @@ public:
                 }
                 break;
             
+            case 'e':
+                {
+                    uint32_t tmp_end_line = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
+                    if (tmp_end_line == UINT32_MAX)
+                       error.SetErrorStringWithFormat ("invalid end line number '%s'", option_arg);
+                    else
+                        m_end_line = tmp_end_line;
+                    break;
+                }
+                break;
             case 'r':
                 {
                     m_avoid_regexp.clear();
@@ -441,6 +451,7 @@ public:
             m_step_in_target.clear();
             m_class_name.clear();
             m_step_count = 1;
+            m_end_line = LLDB_INVALID_LINE_NUMBER;
         }
 
         const OptionDefinition*
@@ -461,6 +472,7 @@ public:
         std::string m_step_in_target;
         std::string m_class_name;
         uint32_t m_step_count;
+        uint32_t m_end_line;
     };
 
     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
@@ -559,6 +571,14 @@ protected:
             }
         }
 
+        if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER
+            && m_step_type != eStepTypeInto)
+        {
+            result.AppendErrorWithFormat("end line option is only valid for step into");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+        
         const bool abort_other_plans = false;
         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
         
@@ -586,8 +606,70 @@ protected:
 
             if (frame->HasDebugInformation ())
             {
+                AddressRange range = frame->GetSymbolContext(eSymbolContextEverything).line_entry.range;
+                if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER)
+                {
+                    SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything);
+                    if (sc.line_entry.line > m_options.m_end_line)
+                    {
+                        result.AppendErrorWithFormat("end line option %d must be after the current line: %d",
+                                                     m_options.m_end_line,
+                                                     sc.line_entry.line);
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+
+                    CompileUnit *cu = sc.comp_unit;
+                    uint32_t line_index = 0;
+                    bool found = false;
+                    while (1)
+                    {
+                        LineEntry this_line;
+                        line_index = cu->FindLineEntry(line_index, sc.line_entry.line, nullptr, false, &this_line);
+                        if (line_index == UINT32_MAX)
+                            break;
+                        if (LineEntry::Compare(this_line, sc.line_entry) == 0)
+                        {
+                            found = true;
+                            break;
+                        }
+                    }
+                    LineEntry end_entry;
+                    if (!found)
+                    {
+                        // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit.
+                        result.AppendErrorWithFormat("Can't find the current line entry in the CompUnit - can't process "
+                                                     "the end-line option");
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                    
+                    line_index = cu->FindLineEntry(line_index, m_options.m_end_line, nullptr, false, &end_entry);
+                    if (line_index == UINT32_MAX)
+                    {
+                        result.AppendErrorWithFormat("could not find a line table entry corresponding "
+                                                     "to end line number %d",
+                                                     m_options.m_end_line);
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                    
+                    Block *func_block = sc.GetFunctionBlock();
+                    if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX)
+                    {
+                        result.AppendErrorWithFormat("end line number %d is not contained within the current function.",
+                                                     m_options.m_end_line);
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                    
+                    lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress()
+                                              - range.GetBaseAddress().GetFileAddress();
+                    range.SetByteSize(range_size);
+                }
+                
                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
-                                                                frame->GetSymbolContext(eSymbolContextEverything).line_entry,
+                                                                range,
                                                                 frame->GetSymbolContext(eSymbolContextEverything),
                                                                 m_options.m_step_in_target.c_str(),
                                                                 stop_other_threads,
@@ -737,6 +819,7 @@ CommandObjectThreadStepWithTypeAndScope:
 { 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."},
 { 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."},
 { 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."},
+{ 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."},
 { 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."},
 { 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."},
 { 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."},




More information about the lldb-commits mailing list