Skip to content

Commit d067401

Browse files
committed
[lldb] Removed gdbserver ports map from lldb-server
Listen to gdbserver-port, accept the connection and run lldb-server gdbserver --fd on all platforms. Refactored Acceptor to listen on 2 ports in the main thread. Parameters --min-gdbserver-port and --max-gdbserver-port are deprecated now. This is the part 2 of llvm#101283. Fixes llvm#97537, fixes llvm#101475.
1 parent ba52a09 commit d067401

File tree

22 files changed

+554
-636
lines changed

22 files changed

+554
-636
lines changed

lldb/docs/man/lldb-server.rst

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,8 @@ GDB-SERVER CONNECTIONS
147147

148148
.. option:: --gdbserver-port <port>
149149

150-
Define a port to be used for gdb-server connections. Can be specified multiple
151-
times to allow multiple ports. Has no effect if --min-gdbserver-port
152-
and --max-gdbserver-port are specified.
153-
154-
.. option:: --min-gdbserver-port <port>
155-
.. option:: --max-gdbserver-port <port>
156-
157-
Specify the range of ports that can be used for gdb-server connections. Both
158-
options need to be specified simultaneously. Overrides --gdbserver-port.
150+
Define a port to be used for gdb-server connections. This port is used for
151+
multiple connections.
159152

160153
.. option:: --port-offset <offset>
161154

lldb/docs/resources/qemu-testing.rst

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,30 +149,21 @@ to the host (refer to QEMU's manuals for the specific options).
149149
* At least one to connect to the intial ``lldb-server``.
150150
* One more if you want to use ``lldb-server`` in ``platform mode``, and have it
151151
start a ``gdbserver`` instance for you.
152-
* A bunch more if you want to run tests against the ``lldb-server`` platform.
153152

154153
If you are doing either of the latter 2 you should also restrict what ports
155154
``lldb-server tries`` to use, otherwise it will randomly pick one that is almost
156155
certainly not forwarded. An example of this is shown below.
157156

158157
::
159158

160-
$ lldb-server plaform --server --listen 0.0.0.0:54321 \
161-
--min-gdbserver-port 49140 --max-gdbserver-port 49150
159+
$ lldb-server plaform --server --listen 0.0.0.0:54321 --gdbserver-port 49140
162160

163161
The result of this is that:
164162

165163
* ``lldb-server`` platform mode listens externally on port ``54321``.
166164

167-
* When it is asked to start a new gdbserver mode instance, it will use a port
168-
in the range ``49140`` to ``49150``.
165+
* When it is asked to start a new gdbserver mode instance, it will use the port
166+
``49140``.
169167

170-
Your VM configuration should have ports ``54321``, and ``49140`` to ``49150``
171-
forwarded for this to work.
172-
173-
.. note::
174-
These options are used to create a "port map" within ``lldb-server``.
175-
Unfortunately this map is not cleaned up on Windows on connection close,
176-
and across a few uses you may run out of valid ports. To work around this,
177-
restart the platform every so often, especially after running a set of tests.
178-
This is tracked here: https://github.com/llvm/llvm-project/issues/90923
168+
Your VM configuration should have ports ``54321`` and ``49140`` forwarded for
169+
this to work.

lldb/include/lldb/Host/Socket.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ namespace lldb_private {
3434
#if defined(_WIN32)
3535
typedef SOCKET NativeSocket;
3636
typedef lldb::pipe_t shared_fd_t;
37+
typedef const char *set_socket_option_arg_type;
3738
#else
3839
typedef int NativeSocket;
3940
typedef NativeSocket shared_fd_t;
41+
typedef const void *set_socket_option_arg_type;
4042
#endif
4143
class Socket;
4244
class TCPSocket;
@@ -132,12 +134,8 @@ class Socket : public IOObject {
132134
// If this Socket is connected then return the URI used to connect.
133135
virtual std::string GetRemoteConnectionURI() const { return ""; };
134136

135-
protected:
136-
Socket(SocketProtocol protocol, bool should_close,
137-
bool m_child_process_inherit);
138-
139-
virtual size_t Send(const void *buf, const size_t num_bytes);
140-
137+
static int CloseSocket(NativeSocket sockfd);
138+
static Status GetLastError();
141139
static void SetLastError(Status &error);
142140
static NativeSocket CreateSocket(const int domain, const int type,
143141
const int protocol,
@@ -146,6 +144,12 @@ class Socket : public IOObject {
146144
socklen_t *addrlen,
147145
bool child_processes_inherit, Status &error);
148146

147+
protected:
148+
Socket(SocketProtocol protocol, bool should_close,
149+
bool m_child_process_inherit);
150+
151+
virtual size_t Send(const void *buf, const size_t num_bytes);
152+
149153
SocketProtocol m_protocol;
150154
NativeSocket m_socket;
151155
bool m_child_processes_inherit;

lldb/source/Host/common/Socket.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,7 @@ Status Socket::Close() {
386386
LLDB_LOGF(log, "%p Socket::Close (fd = %" PRIu64 ")",
387387
static_cast<void *>(this), static_cast<uint64_t>(m_socket));
388388

389-
#if defined(_WIN32)
390-
bool success = closesocket(m_socket) == 0;
391-
#else
392-
bool success = ::close(m_socket) == 0;
393-
#endif
389+
bool success = CloseSocket(m_socket) == 0;
394390
// A reference to a FD was passed in, set it to an invalid value
395391
m_socket = kInvalidSocketValue;
396392
if (!success) {
@@ -427,6 +423,24 @@ void Socket::SetLastError(Status &error) {
427423
#endif
428424
}
429425

426+
Status Socket::GetLastError() {
427+
std::error_code EC;
428+
#ifdef _WIN32
429+
EC = llvm::mapWindowsError(WSAGetLastError());
430+
#else
431+
EC = std::error_code(errno, std::generic_category());
432+
#endif
433+
return EC;
434+
}
435+
436+
int Socket::CloseSocket(NativeSocket sockfd) {
437+
#ifdef _WIN32
438+
return ::closesocket(sockfd);
439+
#else
440+
return ::close(sockfd);
441+
#endif
442+
}
443+
430444
NativeSocket Socket::CreateSocket(const int domain, const int type,
431445
const int protocol,
432446
bool child_processes_inherit, Status &error) {

lldb/source/Host/common/TCPSocket.cpp

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,9 @@
3232
#include <winsock2.h>
3333
#endif
3434

35-
#ifdef _WIN32
36-
#define CLOSE_SOCKET closesocket
37-
typedef const char *set_socket_option_arg_type;
38-
#else
39-
#include <unistd.h>
40-
#define CLOSE_SOCKET ::close
41-
typedef const void *set_socket_option_arg_type;
42-
#endif
43-
4435
using namespace lldb;
4536
using namespace lldb_private;
4637

47-
static Status GetLastSocketError() {
48-
std::error_code EC;
49-
#ifdef _WIN32
50-
EC = llvm::mapWindowsError(WSAGetLastError());
51-
#else
52-
EC = std::error_code(errno, std::generic_category());
53-
#endif
54-
return EC;
55-
}
56-
5738
static const int kType = SOCK_STREAM;
5839

5940
TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
@@ -212,7 +193,7 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
212193
reinterpret_cast<set_socket_option_arg_type>(&option_value);
213194
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
214195
sizeof(option_value)) == -1) {
215-
CLOSE_SOCKET(fd);
196+
CloseSocket(fd);
216197
continue;
217198
}
218199

@@ -228,8 +209,8 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
228209
err = ::listen(fd, backlog);
229210

230211
if (err == -1) {
231-
error = GetLastSocketError();
232-
CLOSE_SOCKET(fd);
212+
error = GetLastError();
213+
CloseSocket(fd);
233214
continue;
234215
}
235216

@@ -250,7 +231,7 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
250231

251232
void TCPSocket::CloseListenSockets() {
252233
for (auto socket : m_listen_sockets)
253-
CLOSE_SOCKET(socket.first);
234+
CloseSocket(socket.first);
254235
m_listen_sockets.clear();
255236
}
256237

@@ -295,7 +276,7 @@ Status TCPSocket::Accept(Socket *&conn_socket) {
295276
lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
296277
if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
297278
if (sock != kInvalidSocketValue) {
298-
CLOSE_SOCKET(sock);
279+
CloseSocket(sock);
299280
sock = kInvalidSocketValue;
300281
}
301282
llvm::errs() << llvm::formatv(

lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,10 @@ ConnectionFileDescriptor::Connect(llvm::StringRef path,
162162
.Case("unix-connect", &ConnectionFileDescriptor::ConnectNamedSocket)
163163
.Case("unix-abstract-connect",
164164
&ConnectionFileDescriptor::ConnectAbstractSocket)
165-
#if LLDB_ENABLE_POSIX
165+
#if LLDB_ENABLE_POSIX || defined(_WIN32)
166166
.Case("fd", &ConnectionFileDescriptor::ConnectFD)
167+
#endif
168+
#if LLDB_ENABLE_POSIX
167169
.Case("file", &ConnectionFileDescriptor::ConnectFile)
168170
.Case("serial", &ConnectionFileDescriptor::ConnectSerialPort)
169171
#endif
@@ -667,7 +669,22 @@ ConnectionStatus
667669
ConnectionFileDescriptor::ConnectFD(llvm::StringRef s,
668670
socket_id_callback_type socket_id_callback,
669671
Status *error_ptr) {
670-
#if LLDB_ENABLE_POSIX
672+
#ifdef _WIN32
673+
int64_t fd = -1;
674+
if (!s.getAsInteger(0, fd)) {
675+
// Assume we own fd.
676+
std::unique_ptr<TCPSocket> tcp_socket =
677+
std::make_unique<TCPSocket>((NativeSocket)fd, true, false);
678+
m_io_sp = std::move(tcp_socket);
679+
m_uri = s.str();
680+
return eConnectionStatusSuccess;
681+
}
682+
if (error_ptr)
683+
*error_ptr = Status::FromErrorStringWithFormat(
684+
"invalid file descriptor: \"%s\"", s.str().c_str());
685+
m_io_sp.reset();
686+
return eConnectionStatusError;
687+
#elif LLDB_ENABLE_POSIX
671688
// Just passing a native file descriptor within this current process that
672689
// is already opened (possibly from a service or other source).
673690
int fd = -1;

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -879,20 +879,12 @@ lldb::thread_result_t GDBRemoteCommunication::ListenThread() {
879879
return {};
880880
}
881881

882-
Status GDBRemoteCommunication::StartDebugserverProcess(
883-
const char *url, Platform *platform, ProcessLaunchInfo &launch_info,
884-
uint16_t *port, const Args *inferior_args, int pass_comm_fd) {
882+
bool GDBRemoteCommunication::GetDebugserverPath(
883+
Platform *platform, FileSpec &debugserver_file_spec) {
885884
Log *log = GetLog(GDBRLog::Process);
886-
LLDB_LOGF(log, "GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")",
887-
__FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
888-
889-
Status error;
890885
// If we locate debugserver, keep that located version around
891886
static FileSpec g_debugserver_file_spec;
892887

893-
char debugserver_path[PATH_MAX];
894-
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
895-
896888
Environment host_env = Host::GetEnvironment();
897889

898890
// Always check to see if we have an environment override for the path to the
@@ -943,8 +935,20 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
943935
}
944936
}
945937
}
938+
return debugserver_exists;
939+
}
946940

947-
if (debugserver_exists) {
941+
Status GDBRemoteCommunication::StartDebugserverProcess(
942+
const char *url, Platform *platform, ProcessLaunchInfo &launch_info,
943+
uint16_t *port, const Args *inferior_args, shared_fd_t pass_comm_fd) {
944+
Log *log = GetLog(GDBRLog::Process);
945+
LLDB_LOGF(log, "GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")",
946+
__FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
947+
948+
Status error;
949+
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
950+
if (GetDebugserverPath(platform, debugserver_file_spec)) {
951+
char debugserver_path[PATH_MAX];
948952
debugserver_file_spec.GetPath(debugserver_path, sizeof(debugserver_path));
949953

950954
Args &debugserver_args = launch_info.GetArguments();
@@ -959,16 +963,19 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
959963
#endif
960964

961965
// If a url is supplied then use it
962-
if (url)
966+
if (url && url[0])
963967
debugserver_args.AppendArgument(llvm::StringRef(url));
964968

965-
if (pass_comm_fd >= 0) {
969+
if (pass_comm_fd != SharedSocket::kInvalidFD) {
966970
StreamString fd_arg;
967-
fd_arg.Printf("--fd=%i", pass_comm_fd);
971+
fd_arg.Printf("--fd=%" PRIi64, (int64_t)pass_comm_fd);
968972
debugserver_args.AppendArgument(fd_arg.GetString());
969973
// Send "pass_comm_fd" down to the inferior so it can use it to
970-
// communicate back with this process
971-
launch_info.AppendDuplicateFileAction(pass_comm_fd, pass_comm_fd);
974+
// communicate back with this process. Ignored on Windows.
975+
#ifndef _WIN32
976+
launch_info.AppendDuplicateFileAction((int)pass_comm_fd,
977+
(int)pass_comm_fd);
978+
#endif
972979
}
973980

974981
// use native registers, not the GDB registers
@@ -988,7 +995,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
988995
// port is null when debug server should listen on domain socket - we're
989996
// not interested in port value but rather waiting for debug server to
990997
// become available.
991-
if (pass_comm_fd == -1) {
998+
if (pass_comm_fd == SharedSocket::kInvalidFD) {
992999
if (url) {
9931000
// Create a temporary file to get the stdout/stderr and redirect the output of
9941001
// the command into this file. We will later read this file if all goes well
@@ -1059,6 +1066,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
10591066
}
10601067
}
10611068
}
1069+
1070+
Environment host_env = Host::GetEnvironment();
10621071
std::string env_debugserver_log_file =
10631072
host_env.lookup("LLDB_DEBUGSERVER_LOG_FILE");
10641073
if (!env_debugserver_log_file.empty()) {
@@ -1132,7 +1141,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
11321141

11331142
if (error.Success() &&
11341143
(launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) &&
1135-
pass_comm_fd == -1) {
1144+
pass_comm_fd == SharedSocket::kInvalidFD) {
11361145
if (named_pipe_path.size() > 0) {
11371146
error = socket_pipe.OpenAsReader(named_pipe_path, false);
11381147
if (error.Fail())

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "lldb/Core/Communication.h"
2222
#include "lldb/Host/Config.h"
2323
#include "lldb/Host/HostThread.h"
24+
#include "lldb/Host/Socket.h"
2425
#include "lldb/Utility/Args.h"
2526
#include "lldb/Utility/Listener.h"
2627
#include "lldb/Utility/Predicate.h"
@@ -146,15 +147,18 @@ class GDBRemoteCommunication : public Communication {
146147

147148
std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
148149

150+
// Get the debugserver path and check that it exist.
151+
bool GetDebugserverPath(Platform *platform, FileSpec &debugserver_file_spec);
152+
149153
// Start a debugserver instance on the current host using the
150154
// supplied connection URL.
151155
Status StartDebugserverProcess(
152156
const char *url,
153157
Platform *platform, // If non nullptr, then check with the platform for
154158
// the GDB server binary if it can't be located
155159
ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
156-
int pass_comm_fd); // Communication file descriptor to pass during
157-
// fork/exec to avoid having to connect/accept
160+
shared_fd_t pass_comm_fd); // Communication file descriptor to pass during
161+
// fork/exec to avoid having to connect/accept
158162

159163
void DumpHistory(Stream &strm);
160164

0 commit comments

Comments
 (0)