1//===-- ScriptInterpreter.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_INTERPRETER_SCRIPTINTERPRETER_H
10#define LLDB_INTERPRETER_SCRIPTINTERPRETER_H
11
12#include "lldb/API/SBAttachInfo.h"
13#include "lldb/API/SBBreakpoint.h"
14#include "lldb/API/SBData.h"
15#include "lldb/API/SBError.h"
16#include "lldb/API/SBLaunchInfo.h"
17#include "lldb/API/SBMemoryRegionInfo.h"
18#include "lldb/Breakpoint/BreakpointOptions.h"
19#include "lldb/Core/PluginInterface.h"
20#include "lldb/Core/SearchFilter.h"
21#include "lldb/Core/ThreadedCommunication.h"
22#include "lldb/Host/PseudoTerminal.h"
23#include "lldb/Host/StreamFile.h"
24#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"
25#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
26#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
27#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
28#include "lldb/Interpreter/ScriptObject.h"
29#include "lldb/Utility/Broadcaster.h"
30#include "lldb/Utility/Status.h"
31#include "lldb/Utility/StructuredData.h"
32#include "lldb/lldb-private.h"
33#include <optional>
34
35namespace lldb_private {
36
37class ScriptInterpreterLocker {
38public:
39  ScriptInterpreterLocker() = default;
40
41  virtual ~ScriptInterpreterLocker() = default;
42
43private:
44  ScriptInterpreterLocker(const ScriptInterpreterLocker &) = delete;
45  const ScriptInterpreterLocker &
46  operator=(const ScriptInterpreterLocker &) = delete;
47};
48
49class ExecuteScriptOptions {
50public:
51  ExecuteScriptOptions() = default;
52
53  bool GetEnableIO() const { return m_enable_io; }
54
55  bool GetSetLLDBGlobals() const { return m_set_lldb_globals; }
56
57  // If this is true then any exceptions raised by the script will be
58  // cleared with PyErr_Clear().   If false then they will be left for
59  // the caller to clean up
60  bool GetMaskoutErrors() const { return m_maskout_errors; }
61
62  ExecuteScriptOptions &SetEnableIO(bool enable) {
63    m_enable_io = enable;
64    return *this;
65  }
66
67  ExecuteScriptOptions &SetSetLLDBGlobals(bool set) {
68    m_set_lldb_globals = set;
69    return *this;
70  }
71
72  ExecuteScriptOptions &SetMaskoutErrors(bool maskout) {
73    m_maskout_errors = maskout;
74    return *this;
75  }
76
77private:
78  bool m_enable_io = true;
79  bool m_set_lldb_globals = true;
80  bool m_maskout_errors = true;
81};
82
83class LoadScriptOptions {
84public:
85  LoadScriptOptions() = default;
86
87  bool GetInitSession() const { return m_init_session; }
88  bool GetSilent() const { return m_silent; }
89
90  LoadScriptOptions &SetInitSession(bool b) {
91    m_init_session = b;
92    return *this;
93  }
94
95  LoadScriptOptions &SetSilent(bool b) {
96    m_silent = b;
97    return *this;
98  }
99
100private:
101  bool m_init_session = false;
102  bool m_silent = false;
103};
104
105class ScriptInterpreterIORedirect {
106public:
107  /// Create an IO redirect. If IO is enabled, this will redirects the output
108  /// to the command return object if set or to the debugger otherwise. If IO
109  /// is disabled, it will redirect all IO to /dev/null.
110  static llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
111  Create(bool enable_io, Debugger &debugger, CommandReturnObject *result);
112
113  ~ScriptInterpreterIORedirect();
114
115  lldb::FileSP GetInputFile() const { return m_input_file_sp; }
116  lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); }
117  lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); }
118
119  /// Flush our output and error file handles.
120  void Flush();
121
122private:
123  ScriptInterpreterIORedirect(std::unique_ptr<File> input,
124                              std::unique_ptr<File> output);
125  ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result);
126
127  lldb::FileSP m_input_file_sp;
128  lldb::StreamFileSP m_output_file_sp;
129  lldb::StreamFileSP m_error_file_sp;
130  ThreadedCommunication m_communication;
131  bool m_disconnect;
132};
133
134class ScriptInterpreter : public PluginInterface {
135public:
136  enum ScriptReturnType {
137    eScriptReturnTypeCharPtr,
138    eScriptReturnTypeBool,
139    eScriptReturnTypeShortInt,
140    eScriptReturnTypeShortIntUnsigned,
141    eScriptReturnTypeInt,
142    eScriptReturnTypeIntUnsigned,
143    eScriptReturnTypeLongInt,
144    eScriptReturnTypeLongIntUnsigned,
145    eScriptReturnTypeLongLong,
146    eScriptReturnTypeLongLongUnsigned,
147    eScriptReturnTypeFloat,
148    eScriptReturnTypeDouble,
149    eScriptReturnTypeChar,
150    eScriptReturnTypeCharStrOrNone,
151    eScriptReturnTypeOpaqueObject
152  };
153
154  ScriptInterpreter(Debugger &debugger, lldb::ScriptLanguage script_lang);
155
156  virtual StructuredData::DictionarySP GetInterpreterInfo();
157
158  ~ScriptInterpreter() override = default;
159
160  virtual bool Interrupt() { return false; }
161
162  virtual bool ExecuteOneLine(
163      llvm::StringRef command, CommandReturnObject *result,
164      const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0;
165
166  virtual void ExecuteInterpreterLoop() = 0;
167
168  virtual bool ExecuteOneLineWithReturn(
169      llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value,
170      const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
171    return true;
172  }
173
174  virtual Status ExecuteMultipleLines(
175      const char *in_string,
176      const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
177    Status error;
178    error.SetErrorString("not implemented");
179    return error;
180  }
181
182  virtual Status
183  ExportFunctionDefinitionToInterpreter(StringList &function_def) {
184    Status error;
185    error.SetErrorString("not implemented");
186    return error;
187  }
188
189  virtual Status GenerateBreakpointCommandCallbackData(StringList &input,
190                                                       std::string &output,
191                                                       bool has_extra_args,
192                                                       bool is_callback) {
193    Status error;
194    error.SetErrorString("not implemented");
195    return error;
196  }
197
198  virtual bool GenerateWatchpointCommandCallbackData(StringList &input,
199                                                     std::string &output,
200                                                     bool is_callback) {
201    return false;
202  }
203
204  virtual bool GenerateTypeScriptFunction(const char *oneliner,
205                                          std::string &output,
206                                          const void *name_token = nullptr) {
207    return false;
208  }
209
210  virtual bool GenerateTypeScriptFunction(StringList &input,
211                                          std::string &output,
212                                          const void *name_token = nullptr) {
213    return false;
214  }
215
216  virtual bool GenerateScriptAliasFunction(StringList &input,
217                                           std::string &output) {
218    return false;
219  }
220
221  virtual bool GenerateTypeSynthClass(StringList &input, std::string &output,
222                                      const void *name_token = nullptr) {
223    return false;
224  }
225
226  virtual bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
227                                      const void *name_token = nullptr) {
228    return false;
229  }
230
231  virtual StructuredData::ObjectSP
232  CreateSyntheticScriptedProvider(const char *class_name,
233                                  lldb::ValueObjectSP valobj) {
234    return StructuredData::ObjectSP();
235  }
236
237  virtual StructuredData::GenericSP
238  CreateScriptCommandObject(const char *class_name) {
239    return StructuredData::GenericSP();
240  }
241
242  virtual StructuredData::GenericSP
243  CreateFrameRecognizer(const char *class_name) {
244    return StructuredData::GenericSP();
245  }
246
247  virtual lldb::ValueObjectListSP GetRecognizedArguments(
248      const StructuredData::ObjectSP &implementor,
249      lldb::StackFrameSP frame_sp) {
250    return lldb::ValueObjectListSP();
251  }
252
253  virtual StructuredData::ObjectSP
254  CreateScriptedThreadPlan(const char *class_name,
255                           const StructuredDataImpl &args_data,
256                           std::string &error_str,
257                           lldb::ThreadPlanSP thread_plan_sp) {
258    return StructuredData::ObjectSP();
259  }
260
261  virtual bool
262  ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
263                                 Event *event, bool &script_error) {
264    script_error = true;
265    return true;
266  }
267
268  virtual bool
269  ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
270                               Event *event, bool &script_error) {
271    script_error = true;
272    return true;
273  }
274
275  virtual bool
276  ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
277                            bool &script_error) {
278    script_error = true;
279    return true;
280  }
281
282  virtual lldb::StateType
283  ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
284                                bool &script_error) {
285    script_error = true;
286    return lldb::eStateStepping;
287  }
288
289  virtual bool
290  ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp,
291                                       lldb_private::Stream *stream,
292                                       bool &script_error) {
293    script_error = true;
294    return false;
295  }
296
297  virtual StructuredData::GenericSP
298  CreateScriptedBreakpointResolver(const char *class_name,
299                                   const StructuredDataImpl &args_data,
300                                   lldb::BreakpointSP &bkpt_sp) {
301    return StructuredData::GenericSP();
302  }
303
304  virtual bool
305  ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
306                                           SymbolContext *sym_ctx)
307  {
308    return false;
309  }
310
311  virtual lldb::SearchDepth
312  ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
313  {
314    return lldb::eSearchDepthModule;
315  }
316
317  virtual StructuredData::GenericSP
318  CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
319                         const StructuredDataImpl &args_data, Status &error) {
320    error.SetErrorString("Creating scripted stop-hooks with the current "
321                         "script interpreter is not supported.");
322    return StructuredData::GenericSP();
323  }
324
325  // This dispatches to the handle_stop method of the stop-hook class.  It
326  // returns a "should_stop" bool.
327  virtual bool
328  ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
329                             ExecutionContext &exc_ctx,
330                             lldb::StreamSP stream_sp) {
331    return true;
332  }
333
334  virtual StructuredData::ObjectSP
335  LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
336    return StructuredData::ObjectSP();
337  }
338
339  virtual StructuredData::DictionarySP
340  GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
341                     const char *setting_name, lldb_private::Status &error) {
342    return StructuredData::DictionarySP();
343  }
344
345  virtual Status GenerateFunction(const char *signature,
346                                  const StringList &input,
347                                  bool is_callback) {
348    Status error;
349    error.SetErrorString("unimplemented");
350    return error;
351  }
352
353  virtual void CollectDataForBreakpointCommandCallback(
354      std::vector<std::reference_wrapper<BreakpointOptions>> &options,
355      CommandReturnObject &result);
356
357  virtual void
358  CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
359                                          CommandReturnObject &result);
360
361  /// Set the specified text as the callback for the breakpoint.
362  Status SetBreakpointCommandCallback(
363      std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
364      const char *callback_text);
365
366  virtual Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
367                                              const char *callback_text,
368                                              bool is_callback) {
369    Status error;
370    error.SetErrorString("unimplemented");
371    return error;
372  }
373
374  /// This one is for deserialization:
375  virtual Status SetBreakpointCommandCallback(
376      BreakpointOptions &bp_options,
377      std::unique_ptr<BreakpointOptions::CommandData> &data_up) {
378    Status error;
379    error.SetErrorString("unimplemented");
380    return error;
381  }
382
383  Status SetBreakpointCommandCallbackFunction(
384      std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
385      const char *function_name, StructuredData::ObjectSP extra_args_sp);
386
387  /// Set a script function as the callback for the breakpoint.
388  virtual Status
389  SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options,
390                                       const char *function_name,
391                                       StructuredData::ObjectSP extra_args_sp) {
392    Status error;
393    error.SetErrorString("unimplemented");
394    return error;
395  }
396
397  /// Set a one-liner as the callback for the watchpoint.
398  virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
399                                            const char *user_input,
400                                            bool is_callback) {}
401
402  virtual bool GetScriptedSummary(const char *function_name,
403                                  lldb::ValueObjectSP valobj,
404                                  StructuredData::ObjectSP &callee_wrapper_sp,
405                                  const TypeSummaryOptions &options,
406                                  std::string &retval) {
407    return false;
408  }
409
410  // Calls the specified formatter matching Python function and returns its
411  // result (true if it's a match, false if we should keep looking for a
412  // matching formatter).
413  virtual bool FormatterCallbackFunction(const char *function_name,
414                                         lldb::TypeImplSP type_impl_sp) {
415    return true;
416  }
417
418  virtual void Clear() {
419    // Clean up any ref counts to SBObjects that might be in global variables
420  }
421
422  virtual size_t
423  CalculateNumChildren(const StructuredData::ObjectSP &implementor,
424                       uint32_t max) {
425    return 0;
426  }
427
428  virtual lldb::ValueObjectSP
429  GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) {
430    return lldb::ValueObjectSP();
431  }
432
433  virtual int
434  GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
435                          const char *child_name) {
436    return UINT32_MAX;
437  }
438
439  virtual bool
440  UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) {
441    return false;
442  }
443
444  virtual bool MightHaveChildrenSynthProviderInstance(
445      const StructuredData::ObjectSP &implementor) {
446    return true;
447  }
448
449  virtual lldb::ValueObjectSP
450  GetSyntheticValue(const StructuredData::ObjectSP &implementor) {
451    return nullptr;
452  }
453
454  virtual ConstString
455  GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) {
456    return ConstString();
457  }
458
459  virtual bool
460  RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
461                        ScriptedCommandSynchronicity synchronicity,
462                        lldb_private::CommandReturnObject &cmd_retobj,
463                        Status &error,
464                        const lldb_private::ExecutionContext &exe_ctx) {
465    return false;
466  }
467
468  virtual bool RunScriptBasedCommand(
469      StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
470      ScriptedCommandSynchronicity synchronicity,
471      lldb_private::CommandReturnObject &cmd_retobj, Status &error,
472      const lldb_private::ExecutionContext &exe_ctx) {
473    return false;
474  }
475
476  virtual bool RunScriptFormatKeyword(const char *impl_function,
477                                      Process *process, std::string &output,
478                                      Status &error) {
479    error.SetErrorString("unimplemented");
480    return false;
481  }
482
483  virtual bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
484                                      std::string &output, Status &error) {
485    error.SetErrorString("unimplemented");
486    return false;
487  }
488
489  virtual bool RunScriptFormatKeyword(const char *impl_function, Target *target,
490                                      std::string &output, Status &error) {
491    error.SetErrorString("unimplemented");
492    return false;
493  }
494
495  virtual bool RunScriptFormatKeyword(const char *impl_function,
496                                      StackFrame *frame, std::string &output,
497                                      Status &error) {
498    error.SetErrorString("unimplemented");
499    return false;
500  }
501
502  virtual bool RunScriptFormatKeyword(const char *impl_function,
503                                      ValueObject *value, std::string &output,
504                                      Status &error) {
505    error.SetErrorString("unimplemented");
506    return false;
507  }
508
509  virtual bool GetDocumentationForItem(const char *item, std::string &dest) {
510    dest.clear();
511    return false;
512  }
513
514  virtual bool
515  GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
516                               std::string &dest) {
517    dest.clear();
518    return false;
519  }
520
521  virtual uint32_t
522  GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) {
523    return 0;
524  }
525
526  virtual bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
527                                           std::string &dest) {
528    dest.clear();
529    return false;
530  }
531
532  virtual bool CheckObjectExists(const char *name) { return false; }
533
534  virtual bool
535  LoadScriptingModule(const char *filename, const LoadScriptOptions &options,
536                      lldb_private::Status &error,
537                      StructuredData::ObjectSP *module_sp = nullptr,
538                      FileSpec extra_search_dir = {});
539
540  virtual bool IsReservedWord(const char *word) { return false; }
541
542  virtual std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock();
543
544  const char *GetScriptInterpreterPtyName();
545
546  virtual llvm::Expected<unsigned>
547  GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) {
548    return llvm::createStringError(
549    llvm::inconvertibleErrorCode(), "Unimplemented function");
550  }
551
552  static std::string LanguageToString(lldb::ScriptLanguage language);
553
554  static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string);
555
556  lldb::ScriptLanguage GetLanguage() { return m_script_lang; }
557
558  virtual lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() {
559    return {};
560  }
561
562  virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() {
563    return {};
564  }
565
566  virtual lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() {
567    return {};
568  }
569
570  virtual lldb::ScriptedPlatformInterfaceUP GetScriptedPlatformInterface() {
571    return {};
572  }
573
574  virtual StructuredData::ObjectSP
575  CreateStructuredDataFromScriptObject(ScriptObject obj) {
576    return {};
577  }
578
579  lldb::DataExtractorSP
580  GetDataExtractorFromSBData(const lldb::SBData &data) const;
581
582  Status GetStatusFromSBError(const lldb::SBError &error) const;
583
584  lldb::BreakpointSP
585  GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const;
586
587  lldb::ProcessAttachInfoSP
588  GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const;
589
590  lldb::ProcessLaunchInfoSP
591  GetOpaqueTypeFromSBLaunchInfo(const lldb::SBLaunchInfo &launch_info) const;
592
593  std::optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo(
594      const lldb::SBMemoryRegionInfo &mem_region) const;
595
596protected:
597  Debugger &m_debugger;
598  lldb::ScriptLanguage m_script_lang;
599};
600
601} // namespace lldb_private
602
603#endif // LLDB_INTERPRETER_SCRIPTINTERPRETER_H
604