[Lldb-commits] [lldb] r113596 - in /lldb/trunk: include/lldb/Interpreter/ScriptInterpreter.h include/lldb/Interpreter/ScriptInterpreterPython.h source/Commands/CommandObjectBreakpointCommand.cpp source/Interpreter/ScriptInterpreterPython.cpp test/conditional_break/TestConditionalBreak.py

Jim Ingham jingham at apple.com
Fri Sep 10 12:38:27 PDT 2010


This is a fine idea, but can we do is some other way than by relying on there being only one breakpoint-id given to "command add"?  It would actually be convenient to do:

breakpoint command add -p 1 3 5 6
> commands
> DONE

and have the commands apply to the list of breakpoints.  I intended to do this but just haven't gotten around to it...

Also, it looks like your implementation only works for script command callbacks?  Seems equally useful to add a little command-line one-liner.  

So maybe it would be better to add an option which takes the command data directly.  Maybe use "-d" for data or "-o" for one-liner?  Anyway then you'd do

(lldb) breakpoint command add -p -d "Script Data" <breakpoint-id>

or

(lldb) breakpoint command add -c -d "backtrace" <breakpoint-id>

and then:

(lldb) breakpoint command add -c -d "backtrace" 1 2 3 4 5

when I get around to adding breakpoint lists to the arguments, which would be really handy.

Another thing about putting it into an option is that it would be pretty easy to then make a "command completer" so you could use <TAB> in the "Script Data".  It's possible to add completers to inhomogenous positional arguments but it's more work.

Jim

On Sep 10, 2010, at 11:21 AM, Johnny Chen wrote:

> Author: johnny
> Date: Fri Sep 10 13:21:10 2010
> New Revision: 113596
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=113596&view=rev
> Log:
> Added the capability to specify a one-liner Python script as the callback
> command for a breakpoint, for example:
> 
> (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
> 
> The ScriptInterpreter interface has an extra method:
> 
>    /// Set a one-liner as the callback for the breakpoint command.
>    virtual void 
>    SetBreakpointCommandCallback (CommandInterpreter &interpreter,
>                                  BreakpointOptions *bp_options,
>                                  const char *oneliner);
> 
> to accomplish the above.
> 
> Also added a test case to demonstrate lldb's use of breakpoint callback command
> to stop at function c() only when its immediate caller is function a().  The
> following session shows the user entering the following commands:
> 
> 1) command source .lldb (set up executable, breakpoint, and breakpoint command)
> 2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a())
> 3) bt (to see that indeed c()'s immediate caller is a())
> 4) c (to continue and finish the program)
> 
> test/conditional_break $ ../../build/Debug/lldb
> (lldb) command source .lldb
> Executing commands in '.lldb'.
> (lldb) file a.out
> Current executable set to 'a.out' (x86_64).
> (lldb) breakpoint set -n c
> Breakpoint created: 1: name = 'c', locations = 1
> (lldb) script import sys, os
> (lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir))
> (lldb) script import conditional_break
> (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()"
> (lldb) run
> run
> Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out'  (x86_64)
> (lldb) Checking call frames...
> Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
>  frame #0: a.out`c at main.c:39
>  frame #1: a.out`b at main.c:34
>  frame #2: a.out`a at main.c:25
>  frame #3: a.out`main at main.c:44
>  frame #4: a.out`start
> c called from b
> Continuing...
> Checking call frames...
> Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
>  frame #0: a.out`c at main.c:39
>  frame #1: a.out`b at main.c:34
>  frame #2: a.out`main at main.c:47
>  frame #3: a.out`start
> c called from b
> Continuing...
> Checking call frames...
> Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread:
>  frame #0: a.out`c at main.c:39
>  frame #1: a.out`a at main.c:27
>  frame #2: a.out`main at main.c:50
>  frame #3: a.out`start
> c called from a
> Stopped at c() with immediate caller as a().
> a(1) returns 4
> b(2) returns 5
> Process 20420 Stopped
> * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
>  36   	
>  37   	int c(int val)
>  38   	{
>  39 ->	    return val + 3;
>  40   	}
>  41   	
>  42   	int main (int argc, char const *argv[])
> (lldb) bt
> bt
> thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
>  frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39
>  frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27
>  frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50
>  frame #3: 0x0000000100000d88 a.out`start + 52
> (lldb) c
> c
> Resuming process 20420
> Process 20420 Exited
> a(3) returns 6
> (lldb) 
> 
> Modified:
>    lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
>    lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
>    lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
>    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
>    lldb/trunk/test/conditional_break/TestConditionalBreak.py
> 
> Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=113596&r1=113595&r2=113596&view=diff
> ==============================================================================
> --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)
> +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Fri Sep 10 13:21:10 2010
> @@ -77,6 +77,15 @@
>                                              BreakpointOptions *bp_options,
>                                              CommandReturnObject &result);
> 
> +    /// Set a one-liner as the callback for the breakpoint command.
> +    virtual void 
> +    SetBreakpointCommandCallback (CommandInterpreter &interpreter,
> +                                  BreakpointOptions *bp_options,
> +                                  const char *oneliner)
> +    {
> +        return;
> +    }
> +
>     const char *
>     GetScriptInterpreterPtyName ();
> 
> 
> Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=113596&r1=113595&r2=113596&view=diff
> ==============================================================================
> --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
> +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Fri Sep 10 13:21:10 2010
> @@ -62,6 +62,12 @@
>                                              BreakpointOptions *bp_options,
>                                              CommandReturnObject &result);
> 
> +    /// Set a one-liner as the callback for the breakpoint command.
> +    void 
> +    SetBreakpointCommandCallback (CommandInterpreter &interpreter,
> +                                  BreakpointOptions *bp_options,
> +                                  const char *oneliner);
> +
>     StringList
>     ReadCommandInputFromUser (FILE *in_file);
> 
> 
> Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp?rev=113596&r1=113595&r2=113596&view=diff
> ==============================================================================
> --- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp (original)
> +++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp Fri Sep 10 13:21:10 2010
> @@ -258,9 +258,15 @@
>                     {
>                         if (m_options.m_use_script_language)
>                         {
> -                            interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter,
> -                                                                                                         bp_loc_sp->GetLocationOptions(),
> -                                                                                                         result);
> +                            // Special handling for one-liner.
> +                            if (command.GetArgumentCount() == 2)
> +                                interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (interpreter,
> +                                                                                                  bp_loc_sp->GetLocationOptions(),
> +                                                                                                  command.GetArgumentAtIndex(1));
> +                            else
> +                                interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter,
> +                                                                                                             bp_loc_sp->GetLocationOptions(),
> +                                                                                                             result);
>                         }
>                         else
>                         {
> @@ -274,9 +280,15 @@
>                 {
>                     if (m_options.m_use_script_language)
>                     {
> -                        interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter,
> -                                                                                                     bp->GetOptions(),
> -                                                                                                     result);
> +                        // Special handling for one-liner.
> +                        if (command.GetArgumentCount() == 2)
> +                            interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (interpreter,
> +                                                                                              bp->GetOptions(),
> +                                                                                              command.GetArgumentAtIndex(1));
> +                        else
> +                            interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter,
> +                                                                                                         bp->GetOptions(),
> +                                                                                                         result);
>                     }
>                     else
>                     {
> 
> Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=113596&r1=113595&r2=113596&view=diff
> ==============================================================================
> --- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
> +++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Fri Sep 10 13:21:10 2010
> @@ -653,6 +653,26 @@
>     }
> }
> 
> +// Set a Python one-liner as the callback for the breakpoint command.
> +void
> +ScriptInterpreterPython::SetBreakpointCommandCallback (CommandInterpreter &interpreter,
> +                                                       BreakpointOptions *bp_options,
> +                                                       const char *oneliner)
> +{
> +    std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
> +
> +    // It's necessary to set both user_source and script_source to the oneliner.
> +    // The former is used to generate callback description (as in breakpoint command list)
> +    // while the latter is used for Python to interpret during the actual callback.
> +    data_ap->user_source.AppendString (oneliner);
> +    data_ap->script_source.AppendString (oneliner);
> +
> +    BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
> +    bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
> +
> +    return;
> +}
> +
> bool
> ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
> {
> 
> Modified: lldb/trunk/test/conditional_break/TestConditionalBreak.py
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/conditional_break/TestConditionalBreak.py?rev=113596&r1=113595&r2=113596&view=diff
> ==============================================================================
> --- lldb/trunk/test/conditional_break/TestConditionalBreak.py (original)
> +++ lldb/trunk/test/conditional_break/TestConditionalBreak.py Fri Sep 10 13:21:10 2010
> @@ -13,16 +13,27 @@
>     mydir = "conditional_break"
> 
>     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
> -    def test_with_dsym(self):
> +    def test_with_dsym_python(self):
>         """Exercise some thread and frame APIs to break if c() is called by a()."""
>         self.buildDsym()
>         self.do_conditional_break()
> 
> -    def test_with_dwarf(self):
> +    def test_with_dwarf_python(self):
>         """Exercise some thread and frame APIs to break if c() is called by a()."""
>         self.buildDwarf()
>         self.do_conditional_break()
> 
> +    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
> +    def test_with_dsym_command(self):
> +        """Simulate a user using lldb commands to break on c() if called from a()."""
> +        self.buildDsym()
> +        self.simulate_conditional_break_by_user()
> +
> +    def test_with_dwarf_command(self):
> +        """Simulate a user using lldb commands to break on c() if called from a()."""
> +        self.buildDwarf()
> +        self.simulate_conditional_break_by_user()
> +
>     def do_conditional_break(self):
>         """Exercise some thread and frame APIs to break if c() is called by a()."""
>         exe = os.path.join(os.getcwd(), "a.out")
> @@ -70,6 +81,33 @@
>             #process.Continue()
>             self.runCmd("process continue")
> 
> +    def simulate_conditional_break_by_user(self):
> +        """Simulate a user using lldb commands to break on c() if called from a()."""
> +
> +        # Sourcing .lldb in the current working directory, which sets the main
> +        # executable, sets the breakpoint on c(), and adds the callback for the
> +        # breakpoint such that lldb only stops when the caller of c() is a().
> +        # the "my" package that defines the date() function.
> +        self.runCmd("command source .lldb")
> +
> +        self.runCmd("run", RUN_SUCCEEDED)
> +
> +        # The stop reason of the thread should be breakpoint.
> +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
> +            substrs = ['state is Stopped', 'stop reason = breakpoint'])
> +
> +        # The frame info for frame #0 points to a.out`c and its immediate caller
> +        # (frame #1) points to a.out`a.
> +
> +        self.expect("frame info", "We should stop at c()",
> +            substrs = ["a.out`c"])
> +
> +        # Select our parent frame as the current frame.
> +        self.runCmd("frame select 1")
> +        self.expect("frame info", "The immediate caller should be a()",
> +            substrs = ["a.out`a"])
> +
> +
> 
> if __name__ == '__main__':
>     import atexit
> 
> 
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits





More information about the lldb-commits mailing list