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