Coverage Report

Created: 2023-09-21 18:56

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