1*63dd5d25SJonas Devlieghere //===-- ScriptInterpreterPythonImpl.h ---------------------------*- C++ -*-===//
2*63dd5d25SJonas Devlieghere //
3*63dd5d25SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*63dd5d25SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
5*63dd5d25SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*63dd5d25SJonas Devlieghere //
7*63dd5d25SJonas Devlieghere //===----------------------------------------------------------------------===//
8*63dd5d25SJonas Devlieghere 
9*63dd5d25SJonas Devlieghere #ifdef LLDB_DISABLE_PYTHON
10*63dd5d25SJonas Devlieghere 
11*63dd5d25SJonas Devlieghere // Python is disabled in this build
12*63dd5d25SJonas Devlieghere 
13*63dd5d25SJonas Devlieghere #else
14*63dd5d25SJonas Devlieghere 
15*63dd5d25SJonas Devlieghere #include "lldb-python.h"
16*63dd5d25SJonas Devlieghere 
17*63dd5d25SJonas Devlieghere #include "PythonDataObjects.h"
18*63dd5d25SJonas Devlieghere #include "ScriptInterpreterPython.h"
19*63dd5d25SJonas Devlieghere 
20*63dd5d25SJonas Devlieghere #include "lldb/Host/Terminal.h"
21*63dd5d25SJonas Devlieghere #include "lldb/Utility/StreamString.h"
22*63dd5d25SJonas Devlieghere 
23*63dd5d25SJonas Devlieghere #include "llvm/ADT/STLExtras.h"
24*63dd5d25SJonas Devlieghere #include "llvm/ADT/StringRef.h"
25*63dd5d25SJonas Devlieghere 
26*63dd5d25SJonas Devlieghere namespace lldb_private {
27*63dd5d25SJonas Devlieghere class IOHandlerPythonInterpreter;
28*63dd5d25SJonas Devlieghere class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
29*63dd5d25SJonas Devlieghere public:
30*63dd5d25SJonas Devlieghere   friend class IOHandlerPythonInterpreter;
31*63dd5d25SJonas Devlieghere 
32*63dd5d25SJonas Devlieghere   ScriptInterpreterPythonImpl(CommandInterpreter &interpreter);
33*63dd5d25SJonas Devlieghere 
34*63dd5d25SJonas Devlieghere   ~ScriptInterpreterPythonImpl() override;
35*63dd5d25SJonas Devlieghere 
36*63dd5d25SJonas Devlieghere   bool Interrupt() override;
37*63dd5d25SJonas Devlieghere 
38*63dd5d25SJonas Devlieghere   bool ExecuteOneLine(
39*63dd5d25SJonas Devlieghere       llvm::StringRef command, CommandReturnObject *result,
40*63dd5d25SJonas Devlieghere       const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
41*63dd5d25SJonas Devlieghere 
42*63dd5d25SJonas Devlieghere   void ExecuteInterpreterLoop() override;
43*63dd5d25SJonas Devlieghere 
44*63dd5d25SJonas Devlieghere   bool ExecuteOneLineWithReturn(
45*63dd5d25SJonas Devlieghere       llvm::StringRef in_string,
46*63dd5d25SJonas Devlieghere       ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
47*63dd5d25SJonas Devlieghere       const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
48*63dd5d25SJonas Devlieghere 
49*63dd5d25SJonas Devlieghere   lldb_private::Status ExecuteMultipleLines(
50*63dd5d25SJonas Devlieghere       const char *in_string,
51*63dd5d25SJonas Devlieghere       const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
52*63dd5d25SJonas Devlieghere 
53*63dd5d25SJonas Devlieghere   Status
54*63dd5d25SJonas Devlieghere   ExportFunctionDefinitionToInterpreter(StringList &function_def) override;
55*63dd5d25SJonas Devlieghere 
56*63dd5d25SJonas Devlieghere   bool GenerateTypeScriptFunction(StringList &input, std::string &output,
57*63dd5d25SJonas Devlieghere                                   const void *name_token = nullptr) override;
58*63dd5d25SJonas Devlieghere 
59*63dd5d25SJonas Devlieghere   bool GenerateTypeSynthClass(StringList &input, std::string &output,
60*63dd5d25SJonas Devlieghere                               const void *name_token = nullptr) override;
61*63dd5d25SJonas Devlieghere 
62*63dd5d25SJonas Devlieghere   bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
63*63dd5d25SJonas Devlieghere                               const void *name_token = nullptr) override;
64*63dd5d25SJonas Devlieghere 
65*63dd5d25SJonas Devlieghere   // use this if the function code is just a one-liner script
66*63dd5d25SJonas Devlieghere   bool GenerateTypeScriptFunction(const char *oneliner, std::string &output,
67*63dd5d25SJonas Devlieghere                                   const void *name_token = nullptr) override;
68*63dd5d25SJonas Devlieghere 
69*63dd5d25SJonas Devlieghere   bool GenerateScriptAliasFunction(StringList &input,
70*63dd5d25SJonas Devlieghere                                    std::string &output) override;
71*63dd5d25SJonas Devlieghere 
72*63dd5d25SJonas Devlieghere   StructuredData::ObjectSP
73*63dd5d25SJonas Devlieghere   CreateSyntheticScriptedProvider(const char *class_name,
74*63dd5d25SJonas Devlieghere                                   lldb::ValueObjectSP valobj) override;
75*63dd5d25SJonas Devlieghere 
76*63dd5d25SJonas Devlieghere   StructuredData::GenericSP
77*63dd5d25SJonas Devlieghere   CreateScriptCommandObject(const char *class_name) override;
78*63dd5d25SJonas Devlieghere 
79*63dd5d25SJonas Devlieghere   StructuredData::ObjectSP
80*63dd5d25SJonas Devlieghere   CreateScriptedThreadPlan(const char *class_name,
81*63dd5d25SJonas Devlieghere                            lldb::ThreadPlanSP thread_plan) override;
82*63dd5d25SJonas Devlieghere 
83*63dd5d25SJonas Devlieghere   bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
84*63dd5d25SJonas Devlieghere                                       Event *event,
85*63dd5d25SJonas Devlieghere                                       bool &script_error) override;
86*63dd5d25SJonas Devlieghere 
87*63dd5d25SJonas Devlieghere   bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
88*63dd5d25SJonas Devlieghere                                     Event *event, bool &script_error) override;
89*63dd5d25SJonas Devlieghere 
90*63dd5d25SJonas Devlieghere   bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
91*63dd5d25SJonas Devlieghere                                  bool &script_error) override;
92*63dd5d25SJonas Devlieghere 
93*63dd5d25SJonas Devlieghere   lldb::StateType
94*63dd5d25SJonas Devlieghere   ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
95*63dd5d25SJonas Devlieghere                                 bool &script_error) override;
96*63dd5d25SJonas Devlieghere 
97*63dd5d25SJonas Devlieghere   StructuredData::GenericSP
98*63dd5d25SJonas Devlieghere   CreateScriptedBreakpointResolver(const char *class_name,
99*63dd5d25SJonas Devlieghere                                    StructuredDataImpl *args_data,
100*63dd5d25SJonas Devlieghere                                    lldb::BreakpointSP &bkpt_sp) override;
101*63dd5d25SJonas Devlieghere   bool ScriptedBreakpointResolverSearchCallback(
102*63dd5d25SJonas Devlieghere       StructuredData::GenericSP implementor_sp,
103*63dd5d25SJonas Devlieghere       SymbolContext *sym_ctx) override;
104*63dd5d25SJonas Devlieghere 
105*63dd5d25SJonas Devlieghere   lldb::SearchDepth ScriptedBreakpointResolverSearchDepth(
106*63dd5d25SJonas Devlieghere       StructuredData::GenericSP implementor_sp) override;
107*63dd5d25SJonas Devlieghere 
108*63dd5d25SJonas Devlieghere   StructuredData::GenericSP
109*63dd5d25SJonas Devlieghere   CreateFrameRecognizer(const char *class_name) override;
110*63dd5d25SJonas Devlieghere 
111*63dd5d25SJonas Devlieghere   lldb::ValueObjectListSP
112*63dd5d25SJonas Devlieghere   GetRecognizedArguments(const StructuredData::ObjectSP &implementor,
113*63dd5d25SJonas Devlieghere                          lldb::StackFrameSP frame_sp) override;
114*63dd5d25SJonas Devlieghere 
115*63dd5d25SJonas Devlieghere   StructuredData::GenericSP
116*63dd5d25SJonas Devlieghere   OSPlugin_CreatePluginObject(const char *class_name,
117*63dd5d25SJonas Devlieghere                               lldb::ProcessSP process_sp) override;
118*63dd5d25SJonas Devlieghere 
119*63dd5d25SJonas Devlieghere   StructuredData::DictionarySP
120*63dd5d25SJonas Devlieghere   OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
121*63dd5d25SJonas Devlieghere 
122*63dd5d25SJonas Devlieghere   StructuredData::ArraySP
123*63dd5d25SJonas Devlieghere   OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
124*63dd5d25SJonas Devlieghere 
125*63dd5d25SJonas Devlieghere   StructuredData::StringSP
126*63dd5d25SJonas Devlieghere   OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
127*63dd5d25SJonas Devlieghere                                lldb::tid_t thread_id) override;
128*63dd5d25SJonas Devlieghere 
129*63dd5d25SJonas Devlieghere   StructuredData::DictionarySP
130*63dd5d25SJonas Devlieghere   OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
131*63dd5d25SJonas Devlieghere                         lldb::tid_t tid, lldb::addr_t context) override;
132*63dd5d25SJonas Devlieghere 
133*63dd5d25SJonas Devlieghere   StructuredData::ObjectSP
134*63dd5d25SJonas Devlieghere   LoadPluginModule(const FileSpec &file_spec,
135*63dd5d25SJonas Devlieghere                    lldb_private::Status &error) override;
136*63dd5d25SJonas Devlieghere 
137*63dd5d25SJonas Devlieghere   StructuredData::DictionarySP
138*63dd5d25SJonas Devlieghere   GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
139*63dd5d25SJonas Devlieghere                      const char *setting_name,
140*63dd5d25SJonas Devlieghere                      lldb_private::Status &error) override;
141*63dd5d25SJonas Devlieghere 
142*63dd5d25SJonas Devlieghere   size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
143*63dd5d25SJonas Devlieghere                               uint32_t max) override;
144*63dd5d25SJonas Devlieghere 
145*63dd5d25SJonas Devlieghere   lldb::ValueObjectSP
146*63dd5d25SJonas Devlieghere   GetChildAtIndex(const StructuredData::ObjectSP &implementor,
147*63dd5d25SJonas Devlieghere                   uint32_t idx) override;
148*63dd5d25SJonas Devlieghere 
149*63dd5d25SJonas Devlieghere   int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
150*63dd5d25SJonas Devlieghere                               const char *child_name) override;
151*63dd5d25SJonas Devlieghere 
152*63dd5d25SJonas Devlieghere   bool UpdateSynthProviderInstance(
153*63dd5d25SJonas Devlieghere       const StructuredData::ObjectSP &implementor) override;
154*63dd5d25SJonas Devlieghere 
155*63dd5d25SJonas Devlieghere   bool MightHaveChildrenSynthProviderInstance(
156*63dd5d25SJonas Devlieghere       const StructuredData::ObjectSP &implementor) override;
157*63dd5d25SJonas Devlieghere 
158*63dd5d25SJonas Devlieghere   lldb::ValueObjectSP
159*63dd5d25SJonas Devlieghere   GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
160*63dd5d25SJonas Devlieghere 
161*63dd5d25SJonas Devlieghere   ConstString
162*63dd5d25SJonas Devlieghere   GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
163*63dd5d25SJonas Devlieghere 
164*63dd5d25SJonas Devlieghere   bool
165*63dd5d25SJonas Devlieghere   RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
166*63dd5d25SJonas Devlieghere                         ScriptedCommandSynchronicity synchronicity,
167*63dd5d25SJonas Devlieghere                         lldb_private::CommandReturnObject &cmd_retobj,
168*63dd5d25SJonas Devlieghere                         Status &error,
169*63dd5d25SJonas Devlieghere                         const lldb_private::ExecutionContext &exe_ctx) override;
170*63dd5d25SJonas Devlieghere 
171*63dd5d25SJonas Devlieghere   bool RunScriptBasedCommand(
172*63dd5d25SJonas Devlieghere       StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
173*63dd5d25SJonas Devlieghere       ScriptedCommandSynchronicity synchronicity,
174*63dd5d25SJonas Devlieghere       lldb_private::CommandReturnObject &cmd_retobj, Status &error,
175*63dd5d25SJonas Devlieghere       const lldb_private::ExecutionContext &exe_ctx) override;
176*63dd5d25SJonas Devlieghere 
177*63dd5d25SJonas Devlieghere   Status GenerateFunction(const char *signature,
178*63dd5d25SJonas Devlieghere                           const StringList &input) override;
179*63dd5d25SJonas Devlieghere 
180*63dd5d25SJonas Devlieghere   Status GenerateBreakpointCommandCallbackData(StringList &input,
181*63dd5d25SJonas Devlieghere                                                std::string &output) override;
182*63dd5d25SJonas Devlieghere 
183*63dd5d25SJonas Devlieghere   bool GenerateWatchpointCommandCallbackData(StringList &input,
184*63dd5d25SJonas Devlieghere                                              std::string &output) override;
185*63dd5d25SJonas Devlieghere 
186*63dd5d25SJonas Devlieghere   bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
187*63dd5d25SJonas Devlieghere                           StructuredData::ObjectSP &callee_wrapper_sp,
188*63dd5d25SJonas Devlieghere                           const TypeSummaryOptions &options,
189*63dd5d25SJonas Devlieghere                           std::string &retval) override;
190*63dd5d25SJonas Devlieghere 
191*63dd5d25SJonas Devlieghere   void Clear() override;
192*63dd5d25SJonas Devlieghere 
193*63dd5d25SJonas Devlieghere   bool GetDocumentationForItem(const char *item, std::string &dest) override;
194*63dd5d25SJonas Devlieghere 
195*63dd5d25SJonas Devlieghere   bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
196*63dd5d25SJonas Devlieghere                                     std::string &dest) override;
197*63dd5d25SJonas Devlieghere 
198*63dd5d25SJonas Devlieghere   uint32_t
199*63dd5d25SJonas Devlieghere   GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
200*63dd5d25SJonas Devlieghere 
201*63dd5d25SJonas Devlieghere   bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
202*63dd5d25SJonas Devlieghere                                    std::string &dest) override;
203*63dd5d25SJonas Devlieghere 
204*63dd5d25SJonas Devlieghere   bool CheckObjectExists(const char *name) override {
205*63dd5d25SJonas Devlieghere     if (!name || !name[0])
206*63dd5d25SJonas Devlieghere       return false;
207*63dd5d25SJonas Devlieghere     std::string temp;
208*63dd5d25SJonas Devlieghere     return GetDocumentationForItem(name, temp);
209*63dd5d25SJonas Devlieghere   }
210*63dd5d25SJonas Devlieghere 
211*63dd5d25SJonas Devlieghere   bool RunScriptFormatKeyword(const char *impl_function, Process *process,
212*63dd5d25SJonas Devlieghere                               std::string &output, Status &error) override;
213*63dd5d25SJonas Devlieghere 
214*63dd5d25SJonas Devlieghere   bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
215*63dd5d25SJonas Devlieghere                               std::string &output, Status &error) override;
216*63dd5d25SJonas Devlieghere 
217*63dd5d25SJonas Devlieghere   bool RunScriptFormatKeyword(const char *impl_function, Target *target,
218*63dd5d25SJonas Devlieghere                               std::string &output, Status &error) override;
219*63dd5d25SJonas Devlieghere 
220*63dd5d25SJonas Devlieghere   bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
221*63dd5d25SJonas Devlieghere                               std::string &output, Status &error) override;
222*63dd5d25SJonas Devlieghere 
223*63dd5d25SJonas Devlieghere   bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
224*63dd5d25SJonas Devlieghere                               std::string &output, Status &error) override;
225*63dd5d25SJonas Devlieghere 
226*63dd5d25SJonas Devlieghere   bool
227*63dd5d25SJonas Devlieghere   LoadScriptingModule(const char *filename, bool can_reload, bool init_session,
228*63dd5d25SJonas Devlieghere                       lldb_private::Status &error,
229*63dd5d25SJonas Devlieghere                       StructuredData::ObjectSP *module_sp = nullptr) override;
230*63dd5d25SJonas Devlieghere 
231*63dd5d25SJonas Devlieghere   bool IsReservedWord(const char *word) override;
232*63dd5d25SJonas Devlieghere 
233*63dd5d25SJonas Devlieghere   std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
234*63dd5d25SJonas Devlieghere 
235*63dd5d25SJonas Devlieghere   void CollectDataForBreakpointCommandCallback(
236*63dd5d25SJonas Devlieghere       std::vector<BreakpointOptions *> &bp_options_vec,
237*63dd5d25SJonas Devlieghere       CommandReturnObject &result) override;
238*63dd5d25SJonas Devlieghere 
239*63dd5d25SJonas Devlieghere   void
240*63dd5d25SJonas Devlieghere   CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
241*63dd5d25SJonas Devlieghere                                           CommandReturnObject &result) override;
242*63dd5d25SJonas Devlieghere 
243*63dd5d25SJonas Devlieghere   /// Set the callback body text into the callback for the breakpoint.
244*63dd5d25SJonas Devlieghere   Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
245*63dd5d25SJonas Devlieghere                                       const char *callback_body) override;
246*63dd5d25SJonas Devlieghere 
247*63dd5d25SJonas Devlieghere   void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
248*63dd5d25SJonas Devlieghere                                             const char *function_name) override;
249*63dd5d25SJonas Devlieghere 
250*63dd5d25SJonas Devlieghere   /// This one is for deserialization:
251*63dd5d25SJonas Devlieghere   Status SetBreakpointCommandCallback(
252*63dd5d25SJonas Devlieghere       BreakpointOptions *bp_options,
253*63dd5d25SJonas Devlieghere       std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
254*63dd5d25SJonas Devlieghere 
255*63dd5d25SJonas Devlieghere   /// Set a one-liner as the callback for the watchpoint.
256*63dd5d25SJonas Devlieghere   void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
257*63dd5d25SJonas Devlieghere                                     const char *oneliner) override;
258*63dd5d25SJonas Devlieghere 
259*63dd5d25SJonas Devlieghere   void ResetOutputFileHandle(FILE *new_fh) override;
260*63dd5d25SJonas Devlieghere 
261*63dd5d25SJonas Devlieghere   const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
262*63dd5d25SJonas Devlieghere 
263*63dd5d25SJonas Devlieghere   PyThreadState *GetThreadState() { return m_command_thread_state; }
264*63dd5d25SJonas Devlieghere 
265*63dd5d25SJonas Devlieghere   void SetThreadState(PyThreadState *s) {
266*63dd5d25SJonas Devlieghere     if (s)
267*63dd5d25SJonas Devlieghere       m_command_thread_state = s;
268*63dd5d25SJonas Devlieghere   }
269*63dd5d25SJonas Devlieghere 
270*63dd5d25SJonas Devlieghere   //----------------------------------------------------------------------
271*63dd5d25SJonas Devlieghere   // IOHandlerDelegate
272*63dd5d25SJonas Devlieghere   //----------------------------------------------------------------------
273*63dd5d25SJonas Devlieghere   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
274*63dd5d25SJonas Devlieghere 
275*63dd5d25SJonas Devlieghere   void IOHandlerInputComplete(IOHandler &io_handler,
276*63dd5d25SJonas Devlieghere                               std::string &data) override;
277*63dd5d25SJonas Devlieghere 
278*63dd5d25SJonas Devlieghere   static lldb::ScriptInterpreterSP
279*63dd5d25SJonas Devlieghere   CreateInstance(CommandInterpreter &interpreter);
280*63dd5d25SJonas Devlieghere 
281*63dd5d25SJonas Devlieghere   //------------------------------------------------------------------
282*63dd5d25SJonas Devlieghere   // PluginInterface protocol
283*63dd5d25SJonas Devlieghere   //------------------------------------------------------------------
284*63dd5d25SJonas Devlieghere   lldb_private::ConstString GetPluginName() override;
285*63dd5d25SJonas Devlieghere 
286*63dd5d25SJonas Devlieghere   uint32_t GetPluginVersion() override;
287*63dd5d25SJonas Devlieghere 
288*63dd5d25SJonas Devlieghere   class Locker : public ScriptInterpreterLocker {
289*63dd5d25SJonas Devlieghere   public:
290*63dd5d25SJonas Devlieghere     enum OnEntry {
291*63dd5d25SJonas Devlieghere       AcquireLock = 0x0001,
292*63dd5d25SJonas Devlieghere       InitSession = 0x0002,
293*63dd5d25SJonas Devlieghere       InitGlobals = 0x0004,
294*63dd5d25SJonas Devlieghere       NoSTDIN = 0x0008
295*63dd5d25SJonas Devlieghere     };
296*63dd5d25SJonas Devlieghere 
297*63dd5d25SJonas Devlieghere     enum OnLeave {
298*63dd5d25SJonas Devlieghere       FreeLock = 0x0001,
299*63dd5d25SJonas Devlieghere       FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
300*63dd5d25SJonas Devlieghere                                  // when calling constructor
301*63dd5d25SJonas Devlieghere       TearDownSession = 0x0004
302*63dd5d25SJonas Devlieghere     };
303*63dd5d25SJonas Devlieghere 
304*63dd5d25SJonas Devlieghere     Locker(ScriptInterpreterPythonImpl *py_interpreter = nullptr,
305*63dd5d25SJonas Devlieghere            uint16_t on_entry = AcquireLock | InitSession,
306*63dd5d25SJonas Devlieghere            uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr,
307*63dd5d25SJonas Devlieghere            FILE *out = nullptr, FILE *err = nullptr);
308*63dd5d25SJonas Devlieghere 
309*63dd5d25SJonas Devlieghere     ~Locker() override;
310*63dd5d25SJonas Devlieghere 
311*63dd5d25SJonas Devlieghere   private:
312*63dd5d25SJonas Devlieghere     bool DoAcquireLock();
313*63dd5d25SJonas Devlieghere 
314*63dd5d25SJonas Devlieghere     bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
315*63dd5d25SJonas Devlieghere 
316*63dd5d25SJonas Devlieghere     bool DoFreeLock();
317*63dd5d25SJonas Devlieghere 
318*63dd5d25SJonas Devlieghere     bool DoTearDownSession();
319*63dd5d25SJonas Devlieghere 
320*63dd5d25SJonas Devlieghere     bool m_teardown_session;
321*63dd5d25SJonas Devlieghere     ScriptInterpreterPythonImpl *m_python_interpreter;
322*63dd5d25SJonas Devlieghere     //    	FILE*                    m_tmp_fh;
323*63dd5d25SJonas Devlieghere     PyGILState_STATE m_GILState;
324*63dd5d25SJonas Devlieghere   };
325*63dd5d25SJonas Devlieghere 
326*63dd5d25SJonas Devlieghere   static bool BreakpointCallbackFunction(void *baton,
327*63dd5d25SJonas Devlieghere                                          StoppointCallbackContext *context,
328*63dd5d25SJonas Devlieghere                                          lldb::user_id_t break_id,
329*63dd5d25SJonas Devlieghere                                          lldb::user_id_t break_loc_id);
330*63dd5d25SJonas Devlieghere   static bool WatchpointCallbackFunction(void *baton,
331*63dd5d25SJonas Devlieghere                                          StoppointCallbackContext *context,
332*63dd5d25SJonas Devlieghere                                          lldb::user_id_t watch_id);
333*63dd5d25SJonas Devlieghere   static void InitializePrivate();
334*63dd5d25SJonas Devlieghere 
335*63dd5d25SJonas Devlieghere   class SynchronicityHandler {
336*63dd5d25SJonas Devlieghere   private:
337*63dd5d25SJonas Devlieghere     lldb::DebuggerSP m_debugger_sp;
338*63dd5d25SJonas Devlieghere     ScriptedCommandSynchronicity m_synch_wanted;
339*63dd5d25SJonas Devlieghere     bool m_old_asynch;
340*63dd5d25SJonas Devlieghere 
341*63dd5d25SJonas Devlieghere   public:
342*63dd5d25SJonas Devlieghere     SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
343*63dd5d25SJonas Devlieghere 
344*63dd5d25SJonas Devlieghere     ~SynchronicityHandler();
345*63dd5d25SJonas Devlieghere   };
346*63dd5d25SJonas Devlieghere 
347*63dd5d25SJonas Devlieghere   enum class AddLocation { Beginning, End };
348*63dd5d25SJonas Devlieghere 
349*63dd5d25SJonas Devlieghere   static void AddToSysPath(AddLocation location, std::string path);
350*63dd5d25SJonas Devlieghere 
351*63dd5d25SJonas Devlieghere   bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
352*63dd5d25SJonas Devlieghere 
353*63dd5d25SJonas Devlieghere   void LeaveSession();
354*63dd5d25SJonas Devlieghere 
355*63dd5d25SJonas Devlieghere   void SaveTerminalState(int fd);
356*63dd5d25SJonas Devlieghere 
357*63dd5d25SJonas Devlieghere   void RestoreTerminalState();
358*63dd5d25SJonas Devlieghere 
359*63dd5d25SJonas Devlieghere   uint32_t IsExecutingPython() const { return m_lock_count > 0; }
360*63dd5d25SJonas Devlieghere 
361*63dd5d25SJonas Devlieghere   uint32_t IncrementLockCount() { return ++m_lock_count; }
362*63dd5d25SJonas Devlieghere 
363*63dd5d25SJonas Devlieghere   uint32_t DecrementLockCount() {
364*63dd5d25SJonas Devlieghere     if (m_lock_count > 0)
365*63dd5d25SJonas Devlieghere       --m_lock_count;
366*63dd5d25SJonas Devlieghere     return m_lock_count;
367*63dd5d25SJonas Devlieghere   }
368*63dd5d25SJonas Devlieghere 
369*63dd5d25SJonas Devlieghere   enum ActiveIOHandler {
370*63dd5d25SJonas Devlieghere     eIOHandlerNone,
371*63dd5d25SJonas Devlieghere     eIOHandlerBreakpoint,
372*63dd5d25SJonas Devlieghere     eIOHandlerWatchpoint
373*63dd5d25SJonas Devlieghere   };
374*63dd5d25SJonas Devlieghere 
375*63dd5d25SJonas Devlieghere   PythonObject &GetMainModule();
376*63dd5d25SJonas Devlieghere 
377*63dd5d25SJonas Devlieghere   PythonDictionary &GetSessionDictionary();
378*63dd5d25SJonas Devlieghere 
379*63dd5d25SJonas Devlieghere   PythonDictionary &GetSysModuleDictionary();
380*63dd5d25SJonas Devlieghere 
381*63dd5d25SJonas Devlieghere   bool GetEmbeddedInterpreterModuleObjects();
382*63dd5d25SJonas Devlieghere 
383*63dd5d25SJonas Devlieghere   bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file,
384*63dd5d25SJonas Devlieghere                     const char *mode);
385*63dd5d25SJonas Devlieghere 
386*63dd5d25SJonas Devlieghere   PythonFile m_saved_stdin;
387*63dd5d25SJonas Devlieghere   PythonFile m_saved_stdout;
388*63dd5d25SJonas Devlieghere   PythonFile m_saved_stderr;
389*63dd5d25SJonas Devlieghere   PythonObject m_main_module;
390*63dd5d25SJonas Devlieghere   PythonDictionary m_session_dict;
391*63dd5d25SJonas Devlieghere   PythonDictionary m_sys_module_dict;
392*63dd5d25SJonas Devlieghere   PythonObject m_run_one_line_function;
393*63dd5d25SJonas Devlieghere   PythonObject m_run_one_line_str_global;
394*63dd5d25SJonas Devlieghere   std::string m_dictionary_name;
395*63dd5d25SJonas Devlieghere   TerminalState m_terminal_state;
396*63dd5d25SJonas Devlieghere   ActiveIOHandler m_active_io_handler;
397*63dd5d25SJonas Devlieghere   bool m_session_is_active;
398*63dd5d25SJonas Devlieghere   bool m_pty_slave_is_open;
399*63dd5d25SJonas Devlieghere   bool m_valid_session;
400*63dd5d25SJonas Devlieghere   uint32_t m_lock_count;
401*63dd5d25SJonas Devlieghere   PyThreadState *m_command_thread_state;
402*63dd5d25SJonas Devlieghere };
403*63dd5d25SJonas Devlieghere 
404*63dd5d25SJonas Devlieghere class IOHandlerPythonInterpreter : public IOHandler {
405*63dd5d25SJonas Devlieghere public:
406*63dd5d25SJonas Devlieghere   IOHandlerPythonInterpreter(Debugger &debugger,
407*63dd5d25SJonas Devlieghere                              ScriptInterpreterPythonImpl *python)
408*63dd5d25SJonas Devlieghere       : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
409*63dd5d25SJonas Devlieghere         m_python(python) {}
410*63dd5d25SJonas Devlieghere 
411*63dd5d25SJonas Devlieghere   ~IOHandlerPythonInterpreter() override {}
412*63dd5d25SJonas Devlieghere 
413*63dd5d25SJonas Devlieghere   ConstString GetControlSequence(char ch) override {
414*63dd5d25SJonas Devlieghere     if (ch == 'd')
415*63dd5d25SJonas Devlieghere       return ConstString("quit()\n");
416*63dd5d25SJonas Devlieghere     return ConstString();
417*63dd5d25SJonas Devlieghere   }
418*63dd5d25SJonas Devlieghere 
419*63dd5d25SJonas Devlieghere   void Run() override {
420*63dd5d25SJonas Devlieghere     if (m_python) {
421*63dd5d25SJonas Devlieghere       int stdin_fd = GetInputFD();
422*63dd5d25SJonas Devlieghere       if (stdin_fd >= 0) {
423*63dd5d25SJonas Devlieghere         Terminal terminal(stdin_fd);
424*63dd5d25SJonas Devlieghere         TerminalState terminal_state;
425*63dd5d25SJonas Devlieghere         const bool is_a_tty = terminal.IsATerminal();
426*63dd5d25SJonas Devlieghere 
427*63dd5d25SJonas Devlieghere         if (is_a_tty) {
428*63dd5d25SJonas Devlieghere           terminal_state.Save(stdin_fd, false);
429*63dd5d25SJonas Devlieghere           terminal.SetCanonical(false);
430*63dd5d25SJonas Devlieghere           terminal.SetEcho(true);
431*63dd5d25SJonas Devlieghere         }
432*63dd5d25SJonas Devlieghere 
433*63dd5d25SJonas Devlieghere         ScriptInterpreterPythonImpl::Locker locker(
434*63dd5d25SJonas Devlieghere             m_python,
435*63dd5d25SJonas Devlieghere             ScriptInterpreterPythonImpl::Locker::AcquireLock |
436*63dd5d25SJonas Devlieghere                 ScriptInterpreterPythonImpl::Locker::InitSession |
437*63dd5d25SJonas Devlieghere                 ScriptInterpreterPythonImpl::Locker::InitGlobals,
438*63dd5d25SJonas Devlieghere             ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |
439*63dd5d25SJonas Devlieghere                 ScriptInterpreterPythonImpl::Locker::TearDownSession);
440*63dd5d25SJonas Devlieghere 
441*63dd5d25SJonas Devlieghere         // The following call drops into the embedded interpreter loop and
442*63dd5d25SJonas Devlieghere         // stays there until the user chooses to exit from the Python
443*63dd5d25SJonas Devlieghere         // interpreter. This embedded interpreter will, as any Python code that
444*63dd5d25SJonas Devlieghere         // performs I/O, unlock the GIL before a system call that can hang, and
445*63dd5d25SJonas Devlieghere         // lock it when the syscall has returned.
446*63dd5d25SJonas Devlieghere 
447*63dd5d25SJonas Devlieghere         // We need to surround the call to the embedded interpreter with calls
448*63dd5d25SJonas Devlieghere         // to PyGILState_Ensure and PyGILState_Release (using the Locker
449*63dd5d25SJonas Devlieghere         // above). This is because Python has a global lock which must be held
450*63dd5d25SJonas Devlieghere         // whenever we want to touch any Python objects. Otherwise, if the user
451*63dd5d25SJonas Devlieghere         // calls Python code, the interpreter state will be off, and things
452*63dd5d25SJonas Devlieghere         // could hang (it's happened before).
453*63dd5d25SJonas Devlieghere 
454*63dd5d25SJonas Devlieghere         StreamString run_string;
455*63dd5d25SJonas Devlieghere         run_string.Printf("run_python_interpreter (%s)",
456*63dd5d25SJonas Devlieghere                           m_python->GetDictionaryName());
457*63dd5d25SJonas Devlieghere         PyRun_SimpleString(run_string.GetData());
458*63dd5d25SJonas Devlieghere 
459*63dd5d25SJonas Devlieghere         if (is_a_tty)
460*63dd5d25SJonas Devlieghere           terminal_state.Restore();
461*63dd5d25SJonas Devlieghere       }
462*63dd5d25SJonas Devlieghere     }
463*63dd5d25SJonas Devlieghere     SetIsDone(true);
464*63dd5d25SJonas Devlieghere   }
465*63dd5d25SJonas Devlieghere 
466*63dd5d25SJonas Devlieghere   void Cancel() override {}
467*63dd5d25SJonas Devlieghere 
468*63dd5d25SJonas Devlieghere   bool Interrupt() override { return m_python->Interrupt(); }
469*63dd5d25SJonas Devlieghere 
470*63dd5d25SJonas Devlieghere   void GotEOF() override {}
471*63dd5d25SJonas Devlieghere 
472*63dd5d25SJonas Devlieghere protected:
473*63dd5d25SJonas Devlieghere   ScriptInterpreterPythonImpl *m_python;
474*63dd5d25SJonas Devlieghere };
475*63dd5d25SJonas Devlieghere 
476*63dd5d25SJonas Devlieghere } // namespace lldb_private
477*63dd5d25SJonas Devlieghere 
478*63dd5d25SJonas Devlieghere #endif
479