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