| //===-- ScriptInterpreter.h -------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H |
| #define LLDB_INTERPRETER_SCRIPTINTERPRETER_H |
| |
| #include "lldb/API/SBData.h" |
| #include "lldb/API/SBError.h" |
| #include "lldb/API/SBMemoryRegionInfo.h" |
| #include "lldb/Breakpoint/BreakpointOptions.h" |
| #include "lldb/Core/Communication.h" |
| #include "lldb/Core/PluginInterface.h" |
| #include "lldb/Core/SearchFilter.h" |
| #include "lldb/Core/StreamFile.h" |
| #include "lldb/Host/PseudoTerminal.h" |
| #include "lldb/Interpreter/ScriptedProcessInterface.h" |
| #include "lldb/Utility/Broadcaster.h" |
| #include "lldb/Utility/Status.h" |
| #include "lldb/Utility/StructuredData.h" |
| #include "lldb/lldb-private.h" |
| |
| namespace lldb_private { |
| |
| class ScriptInterpreterLocker { |
| public: |
| ScriptInterpreterLocker() = default; |
| |
| virtual ~ScriptInterpreterLocker() = default; |
| |
| private: |
| ScriptInterpreterLocker(const ScriptInterpreterLocker &) = delete; |
| const ScriptInterpreterLocker & |
| operator=(const ScriptInterpreterLocker &) = delete; |
| }; |
| |
| class ExecuteScriptOptions { |
| public: |
| ExecuteScriptOptions() = default; |
| |
| bool GetEnableIO() const { return m_enable_io; } |
| |
| bool GetSetLLDBGlobals() const { return m_set_lldb_globals; } |
| |
| // If this is true then any exceptions raised by the script will be |
| // cleared with PyErr_Clear(). If false then they will be left for |
| // the caller to clean up |
| bool GetMaskoutErrors() const { return m_maskout_errors; } |
| |
| ExecuteScriptOptions &SetEnableIO(bool enable) { |
| m_enable_io = enable; |
| return *this; |
| } |
| |
| ExecuteScriptOptions &SetSetLLDBGlobals(bool set) { |
| m_set_lldb_globals = set; |
| return *this; |
| } |
| |
| ExecuteScriptOptions &SetMaskoutErrors(bool maskout) { |
| m_maskout_errors = maskout; |
| return *this; |
| } |
| |
| private: |
| bool m_enable_io = true; |
| bool m_set_lldb_globals = true; |
| bool m_maskout_errors = true; |
| }; |
| |
| class LoadScriptOptions { |
| public: |
| LoadScriptOptions() = default; |
| |
| bool GetInitSession() const { return m_init_session; } |
| bool GetSilent() const { return m_silent; } |
| |
| LoadScriptOptions &SetInitSession(bool b) { |
| m_init_session = b; |
| return *this; |
| } |
| |
| LoadScriptOptions &SetSilent(bool b) { |
| m_silent = b; |
| return *this; |
| } |
| |
| private: |
| bool m_init_session = false; |
| bool m_silent = false; |
| }; |
| |
| class ScriptInterpreterIORedirect { |
| public: |
| /// Create an IO redirect. If IO is enabled, this will redirects the output |
| /// to the command return object if set or to the debugger otherwise. If IO |
| /// is disabled, it will redirect all IO to /dev/null. |
| static llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> |
| Create(bool enable_io, Debugger &debugger, CommandReturnObject *result); |
| |
| ~ScriptInterpreterIORedirect(); |
| |
| lldb::FileSP GetInputFile() const { return m_input_file_sp; } |
| lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); } |
| lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); } |
| |
| /// Flush our output and error file handles. |
| void Flush(); |
| |
| private: |
| ScriptInterpreterIORedirect(std::unique_ptr<File> input, |
| std::unique_ptr<File> output); |
| ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result); |
| |
| lldb::FileSP m_input_file_sp; |
| lldb::StreamFileSP m_output_file_sp; |
| lldb::StreamFileSP m_error_file_sp; |
| Communication m_communication; |
| bool m_disconnect; |
| }; |
| |
| class ScriptInterpreter : public PluginInterface { |
| public: |
| enum ScriptReturnType { |
| eScriptReturnTypeCharPtr, |
| eScriptReturnTypeBool, |
| eScriptReturnTypeShortInt, |
| eScriptReturnTypeShortIntUnsigned, |
| eScriptReturnTypeInt, |
| eScriptReturnTypeIntUnsigned, |
| eScriptReturnTypeLongInt, |
| eScriptReturnTypeLongIntUnsigned, |
| eScriptReturnTypeLongLong, |
| eScriptReturnTypeLongLongUnsigned, |
| eScriptReturnTypeFloat, |
| eScriptReturnTypeDouble, |
| eScriptReturnTypeChar, |
| eScriptReturnTypeCharStrOrNone, |
| eScriptReturnTypeOpaqueObject |
| }; |
| |
| ScriptInterpreter( |
| Debugger &debugger, lldb::ScriptLanguage script_lang, |
| lldb::ScriptedProcessInterfaceUP scripted_process_interface_up = |
| std::make_unique<ScriptedProcessInterface>()); |
| |
| virtual StructuredData::DictionarySP GetInterpreterInfo(); |
| |
| ~ScriptInterpreter() override = default; |
| |
| virtual bool Interrupt() { return false; } |
| |
| virtual bool ExecuteOneLine( |
| llvm::StringRef command, CommandReturnObject *result, |
| const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0; |
| |
| virtual void ExecuteInterpreterLoop() = 0; |
| |
| virtual bool ExecuteOneLineWithReturn( |
| llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value, |
| const ExecuteScriptOptions &options = ExecuteScriptOptions()) { |
| return true; |
| } |
| |
| virtual Status ExecuteMultipleLines( |
| const char *in_string, |
| const ExecuteScriptOptions &options = ExecuteScriptOptions()) { |
| Status error; |
| error.SetErrorString("not implemented"); |
| return error; |
| } |
| |
| virtual Status |
| ExportFunctionDefinitionToInterpreter(StringList &function_def) { |
| Status error; |
| error.SetErrorString("not implemented"); |
| return error; |
| } |
| |
| virtual Status GenerateBreakpointCommandCallbackData( |
| StringList &input, |
| std::string &output, |
| bool has_extra_args) { |
| Status error; |
| error.SetErrorString("not implemented"); |
| return error; |
| } |
| |
| virtual bool GenerateWatchpointCommandCallbackData(StringList &input, |
| std::string &output) { |
| return false; |
| } |
| |
| virtual bool GenerateTypeScriptFunction(const char *oneliner, |
| std::string &output, |
| const void *name_token = nullptr) { |
| return false; |
| } |
| |
| virtual bool GenerateTypeScriptFunction(StringList &input, |
| std::string &output, |
| const void *name_token = nullptr) { |
| return false; |
| } |
| |
| virtual bool GenerateScriptAliasFunction(StringList &input, |
| std::string &output) { |
| return false; |
| } |
| |
| virtual bool GenerateTypeSynthClass(StringList &input, std::string &output, |
| const void *name_token = nullptr) { |
| return false; |
| } |
| |
| virtual bool GenerateTypeSynthClass(const char *oneliner, std::string &output, |
| const void *name_token = nullptr) { |
| return false; |
| } |
| |
| virtual StructuredData::ObjectSP |
| CreateSyntheticScriptedProvider(const char *class_name, |
| lldb::ValueObjectSP valobj) { |
| return StructuredData::ObjectSP(); |
| } |
| |
| virtual StructuredData::GenericSP |
| CreateScriptCommandObject(const char *class_name) { |
| return StructuredData::GenericSP(); |
| } |
| |
| virtual StructuredData::GenericSP |
| CreateFrameRecognizer(const char *class_name) { |
| return StructuredData::GenericSP(); |
| } |
| |
| virtual lldb::ValueObjectListSP GetRecognizedArguments( |
| const StructuredData::ObjectSP &implementor, |
| lldb::StackFrameSP frame_sp) { |
| return lldb::ValueObjectListSP(); |
| } |
| |
| virtual StructuredData::GenericSP |
| OSPlugin_CreatePluginObject(const char *class_name, |
| lldb::ProcessSP process_sp) { |
| return StructuredData::GenericSP(); |
| } |
| |
| virtual StructuredData::DictionarySP |
| OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) { |
| return StructuredData::DictionarySP(); |
| } |
| |
| virtual StructuredData::ArraySP |
| OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) { |
| return StructuredData::ArraySP(); |
| } |
| |
| virtual StructuredData::StringSP |
| OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, |
| lldb::tid_t thread_id) { |
| return StructuredData::StringSP(); |
| } |
| |
| virtual StructuredData::DictionarySP |
| OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, |
| lldb::tid_t tid, lldb::addr_t context) { |
| return StructuredData::DictionarySP(); |
| } |
| |
| virtual StructuredData::ObjectSP |
| CreateScriptedThreadPlan(const char *class_name, |
| StructuredDataImpl *args_data, |
| std::string &error_str, |
| lldb::ThreadPlanSP thread_plan_sp) { |
| return StructuredData::ObjectSP(); |
| } |
| |
| virtual bool |
| ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, |
| Event *event, bool &script_error) { |
| script_error = true; |
| return true; |
| } |
| |
| virtual bool |
| ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, |
| Event *event, bool &script_error) { |
| script_error = true; |
| return true; |
| } |
| |
| virtual bool |
| ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp, |
| bool &script_error) { |
| script_error = true; |
| return true; |
| } |
| |
| virtual lldb::StateType |
| ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, |
| bool &script_error) { |
| script_error = true; |
| return lldb::eStateStepping; |
| } |
| |
| virtual StructuredData::GenericSP |
| CreateScriptedBreakpointResolver(const char *class_name, |
| StructuredDataImpl *args_data, |
| lldb::BreakpointSP &bkpt_sp) { |
| return StructuredData::GenericSP(); |
| } |
| |
| virtual bool |
| ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp, |
| SymbolContext *sym_ctx) |
| { |
| return false; |
| } |
| |
| virtual lldb::SearchDepth |
| ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp) |
| { |
| return lldb::eSearchDepthModule; |
| } |
| |
| virtual StructuredData::GenericSP |
| CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, |
| StructuredDataImpl *args_data, Status &error) { |
| error.SetErrorString("Creating scripted stop-hooks with the current " |
| "script interpreter is not supported."); |
| return StructuredData::GenericSP(); |
| } |
| |
| // This dispatches to the handle_stop method of the stop-hook class. It |
| // returns a "should_stop" bool. |
| virtual bool |
| ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, |
| ExecutionContext &exc_ctx, |
| lldb::StreamSP stream_sp) { |
| return true; |
| } |
| |
| virtual StructuredData::ObjectSP |
| LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { |
| return StructuredData::ObjectSP(); |
| } |
| |
| virtual StructuredData::DictionarySP |
| GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, |
| const char *setting_name, lldb_private::Status &error) { |
| return StructuredData::DictionarySP(); |
| } |
| |
| virtual Status GenerateFunction(const char *signature, |
| const StringList &input) { |
| Status error; |
| error.SetErrorString("unimplemented"); |
| return error; |
| } |
| |
| virtual void CollectDataForBreakpointCommandCallback( |
| std::vector<std::reference_wrapper<BreakpointOptions>> &options, |
| CommandReturnObject &result); |
| |
| virtual void |
| CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, |
| CommandReturnObject &result); |
| |
| /// Set the specified text as the callback for the breakpoint. |
| Status SetBreakpointCommandCallback( |
| std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, |
| const char *callback_text); |
| |
| virtual Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, |
| const char *callback_text) { |
| Status error; |
| error.SetErrorString("unimplemented"); |
| return error; |
| } |
| |
| /// This one is for deserialization: |
| virtual Status SetBreakpointCommandCallback( |
| BreakpointOptions &bp_options, |
| std::unique_ptr<BreakpointOptions::CommandData> &data_up) { |
| Status error; |
| error.SetErrorString("unimplemented"); |
| return error; |
| } |
| |
| Status SetBreakpointCommandCallbackFunction( |
| std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, |
| const char *function_name, StructuredData::ObjectSP extra_args_sp); |
| |
| /// Set a script function as the callback for the breakpoint. |
| virtual Status |
| SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options, |
| const char *function_name, |
| StructuredData::ObjectSP extra_args_sp) { |
| Status error; |
| error.SetErrorString("unimplemented"); |
| return error; |
| } |
| |
| /// Set a one-liner as the callback for the watchpoint. |
| virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options, |
| const char *oneliner) {} |
| |
| virtual bool GetScriptedSummary(const char *function_name, |
| lldb::ValueObjectSP valobj, |
| StructuredData::ObjectSP &callee_wrapper_sp, |
| const TypeSummaryOptions &options, |
| std::string &retval) { |
| return false; |
| } |
| |
| virtual void Clear() { |
| // Clean up any ref counts to SBObjects that might be in global variables |
| } |
| |
| virtual size_t |
| CalculateNumChildren(const StructuredData::ObjectSP &implementor, |
| uint32_t max) { |
| return 0; |
| } |
| |
| virtual lldb::ValueObjectSP |
| GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) { |
| return lldb::ValueObjectSP(); |
| } |
| |
| virtual int |
| GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, |
| const char *child_name) { |
| return UINT32_MAX; |
| } |
| |
| virtual bool |
| UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) { |
| return false; |
| } |
| |
| virtual bool MightHaveChildrenSynthProviderInstance( |
| const StructuredData::ObjectSP &implementor) { |
| return true; |
| } |
| |
| virtual lldb::ValueObjectSP |
| GetSyntheticValue(const StructuredData::ObjectSP &implementor) { |
| return nullptr; |
| } |
| |
| virtual ConstString |
| GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) { |
| return ConstString(); |
| } |
| |
| virtual bool |
| RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, |
| ScriptedCommandSynchronicity synchronicity, |
| lldb_private::CommandReturnObject &cmd_retobj, |
| Status &error, |
| const lldb_private::ExecutionContext &exe_ctx) { |
| return false; |
| } |
| |
| virtual bool RunScriptBasedCommand( |
| StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, |
| ScriptedCommandSynchronicity synchronicity, |
| lldb_private::CommandReturnObject &cmd_retobj, Status &error, |
| const lldb_private::ExecutionContext &exe_ctx) { |
| return false; |
| } |
| |
| virtual bool RunScriptFormatKeyword(const char *impl_function, |
| Process *process, std::string &output, |
| Status &error) { |
| error.SetErrorString("unimplemented"); |
| return false; |
| } |
| |
| virtual bool RunScriptFormatKeyword(const char *impl_function, Thread *thread, |
| std::string &output, Status &error) { |
| error.SetErrorString("unimplemented"); |
| return false; |
| } |
| |
| virtual bool RunScriptFormatKeyword(const char *impl_function, Target *target, |
| std::string &output, Status &error) { |
| error.SetErrorString("unimplemented"); |
| return false; |
| } |
| |
| virtual bool RunScriptFormatKeyword(const char *impl_function, |
| StackFrame *frame, std::string &output, |
| Status &error) { |
| error.SetErrorString("unimplemented"); |
| return false; |
| } |
| |
| virtual bool RunScriptFormatKeyword(const char *impl_function, |
| ValueObject *value, std::string &output, |
| Status &error) { |
| error.SetErrorString("unimplemented"); |
| return false; |
| } |
| |
| virtual bool GetDocumentationForItem(const char *item, std::string &dest) { |
| dest.clear(); |
| return false; |
| } |
| |
| virtual bool |
| GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, |
| std::string &dest) { |
| dest.clear(); |
| return false; |
| } |
| |
| virtual uint32_t |
| GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) { |
| return 0; |
| } |
| |
| virtual bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, |
| std::string &dest) { |
| dest.clear(); |
| return false; |
| } |
| |
| virtual bool CheckObjectExists(const char *name) { return false; } |
| |
| virtual bool |
| LoadScriptingModule(const char *filename, const LoadScriptOptions &options, |
| lldb_private::Status &error, |
| StructuredData::ObjectSP *module_sp = nullptr, |
| FileSpec extra_search_dir = {}); |
| |
| virtual bool IsReservedWord(const char *word) { return false; } |
| |
| virtual std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock(); |
| |
| const char *GetScriptInterpreterPtyName(); |
| |
| virtual llvm::Expected<unsigned> |
| GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) { |
| return llvm::createStringError( |
| llvm::inconvertibleErrorCode(), "Unimplemented function"); |
| } |
| |
| static std::string LanguageToString(lldb::ScriptLanguage language); |
| |
| static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string); |
| |
| lldb::ScriptLanguage GetLanguage() { return m_script_lang; } |
| |
| ScriptedProcessInterface &GetScriptedProcessInterface() { |
| return *m_scripted_process_interface_up; |
| } |
| |
| lldb::DataExtractorSP |
| GetDataExtractorFromSBData(const lldb::SBData &data) const; |
| |
| Status GetStatusFromSBError(const lldb::SBError &error) const; |
| |
| llvm::Optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo( |
| const lldb::SBMemoryRegionInfo &mem_region) const; |
| |
| protected: |
| Debugger &m_debugger; |
| lldb::ScriptLanguage m_script_lang; |
| lldb::ScriptedProcessInterfaceUP m_scripted_process_interface_up; |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // LLDB_INTERPRETER_SCRIPTINTERPRETER_H |