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