summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp22
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp76
-rw-r--r--lldb/tools/debugserver/source/debugserver.cpp47
5 files changed, 118 insertions, 33 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 14fe8773597..d194477b504 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -1091,7 +1091,8 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url,
Platform *platform,
ProcessLaunchInfo &launch_info,
uint16_t *port,
- const Args& inferior_args)
+ const Args* inferior_args,
+ int pass_comm_fd)
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
@@ -1171,6 +1172,16 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url,
if (url)
debugserver_args.AppendArgument(url);
+ if (pass_comm_fd >= 0)
+ {
+ StreamString fd_arg;
+ fd_arg.Printf("--fd=%i", pass_comm_fd);
+ debugserver_args.AppendArgument(fd_arg.GetData());
+ // 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);
+ }
+
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
@@ -1189,7 +1200,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url,
// 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 ((port != nullptr && *port == 0) || port == nullptr)
+ if (pass_comm_fd == -1 && ((port != nullptr && *port == 0) || port == nullptr))
{
if (url)
{
@@ -1304,10 +1315,10 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url,
}
} while (has_env_var);
- if (inferior_args.GetArgumentCount() > 0)
+ if (inferior_args && inferior_args->GetArgumentCount() > 0)
{
debugserver_args.AppendArgument ("--");
- debugserver_args.AppendArguments (inferior_args);
+ debugserver_args.AppendArguments (*inferior_args);
}
// Copy the current environment to the gdbserver/debugserver instance
@@ -1337,8 +1348,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url,
}
error = Host::LaunchProcess(launch_info);
- if (error.Success() &&
- launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ if (error.Success() && (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) && pass_comm_fd == -1)
{
if (named_pipe_path.size() > 0)
{
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 13325410e48..623f0d16653 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -162,7 +162,8 @@ public:
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 = Args());
+ const Args *inferior_args,
+ int 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 d6900c27293..1cac61277e7 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -149,7 +149,8 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args&
nullptr,
debugserver_launch_info,
port_ptr,
- args);
+ &args,
+ -1);
pid = debugserver_launch_info.GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 07ec61f2544..eb82dc1eba3 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -16,6 +16,7 @@
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
#endif
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -64,6 +65,7 @@
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/SystemRuntime.h"
+#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/PseudoTerminal.h"
// Project includes
@@ -3602,6 +3604,23 @@ ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
}
return error;
}
+#if defined (__APPLE__)
+#define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1
+#endif
+
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+static bool SetCloexecFlag(int fd)
+{
+#if defined(FD_CLOEXEC)
+ int flags = ::fcntl(fd, F_GETFD);
+ if (flags == -1)
+ return false;
+ return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
+#else
+ return false;
+#endif
+}
+#endif
Error
ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
@@ -3624,30 +3643,34 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
false);
debugserver_launch_info.SetUserID(process_info.GetUserID());
-#if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__))
- // On iOS, still do a local connection using a random port
- const char *hostname = "127.0.0.1";
- uint16_t port = get_random_port ();
-#else
- // Set hostname being NULL to do the reverse connect where debugserver
- // will bind to port zero and it will communicate back to us the port
- // that we will connect to
- const char *hostname = nullptr;
- uint16_t port = 0;
-#endif
- StreamString url_str;
- const char* url = nullptr;
- if (hostname != nullptr)
+ int communication_fd = -1;
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+ // Auto close the sockets we might open up unless everything goes OK. This
+ // helps us not leak file descriptors when things go wrong.
+ lldb_utility::CleanUp <int, int> our_socket(-1, -1, close);
+ lldb_utility::CleanUp <int, int> gdb_socket(-1, -1, close);
+
+ // Use a socketpair on Apple for now until other platforms can verify it
+ // works and is fast enough
{
- url_str.Printf("%s:%u", hostname, port);
- url = url_str.GetData();
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ our_socket.set(sockets[0]);
+ gdb_socket.set(sockets[1]);
}
- error = m_gdb_comm.StartDebugserverProcess (url,
- GetTarget().GetPlatform().get(),
- debugserver_launch_info,
- &port);
+ // Don't let any child processes inherit our communication socket
+ SetCloexecFlag(our_socket.get());
+ communication_fd = gdb_socket.get();
+#endif
+
+ error = m_gdb_comm.StartDebugserverProcess(nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, nullptr, nullptr, communication_fd);
if (error.Success ())
m_debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -3655,7 +3678,14 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+ // Our process spawned correctly, we can now set our connection to use our
+ // end of the socket pair
+ m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket.release(), true));
+#endif
StartAsyncThread ();
+ }
if (error.Fail())
{
@@ -3669,13 +3699,11 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
if (m_gdb_comm.IsConnected())
{
// Finish the connection process by doing the handshake without connecting (send NULL URL)
- ConnectToDebugserver (NULL);
+ ConnectToDebugserver(NULL);
}
else
{
- StreamString connect_url;
- connect_url.Printf("connect://%s:%u", hostname, port);
- error = ConnectToDebugserver (connect_url.GetString().c_str());
+ error.SetErrorString("connection failed");
}
}
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index a22f046771d..e9ddbf47faa 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -872,6 +872,7 @@ static struct option g_long_options[] =
{ "working-dir", required_argument, NULL, 'W' }, // The working directory that the inferior process should have (only if debugserver launches the process)
{ "platform", required_argument, NULL, 'p' }, // Put this executable into a remote platform mode
{ "unix-socket", required_argument, NULL, 'u' }, // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use
+ { "fd", required_argument, NULL, 'FDSC' }, // A file descriptor was passed to this process when spawned that is already open and ready for communication
{ "named-pipe", required_argument, NULL, 'P' },
{ "reverse-connect", no_argument, NULL, 'R' },
{ "env", required_argument, NULL, 'e' }, // When debugserver launches the process, set a single environment entry as specified by the option value ("./debugserver -e FOO=1 -e BAR=2 localhost:1234 -- /bin/ls")
@@ -949,6 +950,7 @@ main (int argc, char *argv[])
int ch;
int long_option_index = 0;
int debug = 0;
+ int communication_fd = -1;
std::string compile_options;
std::string waitfor_pid_name; // Wait for a process that starts with this name
std::string attach_pid_name;
@@ -1248,6 +1250,12 @@ main (int argc, char *argv[])
remote->Context().PushEnvironment(env_entry);
}
break;
+
+ case 'FDSC':
+ // File descriptor passed to this process during fork/exec and is already
+ // open and ready for communication.
+ communication_fd = atoi(optarg);
+ break;
}
}
@@ -1324,7 +1332,7 @@ main (int argc, char *argv[])
char str[PATH_MAX];
str[0] = '\0';
- if (g_lockdown_opt == 0 && g_applist_opt == 0)
+ if (g_lockdown_opt == 0 && g_applist_opt == 0 && communication_fd == -1)
{
// Make sure we at least have port
if (argc < 1)
@@ -1475,6 +1483,15 @@ main (int argc, char *argv[])
if (remote->Comm().OpenFile (str))
mode = eRNBRunLoopModeExit;
}
+ else if (communication_fd >= 0)
+ {
+ // We were passed a file descriptor to use during fork/exec that is already open
+ // in our process, so lets just use it!
+ if (remote->Comm().useFD(communication_fd))
+ mode = eRNBRunLoopModeExit;
+ else
+ remote->StartReadRemoteDataThread();
+ }
if (mode != eRNBRunLoopModeExit)
{
@@ -1600,6 +1617,16 @@ main (int argc, char *argv[])
if (remote->Comm().OpenFile (str))
mode = eRNBRunLoopModeExit;
}
+ else if (communication_fd >= 0)
+ {
+ // We were passed a file descriptor to use during fork/exec that is already open
+ // in our process, so lets just use it!
+ if (remote->Comm().useFD(communication_fd))
+ mode = eRNBRunLoopModeExit;
+ else
+ remote->StartReadRemoteDataThread();
+ }
+
if (mode != eRNBRunLoopModeExit)
RNBLogSTDOUT ("Waiting for debugger instructions for process %d.\n", attach_pid);
}
@@ -1625,6 +1652,15 @@ main (int argc, char *argv[])
if (remote->Comm().OpenFile (str))
mode = eRNBRunLoopModeExit;
}
+ else if (communication_fd >= 0)
+ {
+ // We were passed a file descriptor to use during fork/exec that is already open
+ // in our process, so lets just use it!
+ if (remote->Comm().useFD(communication_fd))
+ mode = eRNBRunLoopModeExit;
+ else
+ remote->StartReadRemoteDataThread();
+ }
if (mode != eRNBRunLoopModeExit)
{
@@ -1657,6 +1693,15 @@ main (int argc, char *argv[])
if (remote->Comm().OpenFile (str))
mode = eRNBRunLoopModeExit;
}
+ else if (communication_fd >= 0)
+ {
+ // We were passed a file descriptor to use during fork/exec that is already open
+ // in our process, so lets just use it!
+ if (remote->Comm().useFD(communication_fd))
+ mode = eRNBRunLoopModeExit;
+ else
+ remote->StartReadRemoteDataThread();
+ }
if (mode != eRNBRunLoopModeExit)
mode = RNBRunLoopPlatform (remote);
OpenPOWER on IntegriCloud