Revert to getting a random port and sending that down to debugserver for iOS. The sandboxing is not letting debugserver reverse connect back to lldb.

<rdar://problem/15789865>

llvm-svn: 198963
This commit is contained in:
Greg Clayton 2014-01-10 22:24:11 +00:00
parent 9485dcfb1a
commit fda4fab505
4 changed files with 100 additions and 37 deletions

View File

@ -598,12 +598,12 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
}
Error
GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
uint16_t in_port,
lldb_private::ProcessLaunchInfo &launch_info,
uint16_t &port)
uint16_t &out_port)
{
port = 0;
out_port = in_port;
Error error;
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
@ -651,8 +651,17 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
debugserver_args.AppendArgument(debugserver_path);
// If a host and port is supplied then use it
if (host_and_port)
char host_and_port[128];
if (hostname)
{
snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
debugserver_args.AppendArgument(host_and_port);
}
else
{
host_and_port[0] = '\0';
}
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
// make debugserver run in its own session so signals generated by
@ -661,11 +670,17 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
char named_pipe_path[PATH_MAX];
if (host_and_port)
bool listen = false;
if (host_and_port[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"
if (in_port == 0)
{
// Binding to port zero, we need to figure out what port it ends up
// using using a named pipe...
FileSpec tmpdir_file_spec;
if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
{
@ -691,6 +706,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
named_pipe_path[0] = '\0';
}
else
{
listen = true;
}
}
else
{
named_pipe_path[0] = '\0';
@ -701,10 +721,10 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
return error;
ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
port = connection->GetBoundPort(3);
assert (port != 0);
out_port = connection->GetBoundPort(3);
assert (out_port != 0);
char port_cstr[32];
snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", port);
snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", out_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");
@ -746,10 +766,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *host_and_port,
error = name_pipe_file.Read(port_cstr, num_bytes);
assert (error.Success());
assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
port = Args::StringToUInt32(port_cstr, 0);
out_port = Args::StringToUInt32(port_cstr, 0);
name_pipe_file.Close();
}
Host::Unlink(named_pipe_path);
}
else if (listen)
{
}
else
{

View File

@ -121,9 +121,10 @@ public:
// supplied connection URL.
//------------------------------------------------------------------
lldb_private::Error
StartDebugserverProcess (const char *host_and_port,
StartDebugserverProcess (const char *hostname,
uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit
lldb_private::ProcessLaunchInfo &launch_info,
uint16_t &port);
uint16_t &out_port);
void
DumpHistory(lldb_private::Stream &strm);

View File

@ -841,18 +841,16 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
{
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
StreamString host_and_port;
if (hostname.empty())
hostname = "localhost";
host_and_port.Printf("%s:%u", hostname.c_str(), port);
const char *host_and_port_cstr = host_and_port.GetString().c_str();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
error = StartDebugserverProcess (host_and_port_cstr,
error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
port,
debugserver_launch_info,
port);

View File

@ -167,6 +167,34 @@ namespace {
} // anonymous namespace end
static bool rand_initialized = false;
// TODO Randomly assigning a port is unsafe. We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing
// it to debugserver.
#if defined (__APPLE__)
#define LOW_PORT (IPPORT_RESERVED)
#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
#else
#define LOW_PORT (1024u)
#define HIGH_PORT (49151u)
#endif
static inline uint16_t
get_random_port ()
{
if (!rand_initialized)
{
time_t seed = time(NULL);
rand_initialized = true;
srand(seed);
}
return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
}
lldb_private::ConstString
ProcessGDBRemote::GetPluginNameStatic()
{
@ -2514,7 +2542,6 @@ Error
ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
{
Error error;
uint16_t port = 0;
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
{
// If we locate debugserver, keep that located version around
@ -2524,7 +2551,20 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
debugserver_launch_info.SetUserID(process_info.GetUserID());
error = m_gdb_comm.StartDebugserverProcess (NULL,
#if defined (__APPLE__) && defined (__arm__)
// On iOS, still do a local connection using a random port
const char *hostname = "localhost";
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 = NULL;
uint16_t port = 0;
#endif
error = m_gdb_comm.StartDebugserverProcess (hostname,
port,
debugserver_launch_info,
port);
@ -2552,9 +2592,9 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
}
else
{
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://localhost:%u", port);
error = ConnectToDebugserver (connect_url);
StreamString connect_url;
connect_url.Printf("connect://%s:%u", hostname, port);
error = ConnectToDebugserver (connect_url.GetString().c_str());
}
}