Skip to content

[lldb] Removed gdbserver ports map from lldb-server #104238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 3, 2024

Conversation

slydiman
Copy link
Contributor

@slydiman slydiman commented Aug 14, 2024

Listen to gdbserver-port, accept the connection and run lldb-server gdbserver --fd on all platforms.
Parameters --min-gdbserver-port and --max-gdbserver-port are deprecated now.

This is the part 2 of #101283.

Fixes #97537.

@llvmbot
Copy link
Member

llvmbot commented Aug 14, 2024

@llvm/pr-subscribers-lldb

Author: Dmitry Vasilyev (slydiman)

Changes

Listen to gdbserver-port, accept the connection and run lldb-server gdbserver --fd on all platforms. Added acceptor_gdb and gdb_thread to lldb-platform.cpp SharedSocket has been moved to ConnectionFileDescriptorPosix.

Parameters --min-gdbserver-port and --max-gdbserver-port are deprecated now.

This is the part 2 of #101283.

Fixes #97537.


Patch is 61.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104238.diff

17 Files Affected:

  • (modified) lldb/docs/man/lldb-server.rst (+2-9)
  • (modified) lldb/docs/resources/qemu-testing.rst (+5-14)
  • (modified) lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h (+26)
  • (modified) lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp (+109-3)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (+24-17)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h (+6-2)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp (+97-193)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h (+13-70)
  • (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (+1-1)
  • (removed) lldb/test/Shell/lldb-server/TestGdbserverPort.test (-4)
  • (modified) lldb/tools/lldb-server/Acceptor.cpp (+4-2)
  • (modified) lldb/tools/lldb-server/Acceptor.h (+3)
  • (modified) lldb/tools/lldb-server/lldb-gdbserver.cpp (+16-7)
  • (modified) lldb/tools/lldb-server/lldb-platform.cpp (+152-174)
  • (modified) lldb/unittests/Process/gdb-remote/CMakeLists.txt (-1)
  • (removed) lldb/unittests/Process/gdb-remote/PortMapTest.cpp (-115)
  • (modified) lldb/unittests/tools/lldb-server/tests/TestClient.h (+4)
diff --git a/lldb/docs/man/lldb-server.rst b/lldb/docs/man/lldb-server.rst
index a67c00b305f6d2..31f5360df5e23e 100644
--- a/lldb/docs/man/lldb-server.rst
+++ b/lldb/docs/man/lldb-server.rst
@@ -147,15 +147,8 @@ GDB-SERVER CONNECTIONS
 
 .. option:: --gdbserver-port <port>
 
- Define a port to be used for gdb-server connections. Can be specified multiple
- times to allow multiple ports. Has no effect if --min-gdbserver-port
- and --max-gdbserver-port are specified.
-
-.. option:: --min-gdbserver-port <port>
-.. option:: --max-gdbserver-port <port>
-
- Specify the range of ports that can be used for gdb-server connections. Both
- options need to be specified simultaneously. Overrides --gdbserver-port.
+ Define a port to be used for gdb-server connections. This port is used for
+ multiple connections.
 
 .. option:: --port-offset <offset>
 
diff --git a/lldb/docs/resources/qemu-testing.rst b/lldb/docs/resources/qemu-testing.rst
index 51a30b11717a87..e102f84a1d31f4 100644
--- a/lldb/docs/resources/qemu-testing.rst
+++ b/lldb/docs/resources/qemu-testing.rst
@@ -149,7 +149,6 @@ to the host (refer to QEMU's manuals for the specific options).
 * At least one to connect to the intial ``lldb-server``.
 * One more if you want to use ``lldb-server`` in ``platform mode``, and have it
   start a ``gdbserver`` instance for you.
-* A bunch more if you want to run tests against the ``lldb-server`` platform.
 
 If you are doing either of the latter 2 you should also restrict what ports
 ``lldb-server tries`` to use, otherwise it will randomly pick one that is almost
@@ -157,22 +156,14 @@ certainly not forwarded. An example of this is shown below.
 
 ::
 
-  $ lldb-server plaform --server --listen 0.0.0.0:54321 \
-    --min-gdbserver-port 49140 --max-gdbserver-port 49150
+  $ lldb-server plaform --server --listen 0.0.0.0:54321 --gdbserver-port 49140
 
 The result of this is that:
 
 * ``lldb-server`` platform mode listens externally on port ``54321``.
 
-* When it is asked to start a new gdbserver mode instance, it will use a port
-  in the range ``49140`` to ``49150``.
+* When it is asked to start a new gdbserver mode instance, it will use the port
+  ``49140``.
 
-Your VM configuration should have ports ``54321``, and ``49140`` to ``49150``
-forwarded for this to work.
-
-.. note::
-  These options are used to create a "port map" within ``lldb-server``.
-  Unfortunately this map is not cleaned up on Windows on connection close,
-  and across a few uses you may run out of valid ports. To work around this,
-  restart the platform every so often, especially after running a set of tests.
-  This is tracked here: https://github.com/llvm/llvm-project/issues/90923
+Your VM configuration should have ports ``54321`` and ``49140`` forwarded for
+this to work.
diff --git a/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
index 35773d5907e913..08f486b92e0f07 100644
--- a/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
+++ b/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
@@ -26,6 +26,32 @@ class Status;
 class Socket;
 class SocketAddress;
 
+#ifdef _WIN32
+typedef lldb::pipe_t shared_fd_t;
+#else
+typedef NativeSocket shared_fd_t;
+#endif
+
+class SharedSocket {
+public:
+  static const shared_fd_t kInvalidFD;
+
+  SharedSocket(Connection *conn, Status &error);
+
+  shared_fd_t GetSendableFD() { return m_fd; }
+
+  Status CompleteSending(lldb::pid_t child_pid);
+
+  static Status GetNativeSocket(shared_fd_t fd, NativeSocket &socket);
+
+private:
+#ifdef _WIN32
+  Pipe m_socket_pipe;
+  NativeSocket m_socket;
+#endif
+  shared_fd_t m_fd;
+};
+
 class ConnectionFileDescriptor : public Connection {
 public:
   typedef llvm::function_ref<void(llvm::StringRef local_socket_id)>
diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index fceeff08ed9d36..fa7d2982d72238 100644
--- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -52,6 +52,94 @@
 using namespace lldb;
 using namespace lldb_private;
 
+#ifdef _WIN32
+const shared_fd_t SharedSocket::kInvalidFD = LLDB_INVALID_PIPE;
+#else
+const shared_fd_t SharedSocket::kInvalidFD = Socket::kInvalidSocketValue;
+#endif
+
+SharedSocket::SharedSocket(Connection *conn, Status &error) {
+  m_fd = kInvalidFD;
+
+  const Socket *socket =
+      static_cast<const Socket *>(conn->GetReadObject().get());
+  if (socket == nullptr) {
+    error = Status("invalid conn socket");
+    return;
+  }
+
+#ifdef _WIN32
+  m_socket = socket->GetNativeSocket();
+
+  // Create a pipe to transfer WSAPROTOCOL_INFO to the child process.
+  error = m_socket_pipe.CreateNew(true);
+  if (error.Fail())
+    return;
+
+  m_fd = m_socket_pipe.GetReadPipe();
+#else
+  m_fd = socket->GetNativeSocket();
+  error = Status();
+#endif
+}
+
+Status SharedSocket::CompleteSending(lldb::pid_t child_pid) {
+#ifdef _WIN32
+  // Transfer WSAPROTOCOL_INFO to the child process.
+  m_socket_pipe.CloseReadFileDescriptor();
+
+  WSAPROTOCOL_INFO protocol_info;
+  if (::WSADuplicateSocket(m_socket, child_pid, &protocol_info) ==
+      SOCKET_ERROR) {
+    int last_error = ::WSAGetLastError();
+    return Status("WSADuplicateSocket() failed, error: %d", last_error);
+  }
+
+  size_t num_bytes;
+  Status error =
+      m_socket_pipe.WriteWithTimeout(&protocol_info, sizeof(protocol_info),
+                                     std::chrono::seconds(10), num_bytes);
+  if (error.Fail())
+    return error;
+  if (num_bytes != sizeof(protocol_info))
+    return Status("WriteWithTimeout(WSAPROTOCOL_INFO) failed: %d bytes",
+                  num_bytes);
+#endif
+  return Status();
+}
+
+Status SharedSocket::GetNativeSocket(shared_fd_t fd, NativeSocket &socket) {
+#ifdef _WIN32
+  socket = Socket::kInvalidSocketValue;
+  // Read WSAPROTOCOL_INFO from the parent process and create NativeSocket.
+  WSAPROTOCOL_INFO protocol_info;
+  {
+    Pipe socket_pipe(fd, LLDB_INVALID_PIPE);
+    size_t num_bytes;
+    Status error =
+        socket_pipe.ReadWithTimeout(&protocol_info, sizeof(protocol_info),
+                                    std::chrono::seconds(10), num_bytes);
+    if (error.Fail())
+      return error;
+    if (num_bytes != sizeof(protocol_info)) {
+      return Status(
+          "socket_pipe.ReadWithTimeout(WSAPROTOCOL_INFO) failed: % d bytes",
+          num_bytes);
+    }
+  }
+  socket = ::WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
+                       FROM_PROTOCOL_INFO, &protocol_info, 0, 0);
+  if (socket == INVALID_SOCKET) {
+    return Status("WSASocket(FROM_PROTOCOL_INFO) failed: error %d",
+                  ::WSAGetLastError());
+  }
+  return Status();
+#else
+  socket = fd;
+  return Status();
+#endif
+}
+
 ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit)
     : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
 
@@ -149,7 +237,7 @@ ConnectionFileDescriptor::Connect(llvm::StringRef path,
 
   if (!path.empty()) {
     auto method =
-        llvm::StringSwitch<ConnectionStatus (ConnectionFileDescriptor::*)(
+        llvm::StringSwitch<ConnectionStatus (ConnectionFileDescriptor:: *)(
             llvm::StringRef, socket_id_callback_type, Status *)>(scheme)
             .Case("listen", &ConnectionFileDescriptor::AcceptTCP)
             .Cases("accept", "unix-accept",
@@ -162,8 +250,10 @@ ConnectionFileDescriptor::Connect(llvm::StringRef path,
             .Case("unix-connect", &ConnectionFileDescriptor::ConnectNamedSocket)
             .Case("unix-abstract-connect",
                   &ConnectionFileDescriptor::ConnectAbstractSocket)
-#if LLDB_ENABLE_POSIX
+#if LLDB_ENABLE_POSIX || defined(_WIN32)
             .Case("fd", &ConnectionFileDescriptor::ConnectFD)
+#endif
+#if LLDB_ENABLE_POSIX
             .Case("file", &ConnectionFileDescriptor::ConnectFile)
             .Case("serial", &ConnectionFileDescriptor::ConnectSerialPort)
 #endif
@@ -666,7 +756,23 @@ ConnectionStatus
 ConnectionFileDescriptor::ConnectFD(llvm::StringRef s,
                                     socket_id_callback_type socket_id_callback,
                                     Status *error_ptr) {
-#if LLDB_ENABLE_POSIX
+#ifdef _WIN32
+  int64_t fd = -1;
+  if (!s.getAsInteger(0, fd)) {
+    // Assume we own fd.
+    std::unique_ptr<TCPSocket> tcp_socket =
+        std::make_unique<TCPSocket>((NativeSocket)fd, true, false);
+    m_io_sp = std::move(tcp_socket);
+    m_uri = s.str();
+    return eConnectionStatusSuccess;
+  }
+
+  if (error_ptr)
+    error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"",
+                                        s.str().c_str());
+  m_io_sp.reset();
+  return eConnectionStatusError;
+#elif LLDB_ENABLE_POSIX
   // Just passing a native file descriptor within this current process that
   // is already opened (possibly from a service or other source).
   int fd = -1;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 5d0a3e31d04374..075312016e0b22 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -879,20 +879,12 @@ lldb::thread_result_t GDBRemoteCommunication::ListenThread() {
   return {};
 }
 
-Status GDBRemoteCommunication::StartDebugserverProcess(
-    const char *url, Platform *platform, ProcessLaunchInfo &launch_info,
-    uint16_t *port, const Args *inferior_args, int pass_comm_fd) {
+bool GDBRemoteCommunication::GetDebugserverPath(
+    Platform *platform, FileSpec &debugserver_file_spec) {
   Log *log = GetLog(GDBRLog::Process);
-  LLDB_LOGF(log, "GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")",
-            __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
-
-  Status error;
   // If we locate debugserver, keep that located version around
   static FileSpec g_debugserver_file_spec;
 
-  char debugserver_path[PATH_MAX];
-  FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
-
   Environment host_env = Host::GetEnvironment();
 
   // Always check to see if we have an environment override for the path to the
@@ -943,8 +935,20 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
       }
     }
   }
+  return debugserver_exists;
+}
 
-  if (debugserver_exists) {
+Status GDBRemoteCommunication::StartDebugserverProcess(
+    const char *url, Platform *platform, ProcessLaunchInfo &launch_info,
+    uint16_t *port, const Args *inferior_args, shared_fd_t pass_comm_fd) {
+  Log *log = GetLog(GDBRLog::Process);
+  LLDB_LOGF(log, "GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")",
+            __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
+
+  Status error;
+  FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
+  if (GetDebugserverPath(platform, debugserver_file_spec)) {
+    char debugserver_path[PATH_MAX];
     debugserver_file_spec.GetPath(debugserver_path, sizeof(debugserver_path));
 
     Args &debugserver_args = launch_info.GetArguments();
@@ -962,13 +966,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
     if (url)
       debugserver_args.AppendArgument(llvm::StringRef(url));
 
-    if (pass_comm_fd >= 0) {
+    if (pass_comm_fd != SharedSocket::kInvalidFD) {
       StreamString fd_arg;
-      fd_arg.Printf("--fd=%i", pass_comm_fd);
+      fd_arg.Printf("--fd=%" PRIi64, (int64_t)pass_comm_fd);
       debugserver_args.AppendArgument(fd_arg.GetString());
       // Send "pass_comm_fd" down to the inferior so it can use it to
-      // communicate back with this process
-      launch_info.AppendDuplicateFileAction(pass_comm_fd, pass_comm_fd);
+      // communicate back with this process. Ignored on Windows.
+      launch_info.AppendDuplicateFileAction((int)pass_comm_fd,
+                                            (int)pass_comm_fd);
     }
 
     // use native registers, not the GDB registers
@@ -988,7 +993,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
     // port is null when debug server should listen on domain socket - we're
     // not interested in port value but rather waiting for debug server to
     // become available.
-    if (pass_comm_fd == -1) {
+    if (pass_comm_fd == SharedSocket::kInvalidFD) {
       if (url) {
 // Create a temporary file to get the stdout/stderr and redirect the output of
 // the command into this file. We will later read this file if all goes well
@@ -1059,6 +1064,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
         }
       }
     }
+
+    Environment host_env = Host::GetEnvironment();
     std::string env_debugserver_log_file =
         host_env.lookup("LLDB_DEBUGSERVER_LOG_FILE");
     if (!env_debugserver_log_file.empty()) {
@@ -1132,7 +1139,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
 
     if (error.Success() &&
         (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) &&
-        pass_comm_fd == -1) {
+        pass_comm_fd == SharedSocket::kInvalidFD) {
       if (named_pipe_path.size() > 0) {
         error = socket_pipe.OpenAsReader(named_pipe_path, false);
         if (error.Fail())
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 4e59bd5ec8be6b..bbff31de8aafd6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -20,6 +20,7 @@
 
 #include "lldb/Core/Communication.h"
 #include "lldb/Host/Config.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
 #include "lldb/Host/HostThread.h"
 #include "lldb/Utility/Args.h"
 #include "lldb/Utility/Listener.h"
@@ -146,6 +147,9 @@ class GDBRemoteCommunication : public Communication {
 
   std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
 
+  // Get the debugserver path and check that it exist.
+  bool GetDebugserverPath(Platform *platform, FileSpec &debugserver_file_spec);
+
   // Start a debugserver instance on the current host using the
   // supplied connection URL.
   Status StartDebugserverProcess(
@@ -153,8 +157,8 @@ class GDBRemoteCommunication : public Communication {
       Platform *platform, // If non nullptr, then check with the platform for
                           // the GDB server binary if it can't be located
       ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
-      int pass_comm_fd); // Communication file descriptor to pass during
-                         // fork/exec to avoid having to connect/accept
+      shared_fd_t pass_comm_fd); // Communication file descriptor to pass during
+                                 // fork/exec to avoid having to connect/accept
 
   void DumpHistory(Stream &strm);
 
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 65f1cc12ba307b..5c51c9afbe76df 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -40,83 +40,20 @@
 
 #include "lldb/Utility/StringExtractorGDBRemote.h"
 
+#include "../tools/lldb-server/Acceptor.h"
+
 using namespace lldb;
 using namespace lldb_private::process_gdb_remote;
 using namespace lldb_private;
 
-GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
-                                                       uint16_t max_port) {
-  assert(min_port);
-  for (; min_port < max_port; ++min_port)
-    m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
-}
-
-void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
-  assert(port);
-  // Do not modify existing mappings
-  m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
-}
-
-llvm::Expected<uint16_t>
-GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
-  if (m_port_map.empty())
-    return 0; // Bind to port zero and get a port, we didn't have any
-              // limitations
-
-  for (auto &pair : m_port_map) {
-    if (pair.second == LLDB_INVALID_PROCESS_ID) {
-      pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
-      return pair.first;
-    }
-  }
-  return llvm::createStringError(llvm::inconvertibleErrorCode(),
-                                 "No free port found in port map");
-}
-
-bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
-    uint16_t port, lldb::pid_t pid) {
-  auto pos = m_port_map.find(port);
-  if (pos != m_port_map.end()) {
-    pos->second = pid;
-    return true;
-  }
-  return false;
-}
-
-bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
-  std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
-  if (pos != m_port_map.end()) {
-    pos->second = LLDB_INVALID_PROCESS_ID;
-    return true;
-  }
-  return false;
-}
-
-bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
-    lldb::pid_t pid) {
-  if (!m_port_map.empty()) {
-    for (auto &pair : m_port_map) {
-      if (pair.second == pid) {
-        pair.second = LLDB_INVALID_PROCESS_ID;
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
-  return m_port_map.empty();
-}
+std::mutex GDBRemoteCommunicationServerPlatform::g_spawned_pids_mutex;
+std::set<lldb::pid_t> GDBRemoteCommunicationServerPlatform::g_spawned_pids;
 
 // GDBRemoteCommunicationServerPlatform constructor
 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
-    const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
-    : GDBRemoteCommunicationServerCommon(),
-      m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
-      m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
-  m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
-  m_pending_gdb_server.port = 0;
+    const Socket::SocketProtocol socket_protocol, uint16_t gdbserver_port)
+    : GDBRemoteCommunicationServerCommon(), m_socket_protocol(socket_protocol),
+      m_gdbserver_port(gdbserver_port), m_port_offset(0) {
 
   RegisterMemberFunctionHandler(
       StringExtractorGDBRemote::eServerPacketType_qC,
@@ -160,66 +97,59 @@ GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
     default;
 
 Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
-    const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
-    std::optional<uint16_t> &port, std::string &socket_name) {
-  if (!port) {
-    llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
-    if (available_port)
-      port = *available_port;
-    else
-      return Status(available_port.takeError());
-  }
-
-  // Spawn a new thread to accept the port that gets bound after binding to
-  // port 0 (zero).
+    const lldb_private::Args &args, lldb::pid_t &pid, std::string &socket_name,
+    shared_fd_t fd) {
+  std::ostringstream url;
+  if (fd == SharedSocket::kInvalidFD) {
+    if (m_socket_protocol == Socket::ProtocolTcp) {
+      // Just check that GDBServer exists. GDBServer must be launched after
+      // accepting the connection.
+      FileSpec debugserver_file_spec;
+      if (!GetDebugserverPath(nullptr, debugserver_file_spec))
+        return Status("unable to locate debugserver");
+      return Status();
+    }
 
-  // ignore the hostname send from the remote end, just use the ip address that
-  // we're currently communicating with as the hostname
+    // debugserver does not accept the URL scheme prefix.
+#if !defined(__APPLE__)
+    url << lldb_server::Acceptor::FindSchemeByProtocol(m_socket_protocol)
+        << "://";
+#endif
+    socket_name = GetDomainSocketPath("gdbserver").GetPath();
+    url << socket_name;
+  } else {
+    if (m_socket_protocol != Socket::ProtocolTcp)
+      return Status("protocol must be tcp");
+  }
 
   // Spawn a debugserver and try to get the port it listens to.
   ProcessLaunchInfo debugserver_launch_info;
-  if (hostname.empty())
-    hostname = "127.0.0.1";
-
   Log *log = GetLog(LLDBLog::Platform);
-  LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_st...
[truncated]

Copy link

github-actions bot commented Aug 14, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@slydiman slydiman force-pushed the lldb-server-remove-gdb-ports-map branch from 46808aa to 5732bda Compare August 14, 2024 21:08
@DavidSpickett
Copy link
Collaborator

Thanks for putting so much work into this. I will test this out with my VM setup.

Parameters --min-gdbserver-port and --max-gdbserver-port are deprecated now.

Are they just consumed but the port number is not used because it can use the first port for everything?

(I do see the logic of leaving the options in at first, so we can tell whether any problems are from the changes in this PR or purely from removing the options)

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The termination part definitely needs to be done differently, but overall, I think this is a pretty good start.

(PSA: I will be OOO all of next week.)

Comment on lines 882 to 883
bool GDBRemoteCommunication::GetDebugserverPath(
Platform *platform, FileSpec &debugserver_file_spec) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool GDBRemoteCommunication::GetDebugserverPath(
Platform *platform, FileSpec &debugserver_file_spec) {
FileSpec GDBRemoteCommunication::GetDebugserverPath(
Platform *platform) {

just return an invalid FileSpec for error.

Copy link
Contributor Author

@slydiman slydiman Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to minimize changes. bool debugserver_exists already was here.
Note debugserver_file_spec is initialized in the following code by reference.
Returning FileSpec complicates and slows down the code.

FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
if (GetDebugserverPath(platform, debugserver_file_spec)) {
   ...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minimizing changes is not what I'm concerned with. This change in particular could be easily split off into its own patch.
I don't think

FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
if (GetDebugserverPath(platform, debugserver_file_spec)) {

is inherently better than

launch_info.GetExecutableFile() = GetDebugserverPath(platform);
if (launch_info.GetExecutableFile()) {

or

if (FileSpec debugserver_file_spec = GetDebugserverPath(platform)) {
  launch_info.GetExecutableFile() = debugserver_file_spec;

In fact, I'd say it's the opposite, because that pattern leaves it ambiguous as to what is the value of the by-ref argument in the failure case (is it unchanged, empty/invalid, or undefined)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@@ -40,83 +40,20 @@

#include "lldb/Utility/StringExtractorGDBRemote.h"

#include "../tools/lldb-server/Acceptor.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to move this someplace else (probably Host)

Copy link
Contributor Author

@slydiman slydiman Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have separated this change to #104439.

static int g_debug = 0;
static int g_verbose = 0;
static int g_server = 0;
static volatile bool g_listen_gdb = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

volatile? really?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected to use this for break the gdb port listener thread. But currently there is no public API to close listen socket. See FIXME at the end of lldb-platform.cpp. I think we can just exit the app safely without graceful terminating this thread.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but volatile still isn't the right choice for that. It would have to be an atomic var.

Comment on lines 579 to 640
// FIXME: Make TCPSocket::CloseListenSockets() public and implement
// Acceptor::Close().
/*
if (acceptor_gdb && gdb_thread.IsJoinable()) {
g_listen_gdb = false;
static_cast<TCPSocket *>(acceptor_gdb->m_listener_socket_up.get())
->CloseListenSockets();
lldb::thread_result_t result;
gdb_thread.Join(&result);
}
*/

Copy link
Collaborator

@labath labath Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work. This is exactly the pattern from that kernel bug we were arguing over. It's just not possible to safely close an fd while another thread may be operating on it.

You need to use an out-of-band mechanism (e.g. a pipe) to notify the thread that it's time to terminate. However, since that will involve some form of multiplexing (e.g. select(2)), I would strongly prefer to just multiplex over the two sockets we are accepting (and ditch the extra thread). We should be able to use the MainLoop class for that -- just register the two sockets with the class, and let it call the right callback when needed. Basically, the code should look similar to this, except that it will be listening to two unrelated sockets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, Linux... Such pattern works just fine on Windows. I saw MainLoop. But I think it is much safer just exit the app. Terminating the main thread is enough. I will remove this comment in the code and the g_listen_gdb flag.

Copy link
Collaborator

@labath labath Aug 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<rant>It's not just linux, that kind of pattern is racy on all posix operating systems. It's possible that other OSs will not hang in this situation, but that doesn't mean that usage is safe. Even on windows, that can cause you to call (WSA)accept on a dangling socket descriptor -- since you can never be sure whether the other thread has already called the function, or is it merely about to do that. It's less likely to blow up in your face because windows does not recycle FDs like posix systems do, but I wouldn't recommend that anywhere.</rant>

Exiting the main thread may be convenient, but I definitely wouldn't call it "safe", as that means the other thread may be running, executing random code and memory, while the main thread is shutting everything down and deleting that memory. It may not matter often, as the process is done anyway, but if anyone was observing the exit code, he may be suprised to see a SEGV instead of a clean exit.

Reasoning about a singlethreaded application is much easier than for a multithreaded one. We should already have all of the pieces to do this the right way, so let's just do that.

Comment on lines 23 to 26
#ifdef SendMessage
#undef SendMessage
#endif

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that means we're including a windows header somewhere. Any chance to avoid that? Llvm is pretty strict about that. Lldb is not, though I think it's a good practice.

Copy link
Contributor Author

@slydiman slydiman Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note TestClient.cpp and LLGSTest.cpp already contain this code. Windows headers are necessary for socket definitions. It is impossible to separate them. This fix is necessary because the order of headers has been changed. I have removed the same code in TestClient.cpp and LLGSTest.cpp.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's just due to header moves that's fine.

It's definitely possible to isolate the windows headers. Lllvm does that by making sure it only includes the system headers in implementation files (of the library wrapping them). It'd be nice to have lldb do the same thing, but we're pretty far off.

@slydiman
Copy link
Contributor Author

slydiman commented Aug 15, 2024

@DavidSpickett

Are they just consumed but the port number is not used because it can use the first port for everything?

(I do see the logic of leaving the options in at first, so we can tell whether any problems are from the changes in this PR or purely from removing the options)

We need only 1 port defined by --gdbserver-port. I kept --min-gdbserver-port and --max-gdbserver-port for backward compatibility.

lldb-server p --server --listen *:1234 --gdbserver-port 1235 --min-gdbserver-port 1236 --max-gdbserver-port 1237

1235 is used for gdb

lldb-server p --server --listen *:1234 --min-gdbserver-port 1236 --max-gdbserver-port 1237

1236 is used for gdb

lldb-server p --server --listen *:1234 --max-gdbserver-port 1237 --min-gdbserver-port 1236

1237 is used for gdb

slydiman added a commit to slydiman/llvm-project that referenced this pull request Aug 15, 2024
@DavidSpickett
Copy link
Collaborator

Only had time to build so far but:

/home/davspi01/work/open_source/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp: In function ‘int main_platform(int, char**)’:
/home/davspi01/work/open_source/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp:354:49: warning: comparison is always false due to limited range of data type [-Wtype-limits]
  354 |       if (port_offset < LOW_PORT || port_offset > HIGH_PORT) {
      |                                                 ^
/home/davspi01/work/open_source/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp:372:41: warning: comparison is always false due to limited range of data type [-Wtype-limits]
  372 |       if (portnum < LOW_PORT || portnum > HIGH_PORT) {
      |                                         ^
[2796/2796] Linking CXX executable bin/lldb-server

I think this warning was already there, I'm just seeing it now in a clean build. u means unsigned and portnum is uint16_t.

slydiman added a commit that referenced this pull request Aug 16, 2024
@slydiman
Copy link
Contributor Author

I think this warning was already there, I'm just seeing it now in a clean build. u means unsigned and portnum is uint16_t.

I will revert the original definition #define HIGH_PORT (49151u). Thanks.

@DavidSpickett
Copy link
Collaborator

I did some testing with my usual setup which is x86 Linux to AArch64 Linux running in a simulator.

<simulator>
$ ./lldb-server platform --server --listen 0.0.0.0:1234 --gdbserver-port 49140
<host>
$ ./bin/lldb-dotest --platform-name remote-linux --platform-url connect://172.17.0.2:1234 --platform-working-dir /tmp/test_lldb --arch aarch64 -p TestSVE*

The SVE tests are the ones that found #97537.

And everything works as expected. I don't normally run remote tests with ninja check-lldb, so I just ran the above command in a couple of terminals at the same time and there weren't any problems.

\_ ./lldb-server platform --server --listen 0.0.0.0:1234 --gdbserver-port 49140
    \_ lldb-server platform --child-platform-fd 9 --gdbserver-port 49140
    \_ lldb-server platform --child-platform-fd 9 --gdbserver-port 49140
    \_ /home/davspi01/lldb-server gdbserver  --fd=9 --native-regs
    |   \_ sh -c /usr/bin/lsb_release -i
    |       \_ /usr/bin/python3 -Es /usr/bin/lsb_release -i
    \_ /home/davspi01/lldb-server gdbserver  --fd=9 --native-regs
        \_ sh -c /usr/bin/lsb_release -i
            \_ /usr/bin/python3 -Es /usr/bin/lsb_release -i

Snapshot of the processes during that, all makes sense to me. Main platform, two connected clients and each one has spawned a gdbserver.

@slydiman
Copy link
Contributor Author

slydiman commented Aug 16, 2024

And everything works as expected. I don't normally run remote tests with ninja check-lldb, so I just ran the above command in a couple of terminals at the same time and there weren't any problems.

Note we are testing

  • API, Shell, unittests locally on Windows x86_64
  • API, Shell, unittests locally on Linux x86_64
  • API, Shell tests cross Windows x86_64 host + Linux AArch64 target
  • API, Shell tests cross Linux x86_64 host + Linux AArch64 target

Currently we have 2 tests failed on Windows host/local. But these fails are not related to this patch.

@slydiman slydiman force-pushed the lldb-server-remove-gdb-ports-map branch from 04caaec to d61a1c2 Compare August 16, 2024 13:13
@slydiman slydiman force-pushed the lldb-server-remove-gdb-ports-map branch 2 times, most recently from 5e37411 to b691617 Compare August 19, 2024 14:24
slydiman added a commit to slydiman/llvm-project that referenced this pull request Aug 19, 2024
slydiman added a commit to slydiman/llvm-project that referenced this pull request Aug 19, 2024
slydiman added a commit that referenced this pull request Aug 26, 2024
@slydiman slydiman force-pushed the lldb-server-remove-gdb-ports-map branch from b691617 to 1d4949f Compare August 26, 2024 15:37
@slydiman
Copy link
Contributor Author

slydiman commented Oct 1, 2024

I don't like globals

Is this the only argument? I don't like globals too. But no one suggested better solution w/o huge refactoring of MonitorProcessCallback.

Updated.
The child process will crash 50/50 at the end, but no one will see it. The problem will remain hidden.
Removed fixes #101475 in the description. I can create a separate patch after merging this PR.

@labath
Copy link
Collaborator

labath commented Oct 2, 2024

I don't like globals

Is this the only argument?

No, it's not. You can find my second reason in the full text of my previous message. The third reason is that I think this is something that should be handled independenly of this (already larger that I'd like) patch.

I don't like globals too. But no one suggested better solution w/o huge refactoring of MonitorProcessCallback.

You didn't ask for one either. Declaring it's the only way isn't the most traditional way of soliciting feedback.

Updated. The child process will crash 50/50 at the end, but no one will see it. The problem will remain hidden. Removed fixes #101475 in the description. I can create a separate patch after merging this PR.

👍

I'm going to look at the patch now.

Comment on lines +103 to +107
// Just check that GDBServer exists. GDBServer must be launched after
// accepting the connection.
if (!GetDebugserverPath(nullptr))
return Status::FromErrorString("unable to locate debugserver");
return Status();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still looking for an answer to this one. If it's only the Handle_qLaunchGDBServer that needs to not launch an lldb-server then I don't see why the check couldn't/shouldn't be performed there.

// verify that we know anything about this pid.
if (SpawnedProcessFinished(pid)) {
// not a pid we know about
return SendErrorResponse(10); // ECHILD
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get rid of these comments. If we really wanted these to have a meaning, they should be one of the GDB_ESOMETHING constants defined in GDBRemoteCommunication.h.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

m_spawned_pids.insert(pid);
}

bool GDBRemoteCommunicationServerPlatform::SpawnedProcessFinished(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest inverting this condition and calling this SpawnedProcessIsRunning (or sth like that). The reason being that "Finished" implies that process was running at some point, but this function does not distinguish a terminated process from one that was never run.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return Status();
}

static Status AcceptGdbConnectionsIfNeeded(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return Expected<handles> here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@slydiman
Copy link
Contributor Author

slydiman commented Oct 2, 2024

I am still looking for an answer to this one. If it's only the Handle_qLaunchGDBServer that needs to not launch an lldb-server then I don't see why the check couldn't/shouldn't be performed there.

I cannot answer in the thread, no idea why. The answer is here
#104238 (comment)

LaunchGDBServer() may be called from the child process at the beginnig if inferior_arguments are present. The behavior depends on the protocol. gdbserver will be launched in case of unix sockets. Otherwise we need to check that gdbserver is exists and wait for the tcp gdb connection. This part cannot be optimized/simplified.

@slydiman slydiman requested a review from labath October 3, 2024 11:05
@labath
Copy link
Collaborator

labath commented Oct 3, 2024

I am still looking for an answer to this one. If it's only the Handle_qLaunchGDBServer that needs to not launch an lldb-server then I don't see why the check couldn't/shouldn't be performed there.

I cannot answer in the thread, no idea why. The answer is here #104238 (comment)

LaunchGDBServer() may be called from the child process at the beginnig if inferior_arguments are present. The behavior depends on the protocol. gdbserver will be launched in case of unix sockets. Otherwise we need to check that gdbserver is exists and wait for the tcp gdb connection. This part cannot be optimized/simplified.

Okay, that makes sense. Let's see how this goes.

@slydiman slydiman merged commit 2e89312 into llvm:main Oct 3, 2024
8 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 3, 2024

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building lldb at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/7720

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: commands/expression/issue_11588/Test11588.py (161 of 2684)
UNSUPPORTED: lldb-api :: commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py (162 of 2684)
PASS: lldb-api :: commands/process/attach/attach_denied/TestAttachDenied.py (163 of 2684)
PASS: lldb-api :: commands/session/save/TestSessionSave.py (164 of 2684)
PASS: lldb-api :: commands/session/history/TestSessionHistory.py (165 of 2684)
UNSUPPORTED: lldb-api :: commands/register/register/aarch64_sme_z_registers/save_restore/TestSMEZRegistersSaveRestore.py (166 of 2684)
UNSUPPORTED: lldb-api :: commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py (167 of 2684)
PASS: lldb-api :: commands/process/continue_to_bkpt/TestContinueToBkpts.py (168 of 2684)
PASS: lldb-api :: commands/expression/options/TestExprOptions.py (169 of 2684)
UNSUPPORTED: lldb-api :: commands/target/dump-pcm-info/TestDumpPCMInfo.py (170 of 2684)
FAIL: lldb-api :: commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py (171 of 2684)
******************** TEST 'lldb-api :: commands/platform/launchgdbserver/TestPlatformLaunchGDBServer.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env ARCHIVER=/usr/bin/ar --env OBJCOPY=/usr/bin/objcopy --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/commands/platform/launchgdbserver -p TestPlatformLaunchGDBServer.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 20.0.0git (https://github.com/llvm/llvm-project.git revision 2e89312419c5f7875c947fcf79ea0446cf65a287)
  clang revision 2e89312419c5f7875c947fcf79ea0446cf65a287
  llvm revision 2e89312419c5f7875c947fcf79ea0446cf65a287
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/commands/platform/launchgdbserver
runCmd: settings clear -all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 


@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 3, 2024

LLVM Buildbot has detected a new failure on builder lldb-arm-ubuntu running on linaro-lldb-arm-ubuntu while building lldb at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/18/builds/4885

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: lang/cpp/keywords_enabled/TestCppKeywordsEnabled.py (795 of 2809)
PASS: lldb-api :: lang/cpp/incomplete-types/TestCppIncompleteTypes.py (796 of 2809)
PASS: lldb-api :: lang/cpp/inlines/TestInlines.py (797 of 2809)
PASS: lldb-api :: lang/cpp/lambdas/TestLambdas.py (798 of 2809)
PASS: lldb-api :: lang/cpp/llvm-style/TestLLVMStyle.py (799 of 2809)
UNSUPPORTED: lldb-api :: lang/cpp/modules-import/TestCXXModulesImport.py (800 of 2809)
PASS: lldb-api :: lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py (801 of 2809)
PASS: lldb-api :: lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py (802 of 2809)
PASS: lldb-api :: lang/cpp/multiple-inheritance/TestCppMultipleInheritance.py (803 of 2809)
PASS: lldb-api :: lang/cpp/namespace_conflicts/TestNamespaceConflicts.py (804 of 2809)
FAIL: lldb-api :: lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py (805 of 2809)
******************** TEST 'lldb-api :: lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env ARCHIVER=/usr/local/bin/llvm-ar --env OBJCOPY=/usr/bin/llvm-objcopy --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --arch armv8l --build-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/dsymutil --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/lang/c/shared_lib_stripped_symbols -p TestSharedLibStrippedSymbols.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 20.0.0git (https://github.com/llvm/llvm-project.git revision 2e89312419c5f7875c947fcf79ea0446cf65a287)
  clang revision 2e89312419c5f7875c947fcf79ea0446cf65a287
  llvm revision 2e89312419c5f7875c947fcf79ea0446cf65a287
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_expr_dsym (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_expr_dwarf (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase)
FAIL: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_expr_dwo (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase)
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_frame_variable_dsym (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase) (test case does not fall in any category of interest for this run) 
XFAIL: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_frame_variable_dwarf (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase)
XFAIL: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_frame_variable_dwo (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase)
======================================================================
FAIL: test_expr_dwo (TestSharedLibStrippedSymbols.SharedLibStrippedTestCase)
   Test that types work when defined in a shared library and forwa/d-declared in the main executable
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1769, in test_method
    return attrvalue(self)
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py", line 24, in test_expr
    self.expect(
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2370, in expect
    self.runCmd(
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1000, in runCmd
    self.assertTrue(self.res.Succeeded(), msg + output)
AssertionError: False is not true : Variable(s) displayed correctly
Error output:

slydiman added a commit to slydiman/llvm-project that referenced this pull request Oct 3, 2024
@slydiman
Copy link
Contributor Author

slydiman commented Oct 3, 2024

#111033

slydiman added a commit that referenced this pull request Oct 3, 2024
@DavidSpickett
Copy link
Collaborator

******************** TEST 'lldb-api :: lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py' FAILED ********************

This test is flaky on Arm 32, I'll figure it out.

adrian-prantl pushed a commit to adrian-prantl/llvm-project that referenced this pull request Oct 11, 2024
adrian-prantl pushed a commit to adrian-prantl/llvm-project that referenced this pull request Oct 11, 2024
This is the prerequisite for llvm#104238.

(cherry picked from commit 06ccd32)
@DavidSpickett
Copy link
Collaborator

Hi @slydiman, I am looking at commits that warrant a release note for LLDB 20, and I think your work on lldb-server's port map might fit the bill. If you want to do that yourself you can send a PR adding a bullet point to https://github.com/llvm/llvm-project/blob/main/llvm/docs/ReleaseNotes.md#changes-to-lldb, describing the changes.

Or you can tell me a 1/2 sentence summary of it and I'll meld it into release notes style. I know that it has helped my work because I only have to open 2 ports now (1 platform and 1 gdb-server), but I'm not 100% sure of the detail.

@slydiman
Copy link
Contributor Author

@DavidSpickett

Or you can tell me a 1/2 sentence summary of it and I'll meld it into release notes style

lldb-server now listens to a single port for gdbserver connections and provides it to the connection handler processes. This allows only 2 ports to be opened in the firewall. lldb-server now also works on Windows in the server mode.

Thanks

@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Jan 14, 2025

Thanks! - cfd7e02

@slydiman slydiman deleted the lldb-server-remove-gdb-ports-map branch April 18, 2025 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
5 participants