aboutsummaryrefslogtreecommitdiff
path: root/lldb/include/lldb/Interpreter/ScriptInterpreter.h
blob: 491923e6a6c4fc3a2eb0caa28422be7c79a085c4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
//===-- ScriptInterpreter.h -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H
#define LLDB_INTERPRETER_SCRIPTINTERPRETER_H

#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

class ScriptInterpreterLocker {
public:
  ScriptInterpreterLocker() = default;

  virtual ~ScriptInterpreterLocker() = default;

private:
  ScriptInterpreterLocker(const ScriptInterpreterLocker &) = delete;
  const ScriptInterpreterLocker &
  operator=(const ScriptInterpreterLocker &) = delete;
};

class ScriptInterpreterIORedirect {
public:
  /// Create an IO redirect. If IO is enabled, this will redirects the output
  /// to the command return object if set or to the debugger otherwise. If IO
  /// is disabled, it will redirect all IO to /dev/null.
  static llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
  Create(bool enable_io, Debugger &debugger, CommandReturnObject *result);

  ~ScriptInterpreterIORedirect();

  lldb::FileSP GetInputFile() const { return m_input_file_sp; }
  lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); }
  lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); }

  /// Flush our output and error file handles.
  void Flush();

private:
  ScriptInterpreterIORedirect(std::unique_ptr<File> input,
                              std::unique_ptr<File> output);
  ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result);

  lldb::FileSP m_input_file_sp;
  lldb::StreamFileSP m_output_file_sp;
  lldb::StreamFileSP m_error_file_sp;
  Communication m_communication;
  bool m_disconnect;
};

class ScriptInterpreter : public PluginInterface {
public:
  enum ScriptReturnType {
    eScriptReturnTypeCharPtr,
    eScriptReturnTypeBool,
    eScriptReturnTypeShortInt,
    eScriptReturnTypeShortIntUnsigned,
    eScriptReturnTypeInt,
    eScriptReturnTypeIntUnsigned,
    eScriptReturnTypeLongInt,
    eScriptReturnTypeLongIntUnsigned,
    eScriptReturnTypeLongLong,
    eScriptReturnTypeLongLongUnsigned,
    eScriptReturnTypeFloat,
    eScriptReturnTypeDouble,
    eScriptReturnTypeChar,
    eScriptReturnTypeCharStrOrNone,
    eScriptReturnTypeOpaqueObject
  };

  ScriptInterpreter(Debugger &debugger, lldb::ScriptLanguage script_lang);

  ~ScriptInterpreter() override;

  struct ExecuteScriptOptions {
  public:
    ExecuteScriptOptions()
        : m_enable_io(true), m_set_lldb_globals(true), m_maskout_errors(true) {}

    bool GetEnableIO() const { return m_enable_io; }

    bool GetSetLLDBGlobals() const { return m_set_lldb_globals; }

    // If this is true then any exceptions raised by the script will be
    // cleared with PyErr_Clear().   If false then they will be left for
    // the caller to clean up
    bool GetMaskoutErrors() const { return m_maskout_errors; }

    ExecuteScriptOptions &SetEnableIO(bool enable) {
      m_enable_io = enable;
      return *this;
    }

    ExecuteScriptOptions &SetSetLLDBGlobals(bool set) {
      m_set_lldb_globals = set;
      return *this;
    }

    ExecuteScriptOptions &SetMaskoutErrors(bool maskout) {
      m_maskout_errors = maskout;
      return *this;
    }

  private:
    bool m_enable_io;
    bool m_set_lldb_globals;
    bool m_maskout_errors;
  };

  virtual bool Interrupt() { return false; }

  virtual bool ExecuteOneLine(
      llvm::StringRef command, CommandReturnObject *result,
      const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0;

  virtual void ExecuteInterpreterLoop() = 0;

  virtual bool ExecuteOneLineWithReturn(
      llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value,
      const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
    return true;
  }

  virtual Status ExecuteMultipleLines(
      const char *in_string,
      const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
    Status error;
    error.SetErrorString("not implemented");
    return error;
  }

  virtual Status
  ExportFunctionDefinitionToInterpreter(StringList &function_def) {
    Status error;
    error.SetErrorString("not implemented");
    return error;
  }

  virtual Status GenerateBreakpointCommandCallbackData(
      StringList &input,
      std::string &output,
      bool has_extra_args) {
    Status error;
    error.SetErrorString("not implemented");
    return error;
  }

  virtual bool GenerateWatchpointCommandCallbackData(StringList &input,
                                                     std::string &output) {
    return false;
  }

  virtual bool GenerateTypeScriptFunction(const char *oneliner,
                                          std::string &output,
                                          const void *name_token = nullptr) {
    return false;
  }

  virtual bool GenerateTypeScriptFunction(StringList &input,
                                          std::string &output,
                                          const void *name_token = nullptr) {
    return false;
  }

  virtual bool GenerateScriptAliasFunction(StringList &input,
                                           std::string &output) {
    return false;
  }

  virtual bool GenerateTypeSynthClass(StringList &input, std::string &output,
                                      const void *name_token = nullptr) {
    return false;
  }

  virtual bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
                                      const void *name_token = nullptr) {
    return false;
  }

  virtual StructuredData::ObjectSP
  CreateSyntheticScriptedProvider(const char *class_name,
                                  lldb::ValueObjectSP valobj) {
    return StructuredData::ObjectSP();
  }

  virtual StructuredData::GenericSP
  CreateScriptCommandObject(const char *class_name) {
    return StructuredData::GenericSP();
  }

  virtual StructuredData::GenericSP
  CreateFrameRecognizer(const char *class_name) {
    return StructuredData::GenericSP();
  }

  virtual lldb::ValueObjectListSP GetRecognizedArguments(
      const StructuredData::ObjectSP &implementor,
      lldb::StackFrameSP frame_sp) {
    return lldb::ValueObjectListSP();
  }

  virtual StructuredData::GenericSP
  OSPlugin_CreatePluginObject(const char *class_name,
                              lldb::ProcessSP process_sp) {
    return StructuredData::GenericSP();
  }

  virtual StructuredData::DictionarySP
  OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) {
    return StructuredData::DictionarySP();
  }

  virtual StructuredData::ArraySP
  OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) {
    return StructuredData::ArraySP();
  }

  virtual StructuredData::StringSP
  OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
                               lldb::tid_t thread_id) {
    return StructuredData::StringSP();
  }

  virtual StructuredData::DictionarySP
  OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
                        lldb::tid_t tid, lldb::addr_t context) {
    return StructuredData::DictionarySP();
  }

  virtual StructuredData::ObjectSP
  CreateScriptedThreadPlan(const char *class_name,
                           StructuredDataImpl *args_data,
                           std::string &error_str,
                           lldb::ThreadPlanSP thread_plan_sp) {
    return StructuredData::ObjectSP();
  }

  virtual bool
  ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
                                 Event *event, bool &script_error) {
    script_error = true;
    return true;
  }

  virtual bool
  ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
                               Event *event, bool &script_error) {
    script_error = true;
    return true;
  }

  virtual bool
  ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
                            bool &script_error) {
    script_error = true;
    return true;
  }

  virtual lldb::StateType
  ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
                                bool &script_error) {
    script_error = true;
    return lldb::eStateStepping;
  }

  virtual StructuredData::GenericSP
  CreateScriptedBreakpointResolver(const char *class_name,
                                   StructuredDataImpl *args_data,
                                   lldb::BreakpointSP &bkpt_sp) {
    return StructuredData::GenericSP();
  }

  virtual bool
  ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
                                           SymbolContext *sym_ctx)
  {
    return false;
  }

  virtual lldb::SearchDepth
  ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
  {
    return lldb::eSearchDepthModule;
  }

  virtual StructuredData::ObjectSP
  LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
    return StructuredData::ObjectSP();
  }

  virtual StructuredData::DictionarySP
  GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
                     const char *setting_name, lldb_private::Status &error) {
    return StructuredData::DictionarySP();
  }

  virtual Status GenerateFunction(const char *signature,
                                  const StringList &input) {
    Status error;
    error.SetErrorString("unimplemented");
    return error;
  }

  virtual void CollectDataForBreakpointCommandCallback(
      std::vector<BreakpointOptions *> &options, CommandReturnObject &result);

  virtual void
  CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
                                          CommandReturnObject &result);

  /// Set the specified text as the callback for the breakpoint.
  Status
  SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
                               const char *callback_text);

  virtual Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
                                              const char *callback_text) {
    Status error;
    error.SetErrorString("unimplemented");
    return error;
  }

  /// This one is for deserialization:
  virtual Status SetBreakpointCommandCallback(
      BreakpointOptions *bp_options,
      std::unique_ptr<BreakpointOptions::CommandData> &data_up) {
    Status error;
    error.SetErrorString("unimplemented");
    return error;
  }

  Status SetBreakpointCommandCallbackFunction(
      std::vector<BreakpointOptions *> &bp_options_vec,
      const char *function_name, StructuredData::ObjectSP extra_args_sp);

  /// Set a script function as the callback for the breakpoint.
  virtual Status
  SetBreakpointCommandCallbackFunction(
      BreakpointOptions *bp_options,
      const char *function_name,
      StructuredData::ObjectSP extra_args_sp) {
    Status error;
    error.SetErrorString("unimplemented");
    return error;
  }

  /// Set a one-liner as the callback for the watchpoint.
  virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
                                            const char *oneliner) {}

  virtual bool GetScriptedSummary(const char *function_name,
                                  lldb::ValueObjectSP valobj,
                                  StructuredData::ObjectSP &callee_wrapper_sp,
                                  const TypeSummaryOptions &options,
                                  std::string &retval) {
    return false;
  }

  virtual void Clear() {
    // Clean up any ref counts to SBObjects that might be in global variables
  }

  virtual size_t
  CalculateNumChildren(const StructuredData::ObjectSP &implementor,
                       uint32_t max) {
    return 0;
  }

  virtual lldb::ValueObjectSP
  GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) {
    return lldb::ValueObjectSP();
  }

  virtual int
  GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
                          const char *child_name) {
    return UINT32_MAX;
  }

  virtual bool
  UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) {
    return false;
  }

  virtual bool MightHaveChildrenSynthProviderInstance(
      const StructuredData::ObjectSP &implementor) {
    return true;
  }

  virtual lldb::ValueObjectSP
  GetSyntheticValue(const StructuredData::ObjectSP &implementor) {
    return nullptr;
  }

  virtual ConstString
  GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) {
    return ConstString();
  }

  virtual bool
  RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
                        ScriptedCommandSynchronicity synchronicity,
                        lldb_private::CommandReturnObject &cmd_retobj,
                        Status &error,
                        const lldb_private::ExecutionContext &exe_ctx) {
    return false;
  }

  virtual bool RunScriptBasedCommand(
      StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
      ScriptedCommandSynchronicity synchronicity,
      lldb_private::CommandReturnObject &cmd_retobj, Status &error,
      const lldb_private::ExecutionContext &exe_ctx) {
    return false;
  }

  virtual bool RunScriptFormatKeyword(const char *impl_function,
                                      Process *process, std::string &output,
                                      Status &error) {
    error.SetErrorString("unimplemented");
    return false;
  }

  virtual bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
                                      std::string &output, Status &error) {
    error.SetErrorString("unimplemented");
    return false;
  }

  virtual bool RunScriptFormatKeyword(const char *impl_function, Target *target,
                                      std::string &output, Status &error) {
    error.SetErrorString("unimplemented");
    return false;
  }

  virtual bool RunScriptFormatKeyword(const char *impl_function,
                                      StackFrame *frame, std::string &output,
                                      Status &error) {
    error.SetErrorString("unimplemented");
    return false;
  }

  virtual bool RunScriptFormatKeyword(const char *impl_function,
                                      ValueObject *value, std::string &output,
                                      Status &error) {
    error.SetErrorString("unimplemented");
    return false;
  }

  virtual bool GetDocumentationForItem(const char *item, std::string &dest) {
    dest.clear();
    return false;
  }

  virtual bool
  GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
                               std::string &dest) {
    dest.clear();
    return false;
  }

  virtual uint32_t
  GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) {
    return 0;
  }

  virtual bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
                                           std::string &dest) {
    dest.clear();
    return false;
  }

  virtual bool CheckObjectExists(const char *name) { return false; }

  virtual bool
  LoadScriptingModule(const char *filename, bool init_session,
                      lldb_private::Status &error,
                      StructuredData::ObjectSP *module_sp = nullptr);

  virtual bool IsReservedWord(const char *word) { return false; }

  virtual std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock();

  const char *GetScriptInterpreterPtyName();

  virtual llvm::Expected<unsigned>
  GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) {
    return llvm::createStringError(
    llvm::inconvertibleErrorCode(), "Unimplemented function");
  }

  static std::string LanguageToString(lldb::ScriptLanguage language);

  static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string);

  lldb::ScriptLanguage GetLanguage() { return m_script_lang; }

protected:
  Debugger &m_debugger;
  lldb::ScriptLanguage m_script_lang;
};

} // namespace lldb_private

#endif // LLDB_INTERPRETER_SCRIPTINTERPRETER_H