summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp43
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.h1
-rw-r--r--lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py23
-rw-r--r--lldb/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py4
4 files changed, 65 insertions, 6 deletions
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index 5ab93d72632..dcc9f9bb858 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -37,7 +37,8 @@ CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions (CommandInterp
m_use_script_language (false),
m_script_language (eScriptLanguageNone),
m_use_one_liner (false),
- m_one_liner()
+ m_one_liner(),
+ m_function_name()
{
}
@@ -60,7 +61,7 @@ g_script_option_enumeration[4] =
OptionDefinition
CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
"Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, NULL, eArgTypeBoolean,
@@ -69,6 +70,9 @@ CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, NULL, eArgTypeNone,
"Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
+ { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, NULL, eArgTypePythonFunction,
+ "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
+
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -104,12 +108,10 @@ CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
{
- m_use_commands = false;
m_use_script_language = true;
}
else
{
- m_use_commands = true;
m_use_script_language = false;
}
break;
@@ -122,6 +124,14 @@ CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
}
break;
+
+ case 'F':
+ {
+ m_use_one_liner = false;
+ m_use_script_language = true;
+ m_function_name.assign(option_arg);
+ }
+ break;
default:
break;
@@ -139,6 +149,7 @@ CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting ()
m_use_one_liner = false;
m_stop_on_error = true;
m_one_liner.clear();
+ m_function_name.clear();
}
//-------------------------------------------------------------------------
@@ -191,7 +202,8 @@ Note: Because loose Python code gets collected into functions, if you \n\
want to access global variables in the 'loose' code, you need to \n\
specify that they are global, using the 'global' keyword. Be sure to \n\
use correct Python syntax, including indentation, when entering Python \n\
-breakpoint commands. \n\
+breakpoint commands. \nAs a third option, you can pass the name of an already \
+existing Python function and that function will be attached to the breakpoint. \n\
\n\
Example Python one-line breakpoint command: \n\
\n\
@@ -304,6 +316,13 @@ CommandObjectBreakpointCommandAdd::Execute
return false;
}
+ if (m_options.m_use_script_language == false && m_options.m_function_name.size())
+ {
+ result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
BreakpointIDList valid_bp_ids;
CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
@@ -341,11 +360,25 @@ CommandObjectBreakpointCommandAdd::Execute
{
// Special handling for one-liner specified inline.
if (m_options.m_use_one_liner)
+ {
m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
m_options.m_one_liner.c_str());
+ }
+ // Special handling for using a Python function by name
+ // instead of extending the breakpoint callback data structures, we just automatize
+ // what the user would do manually: make their breakpoint command be a function call
+ else if (m_options.m_function_name.size())
+ {
+ std::string oneliner(m_options.m_function_name);
+ oneliner += "(frame, bp_loc, dict)";
+ m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
+ oneliner.c_str());
+ }
else
+ {
m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
result);
+ }
}
else
{
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.h b/lldb/source/Commands/CommandObjectBreakpointCommand.h
index 65f72d0e290..91b99fef963 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.h
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.h
@@ -123,6 +123,7 @@ public:
bool m_use_one_liner;
std::string m_one_liner;
bool m_stop_on_error;
+ std::string m_function_name;
};
private:
diff --git a/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index 616464e2104..601237c17dd 100644
--- a/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -40,7 +40,7 @@ class BreakpointCommandTestCase(TestBase):
exe = os.path.join(os.getcwd(), "a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
- # Add two breakpoints on the same line. The first time we don't specify the file,
+ # Add three breakpoints on the same line. The first time we don't specify the file,
# since the default file is the one containing main:
self.expect("breakpoint set -l %d" % self.line,
BREAKPOINT_CREATED,
@@ -50,10 +50,15 @@ class BreakpointCommandTestCase(TestBase):
BREAKPOINT_CREATED,
startstr = "Breakpoint created: 2: file ='main.c', line = %d, locations = 1" %
self.line)
+ self.expect("breakpoint set -f main.c -l %d" % self.line,
+ BREAKPOINT_CREATED,
+ startstr = "Breakpoint created: 3: file ='main.c', line = %d, locations = 1" %
+ self.line)
# Now add callbacks for the breakpoints just created.
self.runCmd("breakpoint command add -s command -o 'frame variable -T -s' 1")
self.runCmd("breakpoint command add -s python -o 'here = open(\"output.txt\", \"w\"); print >> here, \"lldb\"; here.close()' 2")
+ self.runCmd("breakpoint command add --python-function bktptcmd.function 3")
# Check that the breakpoint commands are correctly set.
@@ -76,6 +81,11 @@ class BreakpointCommandTestCase(TestBase):
"here = open",
"print >> here",
"here.close()"])
+ self.expect("breakpoint command list 3", "Breakpoint 3 command ok",
+ substrs = ["Breakpoint commands:",
+ "bktptcmd.function(frame, bp_loc, dict)"])
+
+ self.runCmd("command script import --allow-reload ./bktptcmd.py")
# Next lets try some other breakpoint kinds. First break with a regular expression
# and then specify only one file. The first time we should get two locations,
@@ -99,6 +109,8 @@ class BreakpointCommandTestCase(TestBase):
# Run the program. Remove 'output.txt' if it exists.
if os.path.exists('output.txt'):
os.remove('output.txt')
+ if os.path.exists('output2.txt'):
+ os.remove('output2.txt')
self.runCmd("run", RUN_SUCCEEDED)
# Check that the file 'output.txt' exists and contains the string "lldb".
@@ -106,6 +118,8 @@ class BreakpointCommandTestCase(TestBase):
# The 'output.txt' file should now exist.
self.assertTrue(os.path.isfile("output.txt"),
"'output.txt' exists due to breakpoint command for breakpoint 2.")
+ self.assertTrue(os.path.isfile("output2.txt"),
+ "'output2.txt' exists due to breakpoint command for breakpoint 3.")
# Read the output file produced by running the program.
with open('output.txt', 'r') as f:
@@ -114,6 +128,13 @@ class BreakpointCommandTestCase(TestBase):
self.expect(output, "File 'output.txt' and the content matches", exe=False,
startstr = "lldb")
+ with open('output2.txt', 'r') as f:
+ output = f.read()
+
+ self.expect(output, "File 'output2.txt' and the content matches", exe=False,
+ startstr = "lldb")
+
+
# Finish the program.
self.runCmd("process continue")
diff --git a/lldb/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py b/lldb/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py
new file mode 100644
index 00000000000..30186641c64
--- /dev/null
+++ b/lldb/test/functionalities/breakpoint/breakpoint_command/bktptcmd.py
@@ -0,0 +1,4 @@
+def function(frame, bp_loc, dict):
+ there = open("output2.txt", "w");
+ print >> there, "lldb";
+ there.close()
OpenPOWER on IntegriCloud