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