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