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