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