[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