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