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