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