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