[Lldb-commits] [lldb] r261953 - Add the "block" keyword to "thread step-in -e", and an alias that uses it: "sif <target function>" - i.e. step-into-function

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Thu Feb 25 17:37:31 PST 2016


Author: jingham
Date: Thu Feb 25 19:37:30 2016
New Revision: 261953

URL: http://llvm.org/viewvc/llvm-project?rev=261953&view=rev
Log:
Add the "block" keyword to "thread step-in -e", and an alias that uses it: "sif <target function>" - i.e. step-into-function
to allow you to step through a complex calling sequence into a particular function that may span multiple lines.  Also some
test cases for this and the --step-target feature.


Added:
    lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/
    lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py
    lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/main.c
Modified:
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/Makefile?rev=261953&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/Makefile Thu Feb 25 19:37:30 2016
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py?rev=261953&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py Thu Feb 25 19:37:30 2016
@@ -0,0 +1,113 @@
+"""Test the 'step target' feature."""
+
+from __future__ import print_function
+
+import os, time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestStepTarget(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def getCategories(self):
+        return ['basic_process']
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line numbers that we will step to in main:
+        self.main_source = "main.c"
+        self.end_line = line_number(self.main_source, "All done")
+
+    @add_test_categories(['pyapi'])
+
+    def get_to_start (self):
+        self.build()
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        self.main_source_spec = lldb.SBFileSpec (self.main_source)
+
+        break_in_main = target.BreakpointCreateBySourceRegex ('Break here to try targetted stepping', self.main_source_spec)
+        self.assertTrue(break_in_main, VALID_BREAKPOINT)
+        self.assertTrue(break_in_main.GetNumLocations() > 0,"Has locations.")
+
+        # Now launch the process, and do not stop at entry point.
+        process = target.LaunchSimple (None, None, self.get_process_working_directory())
+
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        # The stop reason of the thread should be breakpoint.
+        threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_in_main)
+
+        if len(threads) != 1:
+            self.fail ("Failed to stop at first breakpoint in main.")
+
+        thread = threads[0]
+        return thread
+
+    def test_with_end_line(self):
+        """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms."""
+
+        thread = self.get_to_start()
+
+        error = lldb.SBError()
+        thread.StepInto("lotsOfArgs", self.end_line, error)
+        frame = thread.frames[0]
+
+        self.assertTrue (frame.name == "lotsOfArgs", "Stepped to lotsOfArgs.")
+
+    def test_with_end_line_bad_name(self):
+        """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms."""
+
+        thread = self.get_to_start()
+
+        error = lldb.SBError()
+        thread.StepInto("lotsOfArgssss", self.end_line, error)
+        frame = thread.frames[0]
+        self.assertTrue (frame.line_entry.line == self.end_line, "Stepped to the block end.")
+
+    def test_with_end_line_deeper(self):
+        """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms."""
+
+        thread = self.get_to_start()
+
+        error = lldb.SBError()
+        thread.StepInto("modifyInt", self.end_line, error)
+        frame = thread.frames[0]
+        self.assertTrue (frame.name == "modifyInt", "Stepped to modifyInt.")
+
+    def test_with_command_and_block(self):
+        """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms."""
+
+        thread = self.get_to_start()
+
+        result = lldb.SBCommandReturnObject()
+        self.dbg.GetCommandInterpreter().HandleCommand('thread step-in -t "lotsOfArgs" -e block', result)
+        self.assertTrue(result.Succeeded(), "thread step-in command succeeded.")
+
+        frame = thread.frames[0]
+        self.assertTrue (frame.name == "lotsOfArgs", "Stepped to lotsOfArgs.")
+
+    def test_with_command_and_block_and_bad_name(self):
+        """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms."""
+
+        thread = self.get_to_start()
+
+        result = lldb.SBCommandReturnObject()
+        self.dbg.GetCommandInterpreter().HandleCommand('thread step-in -t "lotsOfArgsssss" -e block', result)
+        self.assertTrue(result.Succeeded(), "thread step-in command succeeded.")
+
+        frame = thread.frames[0]
+
+        self.assertTrue (frame.name == "main", "Stepped back out to main.")
+        # end_line is set to the line after the containing block.  Check that we got there:
+        self.assertTrue(frame.line_entry.line == self.end_line, "Got out of the block")
+
+
+        

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/main.c?rev=261953&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/main.c (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/step-target/main.c Thu Feb 25 19:37:30 2016
@@ -0,0 +1,40 @@
+#include <stdio.h>
+
+void
+lotsOfArgs
+(
+  int firstArg,
+  int secondArg,
+  int thirdArg,
+  int fourthArg
+)
+{
+  printf ("First: %d Second: %d Third: %d Fourth: %d.\n",
+          firstArg,
+          secondArg,
+          thirdArg,
+          fourthArg);
+}
+
+int
+modifyInt(int incoming)
+{
+  return incoming % 2;
+}
+
+int
+main (int argc, char **argv)
+{
+  if (argc > 0)
+    {
+      int var_makes_block = argc + 1;
+      printf ("Break here to try targetted stepping.\n");
+      lotsOfArgs(var_makes_block,
+                 modifyInt(20),
+                 30,
+                 modifyInt(40));
+      printf ("Done calling lotsOfArgs.");
+    }
+  printf ("All done.\n");
+  return 0;
+}

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=261953&r1=261952&r2=261953&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Thu Feb 25 19:37:30 2016
@@ -386,6 +386,11 @@ public:
             
             case 'e':
                 {
+                    if (strcmp(option_arg, "block") == 0)
+                    {
+                        m_end_line_is_block_end = 1;
+                        break;
+                    }
                     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);
@@ -429,6 +434,7 @@ public:
             m_class_name.clear();
             m_step_count = 1;
             m_end_line = LLDB_INVALID_LINE_NUMBER;
+            m_end_line_is_block_end = false;
         }
 
         const OptionDefinition*
@@ -450,6 +456,7 @@ public:
         std::string m_class_name;
         uint32_t m_step_count;
         uint32_t m_end_line;
+        bool     m_end_line_is_block_end;
     };
 
     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
@@ -588,6 +595,30 @@ protected:
                         return false;
                     }
                 }
+                else if (m_options.m_end_line_is_block_end)
+                {
+                    Error error;
+                    Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
+                    if (!block)
+                    {
+                        result.AppendErrorWithFormat("Could not find the current block.");
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                    
+                    AddressRange block_range;
+                    Address pc_address = frame->GetFrameCodeAddress();
+                    block->GetRangeContainingAddress(pc_address, block_range);
+                    if (!block_range.GetBaseAddress().IsValid())
+                    {
+                        result.AppendErrorWithFormat("Could not find the current block address.");
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                    lldb::addr_t pc_offset_in_block = pc_address.GetFileAddress() - block_range.GetBaseAddress().GetFileAddress();
+                    lldb::addr_t range_length = block_range.GetByteSize() - pc_offset_in_block;
+                    range = AddressRange(pc_address, range_length);
+                }
                 else
                 {
                     range = sc.line_entry.range;
@@ -741,7 +772,9 @@ CommandObjectThreadStepWithTypeAndScope:
 { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, nullptr, nullptr,               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, nullptr, nullptr,               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, nullptr, nullptr,               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, nullptr, nullptr,               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, "end-linenumber",            'e', OptionParser::eRequiredArgument, nullptr, nullptr,               1, eArgTypeLineNum,     "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over."
+                                                                                                                                              "  You can also pass the string 'block' to step to the end of the current block."
+                                                                                                                                              "  This is particularly useful in conjunction with --step-target to step through a complex calling sequence."},
 { LLDB_OPT_SET_1, false, "run-mode",                  'm', OptionParser::eRequiredArgument, nullptr, 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, nullptr, nullptr,               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, nullptr, nullptr,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=261953&r1=261952&r2=261953&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Thu Feb 25 19:37:30 2016
@@ -185,6 +185,9 @@ CommandInterpreter::Initialize ()
 
     LoadCommandDictionary ();
 
+    // An alias arguments vector to reuse - reset it before use...
+    OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
+    
     // Set up some initial aliases.
     CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
     if (cmd_obj_sp)
@@ -239,6 +242,11 @@ CommandInterpreter::Initialize ()
     {
         AddAlias ("s", cmd_obj_sp);
         AddAlias ("step", cmd_obj_sp);
+        
+        alias_arguments_vector_sp.reset (new OptionArgVector);
+        ProcessAliasOptionsArgs (cmd_obj_sp, "--end-linenumber block --step-in-target %1", alias_arguments_vector_sp);
+        AddAlias ("sif", cmd_obj_sp);
+        AddOrReplaceAliasOptions("sif", alias_arguments_vector_sp);
     }
 
     cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
@@ -329,8 +337,6 @@ CommandInterpreter::Initialize ()
         AddAlias ("image", cmd_obj_sp);
 
 
-    OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
-    
     cmd_obj_sp = GetCommandSPExact ("expression", false);
     if (cmd_obj_sp)
     {        




More information about the lldb-commits mailing list