1 //===-- ScriptInterpreterPythonImpl.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_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H 10 #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H 11 12 #include "lldb/Host/Config.h" 13 14 #if LLDB_ENABLE_PYTHON 15 16 #include "lldb-python.h" 17 18 #include "PythonDataObjects.h" 19 #include "ScriptInterpreterPython.h" 20 21 #include "lldb/Host/Terminal.h" 22 #include "lldb/Utility/StreamString.h" 23 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/ADT/StringRef.h" 26 27 namespace lldb_private { 28 class IOHandlerPythonInterpreter; 29 class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { 30 public: 31 friend class IOHandlerPythonInterpreter; 32 33 ScriptInterpreterPythonImpl(Debugger &debugger); 34 35 ~ScriptInterpreterPythonImpl() override; 36 37 bool Interrupt() override; 38 39 bool ExecuteOneLine( 40 llvm::StringRef command, CommandReturnObject *result, 41 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; 42 43 void ExecuteInterpreterLoop() override; 44 45 bool ExecuteOneLineWithReturn( 46 llvm::StringRef in_string, 47 ScriptInterpreter::ScriptReturnType return_type, void *ret_value, 48 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; 49 50 lldb_private::Status ExecuteMultipleLines( 51 const char *in_string, 52 const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; 53 54 Status 55 ExportFunctionDefinitionToInterpreter(StringList &function_def) override; 56 57 bool GenerateTypeScriptFunction(StringList &input, std::string &output, 58 const void *name_token = nullptr) override; 59 60 bool GenerateTypeSynthClass(StringList &input, std::string &output, 61 const void *name_token = nullptr) override; 62 63 bool GenerateTypeSynthClass(const char *oneliner, std::string &output, 64 const void *name_token = nullptr) override; 65 66 // use this if the function code is just a one-liner script 67 bool GenerateTypeScriptFunction(const char *oneliner, std::string &output, 68 const void *name_token = nullptr) override; 69 70 bool GenerateScriptAliasFunction(StringList &input, 71 std::string &output) override; 72 73 StructuredData::ObjectSP 74 CreateSyntheticScriptedProvider(const char *class_name, 75 lldb::ValueObjectSP valobj) override; 76 77 StructuredData::GenericSP 78 CreateScriptCommandObject(const char *class_name) override; 79 80 StructuredData::ObjectSP 81 CreateStructuredDataFromScriptObject(ScriptObject obj) override; 82 83 StructuredData::GenericSP 84 CreateScriptedBreakpointResolver(const char *class_name, 85 const StructuredDataImpl &args_data, 86 lldb::BreakpointSP &bkpt_sp) override; 87 bool ScriptedBreakpointResolverSearchCallback( 88 StructuredData::GenericSP implementor_sp, 89 SymbolContext *sym_ctx) override; 90 91 lldb::SearchDepth ScriptedBreakpointResolverSearchDepth( 92 StructuredData::GenericSP implementor_sp) override; 93 94 StructuredData::GenericSP 95 CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, 96 const StructuredDataImpl &args_data, 97 Status &error) override; 98 99 bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, 100 ExecutionContext &exc_ctx, 101 lldb::StreamSP stream_sp) override; 102 103 StructuredData::GenericSP 104 CreateFrameRecognizer(const char *class_name) override; 105 106 lldb::ValueObjectListSP 107 GetRecognizedArguments(const StructuredData::ObjectSP &implementor, 108 lldb::StackFrameSP frame_sp) override; 109 110 bool ShouldHide(const StructuredData::ObjectSP &implementor, 111 lldb::StackFrameSP frame_sp) override; 112 113 lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override; 114 115 lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; 116 117 lldb::ScriptedThreadPlanInterfaceSP 118 CreateScriptedThreadPlanInterface() override; 119 120 lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override; 121 122 StructuredData::ObjectSP 123 LoadPluginModule(const FileSpec &file_spec, 124 lldb_private::Status &error) override; 125 126 StructuredData::DictionarySP 127 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, 128 const char *setting_name, 129 lldb_private::Status &error) override; 130 131 size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, 132 uint32_t max) override; 133 134 lldb::ValueObjectSP 135 GetChildAtIndex(const StructuredData::ObjectSP &implementor, 136 uint32_t idx) override; 137 138 int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, 139 const char *child_name) override; 140 141 bool UpdateSynthProviderInstance( 142 const StructuredData::ObjectSP &implementor) override; 143 144 bool MightHaveChildrenSynthProviderInstance( 145 const StructuredData::ObjectSP &implementor) override; 146 147 lldb::ValueObjectSP 148 GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; 149 150 ConstString 151 GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override; 152 153 bool 154 RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, 155 ScriptedCommandSynchronicity synchronicity, 156 lldb_private::CommandReturnObject &cmd_retobj, 157 Status &error, 158 const lldb_private::ExecutionContext &exe_ctx) override; 159 160 bool RunScriptBasedCommand( 161 StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, 162 ScriptedCommandSynchronicity synchronicity, 163 lldb_private::CommandReturnObject &cmd_retobj, Status &error, 164 const lldb_private::ExecutionContext &exe_ctx) override; 165 166 bool RunScriptBasedParsedCommand( 167 StructuredData::GenericSP impl_obj_sp, Args &args, 168 ScriptedCommandSynchronicity synchronicity, 169 lldb_private::CommandReturnObject &cmd_retobj, Status &error, 170 const lldb_private::ExecutionContext &exe_ctx) override; 171 172 std::optional<std::string> 173 GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp, 174 Args &args) override; 175 176 Status GenerateFunction(const char *signature, const StringList &input, 177 bool is_callback) override; 178 179 Status GenerateBreakpointCommandCallbackData(StringList &input, 180 std::string &output, 181 bool has_extra_args, 182 bool is_callback) override; 183 184 bool GenerateWatchpointCommandCallbackData(StringList &input, 185 std::string &output, 186 bool is_callback) override; 187 188 bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, 189 StructuredData::ObjectSP &callee_wrapper_sp, 190 const TypeSummaryOptions &options, 191 std::string &retval) override; 192 193 bool FormatterCallbackFunction(const char *function_name, 194 lldb::TypeImplSP type_impl_sp) override; 195 196 bool GetDocumentationForItem(const char *item, std::string &dest) override; 197 198 bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, 199 std::string &dest) override; 200 201 uint32_t 202 GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; 203 204 bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, 205 std::string &dest) override; 206 207 StructuredData::ObjectSP 208 GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; 209 210 StructuredData::ObjectSP 211 GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; 212 213 bool SetOptionValueForCommandObject(StructuredData::GenericSP cmd_obj_sp, 214 ExecutionContext *exe_ctx, 215 llvm::StringRef long_option, 216 llvm::StringRef value) override; 217 218 void OptionParsingStartedForCommandObject( 219 StructuredData::GenericSP cmd_obj_sp) override; 220 221 bool CheckObjectExists(const char *name) override { 222 if (!name || !name[0]) 223 return false; 224 std::string temp; 225 return GetDocumentationForItem(name, temp); 226 } 227 228 bool RunScriptFormatKeyword(const char *impl_function, Process *process, 229 std::string &output, Status &error) override; 230 231 bool RunScriptFormatKeyword(const char *impl_function, Thread *thread, 232 std::string &output, Status &error) override; 233 234 bool RunScriptFormatKeyword(const char *impl_function, Target *target, 235 std::string &output, Status &error) override; 236 237 bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame, 238 std::string &output, Status &error) override; 239 240 bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value, 241 std::string &output, Status &error) override; 242 243 bool LoadScriptingModule(const char *filename, 244 const LoadScriptOptions &options, 245 lldb_private::Status &error, 246 StructuredData::ObjectSP *module_sp = nullptr, 247 FileSpec extra_search_dir = {}) override; 248 249 bool IsReservedWord(const char *word) override; 250 251 std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override; 252 253 void CollectDataForBreakpointCommandCallback( 254 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, 255 CommandReturnObject &result) override; 256 257 void 258 CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, 259 CommandReturnObject &result) override; 260 261 /// Set the callback body text into the callback for the breakpoint. 262 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, 263 const char *callback_body, 264 bool is_callback) override; 265 266 Status SetBreakpointCommandCallbackFunction( 267 BreakpointOptions &bp_options, const char *function_name, 268 StructuredData::ObjectSP extra_args_sp) override; 269 270 /// This one is for deserialization: 271 Status SetBreakpointCommandCallback( 272 BreakpointOptions &bp_options, 273 std::unique_ptr<BreakpointOptions::CommandData> &data_up) override; 274 275 Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, 276 const char *command_body_text, 277 StructuredData::ObjectSP extra_args_sp, 278 bool uses_extra_args, 279 bool is_callback); 280 281 /// Set a one-liner as the callback for the watchpoint. 282 void SetWatchpointCommandCallback(WatchpointOptions *wp_options, 283 const char *user_input, 284 bool is_callback) override; 285 286 const char *GetDictionaryName() { return m_dictionary_name.c_str(); } 287 288 PyThreadState *GetThreadState() { return m_command_thread_state; } 289 290 void SetThreadState(PyThreadState *s) { 291 if (s) 292 m_command_thread_state = s; 293 } 294 295 // IOHandlerDelegate 296 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override; 297 298 void IOHandlerInputComplete(IOHandler &io_handler, 299 std::string &data) override; 300 301 static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger); 302 303 // PluginInterface protocol 304 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 305 306 class Locker : public ScriptInterpreterLocker { 307 public: 308 enum OnEntry { 309 AcquireLock = 0x0001, 310 InitSession = 0x0002, 311 InitGlobals = 0x0004, 312 NoSTDIN = 0x0008 313 }; 314 315 enum OnLeave { 316 FreeLock = 0x0001, 317 FreeAcquiredLock = 0x0002, // do not free the lock if we already held it 318 // when calling constructor 319 TearDownSession = 0x0004 320 }; 321 322 Locker(ScriptInterpreterPythonImpl *py_interpreter, 323 uint16_t on_entry = AcquireLock | InitSession, 324 uint16_t on_leave = FreeLock | TearDownSession, 325 lldb::FileSP in = nullptr, lldb::FileSP out = nullptr, 326 lldb::FileSP err = nullptr); 327 328 ~Locker() override; 329 330 private: 331 bool DoAcquireLock(); 332 333 bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in, 334 lldb::FileSP out, lldb::FileSP err); 335 336 bool DoFreeLock(); 337 338 bool DoTearDownSession(); 339 340 bool m_teardown_session; 341 ScriptInterpreterPythonImpl *m_python_interpreter; 342 PyGILState_STATE m_GILState; 343 }; 344 345 static bool BreakpointCallbackFunction(void *baton, 346 StoppointCallbackContext *context, 347 lldb::user_id_t break_id, 348 lldb::user_id_t break_loc_id); 349 static bool WatchpointCallbackFunction(void *baton, 350 StoppointCallbackContext *context, 351 lldb::user_id_t watch_id); 352 static void Initialize(); 353 354 class SynchronicityHandler { 355 private: 356 lldb::DebuggerSP m_debugger_sp; 357 ScriptedCommandSynchronicity m_synch_wanted; 358 bool m_old_asynch; 359 360 public: 361 SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity); 362 363 ~SynchronicityHandler(); 364 }; 365 366 enum class AddLocation { Beginning, End }; 367 368 static void AddToSysPath(AddLocation location, std::string path); 369 370 bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, 371 lldb::FileSP err); 372 373 void LeaveSession(); 374 375 uint32_t IsExecutingPython() { 376 std::lock_guard<std::mutex> guard(m_mutex); 377 return m_lock_count > 0; 378 } 379 380 uint32_t IncrementLockCount() { 381 std::lock_guard<std::mutex> guard(m_mutex); 382 return ++m_lock_count; 383 } 384 385 uint32_t DecrementLockCount() { 386 std::lock_guard<std::mutex> guard(m_mutex); 387 if (m_lock_count > 0) 388 --m_lock_count; 389 return m_lock_count; 390 } 391 392 enum ActiveIOHandler { 393 eIOHandlerNone, 394 eIOHandlerBreakpoint, 395 eIOHandlerWatchpoint 396 }; 397 398 python::PythonModule &GetMainModule(); 399 400 python::PythonDictionary &GetSessionDictionary(); 401 402 python::PythonDictionary &GetSysModuleDictionary(); 403 404 llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable( 405 const llvm::StringRef &callable_name) override; 406 407 bool GetEmbeddedInterpreterModuleObjects(); 408 409 bool SetStdHandle(lldb::FileSP file, const char *py_name, 410 python::PythonObject &save_file, const char *mode); 411 412 python::PythonObject m_saved_stdin; 413 python::PythonObject m_saved_stdout; 414 python::PythonObject m_saved_stderr; 415 python::PythonModule m_main_module; 416 python::PythonDictionary m_session_dict; 417 python::PythonDictionary m_sys_module_dict; 418 python::PythonObject m_run_one_line_function; 419 python::PythonObject m_run_one_line_str_global; 420 std::string m_dictionary_name; 421 ActiveIOHandler m_active_io_handler; 422 bool m_session_is_active; 423 bool m_pty_secondary_is_open; 424 bool m_valid_session; 425 uint32_t m_lock_count; 426 std::mutex m_mutex; 427 PyThreadState *m_command_thread_state; 428 }; 429 430 class IOHandlerPythonInterpreter : public IOHandler { 431 public: 432 IOHandlerPythonInterpreter(Debugger &debugger, 433 ScriptInterpreterPythonImpl *python) 434 : IOHandler(debugger, IOHandler::Type::PythonInterpreter), 435 m_python(python) {} 436 437 ~IOHandlerPythonInterpreter() override = default; 438 439 llvm::StringRef GetControlSequence(char ch) override { 440 static constexpr llvm::StringLiteral control_sequence("quit()\n"); 441 if (ch == 'd') 442 return control_sequence; 443 return {}; 444 } 445 446 void Run() override { 447 if (m_python) { 448 int stdin_fd = GetInputFD(); 449 if (stdin_fd >= 0) { 450 Terminal terminal(stdin_fd); 451 TerminalState terminal_state(terminal); 452 453 if (terminal.IsATerminal()) { 454 // FIXME: error handling? 455 llvm::consumeError(terminal.SetCanonical(false)); 456 llvm::consumeError(terminal.SetEcho(true)); 457 } 458 459 ScriptInterpreterPythonImpl::Locker locker( 460 m_python, 461 ScriptInterpreterPythonImpl::Locker::AcquireLock | 462 ScriptInterpreterPythonImpl::Locker::InitSession | 463 ScriptInterpreterPythonImpl::Locker::InitGlobals, 464 ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock | 465 ScriptInterpreterPythonImpl::Locker::TearDownSession); 466 467 // The following call drops into the embedded interpreter loop and 468 // stays there until the user chooses to exit from the Python 469 // interpreter. This embedded interpreter will, as any Python code that 470 // performs I/O, unlock the GIL before a system call that can hang, and 471 // lock it when the syscall has returned. 472 473 // We need to surround the call to the embedded interpreter with calls 474 // to PyGILState_Ensure and PyGILState_Release (using the Locker 475 // above). This is because Python has a global lock which must be held 476 // whenever we want to touch any Python objects. Otherwise, if the user 477 // calls Python code, the interpreter state will be off, and things 478 // could hang (it's happened before). 479 480 StreamString run_string; 481 run_string.Printf("run_python_interpreter (%s)", 482 m_python->GetDictionaryName()); 483 PyRun_SimpleString(run_string.GetData()); 484 } 485 } 486 SetIsDone(true); 487 } 488 489 void Cancel() override {} 490 491 bool Interrupt() override { return m_python->Interrupt(); } 492 493 void GotEOF() override {} 494 495 protected: 496 ScriptInterpreterPythonImpl *m_python; 497 }; 498 499 } // namespace lldb_private 500 501 #endif // LLDB_ENABLE_PYTHON 502 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H 503