1 //===-- ScriptInterpreterPythonImpl.h ---------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
10 #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
12 #include "lldb/Host/Config.h"
14 #if LLDB_ENABLE_PYTHON
16 #include "lldb-python.h"
18 #include "PythonDataObjects.h"
19 #include "ScriptInterpreterPython.h"
21 #include "lldb/Host/Terminal.h"
22 #include "lldb/Utility/StreamString.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/ADT/StringRef.h"
27 namespace lldb_private
{
28 class IOHandlerPythonInterpreter
;
29 class ScriptInterpreterPythonImpl
: public ScriptInterpreterPython
{
31 friend class IOHandlerPythonInterpreter
;
33 ScriptInterpreterPythonImpl(Debugger
&debugger
);
35 ~ScriptInterpreterPythonImpl() override
;
37 bool Interrupt() override
;
40 llvm::StringRef command
, CommandReturnObject
*result
,
41 const ExecuteScriptOptions
&options
= ExecuteScriptOptions()) override
;
43 void ExecuteInterpreterLoop() override
;
45 bool ExecuteOneLineWithReturn(
46 llvm::StringRef in_string
,
47 ScriptInterpreter::ScriptReturnType return_type
, void *ret_value
,
48 const ExecuteScriptOptions
&options
= ExecuteScriptOptions()) override
;
50 lldb_private::Status
ExecuteMultipleLines(
51 const char *in_string
,
52 const ExecuteScriptOptions
&options
= ExecuteScriptOptions()) override
;
55 ExportFunctionDefinitionToInterpreter(StringList
&function_def
) override
;
57 bool GenerateTypeScriptFunction(StringList
&input
, std::string
&output
,
58 const void *name_token
= nullptr) override
;
60 bool GenerateTypeSynthClass(StringList
&input
, std::string
&output
,
61 const void *name_token
= nullptr) override
;
63 bool GenerateTypeSynthClass(const char *oneliner
, std::string
&output
,
64 const void *name_token
= nullptr) override
;
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
;
70 bool GenerateScriptAliasFunction(StringList
&input
,
71 std::string
&output
) override
;
73 StructuredData::ObjectSP
74 CreateSyntheticScriptedProvider(const char *class_name
,
75 lldb::ValueObjectSP valobj
) override
;
77 StructuredData::GenericSP
78 CreateScriptCommandObject(const char *class_name
) override
;
80 StructuredData::ObjectSP
81 CreateStructuredDataFromScriptObject(ScriptObject obj
) override
;
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
;
91 lldb::SearchDepth
ScriptedBreakpointResolverSearchDepth(
92 StructuredData::GenericSP implementor_sp
) override
;
94 StructuredData::GenericSP
95 CreateFrameRecognizer(const char *class_name
) override
;
97 lldb::ValueObjectListSP
98 GetRecognizedArguments(const StructuredData::ObjectSP
&implementor
,
99 lldb::StackFrameSP frame_sp
) override
;
101 bool ShouldHide(const StructuredData::ObjectSP
&implementor
,
102 lldb::StackFrameSP frame_sp
) override
;
104 lldb::ScriptedProcessInterfaceUP
CreateScriptedProcessInterface() override
;
106 lldb::ScriptedStopHookInterfaceSP
CreateScriptedStopHookInterface() override
;
108 lldb::ScriptedThreadInterfaceSP
CreateScriptedThreadInterface() override
;
110 lldb::ScriptedThreadPlanInterfaceSP
111 CreateScriptedThreadPlanInterface() override
;
113 lldb::OperatingSystemInterfaceSP
CreateOperatingSystemInterface() override
;
115 StructuredData::ObjectSP
116 LoadPluginModule(const FileSpec
&file_spec
,
117 lldb_private::Status
&error
) override
;
119 StructuredData::DictionarySP
120 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp
, Target
*target
,
121 const char *setting_name
,
122 lldb_private::Status
&error
) override
;
124 size_t CalculateNumChildren(const StructuredData::ObjectSP
&implementor
,
125 uint32_t max
) override
;
128 GetChildAtIndex(const StructuredData::ObjectSP
&implementor
,
129 uint32_t idx
) override
;
131 int GetIndexOfChildWithName(const StructuredData::ObjectSP
&implementor
,
132 const char *child_name
) override
;
134 bool UpdateSynthProviderInstance(
135 const StructuredData::ObjectSP
&implementor
) override
;
137 bool MightHaveChildrenSynthProviderInstance(
138 const StructuredData::ObjectSP
&implementor
) override
;
141 GetSyntheticValue(const StructuredData::ObjectSP
&implementor
) override
;
144 GetSyntheticTypeName(const StructuredData::ObjectSP
&implementor
) override
;
147 RunScriptBasedCommand(const char *impl_function
, llvm::StringRef args
,
148 ScriptedCommandSynchronicity synchronicity
,
149 lldb_private::CommandReturnObject
&cmd_retobj
,
151 const lldb_private::ExecutionContext
&exe_ctx
) override
;
153 bool RunScriptBasedCommand(
154 StructuredData::GenericSP impl_obj_sp
, llvm::StringRef args
,
155 ScriptedCommandSynchronicity synchronicity
,
156 lldb_private::CommandReturnObject
&cmd_retobj
, Status
&error
,
157 const lldb_private::ExecutionContext
&exe_ctx
) override
;
159 bool RunScriptBasedParsedCommand(
160 StructuredData::GenericSP impl_obj_sp
, Args
&args
,
161 ScriptedCommandSynchronicity synchronicity
,
162 lldb_private::CommandReturnObject
&cmd_retobj
, Status
&error
,
163 const lldb_private::ExecutionContext
&exe_ctx
) override
;
165 std::optional
<std::string
>
166 GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp
,
167 Args
&args
) override
;
169 StructuredData::DictionarySP
HandleArgumentCompletionForScriptedCommand(
170 StructuredData::GenericSP impl_obj_sp
, std::vector
<llvm::StringRef
> &args
,
171 size_t args_pos
, size_t char_in_arg
) override
;
173 StructuredData::DictionarySP
HandleOptionArgumentCompletionForScriptedCommand(
174 StructuredData::GenericSP impl_obj_sp
, llvm::StringRef
&long_options
,
175 size_t char_in_arg
) override
;
177 Status
GenerateFunction(const char *signature
, const StringList
&input
,
178 bool is_callback
) override
;
180 Status
GenerateBreakpointCommandCallbackData(StringList
&input
,
183 bool is_callback
) override
;
185 bool GenerateWatchpointCommandCallbackData(StringList
&input
,
187 bool is_callback
) override
;
189 bool GetScriptedSummary(const char *function_name
, lldb::ValueObjectSP valobj
,
190 StructuredData::ObjectSP
&callee_wrapper_sp
,
191 const TypeSummaryOptions
&options
,
192 std::string
&retval
) override
;
194 bool FormatterCallbackFunction(const char *function_name
,
195 lldb::TypeImplSP type_impl_sp
) override
;
197 bool GetDocumentationForItem(const char *item
, std::string
&dest
) override
;
199 bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp
,
200 std::string
&dest
) override
;
203 GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp
) override
;
205 bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp
,
206 std::string
&dest
) override
;
208 StructuredData::ObjectSP
209 GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp
) override
;
211 StructuredData::ObjectSP
212 GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp
) override
;
214 bool SetOptionValueForCommandObject(StructuredData::GenericSP cmd_obj_sp
,
215 ExecutionContext
*exe_ctx
,
216 llvm::StringRef long_option
,
217 llvm::StringRef value
) override
;
219 void OptionParsingStartedForCommandObject(
220 StructuredData::GenericSP cmd_obj_sp
) override
;
222 bool CheckObjectExists(const char *name
) override
{
223 if (!name
|| !name
[0])
226 return GetDocumentationForItem(name
, temp
);
229 bool RunScriptFormatKeyword(const char *impl_function
, Process
*process
,
230 std::string
&output
, Status
&error
) override
;
232 bool RunScriptFormatKeyword(const char *impl_function
, Thread
*thread
,
233 std::string
&output
, Status
&error
) override
;
235 bool RunScriptFormatKeyword(const char *impl_function
, Target
*target
,
236 std::string
&output
, Status
&error
) override
;
238 bool RunScriptFormatKeyword(const char *impl_function
, StackFrame
*frame
,
239 std::string
&output
, Status
&error
) override
;
241 bool RunScriptFormatKeyword(const char *impl_function
, ValueObject
*value
,
242 std::string
&output
, Status
&error
) override
;
244 bool LoadScriptingModule(const char *filename
,
245 const LoadScriptOptions
&options
,
246 lldb_private::Status
&error
,
247 StructuredData::ObjectSP
*module_sp
= nullptr,
248 FileSpec extra_search_dir
= {}) override
;
250 bool IsReservedWord(const char *word
) override
;
252 std::unique_ptr
<ScriptInterpreterLocker
> AcquireInterpreterLock() override
;
254 void CollectDataForBreakpointCommandCallback(
255 std::vector
<std::reference_wrapper
<BreakpointOptions
>> &bp_options_vec
,
256 CommandReturnObject
&result
) override
;
259 CollectDataForWatchpointCommandCallback(WatchpointOptions
*wp_options
,
260 CommandReturnObject
&result
) override
;
262 /// Set the callback body text into the callback for the breakpoint.
263 Status
SetBreakpointCommandCallback(BreakpointOptions
&bp_options
,
264 const char *callback_body
,
265 bool is_callback
) override
;
267 Status
SetBreakpointCommandCallbackFunction(
268 BreakpointOptions
&bp_options
, const char *function_name
,
269 StructuredData::ObjectSP extra_args_sp
) override
;
271 /// This one is for deserialization:
272 Status
SetBreakpointCommandCallback(
273 BreakpointOptions
&bp_options
,
274 std::unique_ptr
<BreakpointOptions::CommandData
> &data_up
) override
;
276 Status
SetBreakpointCommandCallback(BreakpointOptions
&bp_options
,
277 const char *command_body_text
,
278 StructuredData::ObjectSP extra_args_sp
,
279 bool uses_extra_args
,
282 /// Set a one-liner as the callback for the watchpoint.
283 void SetWatchpointCommandCallback(WatchpointOptions
*wp_options
,
284 const char *user_input
,
285 bool is_callback
) override
;
287 const char *GetDictionaryName() { return m_dictionary_name
.c_str(); }
289 PyThreadState
*GetThreadState() { return m_command_thread_state
; }
291 void SetThreadState(PyThreadState
*s
) {
293 m_command_thread_state
= s
;
297 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
;
299 void IOHandlerInputComplete(IOHandler
&io_handler
,
300 std::string
&data
) override
;
302 static lldb::ScriptInterpreterSP
CreateInstance(Debugger
&debugger
);
304 // PluginInterface protocol
305 llvm::StringRef
GetPluginName() override
{ return GetPluginNameStatic(); }
307 class Locker
: public ScriptInterpreterLocker
{
310 AcquireLock
= 0x0001,
311 InitSession
= 0x0002,
312 InitGlobals
= 0x0004,
318 FreeAcquiredLock
= 0x0002, // do not free the lock if we already held it
319 // when calling constructor
320 TearDownSession
= 0x0004
323 Locker(ScriptInterpreterPythonImpl
*py_interpreter
,
324 uint16_t on_entry
= AcquireLock
| InitSession
,
325 uint16_t on_leave
= FreeLock
| TearDownSession
,
326 lldb::FileSP in
= nullptr, lldb::FileSP out
= nullptr,
327 lldb::FileSP err
= nullptr);
332 bool DoAcquireLock();
334 bool DoInitSession(uint16_t on_entry_flags
, lldb::FileSP in
,
335 lldb::FileSP out
, lldb::FileSP err
);
339 bool DoTearDownSession();
341 bool m_teardown_session
;
342 ScriptInterpreterPythonImpl
*m_python_interpreter
;
343 PyGILState_STATE m_GILState
;
346 static bool BreakpointCallbackFunction(void *baton
,
347 StoppointCallbackContext
*context
,
348 lldb::user_id_t break_id
,
349 lldb::user_id_t break_loc_id
);
350 static bool WatchpointCallbackFunction(void *baton
,
351 StoppointCallbackContext
*context
,
352 lldb::user_id_t watch_id
);
353 static void Initialize();
355 class SynchronicityHandler
{
357 lldb::DebuggerSP m_debugger_sp
;
358 ScriptedCommandSynchronicity m_synch_wanted
;
362 SynchronicityHandler(lldb::DebuggerSP
, ScriptedCommandSynchronicity
);
364 ~SynchronicityHandler();
367 enum class AddLocation
{ Beginning
, End
};
369 static void AddToSysPath(AddLocation location
, std::string path
);
371 bool EnterSession(uint16_t on_entry_flags
, lldb::FileSP in
, lldb::FileSP out
,
376 uint32_t IsExecutingPython() {
377 std::lock_guard
<std::mutex
> guard(m_mutex
);
378 return m_lock_count
> 0;
381 uint32_t IncrementLockCount() {
382 std::lock_guard
<std::mutex
> guard(m_mutex
);
383 return ++m_lock_count
;
386 uint32_t DecrementLockCount() {
387 std::lock_guard
<std::mutex
> guard(m_mutex
);
388 if (m_lock_count
> 0)
393 enum ActiveIOHandler
{
395 eIOHandlerBreakpoint
,
399 python::PythonModule
&GetMainModule();
401 python::PythonDictionary
&GetSessionDictionary();
403 python::PythonDictionary
&GetSysModuleDictionary();
405 llvm::Expected
<unsigned> GetMaxPositionalArgumentsForCallable(
406 const llvm::StringRef
&callable_name
) override
;
408 bool GetEmbeddedInterpreterModuleObjects();
410 bool SetStdHandle(lldb::FileSP file
, const char *py_name
,
411 python::PythonObject
&save_file
, const char *mode
);
413 python::PythonObject m_saved_stdin
;
414 python::PythonObject m_saved_stdout
;
415 python::PythonObject m_saved_stderr
;
416 python::PythonModule m_main_module
;
417 python::PythonDictionary m_session_dict
;
418 python::PythonDictionary m_sys_module_dict
;
419 python::PythonObject m_run_one_line_function
;
420 python::PythonObject m_run_one_line_str_global
;
421 std::string m_dictionary_name
;
422 ActiveIOHandler m_active_io_handler
;
423 bool m_session_is_active
;
424 bool m_pty_secondary_is_open
;
425 bool m_valid_session
;
426 uint32_t m_lock_count
;
428 PyThreadState
*m_command_thread_state
;
431 class IOHandlerPythonInterpreter
: public IOHandler
{
433 IOHandlerPythonInterpreter(Debugger
&debugger
,
434 ScriptInterpreterPythonImpl
*python
)
435 : IOHandler(debugger
, IOHandler::Type::PythonInterpreter
),
438 ~IOHandlerPythonInterpreter() override
= default;
440 llvm::StringRef
GetControlSequence(char ch
) override
{
441 static constexpr llvm::StringLiteral
control_sequence("quit()\n");
443 return control_sequence
;
447 void Run() override
{
449 int stdin_fd
= GetInputFD();
451 Terminal
terminal(stdin_fd
);
452 TerminalState
terminal_state(terminal
);
454 if (terminal
.IsATerminal()) {
455 // FIXME: error handling?
456 llvm::consumeError(terminal
.SetCanonical(false));
457 llvm::consumeError(terminal
.SetEcho(true));
460 ScriptInterpreterPythonImpl::Locker
locker(
462 ScriptInterpreterPythonImpl::Locker::AcquireLock
|
463 ScriptInterpreterPythonImpl::Locker::InitSession
|
464 ScriptInterpreterPythonImpl::Locker::InitGlobals
,
465 ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock
|
466 ScriptInterpreterPythonImpl::Locker::TearDownSession
);
468 // The following call drops into the embedded interpreter loop and
469 // stays there until the user chooses to exit from the Python
470 // interpreter. This embedded interpreter will, as any Python code that
471 // performs I/O, unlock the GIL before a system call that can hang, and
472 // lock it when the syscall has returned.
474 // We need to surround the call to the embedded interpreter with calls
475 // to PyGILState_Ensure and PyGILState_Release (using the Locker
476 // above). This is because Python has a global lock which must be held
477 // whenever we want to touch any Python objects. Otherwise, if the user
478 // calls Python code, the interpreter state will be off, and things
479 // could hang (it's happened before).
481 StreamString run_string
;
482 run_string
.Printf("run_python_interpreter (%s)",
483 m_python
->GetDictionaryName());
484 PyRun_SimpleString(run_string
.GetData());
490 void Cancel() override
{}
492 bool Interrupt() override
{ return m_python
->Interrupt(); }
494 void GotEOF() override
{}
497 ScriptInterpreterPythonImpl
*m_python
;
500 } // namespace lldb_private
502 #endif // LLDB_ENABLE_PYTHON
503 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H