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/SBData.h"
13 #include "lldb/API/SBError.h"
14 #include "lldb/Breakpoint/BreakpointOptions.h"
15 #include "lldb/Core/Communication.h"
16 #include "lldb/Core/PluginInterface.h"
17 #include "lldb/Core/SearchFilter.h"
18 #include "lldb/Core/StreamFile.h"
19 #include "lldb/Host/PseudoTerminal.h"
20 #include "lldb/Interpreter/ScriptedProcessInterface.h"
21 #include "lldb/Utility/Broadcaster.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/StructuredData.h"
24 #include "lldb/lldb-private.h"
25 
26 namespace lldb_private {
27 
28 class ScriptInterpreterLocker {
29 public:
30   ScriptInterpreterLocker() = default;
31 
32   virtual ~ScriptInterpreterLocker() = default;
33 
34 private:
35   ScriptInterpreterLocker(const ScriptInterpreterLocker &) = delete;
36   const ScriptInterpreterLocker &
37   operator=(const ScriptInterpreterLocker &) = delete;
38 };
39 
40 class ExecuteScriptOptions {
41 public:
42   ExecuteScriptOptions() = default;
43 
44   bool GetEnableIO() const { return m_enable_io; }
45 
46   bool GetSetLLDBGlobals() const { return m_set_lldb_globals; }
47 
48   // If this is true then any exceptions raised by the script will be
49   // cleared with PyErr_Clear().   If false then they will be left for
50   // the caller to clean up
51   bool GetMaskoutErrors() const { return m_maskout_errors; }
52 
53   ExecuteScriptOptions &SetEnableIO(bool enable) {
54     m_enable_io = enable;
55     return *this;
56   }
57 
58   ExecuteScriptOptions &SetSetLLDBGlobals(bool set) {
59     m_set_lldb_globals = set;
60     return *this;
61   }
62 
63   ExecuteScriptOptions &SetMaskoutErrors(bool maskout) {
64     m_maskout_errors = maskout;
65     return *this;
66   }
67 
68 private:
69   bool m_enable_io = true;
70   bool m_set_lldb_globals = true;
71   bool m_maskout_errors = true;
72 };
73 
74 class LoadScriptOptions {
75 public:
76   LoadScriptOptions() = default;
77 
78   bool GetInitSession() const { return m_init_session; }
79   bool GetSilent() const { return m_silent; }
80 
81   LoadScriptOptions &SetInitSession(bool b) {
82     m_init_session = b;
83     return *this;
84   }
85 
86   LoadScriptOptions &SetSilent(bool b) {
87     m_silent = b;
88     return *this;
89   }
90 
91 private:
92   bool m_init_session = false;
93   bool m_silent = false;
94 };
95 
96 class ScriptInterpreterIORedirect {
97 public:
98   /// Create an IO redirect. If IO is enabled, this will redirects the output
99   /// to the command return object if set or to the debugger otherwise. If IO
100   /// is disabled, it will redirect all IO to /dev/null.
101   static llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
102   Create(bool enable_io, Debugger &debugger, CommandReturnObject *result);
103 
104   ~ScriptInterpreterIORedirect();
105 
106   lldb::FileSP GetInputFile() const { return m_input_file_sp; }
107   lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); }
108   lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); }
109 
110   /// Flush our output and error file handles.
111   void Flush();
112 
113 private:
114   ScriptInterpreterIORedirect(std::unique_ptr<File> input,
115                               std::unique_ptr<File> output);
116   ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result);
117 
118   lldb::FileSP m_input_file_sp;
119   lldb::StreamFileSP m_output_file_sp;
120   lldb::StreamFileSP m_error_file_sp;
121   Communication m_communication;
122   bool m_disconnect;
123 };
124 
125 class ScriptInterpreter : public PluginInterface {
126 public:
127   enum ScriptReturnType {
128     eScriptReturnTypeCharPtr,
129     eScriptReturnTypeBool,
130     eScriptReturnTypeShortInt,
131     eScriptReturnTypeShortIntUnsigned,
132     eScriptReturnTypeInt,
133     eScriptReturnTypeIntUnsigned,
134     eScriptReturnTypeLongInt,
135     eScriptReturnTypeLongIntUnsigned,
136     eScriptReturnTypeLongLong,
137     eScriptReturnTypeLongLongUnsigned,
138     eScriptReturnTypeFloat,
139     eScriptReturnTypeDouble,
140     eScriptReturnTypeChar,
141     eScriptReturnTypeCharStrOrNone,
142     eScriptReturnTypeOpaqueObject
143   };
144 
145   ScriptInterpreter(
146       Debugger &debugger, lldb::ScriptLanguage script_lang,
147       lldb::ScriptedProcessInterfaceUP scripted_process_interface_up =
148           std::make_unique<ScriptedProcessInterface>());
149 
150   ~ScriptInterpreter() override = default;
151 
152   virtual bool Interrupt() { return false; }
153 
154   virtual bool ExecuteOneLine(
155       llvm::StringRef command, CommandReturnObject *result,
156       const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0;
157 
158   virtual void ExecuteInterpreterLoop() = 0;
159 
160   virtual bool ExecuteOneLineWithReturn(
161       llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value,
162       const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
163     return true;
164   }
165 
166   virtual Status ExecuteMultipleLines(
167       const char *in_string,
168       const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
169     Status error;
170     error.SetErrorString("not implemented");
171     return error;
172   }
173 
174   virtual Status
175   ExportFunctionDefinitionToInterpreter(StringList &function_def) {
176     Status error;
177     error.SetErrorString("not implemented");
178     return error;
179   }
180 
181   virtual Status GenerateBreakpointCommandCallbackData(
182       StringList &input,
183       std::string &output,
184       bool has_extra_args) {
185     Status error;
186     error.SetErrorString("not implemented");
187     return error;
188   }
189 
190   virtual bool GenerateWatchpointCommandCallbackData(StringList &input,
191                                                      std::string &output) {
192     return false;
193   }
194 
195   virtual bool GenerateTypeScriptFunction(const char *oneliner,
196                                           std::string &output,
197                                           const void *name_token = nullptr) {
198     return false;
199   }
200 
201   virtual bool GenerateTypeScriptFunction(StringList &input,
202                                           std::string &output,
203                                           const void *name_token = nullptr) {
204     return false;
205   }
206 
207   virtual bool GenerateScriptAliasFunction(StringList &input,
208                                            std::string &output) {
209     return false;
210   }
211 
212   virtual bool GenerateTypeSynthClass(StringList &input, std::string &output,
213                                       const void *name_token = nullptr) {
214     return false;
215   }
216 
217   virtual bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
218                                       const void *name_token = nullptr) {
219     return false;
220   }
221 
222   virtual StructuredData::ObjectSP
223   CreateSyntheticScriptedProvider(const char *class_name,
224                                   lldb::ValueObjectSP valobj) {
225     return StructuredData::ObjectSP();
226   }
227 
228   virtual StructuredData::GenericSP
229   CreateScriptCommandObject(const char *class_name) {
230     return StructuredData::GenericSP();
231   }
232 
233   virtual StructuredData::GenericSP
234   CreateFrameRecognizer(const char *class_name) {
235     return StructuredData::GenericSP();
236   }
237 
238   virtual lldb::ValueObjectListSP GetRecognizedArguments(
239       const StructuredData::ObjectSP &implementor,
240       lldb::StackFrameSP frame_sp) {
241     return lldb::ValueObjectListSP();
242   }
243 
244   virtual StructuredData::GenericSP
245   OSPlugin_CreatePluginObject(const char *class_name,
246                               lldb::ProcessSP process_sp) {
247     return StructuredData::GenericSP();
248   }
249 
250   virtual StructuredData::DictionarySP
251   OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) {
252     return StructuredData::DictionarySP();
253   }
254 
255   virtual StructuredData::ArraySP
256   OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) {
257     return StructuredData::ArraySP();
258   }
259 
260   virtual StructuredData::StringSP
261   OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
262                                lldb::tid_t thread_id) {
263     return StructuredData::StringSP();
264   }
265 
266   virtual StructuredData::DictionarySP
267   OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
268                         lldb::tid_t tid, lldb::addr_t context) {
269     return StructuredData::DictionarySP();
270   }
271 
272   virtual StructuredData::ObjectSP
273   CreateScriptedThreadPlan(const char *class_name,
274                            StructuredDataImpl *args_data,
275                            std::string &error_str,
276                            lldb::ThreadPlanSP thread_plan_sp) {
277     return StructuredData::ObjectSP();
278   }
279 
280   virtual bool
281   ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
282                                  Event *event, bool &script_error) {
283     script_error = true;
284     return true;
285   }
286 
287   virtual bool
288   ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
289                                Event *event, bool &script_error) {
290     script_error = true;
291     return true;
292   }
293 
294   virtual bool
295   ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
296                             bool &script_error) {
297     script_error = true;
298     return true;
299   }
300 
301   virtual lldb::StateType
302   ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
303                                 bool &script_error) {
304     script_error = true;
305     return lldb::eStateStepping;
306   }
307 
308   virtual StructuredData::GenericSP
309   CreateScriptedBreakpointResolver(const char *class_name,
310                                    StructuredDataImpl *args_data,
311                                    lldb::BreakpointSP &bkpt_sp) {
312     return StructuredData::GenericSP();
313   }
314 
315   virtual bool
316   ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
317                                            SymbolContext *sym_ctx)
318   {
319     return false;
320   }
321 
322   virtual lldb::SearchDepth
323   ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
324   {
325     return lldb::eSearchDepthModule;
326   }
327 
328   virtual StructuredData::GenericSP
329   CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
330                          StructuredDataImpl *args_data, Status &error) {
331     error.SetErrorString("Creating scripted stop-hooks with the current "
332                          "script interpreter is not supported.");
333     return StructuredData::GenericSP();
334   }
335 
336   // This dispatches to the handle_stop method of the stop-hook class.  It
337   // returns a "should_stop" bool.
338   virtual bool
339   ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
340                              ExecutionContext &exc_ctx,
341                              lldb::StreamSP stream_sp) {
342     return true;
343   }
344 
345   virtual StructuredData::ObjectSP
346   LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
347     return StructuredData::ObjectSP();
348   }
349 
350   virtual StructuredData::DictionarySP
351   GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
352                      const char *setting_name, lldb_private::Status &error) {
353     return StructuredData::DictionarySP();
354   }
355 
356   virtual Status GenerateFunction(const char *signature,
357                                   const StringList &input) {
358     Status error;
359     error.SetErrorString("unimplemented");
360     return error;
361   }
362 
363   virtual void CollectDataForBreakpointCommandCallback(
364       std::vector<std::reference_wrapper<BreakpointOptions>> &options,
365       CommandReturnObject &result);
366 
367   virtual void
368   CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
369                                           CommandReturnObject &result);
370 
371   /// Set the specified text as the callback for the breakpoint.
372   Status SetBreakpointCommandCallback(
373       std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
374       const char *callback_text);
375 
376   virtual Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
377                                               const char *callback_text) {
378     Status error;
379     error.SetErrorString("unimplemented");
380     return error;
381   }
382 
383   /// This one is for deserialization:
384   virtual Status SetBreakpointCommandCallback(
385       BreakpointOptions &bp_options,
386       std::unique_ptr<BreakpointOptions::CommandData> &data_up) {
387     Status error;
388     error.SetErrorString("unimplemented");
389     return error;
390   }
391 
392   Status SetBreakpointCommandCallbackFunction(
393       std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
394       const char *function_name, StructuredData::ObjectSP extra_args_sp);
395 
396   /// Set a script function as the callback for the breakpoint.
397   virtual Status
398   SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options,
399                                        const char *function_name,
400                                        StructuredData::ObjectSP extra_args_sp) {
401     Status error;
402     error.SetErrorString("unimplemented");
403     return error;
404   }
405 
406   /// Set a one-liner as the callback for the watchpoint.
407   virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
408                                             const char *oneliner) {}
409 
410   virtual bool GetScriptedSummary(const char *function_name,
411                                   lldb::ValueObjectSP valobj,
412                                   StructuredData::ObjectSP &callee_wrapper_sp,
413                                   const TypeSummaryOptions &options,
414                                   std::string &retval) {
415     return false;
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   ScriptedProcessInterface &GetScriptedProcessInterface() {
559     return *m_scripted_process_interface_up;
560   }
561 
562   lldb::DataExtractorSP
563   GetDataExtractorFromSBData(const lldb::SBData &data) const;
564 
565   Status GetStatusFromSBError(const lldb::SBError &error) const;
566 
567 protected:
568   Debugger &m_debugger;
569   lldb::ScriptLanguage m_script_lang;
570   lldb::ScriptedProcessInterfaceUP m_scripted_process_interface_up;
571 };
572 
573 } // namespace lldb_private
574 
575 #endif // LLDB_INTERPRETER_SCRIPTINTERPRETER_H
576