[Go to site: main page, start]

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_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
10#define LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
11
12#include "lldb-python.h"
13
14#include "PythonDataObjects.h"
16
17#include "lldb/Host/Terminal.h"
19
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/StringRef.h"
22
23namespace lldb_private {
26public:
28
30
32
33 bool Interrupt() override;
34
35 bool ExecuteOneLine(
36 llvm::StringRef command, CommandReturnObject *result,
37 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
38
39 void ExecuteInterpreterLoop() override;
40
42 llvm::StringRef in_string,
43 ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
44 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
45
47 const char *in_string,
48 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
49
50 Status
52
53 bool GenerateTypeScriptFunction(StringList &input, std::string &output,
54 const void *name_token = nullptr) override;
55
56 bool GenerateTypeSynthClass(StringList &input, std::string &output,
57 const void *name_token = nullptr) override;
58
59 bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
60 const void *name_token = nullptr) override;
61
62 // use this if the function code is just a one-liner script
63 bool GenerateTypeScriptFunction(const char *oneliner, std::string &output,
64 const void *name_token = nullptr) override;
65
67 std::string &output) override;
68
71
73
75
78
81
83
86
89
91
93
96
99
101
103 LoadPluginModule(const FileSpec &file_spec,
104 lldb_private::Status &error) override;
105
107 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
108 const char *setting_name,
109 lldb_private::Status &error) override;
110
111 bool
112 RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
113 ScriptedCommandSynchronicity synchronicity,
115 Status &error,
116 const lldb_private::ExecutionContext &exe_ctx) override;
117
118 Status GenerateFunction(const char *signature, const StringList &input,
119 bool is_callback) override;
120
122 std::string &output,
123 bool has_extra_args,
124 bool is_callback) override;
125
127 std::string &output,
128 bool is_callback) override;
129
130 bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
131 StructuredData::ObjectSP &callee_wrapper_sp,
132 const TypeSummaryOptions &options,
133 std::string &retval) override;
134
135 bool FormatterCallbackFunction(const char *function_name,
136 lldb::TypeImplSP type_impl_sp) override;
137
138 bool GetDocumentationForItem(const char *item, std::string &dest) override;
139
140 bool CheckObjectExists(const char *name) override {
141 if (!name || !name[0])
142 return false;
143 std::string temp;
144 return GetDocumentationForItem(name, temp);
145 }
146
147 bool RunScriptFormatKeyword(const char *impl_function, Process *process,
148 std::string &output, Status &error) override;
149
150 bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
151 std::string &output, Status &error) override;
152
153 bool RunScriptFormatKeyword(const char *impl_function, Target *target,
154 std::string &output, Status &error) override;
155
156 bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
157 std::string &output, Status &error) override;
158
159 bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
160 std::string &output, Status &error) override;
161
162 bool LoadScriptingModule(const char *filename,
163 const LoadScriptOptions &options,
165 StructuredData::ObjectSP *module_sp = nullptr,
166 FileSpec extra_search_dir = {},
167 lldb::TargetSP loaded_into_target_sp = {}) override;
168
169 bool IsReservedWord(const char *word) override;
170
171 std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
172
174 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
175 CommandReturnObject &result) override;
176
177 void
178 CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
179 CommandReturnObject &result) override;
180
181 /// Set the callback body text into the callback for the breakpoint.
182 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
183 const char *callback_body,
184 bool is_callback) override;
185
187 BreakpointOptions &bp_options, const char *function_name,
188 StructuredData::ObjectSP extra_args_sp) override;
189
190 /// This one is for deserialization:
192 BreakpointOptions &bp_options,
193 std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
194
195 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
196 const char *command_body_text,
197 StructuredData::ObjectSP extra_args_sp,
198 bool uses_extra_args, bool is_callback);
199
200 /// Set a one-liner as the callback for the watchpoint.
201 void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
202 const char *user_input,
203 bool is_callback) override;
204
205 const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
206
207 PyThreadState *GetThreadState() { return m_command_thread_state; }
208
209 void SetThreadState(PyThreadState *s) {
210 if (s)
212 }
213
214 // IOHandlerDelegate
215 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
216
217 void IOHandlerInputComplete(IOHandler &io_handler,
218 std::string &data) override;
219
221
222 // PluginInterface protocol
223 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
224
226 public:
227 enum OnEntry {
228 AcquireLock = 0x0001,
229 InitSession = 0x0002,
230 InitGlobals = 0x0004,
231 NoSTDIN = 0x0008,
232 // Keep sys.stdout/stderr on the real terminal instead of routing them
233 // through the output-lock pipe (see EnterSession). Set by the interactive
234 // interpreter, whose input() needs both the real stdin and stdout for
235 // readline-based line editing and echo.
237 };
238
239 enum OnLeave {
240 FreeLock = 0x0001,
241 FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
242 // when calling constructor
244 };
245
246 Locker(ScriptInterpreterPythonImpl *py_interpreter,
247 uint16_t on_entry = AcquireLock | InitSession,
248 uint16_t on_leave = FreeLock | TearDownSession,
249 lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,
250 lldb::FileSP err = nullptr);
251
252 ~Locker() override;
253
254 private:
255 bool DoAcquireLock();
256
257 bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
258 lldb::FileSP out, lldb::FileSP err);
259
260 bool DoFreeLock();
261
262 bool DoTearDownSession();
263
266 PyGILState_STATE m_GILState;
267 };
268
269 static bool BreakpointCallbackFunction(void *baton,
271 lldb::user_id_t break_id,
272 lldb::user_id_t break_loc_id);
273 static bool WatchpointCallbackFunction(void *baton,
275 lldb::user_id_t watch_id);
276 static void Initialize();
277
289
290 enum class AddLocation { Beginning, End };
291
292 static void AddToSysPath(AddLocation location, std::string path);
293
294 bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
295 lldb::FileSP err);
296
297 void LeaveSession();
298
299 uint32_t IsExecutingPython() {
300 std::lock_guard<std::mutex> guard(m_mutex);
301 return m_lock_count > 0;
302 }
303
305 std::lock_guard<std::mutex> guard(m_mutex);
306 return ++m_lock_count;
307 }
308
310 std::lock_guard<std::mutex> guard(m_mutex);
311 if (m_lock_count > 0)
312 --m_lock_count;
313 return m_lock_count;
314 }
315
321
323
325
327
328 llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
329 const llvm::StringRef &callable_name) override;
330
332
333 /// Point sys.\p py_name at \p file. When \p serialize_terminal_output is true
334 /// and \p file is the debugger's own terminal, the output is routed through a
335 /// lock-synchronized pipe instead (see RedirectTerminalHandleThroughLock) so
336 /// it cannot race the statusline redraw.
337 bool SetStdHandle(lldb::FileSP file, const char *py_name,
338 python::PythonObject &save_file, const char *mode,
339 bool serialize_terminal_output);
340
341 /// Pipe-backed sys.stdout/stderr whose writes are serialized against the
342 /// statusline redraw. Defined and documented in the implementation file.
343 class SessionIORedirect;
344
345 /// If \p file is the debugger's own terminal, point sys.\p py_name at a
346 /// pipe-backed file whose writes are serialized through the output lock (see
347 /// SessionIORedirect) and return true. Return false to let SetStdHandle wrap
348 /// \p file normally.
349 bool RedirectTerminalHandleThroughLock(const char *py_name,
350 python::PythonObject &save_file,
351 const char *mode, File &file);
352
356 std::unique_ptr<SessionIORedirect> m_stdout_redirect;
357 std::unique_ptr<SessionIORedirect> m_stderr_redirect;
363 std::string m_dictionary_name;
368 uint32_t m_lock_count;
369 std::mutex m_mutex;
371};
372
374public:
379
380 ~IOHandlerPythonInterpreter() override = default;
381
382 llvm::StringRef GetControlSequence(char ch) override {
383 static constexpr llvm::StringLiteral control_sequence("quit()\n");
384 if (ch == 'd')
385 return control_sequence;
386 return {};
387 }
388
389 void Run() override {
390 if (m_python) {
391 int stdin_fd = GetInputFD();
392 if (stdin_fd >= 0) {
393 Terminal terminal(stdin_fd);
394 TerminalState terminal_state(terminal);
395
396 if (terminal.IsATerminal()) {
397 // FIXME: error handling?
398 llvm::consumeError(terminal.SetCanonical(false));
399 llvm::consumeError(terminal.SetEcho(true));
400 }
401
403 m_python,
410
411 // The following call drops into the embedded interpreter loop and
412 // stays there until the user chooses to exit from the Python
413 // interpreter. This embedded interpreter will, as any Python code that
414 // performs I/O, unlock the GIL before a system call that can hang, and
415 // lock it when the syscall has returned.
416
417 // We need to surround the call to the embedded interpreter with calls
418 // to PyGILState_Ensure and PyGILState_Release (using the Locker
419 // above). This is because Python has a global lock which must be held
420 // whenever we want to touch any Python objects. Otherwise, if the user
421 // calls Python code, the interpreter state will be off, and things
422 // could hang (it's happened before).
423
424 StreamString run_string;
425 run_string.Printf("run_python_interpreter (%s)",
426 m_python->GetDictionaryName());
427 python::RunSimpleString(run_string.GetData());
428 }
429 }
430 SetIsDone(true);
431 }
432
433 void Cancel() override {}
434
435 bool Interrupt() override { return m_python->Interrupt(); }
436
437 void GotEOF() override {}
438
439protected:
441};
442
443} // namespace lldb_private
444
445#endif // LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
static llvm::raw_ostream & error(Stream &strm)
ScriptInterpreterPythonImpl::Locker Locker
A class to manage flag bits.
Definition Debugger.h:100
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A file utility class.
Definition FileSpec.h:56
An abstract base class for files.
Definition FileBase.h:34
~IOHandlerPythonInterpreter() override=default
llvm::StringRef GetControlSequence(char ch) override
IOHandlerPythonInterpreter(Debugger &debugger, ScriptInterpreterPythonImpl *python)
IOHandler(Debugger &debugger, IOHandler::Type type)
Definition IOHandler.cpp:55
void SetIsDone(bool b)
Definition IOHandler.h:81
A plug-in interface definition class for debugging a process.
Definition Process.h:359
bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, lldb::FileSP err)
Locker(ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry=AcquireLock|InitSession, uint16_t on_leave=FreeLock|TearDownSession, lldb::FileSP in=nullptr, lldb::FileSP out=nullptr, lldb::FileSP err=nullptr)
SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity)
bool GenerateTypeScriptFunction(StringList &input, std::string &output, const void *name_token=nullptr) override
Status GenerateFunction(const char *signature, const StringList &input, bool is_callback) override
bool GenerateScriptAliasFunction(StringList &input, std::string &output) override
lldb_private::Status ExecuteMultipleLines(const char *in_string, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
bool GenerateWatchpointCommandCallbackData(StringList &input, std::string &output, bool is_callback) override
Status SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) override
Set a script function as the callback for the breakpoint.
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override
std::unique_ptr< SessionIORedirect > m_stderr_redirect
static bool BreakpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Status &error) override
void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, CommandReturnObject &result) override
lldb::ScriptedCommandInterfaceSP CreateScriptedCommandInterface() override
bool RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) override
lldb::ScriptedFrameProviderInterfaceSP CreateScriptedFrameProviderInterface() override
Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *callback_body, bool is_callback) override
Set the callback body text into the callback for the breakpoint.
lldb::ScriptedStackFrameRecognizerInterfaceSP CreateScriptedStackFrameRecognizerInterface() override
bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, lldb::FileSP err)
void SetWatchpointCommandCallback(WatchpointOptions *wp_options, const char *user_input, bool is_callback) override
Set a one-liner as the callback for the watchpoint.
bool RedirectTerminalHandleThroughLock(const char *py_name, python::PythonObject &save_file, const char *mode, File &file)
If file is the debugger's own terminal, point sys.
std::unique_ptr< ScriptInterpreterLocker > AcquireInterpreterLock() override
void CollectDataForBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions > > &bp_options_vec, CommandReturnObject &result) override
static void AddToSysPath(AddLocation location, std::string path)
lldb::ScriptedStringSummaryInterfaceSP CreateScriptedStringSummaryInterface() override
bool LoadScriptingModule(const char *filename, const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp=nullptr, FileSpec extra_search_dir={}, lldb::TargetSP loaded_into_target_sp={}) override
Status GenerateBreakpointCommandCallbackData(StringList &input, std::string &output, bool has_extra_args, bool is_callback) override
lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override
bool FormatterCallbackFunction(const char *function_name, lldb::TypeImplSP type_impl_sp) override
Status ExportFunctionDefinitionToInterpreter(StringList &function_def) override
bool ExecuteOneLine(llvm::StringRef command, CommandReturnObject *result, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
bool GetDocumentationForItem(const char *item, std::string &dest) override
In Python, a special attribute doc contains the docstring for an object (function,...
lldb::ScriptedSyntheticChildrenInterfaceSP CreateScriptedSyntheticChildrenInterface() override
lldb::ScriptedHookInterfaceSP CreateScriptedHookInterface() override
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval) override
lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override
lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override
bool ExecuteOneLineWithReturn(llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options=ExecuteScriptOptions()) override
lldb::ScriptedBreakpointInterfaceSP CreateScriptedBreakpointInterface() override
bool RunScriptFormatKeyword(const char *impl_function, Process *process, std::string &output, Status &error) override
bool SetStdHandle(lldb::FileSP file, const char *py_name, python::PythonObject &save_file, const char *mode, bool serialize_terminal_output)
Point sys.
bool GenerateTypeSynthClass(StringList &input, std::string &output, const void *name_token=nullptr) override
StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) override
StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) override
llvm::Expected< unsigned > GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) override
static bool WatchpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id)
static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger)
lldb::ScriptedThreadPlanInterfaceSP CreateScriptedThreadPlanInterface() override
std::unique_ptr< SessionIORedirect > m_stdout_redirect
This base class provides an interface to stack frames.
Definition StackFrame.h:44
An error handling class.
Definition Status.h:118
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
const char * GetData() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
A RAII-friendly terminal state saving/restoring class.
Definition Terminal.h:99
llvm::Error SetEcho(bool enabled)
Definition Terminal.cpp:80
llvm::Error SetCanonical(bool enabled)
Definition Terminal.cpp:96
bool IsATerminal() const
Definition Terminal.cpp:35
int RunSimpleString(const char *str)
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::ScriptedSyntheticChildrenInterface > ScriptedSyntheticChildrenInterfaceSP
std::shared_ptr< lldb_private::ScriptedHookInterface > ScriptedHookInterfaceSP
std::shared_ptr< lldb_private::ScriptedStringSummaryInterface > ScriptedStringSummaryInterfaceSP
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::Debugger > DebuggerSP
std::shared_ptr< lldb_private::ScriptedFrameProviderInterface > ScriptedFrameProviderInterfaceSP
std::shared_ptr< lldb_private::ScriptedCommandInterface > ScriptedCommandInterfaceSP
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::TypeImpl > TypeImplSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::File > FileSP
std::shared_ptr< lldb_private::ScriptedStackFrameRecognizerInterface > ScriptedStackFrameRecognizerInterfaceSP
std::unique_ptr< lldb_private::ScriptedProcessInterface > ScriptedProcessInterfaceUP
std::shared_ptr< lldb_private::ScriptedFrameInterface > ScriptedFrameInterfaceSP