LLDB mainline
ScriptInterpreterPythonImpl.h
Go to the documentation of this file.
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"
20
21#include "lldb/Host/Terminal.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 CreateStructuredDataFromScriptObject(ScriptObject obj) override;
82
83 StructuredData::GenericSP
84 CreateFrameRecognizer(const char *class_name) override;
85
87 GetRecognizedArguments(const StructuredData::ObjectSP &implementor,
88 lldb::StackFrameSP frame_sp) override;
89
90 bool ShouldHide(const StructuredData::ObjectSP &implementor,
91 lldb::StackFrameSP frame_sp) override;
92
93 lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;
94
95 lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override;
96
98 CreateScriptedBreakpointInterface() override;
99
100 lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
101
102 lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override;
103
105 CreateScriptedThreadPlanInterface() override;
106
107 lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override;
108
109 StructuredData::ObjectSP
110 LoadPluginModule(const FileSpec &file_spec,
111 lldb_private::Status &error) override;
112
113 StructuredData::DictionarySP
114 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
115 const char *setting_name,
116 lldb_private::Status &error) override;
117
118 size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
119 uint32_t max) override;
120
122 GetChildAtIndex(const StructuredData::ObjectSP &implementor,
123 uint32_t idx) override;
124
125 llvm::Expected<int>
126 GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
127 const char *child_name) override;
128
129 bool UpdateSynthProviderInstance(
130 const StructuredData::ObjectSP &implementor) override;
131
132 bool MightHaveChildrenSynthProviderInstance(
133 const StructuredData::ObjectSP &implementor) override;
134
136 GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
137
138 ConstString
139 GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
140
141 bool
142 RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
143 ScriptedCommandSynchronicity synchronicity,
144 lldb_private::CommandReturnObject &cmd_retobj,
145 Status &error,
146 const lldb_private::ExecutionContext &exe_ctx) override;
147
148 bool RunScriptBasedCommand(
149 StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
150 ScriptedCommandSynchronicity synchronicity,
151 lldb_private::CommandReturnObject &cmd_retobj, Status &error,
152 const lldb_private::ExecutionContext &exe_ctx) override;
153
154 bool RunScriptBasedParsedCommand(
155 StructuredData::GenericSP impl_obj_sp, Args &args,
156 ScriptedCommandSynchronicity synchronicity,
157 lldb_private::CommandReturnObject &cmd_retobj, Status &error,
158 const lldb_private::ExecutionContext &exe_ctx) override;
159
160 std::optional<std::string>
161 GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp,
162 Args &args) override;
163
164 StructuredData::DictionarySP HandleArgumentCompletionForScriptedCommand(
165 StructuredData::GenericSP impl_obj_sp, std::vector<llvm::StringRef> &args,
166 size_t args_pos, size_t char_in_arg) override;
167
168 StructuredData::DictionarySP HandleOptionArgumentCompletionForScriptedCommand(
169 StructuredData::GenericSP impl_obj_sp, llvm::StringRef &long_options,
170 size_t char_in_arg) override;
171
172 Status GenerateFunction(const char *signature, const StringList &input,
173 bool is_callback) override;
174
175 Status GenerateBreakpointCommandCallbackData(StringList &input,
176 std::string &output,
177 bool has_extra_args,
178 bool is_callback) override;
179
180 bool GenerateWatchpointCommandCallbackData(StringList &input,
181 std::string &output,
182 bool is_callback) override;
183
184 bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
185 StructuredData::ObjectSP &callee_wrapper_sp,
186 const TypeSummaryOptions &options,
187 std::string &retval) override;
188
189 bool FormatterCallbackFunction(const char *function_name,
190 lldb::TypeImplSP type_impl_sp) override;
191
192 bool GetDocumentationForItem(const char *item, std::string &dest) override;
193
194 bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
195 std::string &dest) override;
196
197 uint32_t
198 GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
199
200 bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
201 std::string &dest) override;
202
203 StructuredData::ObjectSP
204 GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
205
206 StructuredData::ObjectSP
207 GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
208
209 bool SetOptionValueForCommandObject(StructuredData::GenericSP cmd_obj_sp,
210 ExecutionContext *exe_ctx,
211 llvm::StringRef long_option,
212 llvm::StringRef value) override;
213
214 void OptionParsingStartedForCommandObject(
215 StructuredData::GenericSP cmd_obj_sp) override;
216
217 bool CheckObjectExists(const char *name) override {
218 if (!name || !name[0])
219 return false;
220 std::string temp;
221 return GetDocumentationForItem(name, temp);
222 }
223
224 bool RunScriptFormatKeyword(const char *impl_function, Process *process,
225 std::string &output, Status &error) override;
226
227 bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
228 std::string &output, Status &error) override;
229
230 bool RunScriptFormatKeyword(const char *impl_function, Target *target,
231 std::string &output, Status &error) override;
232
233 bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
234 std::string &output, Status &error) override;
235
236 bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
237 std::string &output, Status &error) override;
238
239 bool LoadScriptingModule(const char *filename,
240 const LoadScriptOptions &options,
242 StructuredData::ObjectSP *module_sp = nullptr,
243 FileSpec extra_search_dir = {},
244 lldb::TargetSP loaded_into_target_sp = {}) override;
245
246 bool IsReservedWord(const char *word) override;
247
248 std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
249
250 void CollectDataForBreakpointCommandCallback(
251 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
252 CommandReturnObject &result) override;
253
254 void
255 CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
256 CommandReturnObject &result) override;
257
258 /// Set the callback body text into the callback for the breakpoint.
259 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
260 const char *callback_body,
261 bool is_callback) override;
262
263 Status SetBreakpointCommandCallbackFunction(
264 BreakpointOptions &bp_options, const char *function_name,
265 StructuredData::ObjectSP extra_args_sp) override;
266
267 /// This one is for deserialization:
268 Status SetBreakpointCommandCallback(
269 BreakpointOptions &bp_options,
270 std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
271
272 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
273 const char *command_body_text,
274 StructuredData::ObjectSP extra_args_sp,
275 bool uses_extra_args,
276 bool is_callback);
277
278 /// Set a one-liner as the callback for the watchpoint.
279 void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
280 const char *user_input,
281 bool is_callback) override;
282
283 const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
284
285 PyThreadState *GetThreadState() { return m_command_thread_state; }
286
287 void SetThreadState(PyThreadState *s) {
288 if (s)
289 m_command_thread_state = s;
290 }
291
292 // IOHandlerDelegate
293 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
294
295 void IOHandlerInputComplete(IOHandler &io_handler,
296 std::string &data) override;
297
298 static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
299
300 // PluginInterface protocol
301 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
302
303 class Locker : public ScriptInterpreterLocker {
304 public:
305 enum OnEntry {
306 AcquireLock = 0x0001,
307 InitSession = 0x0002,
308 InitGlobals = 0x0004,
309 NoSTDIN = 0x0008
310 };
311
312 enum OnLeave {
313 FreeLock = 0x0001,
314 FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
315 // when calling constructor
316 TearDownSession = 0x0004
317 };
318
319 Locker(ScriptInterpreterPythonImpl *py_interpreter,
320 uint16_t on_entry = AcquireLock | InitSession,
321 uint16_t on_leave = FreeLock | TearDownSession,
322 lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,
323 lldb::FileSP err = nullptr);
324
325 ~Locker() override;
326
327 private:
328 bool DoAcquireLock();
329
330 bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
331 lldb::FileSP out, lldb::FileSP err);
332
333 bool DoFreeLock();
334
335 bool DoTearDownSession();
336
337 bool m_teardown_session;
338 ScriptInterpreterPythonImpl *m_python_interpreter;
339 PyGILState_STATE m_GILState;
340 };
341
342 static bool BreakpointCallbackFunction(void *baton,
343 StoppointCallbackContext *context,
344 lldb::user_id_t break_id,
345 lldb::user_id_t break_loc_id);
346 static bool WatchpointCallbackFunction(void *baton,
347 StoppointCallbackContext *context,
348 lldb::user_id_t watch_id);
349 static void Initialize();
350
351 class SynchronicityHandler {
352 private:
353 lldb::DebuggerSP m_debugger_sp;
354 ScriptedCommandSynchronicity m_synch_wanted;
355 bool m_old_asynch;
356
357 public:
358 SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
359
360 ~SynchronicityHandler();
361 };
362
363 enum class AddLocation { Beginning, End };
364
365 static void AddToSysPath(AddLocation location, std::string path);
366
367 bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
368 lldb::FileSP err);
369
370 void LeaveSession();
371
372 uint32_t IsExecutingPython() {
373 std::lock_guard<std::mutex> guard(m_mutex);
374 return m_lock_count > 0;
375 }
376
377 uint32_t IncrementLockCount() {
378 std::lock_guard<std::mutex> guard(m_mutex);
379 return ++m_lock_count;
380 }
381
382 uint32_t DecrementLockCount() {
383 std::lock_guard<std::mutex> guard(m_mutex);
384 if (m_lock_count > 0)
385 --m_lock_count;
386 return m_lock_count;
387 }
388
389 enum ActiveIOHandler {
393 };
394
395 python::PythonModule &GetMainModule();
396
397 python::PythonDictionary &GetSessionDictionary();
398
399 python::PythonDictionary &GetSysModuleDictionary();
400
401 llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
402 const llvm::StringRef &callable_name) override;
403
404 bool GetEmbeddedInterpreterModuleObjects();
405
406 bool SetStdHandle(lldb::FileSP file, const char *py_name,
407 python::PythonObject &save_file, const char *mode);
408
409 python::PythonObject m_saved_stdin;
410 python::PythonObject m_saved_stdout;
411 python::PythonObject m_saved_stderr;
412 python::PythonModule m_main_module;
413 python::PythonDictionary m_session_dict;
414 python::PythonDictionary m_sys_module_dict;
415 python::PythonObject m_run_one_line_function;
416 python::PythonObject m_run_one_line_str_global;
417 std::string m_dictionary_name;
418 ActiveIOHandler m_active_io_handler;
419 bool m_session_is_active;
420 bool m_pty_secondary_is_open;
421 bool m_valid_session;
422 uint32_t m_lock_count;
423 std::mutex m_mutex;
424 PyThreadState *m_command_thread_state;
425};
426
427class IOHandlerPythonInterpreter : public IOHandler {
428public:
429 IOHandlerPythonInterpreter(Debugger &debugger,
430 ScriptInterpreterPythonImpl *python)
431 : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
432 m_python(python) {}
433
434 ~IOHandlerPythonInterpreter() override = default;
435
436 llvm::StringRef GetControlSequence(char ch) override {
437 static constexpr llvm::StringLiteral control_sequence("quit()\n");
438 if (ch == 'd')
439 return control_sequence;
440 return {};
441 }
442
443 void Run() override {
444 if (m_python) {
445 int stdin_fd = GetInputFD();
446 if (stdin_fd >= 0) {
447 Terminal terminal(stdin_fd);
448 TerminalState terminal_state(terminal);
449
450 if (terminal.IsATerminal()) {
451 // FIXME: error handling?
452 llvm::consumeError(terminal.SetCanonical(false));
453 llvm::consumeError(terminal.SetEcho(true));
454 }
455
456 ScriptInterpreterPythonImpl::Locker locker(
457 m_python,
458 ScriptInterpreterPythonImpl::Locker::AcquireLock |
459 ScriptInterpreterPythonImpl::Locker::InitSession |
460 ScriptInterpreterPythonImpl::Locker::InitGlobals,
461 ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |
462 ScriptInterpreterPythonImpl::Locker::TearDownSession);
463
464 // The following call drops into the embedded interpreter loop and
465 // stays there until the user chooses to exit from the Python
466 // interpreter. This embedded interpreter will, as any Python code that
467 // performs I/O, unlock the GIL before a system call that can hang, and
468 // lock it when the syscall has returned.
469
470 // We need to surround the call to the embedded interpreter with calls
471 // to PyGILState_Ensure and PyGILState_Release (using the Locker
472 // above). This is because Python has a global lock which must be held
473 // whenever we want to touch any Python objects. Otherwise, if the user
474 // calls Python code, the interpreter state will be off, and things
475 // could hang (it's happened before).
476
477 StreamString run_string;
478 run_string.Printf("run_python_interpreter (%s)",
479 m_python->GetDictionaryName());
480 python::RunSimpleString(run_string.GetData());
481 }
482 }
483 SetIsDone(true);
484 }
485
486 void Cancel() override {}
487
488 bool Interrupt() override { return m_python->Interrupt(); }
489
490 void GotEOF() override {}
491
492protected:
493 ScriptInterpreterPythonImpl *m_python;
494};
495
496} // namespace lldb_private
497
498#endif // LLDB_ENABLE_PYTHON
499#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
static llvm::raw_ostream & error(Stream &strm)
static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, T t, const char *script_function_name)
@ eIOHandlerWatchpoint
@ eIOHandlerBreakpoint
static std::optional< size_t > CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements, CompilerType element_type)
Calculates the number of elements stored in a container (with element type 'container_elem_type') as ...
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::ScriptedStopHookInterface > ScriptedStopHookInterfaceSP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ScriptInterpreter > ScriptInterpreterSP
std::shared_ptr< lldb_private::ScriptedThreadPlanInterface > ScriptedThreadPlanInterfaceSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::OperatingSystemInterface > OperatingSystemInterfaceSP
std::shared_ptr< lldb_private::ScriptedBreakpointInterface > ScriptedBreakpointInterfaceSP
std::shared_ptr< lldb_private::ScriptedThreadInterface > ScriptedThreadInterfaceSP
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
std::shared_ptr< lldb_private::Debugger > DebuggerSP
uint64_t user_id_t
Definition lldb-types.h:82
std::shared_ptr< lldb_private::TypeImpl > TypeImplSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::File > FileSP
std::unique_ptr< lldb_private::ScriptedProcessInterface > ScriptedProcessInterfaceUP
std::shared_ptr< lldb_private::ScriptedFrameInterface > ScriptedFrameInterfaceSP