summaryrefslogtreecommitdiffstats
path: root/lldb/tools/debugserver/source/debugserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/tools/debugserver/source/debugserver.cpp')
-rw-r--r--lldb/tools/debugserver/source/debugserver.cpp86
1 files changed, 77 insertions, 9 deletions
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index 6e08d5dd8dc..12a873ef8e3 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -17,6 +17,12 @@
#include <string>
#include <vector>
#include <asl.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/un.h>
+#include <sys/types.h>
#include "CFString.h"
#include "DNB.h"
@@ -608,13 +614,68 @@ RNBRunLoopPlatform (RNBRemote *remote)
// Returns 1 for success 0 for failure.
//----------------------------------------------------------------------
+static void
+PortWasBoundCallback (const void *baton, in_port_t port)
+{
+ //::printf ("PortWasBoundCallback (baton = %p, port = %u)\n", baton, port);
+
+ const char *unix_socket_name = (const char *)baton;
+
+ if (unix_socket_name && unix_socket_name[0])
+ {
+ // We were given a unix socket name to use to communicate the port
+ // that we ended up binding to back to our parent process
+ struct sockaddr_un saddr_un;
+ int s = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ perror("error: socket (AF_UNIX, SOCK_STREAM, 0)");
+ exit(1);
+ }
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, unix_socket_name, sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+
+ if (::connect (s, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ {
+ perror("error: connect (socket, &saddr_un, saddr_un_len)");
+ exit(1);
+ }
+
+ //::printf ("connect () sucess!!\n");
+
+
+ // We were able to connect to the socket, now write our PID so whomever
+ // launched us will know this process's ID
+ RNBLogSTDOUT ("Listening to port %i...\n", port);
+
+ char pid_str[64];
+ const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%u", port);
+ const int bytes_sent = ::send (s, pid_str, pid_str_len, 0);
+
+ if (pid_str_len != bytes_sent)
+ {
+ perror("error: send (s, pid_str, pid_str_len, 0)");
+ exit (1);
+ }
+
+ //::printf ("send () sucess!!\n");
+
+ // We are done with the socket
+ close (s);
+ }
+}
+
static int
-StartListening (RNBRemote *remote, int listen_port)
+StartListening (RNBRemote *remote, int listen_port, const char *unix_socket_name)
{
if (!remote->Comm().IsConnected())
{
- RNBLogSTDOUT ("Listening to port %i...\n", listen_port);
- if (remote->Comm().Listen(listen_port) != rnb_success)
+ if (listen_port != 0)
+ RNBLogSTDOUT ("Listening to port %i...\n", listen_port);
+ if (remote->Comm().Listen(listen_port, PortWasBoundCallback, unix_socket_name) != rnb_success)
{
RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n");
return 0;
@@ -709,6 +770,7 @@ static struct option g_long_options[] =
{ "disable-aslr", no_argument, NULL, 'D' }, // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
{ "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
{ NULL, 0, NULL, 0 }
};
@@ -757,7 +819,8 @@ main (int argc, char *argv[])
std::string waitfor_pid_name; // Wait for a process that starts with this name
std::string attach_pid_name;
std::string arch_name;
- std::string working_dir; // The new working directory to use for the inferior
+ std::string working_dir; // The new working directory to use for the inferior
+ std::string unix_socket_name; // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use
useconds_t waitfor_interval = 1000; // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
useconds_t waitfor_duration = 0; // Time in seconds to wait for a process by name, 0 means wait forever.
bool no_stdio = false;
@@ -768,7 +831,7 @@ main (int argc, char *argv[])
RNBRunLoopMode start_mode = eRNBRunLoopModeExit;
- while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:n", g_long_options, &long_option_index)) != -1)
+ while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:nu:", g_long_options, &long_option_index)) != -1)
{
DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
ch, (uint8_t)ch,
@@ -967,6 +1030,11 @@ main (int argc, char *argv[])
case 'p':
start_mode = eRNBRunLoopModePlatformMode;
break;
+
+ case 'u':
+ unix_socket_name.assign (optarg);
+ break;
+
}
}
@@ -1171,7 +1239,7 @@ main (int argc, char *argv[])
#endif
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
@@ -1282,7 +1350,7 @@ main (int argc, char *argv[])
{
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
@@ -1307,7 +1375,7 @@ main (int argc, char *argv[])
{
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
@@ -1334,7 +1402,7 @@ main (int argc, char *argv[])
case eRNBRunLoopModePlatformMode:
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
OpenPOWER on IntegriCloud