Skip to content

Commit 7d5aec3

Browse files
author
git apple-llvm automerger
committed
Merge commit '738af7a6241c' from llvm.org/master into apple/master
2 parents 93a3b31 + 738af7a commit 7d5aec3

26 files changed

+467
-137
lines changed

lldb/include/lldb/API/SBBreakpoint.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class LLDB_API SBBreakpoint {
9494

9595
void SetScriptCallbackFunction(const char *callback_function_name);
9696

97+
SBError SetScriptCallbackFunction(const char *callback_function_name,
98+
SBStructuredData &extra_args);
99+
97100
void SetCommandLineCommands(SBStringList &commands);
98101

99102
bool GetCommandLineCommands(SBStringList &commands);

lldb/include/lldb/API/SBBreakpointLocation.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@ class LLDB_API SBBreakpointLocation {
5555

5656
void SetScriptCallbackFunction(const char *callback_function_name);
5757

58+
SBError SetScriptCallbackFunction(const char *callback_function_name,
59+
lldb::SBStructuredData &extra_args);
60+
5861
SBError SetScriptCallbackBody(const char *script_body_text);
5962

60-
void SetCommandLineCommands(SBStringList &commands);
63+
void SetCommandLineCommands(lldb::SBStringList &commands);
6164

62-
bool GetCommandLineCommands(SBStringList &commands);
65+
bool GetCommandLineCommands(lldb::SBStringList &commands);
6366

6467
void SetThreadID(lldb::tid_t sb_thread_id);
6568

lldb/include/lldb/API/SBBreakpointName.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,12 @@ class LLDB_API SBBreakpointName {
8585

8686
void SetScriptCallbackFunction(const char *callback_function_name);
8787

88-
void SetCommandLineCommands(SBStringList &commands);
88+
SBError SetScriptCallbackFunction(const char *callback_function_name,
89+
SBStructuredData &extra_args);
8990

90-
bool GetCommandLineCommands(SBStringList &commands);
91+
void SetCommandLineCommands(lldb::SBStringList &commands);
92+
93+
bool GetCommandLineCommands(lldb::SBStringList &commands);
9194

9295
SBError SetScriptCallbackBody(const char *script_body_text);
9396

lldb/include/lldb/API/SBStructuredData.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class SBStructuredData {
9393
friend class SBTarget;
9494
friend class SBThread;
9595
friend class SBThreadPlan;
96+
friend class SBBreakpoint;
97+
friend class SBBreakpointLocation;
98+
friend class SBBreakpointName;
9699

97100
StructuredDataImplUP m_impl_up;
98101
};

lldb/include/lldb/Interpreter/OptionGroupPythonClassWithDict.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ namespace lldb_private {
2424
class OptionGroupPythonClassWithDict : public OptionGroup {
2525
public:
2626
OptionGroupPythonClassWithDict(const char *class_use,
27-
int class_option = 'C',
28-
int key_option = 'k',
29-
int value_option = 'v',
30-
const char *class_long_option = "python-class",
31-
const char *key_long_option = "python-class-key",
32-
const char *value_long_option = "python-class-value",
33-
bool required = false);
27+
bool is_class = true,
28+
int class_option = 'C',
29+
int key_option = 'k',
30+
int value_option = 'v');
3431

3532
~OptionGroupPythonClassWithDict() override;
3633

@@ -48,16 +45,17 @@ class OptionGroupPythonClassWithDict : public OptionGroup {
4845
const StructuredData::DictionarySP GetStructuredData() {
4946
return m_dict_sp;
5047
}
51-
const std::string &GetClassName() {
52-
return m_class_name;
48+
const std::string &GetName() {
49+
return m_name;
5350
}
5451

5552
protected:
56-
std::string m_class_name;
53+
std::string m_name;
5754
std::string m_current_key;
5855
StructuredData::DictionarySP m_dict_sp;
5956
std::string m_class_usage_text, m_key_usage_text, m_value_usage_text;
60-
OptionDefinition m_option_definition[3];
57+
bool m_is_class;
58+
OptionDefinition m_option_definition[4];
6159
};
6260

6361
} // namespace lldb_private

lldb/include/lldb/Interpreter/ScriptInterpreter.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,10 @@ class ScriptInterpreter : public PluginInterface {
120120
return error;
121121
}
122122

123-
virtual Status GenerateBreakpointCommandCallbackData(StringList &input,
124-
std::string &output) {
123+
virtual Status GenerateBreakpointCommandCallbackData(
124+
StringList &input,
125+
std::string &output,
126+
bool has_extra_args) {
125127
Status error;
126128
error.SetErrorString("not implemented");
127129
return error;
@@ -311,14 +313,17 @@ class ScriptInterpreter : public PluginInterface {
311313
return error;
312314
}
313315

314-
void SetBreakpointCommandCallbackFunction(
316+
Status SetBreakpointCommandCallbackFunction(
315317
std::vector<BreakpointOptions *> &bp_options_vec,
316-
const char *function_name);
318+
const char *function_name,
319+
StructuredData::ObjectSP extra_args_sp);
317320

318-
/// Set a one-liner as the callback for the breakpoint.
319-
virtual void
320-
SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
321-
const char *function_name) {}
321+
/// Set a script function as the callback for the breakpoint.
322+
virtual Status
323+
SetBreakpointCommandCallbackFunction(
324+
BreakpointOptions *bp_options,
325+
const char *function_name,
326+
StructuredData::ObjectSP extra_args_sp) {}
322327

323328
/// Set a one-liner as the callback for the watchpoint.
324329
virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
@@ -463,6 +468,12 @@ class ScriptInterpreter : public PluginInterface {
463468
const char *GetScriptInterpreterPtyName();
464469

465470
int GetMasterFileDescriptor();
471+
472+
virtual llvm::Expected<size_t>
473+
GetNumFixedArgumentsForCallable(const llvm::StringRef &callable_name) {
474+
return llvm::createStringError(
475+
llvm::inconvertibleErrorCode(), "Unimplemented function");
476+
}
466477

467478
static std::string LanguageToString(lldb::ScriptLanguage language);
468479

lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class BreakpointCommandTestCase(TestBase):
1818
mydir = TestBase.compute_mydir(__file__)
1919

2020
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
21-
def test_breakpoint_command_sequence(self):
21+
def not_test_breakpoint_command_sequence(self):
2222
"""Test a sequence of breakpoint command add, list, and delete."""
2323
self.build()
2424
self.breakpoint_command_sequence()
@@ -107,6 +107,10 @@ def breakpoint_command_sequence(self):
107107
"breakpoint command add -s command -o 'frame variable --show-types --scope' 1 4")
108108
self.runCmd(
109109
"breakpoint command add -s python -o 'import side_effect; side_effect.one_liner = \"one liner was here\"' 2")
110+
111+
import side_effect
112+
self.runCmd("command script import --allow-reload ./bktptcmd.py")
113+
110114
self.runCmd(
111115
"breakpoint command add --python-function bktptcmd.function 3")
112116

@@ -151,8 +155,6 @@ def breakpoint_command_sequence(self):
151155

152156
self.runCmd("breakpoint delete 4")
153157

154-
self.runCmd("command script import --allow-reload ./bktptcmd.py")
155-
156158
# Next lets try some other breakpoint kinds. First break with a regular expression
157159
# and then specify only one file. The first time we should get two locations,
158160
# the second time only one:

lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,15 @@ class PythonBreakpointCommandSettingTestCase(TestBase):
1919

2020
@add_test_categories(['pyapi'])
2121
def test_step_out_python(self):
22-
"""Test stepping out using avoid-no-debug with dsyms."""
22+
"""Test stepping out using a python breakpoint command."""
2323
self.build()
2424
self.do_set_python_command_from_python()
2525

26+
def test_bkpt_cmd_bad_arguments(self):
27+
"""Test what happens when pass structured data to a command:"""
28+
self.build()
29+
self.do_bad_args_to_python_command()
30+
2631
def setUp(self):
2732
TestBase.setUp(self)
2833
self.main_source = "main.c"
@@ -43,6 +48,18 @@ def do_set_python_command_from_python(self):
4348
"Set break point at this line.", self.main_source_spec)
4449
self.assertTrue(func_bkpt, VALID_BREAKPOINT)
4550

51+
fancy_bkpt = self.target.BreakpointCreateBySourceRegex(
52+
"Set break point at this line.", self.main_source_spec)
53+
self.assertTrue(fancy_bkpt, VALID_BREAKPOINT)
54+
55+
fancier_bkpt = self.target.BreakpointCreateBySourceRegex(
56+
"Set break point at this line.", self.main_source_spec)
57+
self.assertTrue(fancier_bkpt, VALID_BREAKPOINT)
58+
59+
not_so_fancy_bkpt = self.target.BreakpointCreateBySourceRegex(
60+
"Set break point at this line.", self.main_source_spec)
61+
self.assertTrue(not_so_fancy_bkpt, VALID_BREAKPOINT)
62+
4663
# Also test that setting a source regex breakpoint with an empty file
4764
# spec list sets it on all files:
4865
no_files_bkpt = self.target.BreakpointCreateBySourceRegex(
@@ -75,14 +92,37 @@ def do_set_python_command_from_python(self):
7592
"Failed to set the script callback body: %s." %
7693
(error.GetCString()))
7794

78-
self.dbg.HandleCommand(
79-
"command script import --allow-reload ./bktptcmd.py")
95+
self.expect("command script import --allow-reload ./bktptcmd.py")
96+
8097
func_bkpt.SetScriptCallbackFunction("bktptcmd.function")
8198

99+
extra_args = lldb.SBStructuredData()
100+
stream = lldb.SBStream()
101+
stream.Print('{"side_effect" : "I am fancy"}')
102+
extra_args.SetFromJSON(stream)
103+
error = fancy_bkpt.SetScriptCallbackFunction("bktptcmd.another_function", extra_args)
104+
self.assertTrue(error.Success(), "Failed to add callback %s"%(error.GetCString()))
105+
106+
stream.Clear()
107+
stream.Print('{"side_effect" : "I am so much fancier"}')
108+
extra_args.SetFromJSON(stream)
109+
110+
# Fancier's callback is set up from the command line
111+
id = fancier_bkpt.GetID()
112+
self.expect("breakpoint command add -F bktptcmd.a_third_function -k side_effect -v 'I am fancier' %d"%(id))
113+
114+
# Not so fancy gets an empty extra_args:
115+
empty_args = lldb.SBStructuredData()
116+
error = not_so_fancy_bkpt.SetScriptCallbackFunction("bktptcmd.empty_extra_args", empty_args)
117+
self.assertTrue(error.Success(), "Failed to add callback %s"%(error.GetCString()))
118+
82119
# Clear out canary variables
83120
side_effect.bktptcmd = None
84121
side_effect.callback = None
85-
122+
side_effect.fancy = None
123+
side_effect.fancier = None
124+
side_effect.not_so_fancy = None
125+
86126
# Now launch the process, and do not stop at entry point.
87127
self.process = self.target.LaunchSimple(
88128
None, None, self.get_process_working_directory())
@@ -97,3 +137,38 @@ def do_set_python_command_from_python(self):
97137

98138
self.assertEquals("callback was here", side_effect.callback)
99139
self.assertEquals("function was here", side_effect.bktptcmd)
140+
self.assertEquals("I am fancy", side_effect.fancy)
141+
self.assertEquals("I am fancier", side_effect.fancier)
142+
self.assertEquals("Not so fancy", side_effect.not_so_fancy)
143+
144+
def do_bad_args_to_python_command(self):
145+
exe = self.getBuildArtifact("a.out")
146+
error = lldb.SBError()
147+
148+
self.target = self.dbg.CreateTarget(exe)
149+
self.assertTrue(self.target, VALID_TARGET)
150+
151+
152+
self.expect("command script import --allow-reload ./bktptcmd.py")
153+
154+
bkpt = self.target.BreakpointCreateBySourceRegex(
155+
"Set break point at this line.", self.main_source_spec)
156+
self.assertTrue(bkpt, VALID_BREAKPOINT)
157+
158+
# Pass a breakpoint command function that doesn't take extra_args,
159+
# but pass it extra args:
160+
161+
extra_args = lldb.SBStructuredData()
162+
stream = lldb.SBStream()
163+
stream.Print('{"side_effect" : "I am fancy"}')
164+
extra_args.SetFromJSON(stream)
165+
166+
error = bkpt.SetScriptCallbackFunction("bktptcmd.function", extra_args)
167+
self.assertTrue(error.Fail(), "Can't pass extra args if the function doesn't take them")
168+
169+
error = bkpt.SetScriptCallbackFunction("bktptcmd.useless_function", extra_args)
170+
self.assertTrue(error.Fail(), "Can't pass extra args if the function has wrong number of args.")
171+
172+
error = bkpt.SetScriptCallbackFunction("bktptcmd.nosuch_function", extra_args)
173+
self.assertTrue(error.Fail(), "Can't pass extra args if the function doesn't exist.")
174+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
from __future__ import print_function
22
import side_effect
33

4+
def useless_function(first, second):
5+
print("I have the wrong number of arguments.")
6+
47
def function(frame, bp_loc, dict):
58
side_effect.bktptcmd = "function was here"
9+
10+
def another_function(frame, bp_loc, extra_args, dict):
11+
se_value = extra_args.GetValueForKey("side_effect")
12+
se_string = se_value.GetStringValue(100)
13+
side_effect.fancy = se_string
14+
15+
def a_third_function(frame, bp_loc, extra_args, dict):
16+
se_value = extra_args.GetValueForKey("side_effect")
17+
se_string = se_value.GetStringValue(100)
18+
side_effect.fancier = se_string
19+
20+
def empty_extra_args(frame, bp_loc, extra_args, dict):
21+
if extra_args.IsValid():
22+
side_effect.not_so_fancy = "Extra args should not be valid"
23+
side_effect.not_so_fancy = "Not so fancy"

lldb/scripts/Python/python-wrapper.swig

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ LLDBSwigPythonBreakpointCallbackFunction
4545
const char *python_function_name,
4646
const char *session_dictionary_name,
4747
const lldb::StackFrameSP& frame_sp,
48-
const lldb::BreakpointLocationSP& bp_loc_sp
48+
const lldb::BreakpointLocationSP& bp_loc_sp,
49+
lldb_private::StructuredDataImpl *args_impl
4950
)
5051
{
5152
lldb::SBFrame sb_frame (frame_sp);
@@ -62,7 +63,19 @@ LLDBSwigPythonBreakpointCallbackFunction
6263

6364
PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
6465
PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc));
65-
PythonObject result = pfunc(frame_arg, bp_loc_arg, dict);
66+
67+
PythonObject result;
68+
// If the called function doesn't take extra_args, drop them here:
69+
auto arg_info = pfunc.GetNumArguments();
70+
if (arg_info.count == 3)
71+
result = pfunc(frame_arg, bp_loc_arg, dict);
72+
else if (arg_info.count == 4) {
73+
lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
74+
PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
75+
result = pfunc(frame_arg, bp_loc_arg, args_arg, dict);
76+
} else {
77+
return stop_at_breakpoint;
78+
}
6679

6780
if (result.get() == Py_False)
6881
stop_at_breakpoint = false;

lldb/scripts/interface/SBBreakpoint.i

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ public:
179179
void
180180
SetScriptCallbackFunction (const char *callback_function_name);
181181

182+
%feature("docstring", "
183+
Set the name of the script function to be called when the breakpoint is hit.
184+
To use this variant, the function should take (frame, bp_loc, extra_args, dict) and
185+
when the breakpoint is hit the extra_args will be passed to the callback function.") SetScriptCallbackFunction;
186+
SBError
187+
SetScriptCallbackFunction (const char *callback_function_name,
188+
SBStructuredData &extra_args);
189+
182190
%feature("docstring", "
183191
Provide the body for the script function to be called when the breakpoint is hit.
184192
The body will be wrapped in a function, which be passed two arguments:

lldb/scripts/interface/SBBreakpointLocation.i

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,19 @@ public:
7373
void SetAutoContinue(bool auto_continue);
7474

7575
%feature("docstring", "
76-
Set the callback to the given Python function name.") SetScriptCallbackFunction;
76+
Set the callback to the given Python function name.
77+
The function takes three arguments (frame, bp_loc, dict).") SetScriptCallbackFunction;
7778
void
7879
SetScriptCallbackFunction (const char *callback_function_name);
7980

81+
%feature("docstring", "
82+
Set the name of the script function to be called when the breakpoint is hit.
83+
To use this variant, the function should take (frame, bp_loc, extra_args, dict) and
84+
when the breakpoint is hit the extra_args will be passed to the callback function.") SetScriptCallbackFunction;
85+
SBError
86+
SetScriptCallbackFunction (const char *callback_function_name,
87+
SBStructuredData &extra_args);
88+
8089
%feature("docstring", "
8190
Provide the body for the script function to be called when the breakpoint location is hit.
8291
The body will be wrapped in a function, which be passed two arguments:

lldb/scripts/interface/SBBreakpointName.i

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ public:
8484

8585
void SetScriptCallbackFunction(const char *callback_function_name);
8686

87+
SBError
88+
SetScriptCallbackFunction (const char *callback_function_name,
89+
SBStructuredData &extra_args);
90+
8791
void SetCommandLineCommands(SBStringList &commands);
8892

8993
bool GetCommandLineCommands(SBStringList &commands);

0 commit comments

Comments
 (0)