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