[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

Johnny Chen johnny.chen at apple.com
Fri Sep 10 13:18:17 PDT 2010


So I broke the "breakpoint command add -p 1 2" use case.
The option thing may be more involved, I'll fix the breakage with a simple workaround for the time being.

On Sep 10, 2010, at 12:38 PM, Jim Ingham wrote:

> 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