summaryrefslogtreecommitdiffstats
path: root/lldb/tools/debugserver/source/debugserver.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2011-01-22 23:43:18 +0000
committerGreg Clayton <gclayton@apple.com>2011-01-22 23:43:18 +0000
commit6779606a7c4853a32b19439c65a808a7dd3cb3ae (patch)
tree86d2fd8d304faa2a9f376049c758c47b38de2f39 /lldb/tools/debugserver/source/debugserver.cpp
parent5a72fdb05b6474d02bc22444240d6b7fc7acb6fe (diff)
downloadbcm5719-llvm-6779606a7c4853a32b19439c65a808a7dd3cb3ae.tar.gz
bcm5719-llvm-6779606a7c4853a32b19439c65a808a7dd3cb3ae.zip
Fixed an issue in "SBError SBProcess::Destroy ()" where it wasn't properly
checking the validity of the shared pointer prior to using it. Fixed the GDB remote plug-in to once again watch for a reply from the "k" packet, and fixed the logic to make sure the thread requesting the kill and the async thread play nice (and very quickly) by synchronizing the packet sending and reply. I also tweaked some of the shut down packet ("k" kill, "D" detach, and the halt packet) to make sure they do the right thing. Fixed "StateType Process::WaitForProcessStopPrivate (...)" to correctly pass the timeout along to WaitForStateChangedEventsPrivate() and made the function behave correctly with respect to timing out. Added separate STDIN, STDOUT, and STDERR support to debugserver. Also added the start of being able to set the working directory for the inferior process. llvm-svn: 124049
Diffstat (limited to 'lldb/tools/debugserver/source/debugserver.cpp')
-rw-r--r--lldb/tools/debugserver/source/debugserver.cpp147
1 files changed, 91 insertions, 56 deletions
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index 6b08b1bf9c1..49f1f0c9f10 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -61,26 +61,18 @@ int g_isatty = 0;
#define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0)
//----------------------------------------------------------------------
-// Run Loop function prototypes
-//----------------------------------------------------------------------
-RNBRunLoopMode RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remote);
-RNBRunLoopMode RNBRunLoopInferiorExecuting (RNBRemoteSP &remote);
-
-
-//----------------------------------------------------------------------
// Get our program path and arguments from the remote connection.
// We will need to start up the remote connection without a PID, get the
// arguments, wait for the new process to finish launching and hit its
// entry point, and then return the run loop mode that should come next.
//----------------------------------------------------------------------
RNBRunLoopMode
-RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remoteSP)
+RNBRunLoopGetStartModeFromRemote (RNBRemote* remote)
{
std::string packet;
- if (remoteSP.get() != NULL)
+ if (remote)
{
- RNBRemote* remote = remoteSP.get();
RNBContext& ctx = remote->Context();
uint32_t event_mask = RNBContext::event_read_packet_available;
@@ -151,7 +143,7 @@ RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remoteSP)
// or crash process state.
//----------------------------------------------------------------------
RNBRunLoopMode
-RNBRunLoopLaunchInferior (RNBRemoteSP &remote, const char *stdio_path, bool no_stdio)
+RNBRunLoopLaunchInferior (RNBRemote *remote, const char *stdin_path, const char *stdout_path, const char *stderr_path, bool no_stdio)
{
RNBContext& ctx = remote->Context();
@@ -208,7 +200,10 @@ RNBRunLoopLaunchInferior (RNBRemoteSP &remote, const char *stdio_path, bool no_s
nub_process_t pid = DNBProcessLaunch (resolved_path,
&inferior_argv[0],
&inferior_envp[0],
- stdio_path,
+ ctx.GetWorkingDirectory(),
+ stdin_path,
+ stdout_path,
+ stderr_path,
no_stdio,
launch_flavor,
g_disable_aslr,
@@ -317,7 +312,7 @@ RNBRunLoopLaunchInferior (RNBRemoteSP &remote, const char *stdio_path, bool no_s
// or crash process state.
//----------------------------------------------------------------------
RNBRunLoopMode
-RNBRunLoopLaunchAttaching (RNBRemoteSP &remote, nub_process_t attach_pid, nub_process_t& pid)
+RNBRunLoopLaunchAttaching (RNBRemote *remote, nub_process_t attach_pid, nub_process_t& pid)
{
RNBContext& ctx = remote->Context();
@@ -381,7 +376,7 @@ signal_handler(int signo)
// Return the new run loop mode based off of the current process state
RNBRunLoopMode
-HandleProcessStateChange (RNBRemoteSP &remote, bool initialize)
+HandleProcessStateChange (RNBRemote *remote, bool initialize)
{
RNBContext& ctx = remote->Context();
nub_process_t pid = ctx.ProcessID();
@@ -460,7 +455,7 @@ HandleProcessStateChange (RNBRemoteSP &remote, bool initialize)
// makes the inferior run, we need to leave this function with a new state
// as the return code.
RNBRunLoopMode
-RNBRunLoopInferiorExecuting (RNBRemoteSP &remote)
+RNBRunLoopInferiorExecuting (RNBRemote *remote)
{
DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__);
RNBContext& ctx = remote->Context();
@@ -565,19 +560,19 @@ RNBRunLoopInferiorExecuting (RNBRemoteSP &remote)
//----------------------------------------------------------------------
static int
-StartListening (RNBRemoteSP remoteSP, int listen_port)
+StartListening (RNBRemote *remote, int listen_port)
{
- if (!remoteSP->Comm().IsConnected())
+ if (!remote->Comm().IsConnected())
{
RNBLogSTDOUT ("Listening to port %i...\n", listen_port);
- if (remoteSP->Comm().Listen(listen_port) != rnb_success)
+ if (remote->Comm().Listen(listen_port) != rnb_success)
{
RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n");
return 0;
}
else
{
- remoteSP->StartReadRemoteDataThread();
+ remote->StartReadRemoteDataThread();
}
}
return 1;
@@ -656,10 +651,14 @@ static struct option g_long_options[] =
{ "waitfor-interval", required_argument, NULL, 'i' }, // Time in usecs to wait between sampling the pid list when waiting for a process by name
{ "waitfor-duration", required_argument, NULL, 'd' }, // The time in seconds to wait for a process to show up by name
{ "native-regs", no_argument, NULL, 'r' }, // Specify to use the native registers instead of the gdb defaults for the architecture.
- { "stdio-path", required_argument, NULL, 's' }, // Set the STDIO path to be used when launching applications
+ { "stdio-path", required_argument, NULL, 's' }, // Set the STDIO path to be used when launching applications (STDIN, STDOUT and STDERR)
+ { "stdin-path", required_argument, NULL, 'I' }, // Set the STDIN path to be used when launching applications
+ { "stdout-path", required_argument, NULL, 'O' }, // Set the STDIN path to be used when launching applications
+ { "stderr-path", required_argument, NULL, 'E' }, // Set the STDIN path to be used when launching applications
{ "no-stdio", no_argument, NULL, 'n' }, // Do not set up any stdio (perhaps the program is a GUI program)
{ "setsid", no_argument, NULL, 'S' }, // call setsid() to make debugserver run in its own sessions
{ "disable-aslr", no_argument, NULL, 'D' }, // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
+ { "chdir", no_argument, NULL, 'c' }, // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
{ NULL, 0, NULL, 0 }
};
@@ -696,8 +695,11 @@ main (int argc, char *argv[])
std::string compile_options;
std::string waitfor_pid_name; // Wait for a process that starts with this name
std::string attach_pid_name;
- std::string stdio_path;
+ std::string stdin_path;
+ std::string stdout_path;
+ std::string stderr_path;
std::string arch_name;
+ std::string working_directory; // The new working directory to use for the inferior
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;
@@ -783,6 +785,11 @@ main (int argc, char *argv[])
}
break;
+ case 'c':
+ if (optarg && optarg[0])
+ working_directory.assign(optarg);
+ break;
+
case 'x':
if (optarg && optarg[0])
{
@@ -856,7 +863,21 @@ main (int argc, char *argv[])
break;
case 's':
- stdio_path = optarg;
+ stdin_path.assign(optarg);
+ stdout_path.assign(optarg);
+ stderr_path.assign(optarg);
+ break;
+
+ case 'I':
+ stdin_path.assign(optarg);
+ break;
+
+ case 'O':
+ stdout_path.assign(optarg);
+ break;
+
+ case 'E':
+ stderr_path.assign(optarg);
break;
case 'n':
@@ -910,7 +931,6 @@ main (int argc, char *argv[])
g_remoteSP.reset (new RNBRemote (use_native_registers, arch_name.c_str()));
-
RNBRemote *remote = g_remoteSP.get();
if (remote == NULL)
{
@@ -918,7 +938,16 @@ main (int argc, char *argv[])
return -1;
}
- g_remoteSP->Initialize();
+ if (!working_directory.empty())
+ {
+ if (remote->Context().SetWorkingDirectory (working_directory.c_str()) == false)
+ {
+ RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_directory.c_str());
+ exit (8);
+ }
+ }
+
+ remote->Initialize();
RNBContext& ctx = remote->Context();
@@ -1054,9 +1083,9 @@ main (int argc, char *argv[])
#if defined (__arm__)
if (g_lockdown_opt)
{
- if (!g_remoteSP->Comm().IsConnected())
+ if (!remote->Comm().IsConnected())
{
- if (g_remoteSP->Comm().ConnectToService () != rnb_success)
+ if (remote->Comm().ConnectToService () != rnb_success)
{
RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n");
mode = eRNBRunLoopModeExit;
@@ -1069,21 +1098,21 @@ main (int argc, char *argv[])
{
DNBLogDebug("Task list: %s", applist_plist.c_str());
- g_remoteSP->Comm().Write(applist_plist.c_str(), applist_plist.size());
+ remote->Comm().Write(applist_plist.c_str(), applist_plist.size());
// Issue a read that will never yield any data until the other side
// closes the socket so this process doesn't just exit and cause the
// socket to close prematurely on the other end and cause data loss.
std::string buf;
- g_remoteSP->Comm().Read(buf);
+ remote->Comm().Read(buf);
}
- g_remoteSP->Comm().Disconnect(false);
+ remote->Comm().Disconnect(false);
mode = eRNBRunLoopModeExit;
break;
}
else
{
// Start watching for remote packets
- g_remoteSP->StartReadRemoteDataThread();
+ remote->StartReadRemoteDataThread();
}
}
}
@@ -1091,19 +1120,19 @@ main (int argc, char *argv[])
#endif
if (listen_port != INT32_MAX)
{
- if (!StartListening (g_remoteSP, listen_port))
+ if (!StartListening (remote, listen_port))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
{
- if (g_remoteSP->Comm().OpenFile (str))
+ if (remote->Comm().OpenFile (str))
mode = eRNBRunLoopModeExit;
}
if (mode != eRNBRunLoopModeExit)
{
RNBLogSTDOUT ("Got a connection, waiting for process information for launching or attaching.\n");
- mode = RNBRunLoopGetStartModeFromRemote (g_remoteSP);
+ mode = RNBRunLoopGetStartModeFromRemote (remote);
}
break;
@@ -1157,7 +1186,7 @@ main (int argc, char *argv[])
RNBLogSTDOUT ("Attaching to process %i...\n", attach_pid);
nub_process_t attached_pid;
- mode = RNBRunLoopLaunchAttaching (g_remoteSP, attach_pid, attached_pid);
+ mode = RNBRunLoopLaunchAttaching (remote, attach_pid, attached_pid);
if (mode != eRNBRunLoopModeInferiorExecuting)
{
const char *error_str = remote->Context().LaunchStatus().AsString();
@@ -1201,12 +1230,12 @@ main (int argc, char *argv[])
{
if (listen_port != INT32_MAX)
{
- if (!StartListening (g_remoteSP, listen_port))
+ if (!StartListening (remote, listen_port))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
{
- if (g_remoteSP->Comm().OpenFile (str))
+ if (remote->Comm().OpenFile (str))
mode = eRNBRunLoopModeExit;
}
if (mode != eRNBRunLoopModeExit)
@@ -1215,33 +1244,39 @@ main (int argc, char *argv[])
break;
case eRNBRunLoopModeInferiorLaunching:
- mode = RNBRunLoopLaunchInferior (g_remoteSP, stdio_path.empty() ? NULL : stdio_path.c_str(), no_stdio);
-
- if (mode == eRNBRunLoopModeInferiorExecuting)
{
- if (listen_port != INT32_MAX)
+ mode = RNBRunLoopLaunchInferior (remote,
+ stdin_path.empty() ? NULL : stdin_path.c_str(),
+ stdout_path.empty() ? NULL : stdout_path.c_str(),
+ stderr_path.empty() ? NULL : stderr_path.c_str(),
+ no_stdio);
+
+ if (mode == eRNBRunLoopModeInferiorExecuting)
{
- if (!StartListening (g_remoteSP, listen_port))
- mode = eRNBRunLoopModeExit;
+ if (listen_port != INT32_MAX)
+ {
+ if (!StartListening (remote, listen_port))
+ mode = eRNBRunLoopModeExit;
+ }
+ else if (str[0] == '/')
+ {
+ if (remote->Comm().OpenFile (str))
+ mode = eRNBRunLoopModeExit;
+ }
+
+ if (mode != eRNBRunLoopModeExit)
+ RNBLogSTDOUT ("Got a connection, waiting for debugger instructions.\n");
}
- else if (str[0] == '/')
+ else
{
- if (g_remoteSP->Comm().OpenFile (str))
- mode = eRNBRunLoopModeExit;
+ const char *error_str = remote->Context().LaunchStatus().AsString();
+ RNBLogSTDERR ("error: failed to launch process %s: %s\n", argv[0], error_str ? error_str : "unknown error.");
}
-
- if (mode != eRNBRunLoopModeExit)
- RNBLogSTDOUT ("Got a connection, waiting for debugger instructions.\n");
- }
- else
- {
- const char *error_str = remote->Context().LaunchStatus().AsString();
- RNBLogSTDERR ("error: failed to launch process %s: %s\n", argv[0], error_str ? error_str : "unknown error.");
}
break;
case eRNBRunLoopModeInferiorExecuting:
- mode = RNBRunLoopInferiorExecuting(g_remoteSP);
+ mode = RNBRunLoopInferiorExecuting(remote);
break;
default:
@@ -1251,8 +1286,8 @@ main (int argc, char *argv[])
}
}
- g_remoteSP->StopReadRemoteDataThread ();
- g_remoteSP->Context().SetProcessID(INVALID_NUB_PROCESS);
+ remote->StopReadRemoteDataThread ();
+ remote->Context().SetProcessID(INVALID_NUB_PROCESS);
return 0;
}
OpenPOWER on IntegriCloud