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/ThreadedCommunication.h" 22#include "lldb/Host/PseudoTerminal.h" 23#include "lldb/Host/StreamFile.h" 24#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h" 25#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h" 26#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h" 27#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h" 28#include "lldb/Interpreter/ScriptObject.h" 29#include "lldb/Utility/Broadcaster.h" 30#include "lldb/Utility/Status.h" 31#include "lldb/Utility/StructuredData.h" 32#include "lldb/lldb-private.h" 33#include <optional> 34 35namespace lldb_private { 36 37class ScriptInterpreterLocker { 38public: 39 ScriptInterpreterLocker() = default; 40 41 virtual ~ScriptInterpreterLocker() = default; 42 43private: 44 ScriptInterpreterLocker(const ScriptInterpreterLocker &) = delete; 45 const ScriptInterpreterLocker & 46 operator=(const ScriptInterpreterLocker &) = delete; 47}; 48 49class ExecuteScriptOptions { 50public: 51 ExecuteScriptOptions() = default; 52 53 bool GetEnableIO() const { return m_enable_io; } 54 55 bool GetSetLLDBGlobals() const { return m_set_lldb_globals; } 56 57 // If this is true then any exceptions raised by the script will be 58 // cleared with PyErr_Clear(). If false then they will be left for 59 // the caller to clean up 60 bool GetMaskoutErrors() const { return m_maskout_errors; } 61 62 ExecuteScriptOptions &SetEnableIO(bool enable) { 63 m_enable_io = enable; 64 return *this; 65 } 66 67 ExecuteScriptOptions &SetSetLLDBGlobals(bool set) { 68 m_set_lldb_globals = set; 69 return *this; 70 } 71 72 ExecuteScriptOptions &SetMaskoutErrors(bool maskout) { 73 m_maskout_errors = maskout; 74 return *this; 75 } 76 77private: 78 bool m_enable_io = true; 79 bool m_set_lldb_globals = true; 80 bool m_maskout_errors = true; 81}; 82 83class LoadScriptOptions { 84public: 85 LoadScriptOptions() = default; 86 87 bool GetInitSession() const { return m_init_session; } 88 bool GetSilent() const { return m_silent; } 89 90 LoadScriptOptions &SetInitSession(bool b) { 91 m_init_session = b; 92 return *this; 93 } 94 95 LoadScriptOptions &SetSilent(bool b) { 96 m_silent = b; 97 return *this; 98 } 99 100private: 101 bool m_init_session = false; 102 bool m_silent = false; 103}; 104 105class ScriptInterpreterIORedirect { 106public: 107 /// Create an IO redirect. If IO is enabled, this will redirects the output 108 /// to the command return object if set or to the debugger otherwise. If IO 109 /// is disabled, it will redirect all IO to /dev/null. 110 static llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> 111 Create(bool enable_io, Debugger &debugger, CommandReturnObject *result); 112 113 ~ScriptInterpreterIORedirect(); 114 115 lldb::FileSP GetInputFile() const { return m_input_file_sp; } 116 lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); } 117 lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); } 118 119 /// Flush our output and error file handles. 120 void Flush(); 121 122private: 123 ScriptInterpreterIORedirect(std::unique_ptr<File> input, 124 std::unique_ptr<File> output); 125 ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result); 126 127 lldb::FileSP m_input_file_sp; 128 lldb::StreamFileSP m_output_file_sp; 129 lldb::StreamFileSP m_error_file_sp; 130 ThreadedCommunication m_communication; 131 bool m_disconnect; 132}; 133 134class ScriptInterpreter : public PluginInterface { 135public: 136 enum ScriptReturnType { 137 eScriptReturnTypeCharPtr, 138 eScriptReturnTypeBool, 139 eScriptReturnTypeShortInt, 140 eScriptReturnTypeShortIntUnsigned, 141 eScriptReturnTypeInt, 142 eScriptReturnTypeIntUnsigned, 143 eScriptReturnTypeLongInt, 144 eScriptReturnTypeLongIntUnsigned, 145 eScriptReturnTypeLongLong, 146 eScriptReturnTypeLongLongUnsigned, 147 eScriptReturnTypeFloat, 148 eScriptReturnTypeDouble, 149 eScriptReturnTypeChar, 150 eScriptReturnTypeCharStrOrNone, 151 eScriptReturnTypeOpaqueObject 152 }; 153 154 ScriptInterpreter(Debugger &debugger, lldb::ScriptLanguage script_lang); 155 156 virtual StructuredData::DictionarySP GetInterpreterInfo(); 157 158 ~ScriptInterpreter() override = default; 159 160 virtual bool Interrupt() { return false; } 161 162 virtual bool ExecuteOneLine( 163 llvm::StringRef command, CommandReturnObject *result, 164 const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0; 165 166 virtual void ExecuteInterpreterLoop() = 0; 167 168 virtual bool ExecuteOneLineWithReturn( 169 llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value, 170 const ExecuteScriptOptions &options = ExecuteScriptOptions()) { 171 return true; 172 } 173 174 virtual Status ExecuteMultipleLines( 175 const char *in_string, 176 const ExecuteScriptOptions &options = ExecuteScriptOptions()) { 177 Status error; 178 error.SetErrorString("not implemented"); 179 return error; 180 } 181 182 virtual Status 183 ExportFunctionDefinitionToInterpreter(StringList &function_def) { 184 Status error; 185 error.SetErrorString("not implemented"); 186 return error; 187 } 188 189 virtual Status GenerateBreakpointCommandCallbackData(StringList &input, 190 std::string &output, 191 bool has_extra_args, 192 bool is_callback) { 193 Status error; 194 error.SetErrorString("not implemented"); 195 return error; 196 } 197 198 virtual bool GenerateWatchpointCommandCallbackData(StringList &input, 199 std::string &output, 200 bool is_callback) { 201 return false; 202 } 203 204 virtual bool GenerateTypeScriptFunction(const char *oneliner, 205 std::string &output, 206 const void *name_token = nullptr) { 207 return false; 208 } 209 210 virtual bool GenerateTypeScriptFunction(StringList &input, 211 std::string &output, 212 const void *name_token = nullptr) { 213 return false; 214 } 215 216 virtual bool GenerateScriptAliasFunction(StringList &input, 217 std::string &output) { 218 return false; 219 } 220 221 virtual bool GenerateTypeSynthClass(StringList &input, std::string &output, 222 const void *name_token = nullptr) { 223 return false; 224 } 225 226 virtual bool GenerateTypeSynthClass(const char *oneliner, std::string &output, 227 const void *name_token = nullptr) { 228 return false; 229 } 230 231 virtual StructuredData::ObjectSP 232 CreateSyntheticScriptedProvider(const char *class_name, 233 lldb::ValueObjectSP valobj) { 234 return StructuredData::ObjectSP(); 235 } 236 237 virtual StructuredData::GenericSP 238 CreateScriptCommandObject(const char *class_name) { 239 return StructuredData::GenericSP(); 240 } 241 242 virtual StructuredData::GenericSP 243 CreateFrameRecognizer(const char *class_name) { 244 return StructuredData::GenericSP(); 245 } 246 247 virtual lldb::ValueObjectListSP GetRecognizedArguments( 248 const StructuredData::ObjectSP &implementor, 249 lldb::StackFrameSP frame_sp) { 250 return lldb::ValueObjectListSP(); 251 } 252 253 virtual StructuredData::ObjectSP 254 CreateScriptedThreadPlan(const char *class_name, 255 const StructuredDataImpl &args_data, 256 std::string &error_str, 257 lldb::ThreadPlanSP thread_plan_sp) { 258 return StructuredData::ObjectSP(); 259 } 260 261 virtual bool 262 ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, 263 Event *event, bool &script_error) { 264 script_error = true; 265 return true; 266 } 267 268 virtual bool 269 ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, 270 Event *event, bool &script_error) { 271 script_error = true; 272 return true; 273 } 274 275 virtual bool 276 ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp, 277 bool &script_error) { 278 script_error = true; 279 return true; 280 } 281 282 virtual lldb::StateType 283 ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, 284 bool &script_error) { 285 script_error = true; 286 return lldb::eStateStepping; 287 } 288 289 virtual bool 290 ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp, 291 lldb_private::Stream *stream, 292 bool &script_error) { 293 script_error = true; 294 return false; 295 } 296 297 virtual StructuredData::GenericSP 298 CreateScriptedBreakpointResolver(const char *class_name, 299 const StructuredDataImpl &args_data, 300 lldb::BreakpointSP &bkpt_sp) { 301 return StructuredData::GenericSP(); 302 } 303 304 virtual bool 305 ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp, 306 SymbolContext *sym_ctx) 307 { 308 return false; 309 } 310 311 virtual lldb::SearchDepth 312 ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp) 313 { 314 return lldb::eSearchDepthModule; 315 } 316 317 virtual StructuredData::GenericSP 318 CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, 319 const StructuredDataImpl &args_data, Status &error) { 320 error.SetErrorString("Creating scripted stop-hooks with the current " 321 "script interpreter is not supported."); 322 return StructuredData::GenericSP(); 323 } 324 325 // This dispatches to the handle_stop method of the stop-hook class. It 326 // returns a "should_stop" bool. 327 virtual bool 328 ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, 329 ExecutionContext &exc_ctx, 330 lldb::StreamSP stream_sp) { 331 return true; 332 } 333 334 virtual StructuredData::ObjectSP 335 LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { 336 return StructuredData::ObjectSP(); 337 } 338 339 virtual StructuredData::DictionarySP 340 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, 341 const char *setting_name, lldb_private::Status &error) { 342 return StructuredData::DictionarySP(); 343 } 344 345 virtual Status GenerateFunction(const char *signature, 346 const StringList &input, 347 bool is_callback) { 348 Status error; 349 error.SetErrorString("unimplemented"); 350 return error; 351 } 352 353 virtual void CollectDataForBreakpointCommandCallback( 354 std::vector<std::reference_wrapper<BreakpointOptions>> &options, 355 CommandReturnObject &result); 356 357 virtual void 358 CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, 359 CommandReturnObject &result); 360 361 /// Set the specified text as the callback for the breakpoint. 362 Status SetBreakpointCommandCallback( 363 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, 364 const char *callback_text); 365 366 virtual Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, 367 const char *callback_text, 368 bool is_callback) { 369 Status error; 370 error.SetErrorString("unimplemented"); 371 return error; 372 } 373 374 /// This one is for deserialization: 375 virtual Status SetBreakpointCommandCallback( 376 BreakpointOptions &bp_options, 377 std::unique_ptr<BreakpointOptions::CommandData> &data_up) { 378 Status error; 379 error.SetErrorString("unimplemented"); 380 return error; 381 } 382 383 Status SetBreakpointCommandCallbackFunction( 384 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, 385 const char *function_name, StructuredData::ObjectSP extra_args_sp); 386 387 /// Set a script function as the callback for the breakpoint. 388 virtual Status 389 SetBreakpointCommandCallbackFunction(BreakpointOptions &bp_options, 390 const char *function_name, 391 StructuredData::ObjectSP extra_args_sp) { 392 Status error; 393 error.SetErrorString("unimplemented"); 394 return error; 395 } 396 397 /// Set a one-liner as the callback for the watchpoint. 398 virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options, 399 const char *user_input, 400 bool is_callback) {} 401 402 virtual bool GetScriptedSummary(const char *function_name, 403 lldb::ValueObjectSP valobj, 404 StructuredData::ObjectSP &callee_wrapper_sp, 405 const TypeSummaryOptions &options, 406 std::string &retval) { 407 return false; 408 } 409 410 // Calls the specified formatter matching Python function and returns its 411 // result (true if it's a match, false if we should keep looking for a 412 // matching formatter). 413 virtual bool FormatterCallbackFunction(const char *function_name, 414 lldb::TypeImplSP type_impl_sp) { 415 return true; 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 virtual lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() { 559 return {}; 560 } 561 562 virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() { 563 return {}; 564 } 565 566 virtual lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() { 567 return {}; 568 } 569 570 virtual lldb::ScriptedPlatformInterfaceUP GetScriptedPlatformInterface() { 571 return {}; 572 } 573 574 virtual StructuredData::ObjectSP 575 CreateStructuredDataFromScriptObject(ScriptObject obj) { 576 return {}; 577 } 578 579 lldb::DataExtractorSP 580 GetDataExtractorFromSBData(const lldb::SBData &data) const; 581 582 Status GetStatusFromSBError(const lldb::SBError &error) const; 583 584 lldb::BreakpointSP 585 GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const; 586 587 lldb::ProcessAttachInfoSP 588 GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const; 589 590 lldb::ProcessLaunchInfoSP 591 GetOpaqueTypeFromSBLaunchInfo(const lldb::SBLaunchInfo &launch_info) const; 592 593 std::optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo( 594 const lldb::SBMemoryRegionInfo &mem_region) const; 595 596protected: 597 Debugger &m_debugger; 598 lldb::ScriptLanguage m_script_lang; 599}; 600 601} // namespace lldb_private 602 603#endif // LLDB_INTERPRETER_SCRIPTINTERPRETER_H 604