mgorny created this revision.
mgorny added reviewers: labath, emaste, krytarowski.
mgorny requested review of this revision.

Introduce a NativeProcessProtocol API for indicating support for
protocol extensions and enabling them.  LLGS calls
GetSupportedExtensions() method on the process factory to determine
which extensions are supported by the plugin.  If the future is both
supported by the plugin and reported as supported by the client, LLGS
enables it and reports to the client as supported by the server.

The extension is enabled on the process instance by calling
SetEnabledExtensions() method.  This is done after qSupported exchange
(if the debugger is attached to any process), as well as after launching
or attaching to a new inferior.

The patch adds 'fork' extension corresponding to 'fork-events+'
qSupported feature and 'vfork' extension for 'vfork-events+'.


https://reviews.llvm.org/D100153

Files:
  lldb/include/lldb/Host/common/NativeProcessProtocol.h
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -99,6 +99,9 @@
   uint32_t m_next_saved_registers_id = 1;
   bool m_handshake_completed = false;
 
+  bool m_fork_events_supported = false;
+  bool m_vfork_events_supported = false;
+
   PacketResult SendONotification(const char *buffer, uint32_t len);
 
   PacketResult SendWResponse(NativeProcessProtocol *process);
@@ -256,6 +259,9 @@
   llvm::Expected<lldb::tid_t> ReadTid(StringExtractorGDBRemote &packet,
                                       bool allow_all = false);
 
+  // Call SetEnabledExtensions() with appropriate flags on the process.
+  void SetEnabledExtensions(NativeProcessProtocol& process);
+
   // For GDBRemoteCommunicationServerLLGS only
   GDBRemoteCommunicationServerLLGS(const GDBRemoteCommunicationServerLLGS &) =
       delete;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -251,6 +251,8 @@
     m_debugged_process_up = std::move(*process_or);
   }
 
+  SetEnabledExtensions(*m_debugged_process_up);
+
   // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
   // needed. llgs local-process debugging may specify PTY paths, which will
   // make these file actions non-null process launch -i/e/o will also make
@@ -318,6 +320,7 @@
     return status;
   }
   m_debugged_process_up = std::move(*process_or);
+  SetEnabledExtensions(*m_debugged_process_up);
 
   // Setup stdout/stderr mapping from inferior.
   auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
@@ -3545,5 +3548,45 @@
         "QPassSignals+", "qXfer:auxv:read+", "qXfer:libraries-svr4:read+",
 #endif
   });
+
+  // check for platform features
+  auto process_features = m_process_factory.GetSupportedExtensions();
+
+  // reset to defaults
+  m_fork_events_supported = false;
+  m_vfork_events_supported = false;
+
+  // check for client features
+  for (auto x : client_features) {
+    if (x == "fork-events+" && (process_features & NativeProcessProtocol::Extension::fork) == NativeProcessProtocol::Extension::fork)
+      m_fork_events_supported = true;
+    else if (x == "vfork-events+" && (process_features & NativeProcessProtocol::Extension::vfork) == NativeProcessProtocol::Extension::vfork)
+      m_vfork_events_supported = true;
+  }
+
+  // report only if actually supported
+  if (m_fork_events_supported)
+    ret.push_back("fork-events+");
+  if (m_vfork_events_supported)
+    ret.push_back("vfork-events+");
+
+  if (m_debugged_process_up)
+    SetEnabledExtensions(*m_debugged_process_up);
   return ret;
 }
+
+void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
+    NativeProcessProtocol &process) {
+  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+  NativeProcessProtocol::Extension flags;
+  if (m_fork_events_supported)
+    flags |= NativeProcessProtocol::Extension::fork;
+  if (m_vfork_events_supported)
+    flags |= NativeProcessProtocol::Extension::vfork;
+
+  llvm::Error error = process.SetEnabledExtensions(flags);
+  if (error)
+    LLDB_LOG_ERROR(log, std::move(error),
+                   "Enabling protocol extensions failed: {0}");
+}
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -353,7 +353,9 @@
 
   // build the qSupported packet
   std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc",
-                                       "multiprocess+"};
+                                       "multiprocess+",
+                                       "fork-events+",
+                                       "vfork-events+"};
   StreamString packet;
   packet.PutCString("qSupported");
   for (uint32_t i = 0; i < features.size(); ++i) {
Index: lldb/include/lldb/Host/common/NativeProcessProtocol.h
===================================================================
--- lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -30,6 +30,8 @@
 #include <vector>
 
 namespace lldb_private {
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
 class MemoryRegionInfo;
 class ResumeActionList;
 
@@ -258,6 +260,14 @@
   virtual Status GetFileLoadAddress(const llvm::StringRef &file_name,
                                     lldb::addr_t &load_addr) = 0;
 
+  /// Extension flag constants, passed to SetEnabledExtension().
+  enum class Extension {
+    fork = (1u << 0),
+    vfork = (1u << 1),
+
+    LLVM_MARK_AS_BITMASK_ENUM(vfork)
+  };
+
   class Factory {
   public:
     virtual ~Factory();
@@ -304,6 +314,14 @@
     virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
     Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
            MainLoop &mainloop) const = 0;
+
+    /// Get the bitmask of extensions supported by this process plugin.
+    ///
+    /// \return
+    ///     A NativeProcessProtocol::Extension bitmask.
+    virtual Extension GetSupportedExtensions() const {
+      return {};
+    }
   };
 
   /// Start tracing a process or its threads.
@@ -358,6 +376,19 @@
     return llvm::make_error<UnimplementedError>();
   }
 
+  /// Method called in order to propagate the bitmap of protocol
+  /// extensions supported by the client.
+  ///
+  /// \param[in] flags
+  ///     The bitmap of enabled extensions.
+  ///
+  /// \return An error if extension-related setup failed, success
+  /// otherwise.
+  virtual llvm::Error SetEnabledExtensions(Extension flags) {
+    m_enabled_extensions = flags;
+    return llvm::Error::success();
+  }
+
 protected:
   struct SoftwareBreakpoint {
     uint32_t ref_count;
@@ -388,6 +419,9 @@
   // stopping it.
   llvm::DenseSet<int> m_signals_to_ignore;
 
+  // Extensions enabled per the last SetEnabledExtensions() call.
+  Extension m_enabled_extensions;
+
   // lldb_private::Host calls should be used to launch a process for debugging,
   // and then the process should be attached to. When attaching to a process
   // lldb_private::Host calls should be used to locate the process to attach
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to