1//===-- ScriptInterpreterPythonImpl.h ---------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
10#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
11
12#include "lldb/Host/Config.h"
13
14#if LLDB_ENABLE_PYTHON
15
16#include "lldb-python.h"
17
18#include "PythonDataObjects.h"
19#include "ScriptInterpreterPython.h"
20
21#include "lldb/Host/Terminal.h"
22#include "lldb/Utility/StreamString.h"
23
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/StringRef.h"
26
27namespace lldb_private {
28class IOHandlerPythonInterpreter;
29class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
30public:
31 friend class IOHandlerPythonInterpreter;
32
33 ScriptInterpreterPythonImpl(Debugger &debugger);
34
35 ~ScriptInterpreterPythonImpl() override;
36
37 bool Interrupt() override;
38
39 bool ExecuteOneLine(
40 llvm::StringRef command, CommandReturnObject *result,
41 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
42
43 void ExecuteInterpreterLoop() override;
44
45 bool ExecuteOneLineWithReturn(
46 llvm::StringRef in_string,
47 ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
48 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
49
50 lldb_private::Status ExecuteMultipleLines(
51 const char *in_string,
52 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
53
54 Status
55 ExportFunctionDefinitionToInterpreter(StringList &function_def) override;
56
57 bool GenerateTypeScriptFunction(StringList &input, std::string &output,
58 const void *name_token = nullptr) override;
59
60 bool GenerateTypeSynthClass(StringList &input, std::string &output,
61 const void *name_token = nullptr) override;
62
63 bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
64 const void *name_token = nullptr) override;
65
66 // use this if the function code is just a one-liner script
67 bool GenerateTypeScriptFunction(const char *oneliner, std::string &output,
68 const void *name_token = nullptr) override;
69
70 bool GenerateScriptAliasFunction(StringList &input,
71 std::string &output) override;
72
73 StructuredData::ObjectSP
74 CreateSyntheticScriptedProvider(const char *class_name,
75 lldb::ValueObjectSP valobj) override;
76
77 StructuredData::GenericSP
78 CreateScriptCommandObject(const char *class_name) override;
79
80 StructuredData::ObjectSP
81 CreateScriptedThreadPlan(const char *class_name,
82 const StructuredDataImpl &args_data,
83 std::string &error_str,
84 lldb::ThreadPlanSP thread_plan) override;
85
86 StructuredData::ObjectSP
87 CreateStructuredDataFromScriptObject(ScriptObject obj) override;
88
89 bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
90 Event *event,
91 bool &script_error) override;
92
93 bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
94 Event *event, bool &script_error) override;
95
96 bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
97 bool &script_error) override;
98
99 lldb::StateType
100 ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
101 bool &script_error) override;
102
103 bool
104 ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp,
105 lldb_private::Stream *s,
106 bool &script_error) override;
107
108 StructuredData::GenericSP
109 CreateScriptedBreakpointResolver(const char *class_name,
110 const StructuredDataImpl &args_data,
111 lldb::BreakpointSP &bkpt_sp) override;
112 bool ScriptedBreakpointResolverSearchCallback(
113 StructuredData::GenericSP implementor_sp,
114 SymbolContext *sym_ctx) override;
115
116 lldb::SearchDepth ScriptedBreakpointResolverSearchDepth(
117 StructuredData::GenericSP implementor_sp) override;
118
119 StructuredData::GenericSP
120 CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
121 const StructuredDataImpl &args_data,
122 Status &error) override;
123
124 bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
125 ExecutionContext &exc_ctx,
126 lldb::StreamSP stream_sp) override;
127
128 StructuredData::GenericSP
129 CreateFrameRecognizer(const char *class_name) override;
130
131 lldb::ValueObjectListSP
132 GetRecognizedArguments(const StructuredData::ObjectSP &implementor,
133 lldb::StackFrameSP frame_sp) override;
134
135 lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;
136
137 lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
138
139 lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override;
140
141 StructuredData::ObjectSP
142 LoadPluginModule(const FileSpec &file_spec,
143 lldb_private::Status &error) override;
144
145 StructuredData::DictionarySP
146 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
147 const char *setting_name,
148 lldb_private::Status &error) override;
149
150 size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
151 uint32_t max) override;
152
153 lldb::ValueObjectSP
154 GetChildAtIndex(const StructuredData::ObjectSP &implementor,
155 uint32_t idx) override;
156
157 int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
158 const char *child_name) override;
159
160 bool UpdateSynthProviderInstance(
161 const StructuredData::ObjectSP &implementor) override;
162
163 bool MightHaveChildrenSynthProviderInstance(
164 const StructuredData::ObjectSP &implementor) override;
165
166 lldb::ValueObjectSP
167 GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
168
169 ConstString
170 GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
171
172 bool
173 RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
174 ScriptedCommandSynchronicity synchronicity,
175 lldb_private::CommandReturnObject &cmd_retobj,
176 Status &error,
177 const lldb_private::ExecutionContext &exe_ctx) override;
178
179 bool RunScriptBasedCommand(
180 StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
181 ScriptedCommandSynchronicity synchronicity,
182 lldb_private::CommandReturnObject &cmd_retobj, Status &error,
183 const lldb_private::ExecutionContext &exe_ctx) override;
184
185 virtual bool RunScriptBasedParsedCommand(
186 StructuredData::GenericSP impl_obj_sp, Args& args,
187 ScriptedCommandSynchronicity synchronicity,
188 lldb_private::CommandReturnObject &cmd_retobj, Status &error,
189 const lldb_private::ExecutionContext &exe_ctx) override;
190
191
192 Status GenerateFunction(const char *signature, const StringList &input,
193 bool is_callback) override;
194
195 Status GenerateBreakpointCommandCallbackData(StringList &input,
196 std::string &output,
197 bool has_extra_args,
198 bool is_callback) override;
199
200 bool GenerateWatchpointCommandCallbackData(StringList &input,
201 std::string &output,
202 bool is_callback) override;
203
204 bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
205 StructuredData::ObjectSP &callee_wrapper_sp,
206 const TypeSummaryOptions &options,
207 std::string &retval) override;
208
209 bool FormatterCallbackFunction(const char *function_name,
210 lldb::TypeImplSP type_impl_sp) override;
211
212 bool GetDocumentationForItem(const char *item, std::string &dest) override;
213
214 bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
215 std::string &dest) override;
216
217 uint32_t
218 GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
219
220 bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
221 std::string &dest) override;
222
223 StructuredData::ObjectSP
224 GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
225
226 StructuredData::ObjectSP
227 GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
228
229 bool SetOptionValueForCommandObject(StructuredData::GenericSP cmd_obj_sp,
230 ExecutionContext *exe_ctx,
231 llvm::StringRef long_option,
232 llvm::StringRef value) override;
233
234 void OptionParsingStartedForCommandObject(
235 StructuredData::GenericSP cmd_obj_sp) override;
236
237 bool CheckObjectExists(const char *name) override {
238 if (!name || !name[0])
239 return false;
240 std::string temp;
241 return GetDocumentationForItem(item: name, dest&: temp);
242 }
243
244 bool RunScriptFormatKeyword(const char *impl_function, Process *process,
245 std::string &output, Status &error) override;
246
247 bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
248 std::string &output, Status &error) override;
249
250 bool RunScriptFormatKeyword(const char *impl_function, Target *target,
251 std::string &output, Status &error) override;
252
253 bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
254 std::string &output, Status &error) override;
255
256 bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
257 std::string &output, Status &error) override;
258
259 bool LoadScriptingModule(const char *filename,
260 const LoadScriptOptions &options,
261 lldb_private::Status &error,
262 StructuredData::ObjectSP *module_sp = nullptr,
263 FileSpec extra_search_dir = {}) override;
264
265 bool IsReservedWord(const char *word) override;
266
267 std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
268
269 void CollectDataForBreakpointCommandCallback(
270 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
271 CommandReturnObject &result) override;
272
273 void
274 CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
275 CommandReturnObject &result) override;
276
277 /// Set the callback body text into the callback for the breakpoint.
278 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
279 const char *callback_body,
280 bool is_callback) override;
281
282 Status SetBreakpointCommandCallbackFunction(
283 BreakpointOptions &bp_options, const char *function_name,
284 StructuredData::ObjectSP extra_args_sp) override;
285
286 /// This one is for deserialization:
287 Status SetBreakpointCommandCallback(
288 BreakpointOptions &bp_options,
289 std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
290
291 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
292 const char *command_body_text,
293 StructuredData::ObjectSP extra_args_sp,
294 bool uses_extra_args,
295 bool is_callback);
296
297 /// Set a one-liner as the callback for the watchpoint.
298 void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
299 const char *user_input,
300 bool is_callback) override;
301
302 const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
303
304 PyThreadState *GetThreadState() { return m_command_thread_state; }
305
306 void SetThreadState(PyThreadState *s) {
307 if (s)
308 m_command_thread_state = s;
309 }
310
311 // IOHandlerDelegate
312 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
313
314 void IOHandlerInputComplete(IOHandler &io_handler,
315 std::string &data) override;
316
317 static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
318
319 // PluginInterface protocol
320 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
321
322 class Locker : public ScriptInterpreterLocker {
323 public:
324 enum OnEntry {
325 AcquireLock = 0x0001,
326 InitSession = 0x0002,
327 InitGlobals = 0x0004,
328 NoSTDIN = 0x0008
329 };
330
331 enum OnLeave {
332 FreeLock = 0x0001,
333 FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
334 // when calling constructor
335 TearDownSession = 0x0004
336 };
337
338 Locker(ScriptInterpreterPythonImpl *py_interpreter,
339 uint16_t on_entry = AcquireLock | InitSession,
340 uint16_t on_leave = FreeLock | TearDownSession,
341 lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,
342 lldb::FileSP err = nullptr);
343
344 ~Locker() override;
345
346 private:
347 bool DoAcquireLock();
348
349 bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
350 lldb::FileSP out, lldb::FileSP err);
351
352 bool DoFreeLock();
353
354 bool DoTearDownSession();
355
356 bool m_teardown_session;
357 ScriptInterpreterPythonImpl *m_python_interpreter;
358 PyGILState_STATE m_GILState;
359 };
360
361 static bool BreakpointCallbackFunction(void *baton,
362 StoppointCallbackContext *context,
363 lldb::user_id_t break_id,
364 lldb::user_id_t break_loc_id);
365 static bool WatchpointCallbackFunction(void *baton,
366 StoppointCallbackContext *context,
367 lldb::user_id_t watch_id);
368 static void Initialize();
369
370 class SynchronicityHandler {
371 private:
372 lldb::DebuggerSP m_debugger_sp;
373 ScriptedCommandSynchronicity m_synch_wanted;
374 bool m_old_asynch;
375
376 public:
377 SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
378
379 ~SynchronicityHandler();
380 };
381
382 enum class AddLocation { Beginning, End };
383
384 static void AddToSysPath(AddLocation location, std::string path);
385
386 bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
387 lldb::FileSP err);
388
389 void LeaveSession();
390
391 uint32_t IsExecutingPython() {
392 std::lock_guard<std::mutex> guard(m_mutex);
393 return m_lock_count > 0;
394 }
395
396 uint32_t IncrementLockCount() {
397 std::lock_guard<std::mutex> guard(m_mutex);
398 return ++m_lock_count;
399 }
400
401 uint32_t DecrementLockCount() {
402 std::lock_guard<std::mutex> guard(m_mutex);
403 if (m_lock_count > 0)
404 --m_lock_count;
405 return m_lock_count;
406 }
407
408 enum ActiveIOHandler {
409 eIOHandlerNone,
410 eIOHandlerBreakpoint,
411 eIOHandlerWatchpoint
412 };
413
414 python::PythonModule &GetMainModule();
415
416 python::PythonDictionary &GetSessionDictionary();
417
418 python::PythonDictionary &GetSysModuleDictionary();
419
420 llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
421 const llvm::StringRef &callable_name) override;
422
423 bool GetEmbeddedInterpreterModuleObjects();
424
425 bool SetStdHandle(lldb::FileSP file, const char *py_name,
426 python::PythonObject &save_file, const char *mode);
427
428 python::PythonObject m_saved_stdin;
429 python::PythonObject m_saved_stdout;
430 python::PythonObject m_saved_stderr;
431 python::PythonModule m_main_module;
432 python::PythonDictionary m_session_dict;
433 python::PythonDictionary m_sys_module_dict;
434 python::PythonObject m_run_one_line_function;
435 python::PythonObject m_run_one_line_str_global;
436 std::string m_dictionary_name;
437 ActiveIOHandler m_active_io_handler;
438 bool m_session_is_active;
439 bool m_pty_secondary_is_open;
440 bool m_valid_session;
441 uint32_t m_lock_count;
442 std::mutex m_mutex;
443 PyThreadState *m_command_thread_state;
444};
445
446class IOHandlerPythonInterpreter : public IOHandler {
447public:
448 IOHandlerPythonInterpreter(Debugger &debugger,
449 ScriptInterpreterPythonImpl *python)
450 : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
451 m_python(python) {}
452
453 ~IOHandlerPythonInterpreter() override = default;
454
455 llvm::StringRef GetControlSequence(char ch) override {
456 static constexpr llvm::StringLiteral control_sequence("quit()\n");
457 if (ch == 'd')
458 return control_sequence;
459 return {};
460 }
461
462 void Run() override {
463 if (m_python) {
464 int stdin_fd = GetInputFD();
465 if (stdin_fd >= 0) {
466 Terminal terminal(stdin_fd);
467 TerminalState terminal_state(terminal);
468
469 if (terminal.IsATerminal()) {
470 // FIXME: error handling?
471 llvm::consumeError(Err: terminal.SetCanonical(false));
472 llvm::consumeError(Err: terminal.SetEcho(true));
473 }
474
475 ScriptInterpreterPythonImpl::Locker locker(
476 m_python,
477 ScriptInterpreterPythonImpl::Locker::AcquireLock |
478 ScriptInterpreterPythonImpl::Locker::InitSession |
479 ScriptInterpreterPythonImpl::Locker::InitGlobals,
480 ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |
481 ScriptInterpreterPythonImpl::Locker::TearDownSession);
482
483 // The following call drops into the embedded interpreter loop and
484 // stays there until the user chooses to exit from the Python
485 // interpreter. This embedded interpreter will, as any Python code that
486 // performs I/O, unlock the GIL before a system call that can hang, and
487 // lock it when the syscall has returned.
488
489 // We need to surround the call to the embedded interpreter with calls
490 // to PyGILState_Ensure and PyGILState_Release (using the Locker
491 // above). This is because Python has a global lock which must be held
492 // whenever we want to touch any Python objects. Otherwise, if the user
493 // calls Python code, the interpreter state will be off, and things
494 // could hang (it's happened before).
495
496 StreamString run_string;
497 run_string.Printf(format: "run_python_interpreter (%s)",
498 m_python->GetDictionaryName());
499 PyRun_SimpleString(run_string.GetData());
500 }
501 }
502 SetIsDone(true);
503 }
504
505 void Cancel() override {}
506
507 bool Interrupt() override { return m_python->Interrupt(); }
508
509 void GotEOF() override {}
510
511protected:
512 ScriptInterpreterPythonImpl *m_python;
513};
514
515} // namespace lldb_private
516
517#endif // LLDB_ENABLE_PYTHON
518#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
519

source code of lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h