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