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