summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp129
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h17
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp7
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp67
4 files changed, 163 insertions, 57 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d53347a2e38..04de58bcd4c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -17,6 +17,7 @@
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
@@ -144,7 +145,9 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
m_private_is_running (false),
m_history (512),
m_send_acks (true),
- m_is_platform (is_platform)
+ m_is_platform (is_platform),
+ m_listen_thread (LLDB_INVALID_HOST_THREAD),
+ m_listen_url ()
{
}
@@ -539,7 +542,56 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
}
Error
-GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
+GDBRemoteCommunication::StartListenThread (const char *hostname, in_port_t port)
+{
+ Error error;
+ if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ {
+ error.SetErrorString("listen thread already running");
+ }
+ else
+ {
+ char listen_url[512];
+ if (hostname && hostname[0])
+ snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname ? hostname : "localhost", port);
+ else
+ snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
+ m_listen_url = listen_url;
+ SetConnection(new ConnectionFileDescriptor());
+ m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error);
+ }
+ return error;
+}
+
+bool
+GDBRemoteCommunication::JoinListenThread ()
+{
+ if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ {
+ Host::ThreadJoin(m_listen_thread, NULL, NULL);
+ m_listen_thread = LLDB_INVALID_HOST_THREAD;
+ }
+ return true;
+}
+
+lldb::thread_result_t
+GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
+{
+ GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
+ Error error;
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection ();
+
+ if (connection)
+ {
+ // Do the listen on another thread so we can continue on...
+ if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess)
+ comm->SetConnection(NULL);
+ }
+ return NULL;
+}
+
+Error
+GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
lldb_private::ProcessLaunchInfo &launch_info,
uint16_t &port)
{
@@ -594,42 +646,69 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
// Start args with "debugserver /file/path -r --"
debugserver_args.AppendArgument(debugserver_path);
- debugserver_args.AppendArgument(debugserver_url);
+
+ // If a host and port is supplied then use it
+ if (host_and_port)
+ debugserver_args.AppendArgument(host_and_port);
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
// make debugserver run in its own session so signals generated by
// special terminal key sequences (^C) don't affect debugserver
debugserver_args.AppendArgument("--setsid");
-
+
char named_pipe_path[PATH_MAX];
-
- // Create a temporary file to get the stdout/stderr and redirect the
- // output of the command into this file. We will later read this file
- // if all goes well and fill the data into "command_output_ptr"
- FileSpec tmpdir_file_spec;
- if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
- {
- tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
- strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
- }
- else
- {
- strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
- }
- if (::mktemp (named_pipe_path))
+ if (host_and_port)
{
- if (::mkfifo(named_pipe_path, 0600) == 0)
+ // Create a temporary file to get the stdout/stderr and redirect the
+ // output of the command into this file. We will later read this file
+ // if all goes well and fill the data into "command_output_ptr"
+ FileSpec tmpdir_file_spec;
+ if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ {
+ tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
+ strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
+ }
+ else
+ {
+ strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
+ }
+
+ if (::mktemp (named_pipe_path))
{
- debugserver_args.AppendArgument("--named-pipe");
- debugserver_args.AppendArgument(named_pipe_path);
+ if (::mkfifo(named_pipe_path, 0600) == 0)
+ {
+ debugserver_args.AppendArgument("--named-pipe");
+ debugserver_args.AppendArgument(named_pipe_path);
+ }
+ else
+ named_pipe_path[0] = '\0';
}
else
named_pipe_path[0] = '\0';
}
else
+ {
named_pipe_path[0] = '\0';
+
+ // No host and port given, so lets listen on our end and make the debugserver
+ // connect to us..
+ error = StartListenThread ("localhost", 0);
+ if (error.Fail())
+ return error;
+
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
+ port = connection->GetBoundPort(3);
+ assert (port != 0);
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", port);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this process
+ debugserver_args.AppendArgument("--reverse-connect");
+ debugserver_args.AppendArgument(port_cstr);
+ }
+
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
if (env_debugserver_log_file)
{
@@ -669,7 +748,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
}
Host::Unlink(named_pipe_path);
}
-
+ else
+ {
+ // Make sure we actually connect with the debugserver...
+ JoinListenThread();
+ }
}
else
{
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 98e29e4a3ec..a21679e51dc 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -108,8 +108,8 @@ public:
// Start a debugserver instance on the current host using the
// supplied connection URL.
//------------------------------------------------------------------
- static lldb_private::Error
- StartDebugserverProcess (const char *connect_url,
+ lldb_private::Error
+ StartDebugserverProcess (const char *host_and_port,
lldb_private::ProcessLaunchInfo &launch_info,
uint16_t &port);
@@ -256,9 +256,22 @@ protected:
// a single process
+ lldb_private::Error
+ StartListenThread (const char *hostname = "localhost",
+ in_port_t port = 0);
+ bool
+ JoinListenThread ();
+
+ static lldb::thread_result_t
+ ListenThread (lldb::thread_arg_t arg);
private:
+
+ lldb::thread_t m_listen_thread;
+ std::string m_listen_url;
+
+
//------------------------------------------------------------------
// For GDBRemoteCommunication only
//------------------------------------------------------------------
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 56414e213b1..50cdd406008 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -812,9 +812,9 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
- error = GDBRemoteCommunication::StartDebugserverProcess (host_and_port_cstr,
- debugserver_launch_info,
- port);
+ error = StartDebugserverProcess (host_and_port_cstr,
+ debugserver_launch_info,
+ port);
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -1130,7 +1130,6 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe
mode_t mode = packet.GetHexMaxU32(false, 0600);
Error error;
int fd = ::open (path.c_str(), flags, mode);
- printf ("open('%s', flags=0x%x, mode=%o) fd = %i (%s)\n", path.c_str(), flags, mode, fd, fd == -1 ? strerror(errno) : "<success>");
const int save_errno = fd == -1 ? errno : 0;
StreamString response;
response.PutChar('F');
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 45278972ec1..c6dc6cff982 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -845,31 +845,35 @@ Error
ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
{
Error error;
- // Sleep and wait a bit for debugserver to start to listen...
- std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
- if (conn_ap.get())
+ // Only connect if we have a valid connect URL
+
+ if (connect_url && connect_url[0])
{
- const uint32_t max_retry_count = 50;
- uint32_t retry_count = 0;
- while (!m_gdb_comm.IsConnected())
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+ if (conn_ap.get())
{
- if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
- {
- m_gdb_comm.SetConnection (conn_ap.release());
- break;
- }
- else if (error.WasInterrupted())
+ const uint32_t max_retry_count = 50;
+ uint32_t retry_count = 0;
+ while (!m_gdb_comm.IsConnected())
{
- // If we were interrupted, don't keep retrying.
- break;
- }
-
- retry_count++;
-
- if (retry_count >= max_retry_count)
- break;
+ if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
+ {
+ m_gdb_comm.SetConnection (conn_ap.release());
+ break;
+ }
+ else if (error.WasInterrupted())
+ {
+ // If we were interrupted, don't keep retrying.
+ break;
+ }
+
+ retry_count++;
+
+ if (retry_count >= max_retry_count)
+ break;
- usleep (100000);
+ usleep (100000);
+ }
}
}
@@ -2501,9 +2505,9 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
debugserver_launch_info.SetUserID(process_info.GetUserID());
- error = GDBRemoteCommunication::StartDebugserverProcess ("localhost:0",
- debugserver_launch_info,
- port);
+ error = m_gdb_comm.StartDebugserverProcess (NULL,
+ debugserver_launch_info,
+ port);
if (error.Success ())
m_debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -2522,10 +2526,17 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
return error;
}
- char connect_url[128];
- snprintf (connect_url, sizeof(connect_url), "connect://localhost:%u", port);
-
- error = ConnectToDebugserver (connect_url);
+ if (m_gdb_comm.IsConnected())
+ {
+ // Finish the connection process by doing the handshake without connecting (send NULL URL)
+ ConnectToDebugserver (NULL);
+ }
+ else
+ {
+ char connect_url[128];
+ snprintf (connect_url, sizeof(connect_url), "connect://localhost:%u", port);
+ error = ConnectToDebugserver (connect_url);
+ }
}
return error;
OpenPOWER on IntegriCloud