summaryrefslogtreecommitdiffstats
path: root/lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp
diff options
context:
space:
mode:
authorTodd Fiala <todd.fiala@gmail.com>2014-07-26 20:39:17 +0000
committerTodd Fiala <todd.fiala@gmail.com>2014-07-26 20:39:17 +0000
commit31bde322f374582d7106f0c847b0ff3b6b6d705b (patch)
treee19a633d1e7fdd6eaf5d859adc0320e4073f6f9e /lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp
parent7b70cadae92a17b6d96cd180c96bb9e83e35d705 (diff)
downloadbcm5719-llvm-31bde322f374582d7106f0c847b0ff3b6b6d705b.tar.gz
bcm5719-llvm-31bde322f374582d7106f0c847b0ff3b6b6d705b.zip
llgs: add --reverse-connect support.
Also includes --reverse-connect tests for llgs and debugserver. llvm-svn: 214031
Diffstat (limited to 'lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp')
-rw-r--r--lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp137
1 files changed, 91 insertions, 46 deletions
diff --git a/lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp b/lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp
index db31d33f1b7..db6077a95b1 100644
--- a/lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp
+++ b/lldb/tools/lldb-gdbserver/lldb-gdbserver.cpp
@@ -53,9 +53,9 @@ using namespace lldb_private;
namespace
{
- static lldb::thread_t s_listen_thread = LLDB_INVALID_HOST_THREAD;
- static std::unique_ptr<ConnectionFileDescriptor> s_listen_connection_up;
- static std::string s_listen_url;
+ lldb::thread_t s_listen_thread = LLDB_INVALID_HOST_THREAD;
+ std::unique_ptr<ConnectionFileDescriptor> s_listen_connection_up;
+ std::string s_listen_url;
}
//----------------------------------------------------------------------
@@ -76,6 +76,7 @@ static struct option g_long_options[] =
{ "attach", required_argument, NULL, 'a' },
{ "named-pipe", required_argument, NULL, 'P' },
{ "native-regs", no_argument, NULL, 'r' }, // Specify to use the native registers instead of the gdb defaults for the architecture. NOTE: this is a do-nothing arg as it's behavior is default now. FIXME remove call from lldb-platform.
+ { "reverse-connect", no_argument, NULL, 'R' }, // Specifies that llgs attaches to the client address:port rather than llgs listening for a connection from address on port.
{ "setsid", no_argument, NULL, 'S' }, // Call setsid() to make llgs run in its own session.
{ NULL, 0, NULL, 0 }
};
@@ -322,16 +323,17 @@ JoinListenThread ()
}
void
-start_listener (GDBRemoteCommunicationServer &gdb_server, const char *const host_and_port, const char *const progname, const char *const named_pipe_path)
+ConnectToRemote (GDBRemoteCommunicationServer &gdb_server, bool reverse_connect, const char *const host_and_port, const char *const progname, const char *const named_pipe_path)
{
Error error;
if (host_and_port && host_and_port[0])
{
+ // Parse out host and port.
std::string final_host_and_port;
- std::string listening_host;
- std::string listening_port;
- uint32_t listening_portno = 0;
+ std::string connection_host;
+ std::string connection_port;
+ uint32_t connection_portno = 0;
// If host_and_port starts with ':', default the host to be "localhost" and expect the remainder to be the port.
if (host_and_port[0] == ':')
@@ -341,9 +343,9 @@ start_listener (GDBRemoteCommunicationServer &gdb_server, const char *const host
const std::string::size_type colon_pos = final_host_and_port.find (':');
if (colon_pos != std::string::npos)
{
- listening_host = final_host_and_port.substr (0, colon_pos);
- listening_port = final_host_and_port.substr (colon_pos + 1);
- listening_portno = Args::StringToUInt32 (listening_port.c_str (), 0);
+ connection_host = final_host_and_port.substr (0, colon_pos);
+ connection_port = final_host_and_port.substr (colon_pos + 1);
+ connection_portno = Args::StringToUInt32 (connection_port.c_str (), 0);
}
else
{
@@ -352,51 +354,89 @@ start_listener (GDBRemoteCommunicationServer &gdb_server, const char *const host
exit (1);
}
- // Start the listener on a new thread. We need to do this so we can resolve the
- // bound listener port.
- StartListenThread(listening_host.c_str (), static_cast<uint16_t> (listening_portno));
- printf ("Listening to port %s for a connection from %s...\n", listening_port.c_str (), listening_host.c_str ());
-
- // If we have a named pipe to write the port number back to, do that now.
- if (named_pipe_path && named_pipe_path[0] && listening_portno == 0)
+ if (reverse_connect)
{
- // FIXME use new generic named pipe support.
- int fd = ::open(named_pipe_path, O_WRONLY);
- if (fd > -1)
+ // llgs will connect to the gdb-remote client.
+
+ // Ensure we have a port number for the connection.
+ if (connection_portno == 0)
{
- const uint16_t bound_port = s_listen_connection_up->GetBoundPort (10);
+ fprintf (stderr, "error: port number must be specified on when using reverse connect");
+ exit (1);
+ }
- char port_str[64];
- const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", bound_port);
- // Write the port number as a C string with the NULL terminator.
- ::write (fd, port_str, port_str_len + 1);
- close (fd);
+ // Build the connection string.
+ char connection_url[512];
+ snprintf(connection_url, sizeof(connection_url), "connect://%s", final_host_and_port.c_str ());
+
+ // Create the connection.
+ std::unique_ptr<ConnectionFileDescriptor> connection_up (new ConnectionFileDescriptor ());
+ connection_up.reset (new ConnectionFileDescriptor ());
+ auto connection_result = connection_up->Connect (connection_url, &error);
+ if (connection_result != eConnectionStatusSuccess)
+ {
+ fprintf (stderr, "error: failed to connect to client at '%s' (connection status: %d)", connection_url, static_cast<int> (connection_result));
+ exit (-1);
}
- else
+ if (error.Fail ())
{
- fprintf (stderr, "failed to open named pipe '%s' for writing\n", named_pipe_path);
+ fprintf (stderr, "error: failed to connect to client at '%s': %s", connection_url, error.AsCString ());
+ exit (-1);
}
- }
- // Join the listener thread.
- if (!JoinListenThread ())
- {
- fprintf (stderr, "failed to join the listener thread\n");
- display_usage (progname);
- exit (1);
- }
-
- // Ensure we connected.
- if (s_listen_connection_up)
- {
+ // We're connected.
printf ("Connection established.\n");
- gdb_server.SetConnection (s_listen_connection_up.release());
+ gdb_server.SetConnection (connection_up.release());
}
else
{
- fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
- display_usage (progname);
- exit (1);
+ // llgs will listen for connections on the given port from the given address.
+ // Start the listener on a new thread. We need to do this so we can resolve the
+ // bound listener port.
+ StartListenThread(connection_host.c_str (), static_cast<uint16_t> (connection_portno));
+ printf ("Listening to port %s for a connection from %s...\n", connection_port.c_str (), connection_host.c_str ());
+
+ // If we have a named pipe to write the port number back to, do that now.
+ if (named_pipe_path && named_pipe_path[0] && connection_portno == 0)
+ {
+ // FIXME use new generic named pipe support.
+ int fd = ::open(named_pipe_path, O_WRONLY);
+ if (fd > -1)
+ {
+ const uint16_t bound_port = s_listen_connection_up->GetBoundPort (10);
+
+ char port_str[64];
+ const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", bound_port);
+ // Write the port number as a C string with the NULL terminator.
+ ::write (fd, port_str, port_str_len + 1);
+ close (fd);
+ }
+ else
+ {
+ fprintf (stderr, "failed to open named pipe '%s' for writing\n", named_pipe_path);
+ }
+ }
+
+ // Join the listener thread.
+ if (!JoinListenThread ())
+ {
+ fprintf (stderr, "failed to join the listener thread\n");
+ display_usage (progname);
+ exit (1);
+ }
+
+ // Ensure we connected.
+ if (s_listen_connection_up)
+ {
+ printf ("Connection established.\n");
+ gdb_server.SetConnection (s_listen_connection_up.release());
+ }
+ else
+ {
+ fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
+ display_usage (progname);
+ exit (1);
+ }
}
}
@@ -411,7 +451,7 @@ start_listener (GDBRemoteCommunicationServer &gdb_server, const char *const host
bool interrupt = false;
bool done = false;
- while (!interrupt && !done && (g_sighup_received_count < 1))
+ while (!interrupt && !done && (g_sighup_received_count < 2))
{
const GDBRemoteCommunication::PacketResult result = gdb_server.GetPacketAndSendResponse (TIMEOUT_USEC, error, interrupt, done);
if ((result != GDBRemoteCommunication::PacketResult::Success) &&
@@ -462,6 +502,7 @@ main (int argc, char *argv[])
std::string platform_name;
std::string attach_target;
std::string named_pipe_path;
+ bool reverse_connect = false;
initialize_lldb_gdbserver ();
@@ -547,6 +588,10 @@ main (int argc, char *argv[])
// Do nothing, native regs is the default these days
break;
+ case 'R':
+ reverse_connect = true;
+ break;
+
#ifndef _WIN32
case 'S':
// Put llgs into a new session. Terminals group processes
@@ -631,7 +676,7 @@ main (int argc, char *argv[])
// Print version info.
printf("%s-%s", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
- start_listener (gdb_server, host_and_port, progname, named_pipe_path.c_str ());
+ ConnectToRemote (gdb_server, reverse_connect, host_and_port, progname, named_pipe_path.c_str ());
terminate_lldb_gdbserver ();
OpenPOWER on IntegriCloud