Revert "[libc] Breakup freelist_malloc into separate files" (#119749)
[llvm-project.git] / lldb / source / Plugins / ScriptInterpreter / Python / ScriptInterpreterPythonImpl.h
blob2dc784777151bb028a81dbb0d798237bb2bdc132
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 //===----------------------------------------------------------------------===//
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 {
30 public:
31 friend class IOHandlerPythonInterpreter;
33 ScriptInterpreterPythonImpl(Debugger &debugger);
35 ~ScriptInterpreterPythonImpl() override;
37 bool Interrupt() override;
39 bool ExecuteOneLine(
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;
54 Status
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;
127 lldb::ValueObjectSP
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;
140 lldb::ValueObjectSP
141 GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
143 ConstString
144 GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
146 bool
147 RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
148 ScriptedCommandSynchronicity synchronicity,
149 lldb_private::CommandReturnObject &cmd_retobj,
150 Status &error,
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,
181 std::string &output,
182 bool has_extra_args,
183 bool is_callback) override;
185 bool GenerateWatchpointCommandCallbackData(StringList &input,
186 std::string &output,
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;
202 uint32_t
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])
224 return false;
225 std::string temp;
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;
258 void
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,
280 bool is_callback);
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) {
292 if (s)
293 m_command_thread_state = s;
296 // IOHandlerDelegate
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 {
308 public:
309 enum OnEntry {
310 AcquireLock = 0x0001,
311 InitSession = 0x0002,
312 InitGlobals = 0x0004,
313 NoSTDIN = 0x0008
316 enum OnLeave {
317 FreeLock = 0x0001,
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);
329 ~Locker() override;
331 private:
332 bool DoAcquireLock();
334 bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
335 lldb::FileSP out, lldb::FileSP err);
337 bool DoFreeLock();
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 {
356 private:
357 lldb::DebuggerSP m_debugger_sp;
358 ScriptedCommandSynchronicity m_synch_wanted;
359 bool m_old_asynch;
361 public:
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,
372 lldb::FileSP err);
374 void LeaveSession();
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)
389 --m_lock_count;
390 return m_lock_count;
393 enum ActiveIOHandler {
394 eIOHandlerNone,
395 eIOHandlerBreakpoint,
396 eIOHandlerWatchpoint
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;
427 std::mutex m_mutex;
428 PyThreadState *m_command_thread_state;
431 class IOHandlerPythonInterpreter : public IOHandler {
432 public:
433 IOHandlerPythonInterpreter(Debugger &debugger,
434 ScriptInterpreterPythonImpl *python)
435 : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
436 m_python(python) {}
438 ~IOHandlerPythonInterpreter() override = default;
440 llvm::StringRef GetControlSequence(char ch) override {
441 static constexpr llvm::StringLiteral control_sequence("quit()\n");
442 if (ch == 'd')
443 return control_sequence;
444 return {};
447 void Run() override {
448 if (m_python) {
449 int stdin_fd = GetInputFD();
450 if (stdin_fd >= 0) {
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(
461 m_python,
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());
487 SetIsDone(true);
490 void Cancel() override {}
492 bool Interrupt() override { return m_python->Interrupt(); }
494 void GotEOF() override {}
496 protected:
497 ScriptInterpreterPythonImpl *m_python;
500 } // namespace lldb_private
502 #endif // LLDB_ENABLE_PYTHON
503 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H