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 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> 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(); } + /// 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 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 Index: lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py =================================================================== --- lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -904,6 +904,8 @@ "qEcho", "QPassSignals", "multiprocess", + "fork-events", + "vfork-events", ] def parse_qSupported_response(self, context): 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 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/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 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,49 @@ "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}"); +}