diff options
Diffstat (limited to 'lldb/tools/debugserver/source/debugserver.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/debugserver.cpp | 86 |
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] == '/') |