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