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