Coverage Report

Created: 2022-01-18 06:27

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