forked from OSchip/llvm-project
Adding a new --python-function (-F) option to breakpoint command add. The option allows the user to specify a Python function name instead of a Python oneliner or interactive script input as a breakpoint command
llvm-svn: 154026
This commit is contained in:
parent
f264d5dc01
commit
8d4a8010cf
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
def function(frame, bp_loc, dict):
|
||||
there = open("output2.txt", "w");
|
||||
print >> there, "lldb";
|
||||
there.close()
|
Loading…
Reference in New Issue