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