brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.1 KiB · ad2ddd2 Raw
503 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H10#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H11 12#include "lldb/Host/Config.h"13 14#if LLDB_ENABLE_PYTHON15 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 27namespace lldb_private {28class IOHandlerPythonInterpreter;29class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {30public: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  Status55  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 script67  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::ObjectSP74  CreateSyntheticScriptedProvider(const char *class_name,75                                  lldb::ValueObjectSP valobj) override;76 77  StructuredData::GenericSP78  CreateScriptCommandObject(const char *class_name) override;79 80  StructuredData::ObjectSP81  CreateStructuredDataFromScriptObject(ScriptObject obj) override;82 83  StructuredData::GenericSP84  CreateFrameRecognizer(const char *class_name) override;85 86  lldb::ValueObjectListSP87  GetRecognizedArguments(const StructuredData::ObjectSP &implementor,88                         lldb::StackFrameSP frame_sp) override;89 90  bool ShouldHide(const StructuredData::ObjectSP &implementor,91                  lldb::StackFrameSP frame_sp) override;92 93  lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override;94 95  lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override;96 97  lldb::ScriptedBreakpointInterfaceSP98  CreateScriptedBreakpointInterface() override;99 100  lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;101 102  lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override;103 104  lldb::ScriptedFrameProviderInterfaceSP105  CreateScriptedFrameProviderInterface() override;106 107  lldb::ScriptedThreadPlanInterfaceSP108  CreateScriptedThreadPlanInterface() override;109 110  lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override;111 112  StructuredData::ObjectSP113  LoadPluginModule(const FileSpec &file_spec,114                   lldb_private::Status &error) override;115 116  StructuredData::DictionarySP117  GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,118                     const char *setting_name,119                     lldb_private::Status &error) override;120 121  size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,122                              uint32_t max) override;123 124  lldb::ValueObjectSP125  GetChildAtIndex(const StructuredData::ObjectSP &implementor,126                  uint32_t idx) override;127 128  llvm::Expected<uint32_t>129  GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,130                          const char *child_name) override;131 132  bool UpdateSynthProviderInstance(133      const StructuredData::ObjectSP &implementor) override;134 135  bool MightHaveChildrenSynthProviderInstance(136      const StructuredData::ObjectSP &implementor) override;137 138  lldb::ValueObjectSP139  GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;140 141  ConstString142  GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;143 144  bool145  RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,146                        ScriptedCommandSynchronicity synchronicity,147                        lldb_private::CommandReturnObject &cmd_retobj,148                        Status &error,149                        const lldb_private::ExecutionContext &exe_ctx) override;150 151  bool RunScriptBasedCommand(152      StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,153      ScriptedCommandSynchronicity synchronicity,154      lldb_private::CommandReturnObject &cmd_retobj, Status &error,155      const lldb_private::ExecutionContext &exe_ctx) override;156 157  bool RunScriptBasedParsedCommand(158      StructuredData::GenericSP impl_obj_sp, Args &args,159      ScriptedCommandSynchronicity synchronicity,160      lldb_private::CommandReturnObject &cmd_retobj, Status &error,161      const lldb_private::ExecutionContext &exe_ctx) override;162 163  std::optional<std::string>164  GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp,165                                     Args &args) override;166 167  StructuredData::DictionarySP HandleArgumentCompletionForScriptedCommand(168      StructuredData::GenericSP impl_obj_sp, std::vector<llvm::StringRef> &args,169      size_t args_pos, size_t char_in_arg) override;170 171  StructuredData::DictionarySP HandleOptionArgumentCompletionForScriptedCommand(172      StructuredData::GenericSP impl_obj_sp, llvm::StringRef &long_options,173      size_t char_in_arg) override;174 175  Status GenerateFunction(const char *signature, const StringList &input,176                          bool is_callback) override;177 178  Status GenerateBreakpointCommandCallbackData(StringList &input,179                                               std::string &output,180                                               bool has_extra_args,181                                               bool is_callback) override;182 183  bool GenerateWatchpointCommandCallbackData(StringList &input,184                                             std::string &output,185                                             bool is_callback) override;186 187  bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,188                          StructuredData::ObjectSP &callee_wrapper_sp,189                          const TypeSummaryOptions &options,190                          std::string &retval) override;191 192  bool FormatterCallbackFunction(const char *function_name,193                                 lldb::TypeImplSP type_impl_sp) 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_t201  GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;202 203  bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,204                                   std::string &dest) override;205                                   206  StructuredData::ObjectSP207  GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;208 209  StructuredData::ObjectSP210  GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;211 212  bool SetOptionValueForCommandObject(StructuredData::GenericSP cmd_obj_sp,213                                      ExecutionContext *exe_ctx,214                                      llvm::StringRef long_option, 215                                      llvm::StringRef value) override;216 217  void OptionParsingStartedForCommandObject(218      StructuredData::GenericSP cmd_obj_sp) override;219 220  bool CheckObjectExists(const char *name) override {221    if (!name || !name[0])222      return false;223    std::string temp;224    return GetDocumentationForItem(name, temp);225  }226 227  bool RunScriptFormatKeyword(const char *impl_function, Process *process,228                              std::string &output, Status &error) override;229 230  bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,231                              std::string &output, Status &error) override;232 233  bool RunScriptFormatKeyword(const char *impl_function, Target *target,234                              std::string &output, Status &error) override;235 236  bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,237                              std::string &output, Status &error) override;238 239  bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,240                              std::string &output, Status &error) override;241 242  bool LoadScriptingModule(const char *filename,243                           const LoadScriptOptions &options,244                           lldb_private::Status &error,245                           StructuredData::ObjectSP *module_sp = nullptr,246                           FileSpec extra_search_dir = {},247                           lldb::TargetSP loaded_into_target_sp = {}) override;248 249  bool IsReservedWord(const char *word) override;250 251  std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;252 253  void CollectDataForBreakpointCommandCallback(254      std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,255      CommandReturnObject &result) override;256 257  void258  CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,259                                          CommandReturnObject &result) override;260 261  /// Set the callback body text into the callback for the breakpoint.262  Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,263                                      const char *callback_body,264                                      bool is_callback) override;265 266  Status SetBreakpointCommandCallbackFunction(267      BreakpointOptions &bp_options, const char *function_name,268      StructuredData::ObjectSP extra_args_sp) override;269 270  /// This one is for deserialization:271  Status SetBreakpointCommandCallback(272      BreakpointOptions &bp_options,273      std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;274 275  Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,276                                      const char *command_body_text,277                                      StructuredData::ObjectSP extra_args_sp,278                                      bool uses_extra_args,279                                      bool is_callback);280 281  /// Set a one-liner as the callback for the watchpoint.282  void SetWatchpointCommandCallback(WatchpointOptions *wp_options,283                                    const char *user_input,284                                    bool is_callback) override;285 286  const char *GetDictionaryName() { return m_dictionary_name.c_str(); }287 288  PyThreadState *GetThreadState() { return m_command_thread_state; }289 290  void SetThreadState(PyThreadState *s) {291    if (s)292      m_command_thread_state = s;293  }294 295  // IOHandlerDelegate296  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;297 298  void IOHandlerInputComplete(IOHandler &io_handler,299                              std::string &data) override;300 301  static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);302 303  // PluginInterface protocol304  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }305 306  class Locker : public ScriptInterpreterLocker {307  public:308    enum OnEntry {309      AcquireLock = 0x0001,310      InitSession = 0x0002,311      InitGlobals = 0x0004,312      NoSTDIN = 0x0008313    };314 315    enum OnLeave {316      FreeLock = 0x0001,317      FreeAcquiredLock = 0x0002, // do not free the lock if we already held it318                                 // when calling constructor319      TearDownSession = 0x0004320    };321 322    Locker(ScriptInterpreterPythonImpl *py_interpreter,323           uint16_t on_entry = AcquireLock | InitSession,324           uint16_t on_leave = FreeLock | TearDownSession,325           lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,326           lldb::FileSP err = nullptr);327 328    ~Locker() override;329 330  private:331    bool DoAcquireLock();332 333    bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,334                       lldb::FileSP out, lldb::FileSP err);335 336    bool DoFreeLock();337 338    bool DoTearDownSession();339 340    bool m_teardown_session;341    ScriptInterpreterPythonImpl *m_python_interpreter;342    PyGILState_STATE m_GILState;343  };344 345  static bool BreakpointCallbackFunction(void *baton,346                                         StoppointCallbackContext *context,347                                         lldb::user_id_t break_id,348                                         lldb::user_id_t break_loc_id);349  static bool WatchpointCallbackFunction(void *baton,350                                         StoppointCallbackContext *context,351                                         lldb::user_id_t watch_id);352  static void Initialize();353 354  class SynchronicityHandler {355  private:356    lldb::DebuggerSP m_debugger_sp;357    ScriptedCommandSynchronicity m_synch_wanted;358    bool m_old_asynch;359 360  public:361    SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);362 363    ~SynchronicityHandler();364  };365 366  enum class AddLocation { Beginning, End };367 368  static void AddToSysPath(AddLocation location, std::string path);369 370  bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,371                    lldb::FileSP err);372 373  void LeaveSession();374 375  uint32_t IsExecutingPython() {376    std::lock_guard<std::mutex> guard(m_mutex);377    return m_lock_count > 0;378  }379 380  uint32_t IncrementLockCount() {381    std::lock_guard<std::mutex> guard(m_mutex);382    return ++m_lock_count;383  }384 385  uint32_t DecrementLockCount() {386    std::lock_guard<std::mutex> guard(m_mutex);387    if (m_lock_count > 0)388      --m_lock_count;389    return m_lock_count;390  }391 392  enum ActiveIOHandler {393    eIOHandlerNone,394    eIOHandlerBreakpoint,395    eIOHandlerWatchpoint396  };397 398  python::PythonModule &GetMainModule();399 400  python::PythonDictionary &GetSessionDictionary();401 402  python::PythonDictionary &GetSysModuleDictionary();403 404  llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(405      const llvm::StringRef &callable_name) override;406 407  bool GetEmbeddedInterpreterModuleObjects();408 409  bool SetStdHandle(lldb::FileSP file, const char *py_name,410                    python::PythonObject &save_file, const char *mode);411 412  python::PythonObject m_saved_stdin;413  python::PythonObject m_saved_stdout;414  python::PythonObject m_saved_stderr;415  python::PythonModule m_main_module;416  python::PythonDictionary m_session_dict;417  python::PythonDictionary m_sys_module_dict;418  python::PythonObject m_run_one_line_function;419  python::PythonObject m_run_one_line_str_global;420  std::string m_dictionary_name;421  ActiveIOHandler m_active_io_handler;422  bool m_session_is_active;423  bool m_pty_secondary_is_open;424  bool m_valid_session;425  uint32_t m_lock_count;426  std::mutex m_mutex;427  PyThreadState *m_command_thread_state;428};429 430class IOHandlerPythonInterpreter : public IOHandler {431public:432  IOHandlerPythonInterpreter(Debugger &debugger,433                             ScriptInterpreterPythonImpl *python)434      : IOHandler(debugger, IOHandler::Type::PythonInterpreter),435        m_python(python) {}436 437  ~IOHandlerPythonInterpreter() override = default;438 439  llvm::StringRef GetControlSequence(char ch) override {440    static constexpr llvm::StringLiteral control_sequence("quit()\n");441    if (ch == 'd')442      return control_sequence;443    return {};444  }445 446  void Run() override {447    if (m_python) {448      int stdin_fd = GetInputFD();449      if (stdin_fd >= 0) {450        Terminal terminal(stdin_fd);451        TerminalState terminal_state(terminal);452 453        if (terminal.IsATerminal()) {454          // FIXME: error handling?455          llvm::consumeError(terminal.SetCanonical(false));456          llvm::consumeError(terminal.SetEcho(true));457        }458 459        ScriptInterpreterPythonImpl::Locker locker(460            m_python,461            ScriptInterpreterPythonImpl::Locker::AcquireLock |462                ScriptInterpreterPythonImpl::Locker::InitSession |463                ScriptInterpreterPythonImpl::Locker::InitGlobals,464            ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |465                ScriptInterpreterPythonImpl::Locker::TearDownSession);466 467        // The following call drops into the embedded interpreter loop and468        // stays there until the user chooses to exit from the Python469        // interpreter. This embedded interpreter will, as any Python code that470        // performs I/O, unlock the GIL before a system call that can hang, and471        // lock it when the syscall has returned.472 473        // We need to surround the call to the embedded interpreter with calls474        // to PyGILState_Ensure and PyGILState_Release (using the Locker475        // above). This is because Python has a global lock which must be held476        // whenever we want to touch any Python objects. Otherwise, if the user477        // calls Python code, the interpreter state will be off, and things478        // could hang (it's happened before).479 480        StreamString run_string;481        run_string.Printf("run_python_interpreter (%s)",482                          m_python->GetDictionaryName());483        python::RunSimpleString(run_string.GetData());484      }485    }486    SetIsDone(true);487  }488 489  void Cancel() override {}490 491  bool Interrupt() override { return m_python->Interrupt(); }492 493  void GotEOF() override {}494 495protected:496  ScriptInterpreterPythonImpl *m_python;497};498 499} // namespace lldb_private500 501#endif // LLDB_ENABLE_PYTHON502#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H503