summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBTarget.h16
-rw-r--r--lldb/include/lldb/Host/Host.h5
-rw-r--r--lldb/include/lldb/Target/Process.h12
-rw-r--r--lldb/source/API/SBTarget.cpp49
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp30
-rw-r--r--lldb/source/Core/UserSettingsController.cpp42
-rw-r--r--lldb/source/Host/common/Host.cpp1
-rw-r--r--lldb/source/Host/macosx/Host.mm10
-rw-r--r--lldb/source/Plugins/Process/Linux/ProcessLinux.cpp3
-rw-r--r--lldb/source/Plugins/Process/Linux/ProcessLinux.h3
-rw-r--r--lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp3
-rw-r--r--lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp91
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h8
-rw-r--r--lldb/source/Target/Process.cpp14
-rw-r--r--lldb/tools/darwin-debug/darwin-debug.cpp45
-rw-r--r--lldb/tools/debugserver/source/DNB.cpp17
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachProcess.cpp28
-rw-r--r--lldb/tools/debugserver/source/debugserver.cpp28
19 files changed, 296 insertions, 114 deletions
diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index bf9d8007351..8532150c9a6 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -55,16 +55,20 @@ public:
GetProcess ();
lldb::SBProcess
- LaunchProcess (char const **argv,
- char const **envp,
- const char *tty,
- uint32_t launch_flags, // See LaunchFlags
- bool stop_at_entry);
+ Launch (char const **argv,
+ char const **envp,
+ const char *tty,
+ uint32_t launch_flags, // See LaunchFlags
+ bool stop_at_entry,
+ lldb::SBError& error);
lldb::SBProcess
Launch (char const **argv,
char const **envp,
- const char *tty,
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ const char *working_directory,
uint32_t launch_flags, // See LaunchFlags
bool stop_at_entry,
lldb::SBError& error);
diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h
index 91cfee41b55..2b8d9abe756 100644
--- a/lldb/include/lldb/Host/Host.h
+++ b/lldb/include/lldb/Host/Host.h
@@ -329,8 +329,9 @@ public:
static lldb::pid_t
LaunchInNewTerminal (const char *tty_name, // Optional partial or full tty name ("/dev/ttys000" or "ttys000")
- const char **argv, // argv[0] is executable
- const char **envp,
+ const char **argv, // argv[0] is executable, argv[1] and on are the arguments
+ const char **envp,
+ const char *working_dir,
const ArchSpec *arch_spec,
bool stop_at_entry,
bool disable_aslr);
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 0076da13076..adefc33c1dc 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -540,6 +540,9 @@ public:
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
+ /// @param[in] working_directory
+ /// The working directory to have the child process run in
+ ///
/// @return
/// An error object. Call GetID() to get the process ID if
/// the error object is success.
@@ -550,7 +553,8 @@ public:
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path);
+ const char *stderr_path,
+ const char *working_directory);
//------------------------------------------------------------------
/// Attach to an existing process using a process ID.
@@ -950,6 +954,9 @@ public:
/// process. If all stdXX_path arguments are NULL, a pseudo
/// terminal will be used.
///
+ /// @param[in] working_directory
+ /// The working directory to have the child process run in
+ ///
/// @return
/// A new valid process ID, or LLDB_INVALID_PROCESS_ID if
/// launching fails.
@@ -961,7 +968,8 @@ public:
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path) = 0;
+ const char *stderr_path,
+ const char *working_directory) = 0;
//------------------------------------------------------------------
/// Called after launching a process.
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index b23262b0005..5247189e383 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -117,51 +117,48 @@ SBTarget::GetDebugger () const
}
SBProcess
-SBTarget::LaunchProcess
+SBTarget::Launch
(
char const **argv,
char const **envp,
const char *tty,
uint32_t launch_flags,
- bool stop_at_entry
+ bool stop_at_entry,
+ SBError &error
)
{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
- if (log)
- log->Printf ("SBTarget(%p)::LaunchProcess (argv=%p, envp=%p, tty=\"%s\", launch_flags=%d, stop_at_entry=%i)",
- m_opaque_sp.get(), argv, envp, tty, launch_flags, stop_at_entry);
-
- SBError sb_error;
- SBProcess sb_process = Launch (argv, envp, tty, launch_flags, stop_at_entry, sb_error);
-
- log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
- if (log)
- {
- log->Printf ("SBTarget(%p)::LaunchProcess (...) => SBProcess(%p)",
- m_opaque_sp.get(), sb_process.get());
- }
-
- return sb_process;
+ return Launch (argv, envp, tty, tty, tty, NULL, launch_flags, stop_at_entry, error);
}
SBProcess
-SBTarget::Launch
+SBTarget::Launch
(
char const **argv,
char const **envp,
- const char *tty,
- uint32_t launch_flags,
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ const char *working_directory,
+ uint32_t launch_flags, // See LaunchFlags
bool stop_at_entry,
- SBError &error
+ lldb::SBError& error
)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
- log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, tty=\"%s\", launch_flags=%d, stop_at_entry=%i, &error (%p))...",
- m_opaque_sp.get(), argv, envp, tty, launch_flags, stop_at_entry, error.get());
+ log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
+ m_opaque_sp.get(),
+ argv,
+ envp,
+ stdin_path ? stdin_path : "NULL",
+ stdout_path ? stdout_path : "NULL",
+ stderr_path ? stderr_path : "NULL",
+ working_directory ? working_directory : "NULL",
+ launch_flags,
+ stop_at_entry,
+ error.get());
}
SBProcess sb_process;
if (m_opaque_sp)
@@ -171,7 +168,7 @@ SBTarget::Launch
if (sb_process.IsValid())
{
- error.SetError (sb_process->Launch (argv, envp, launch_flags, tty, tty, tty));
+ error.SetError (sb_process->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory));
if (error.Success())
{
// We we are stopping at the entry point, we can return now!
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index c07de3ee6ae..5239b7bf2d6 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -57,12 +57,13 @@ public:
switch (short_option)
{
- case 's': stop_at_entry = true; break;
- case 'e': stderr_path = option_arg; break;
- case 'i': stdin_path = option_arg; break;
- case 'o': stdout_path = option_arg; break;
- case 'p': plugin_name = option_arg; break;
- case 'n': no_stdio = true; break;
+ case 's': stop_at_entry = true; break;
+ case 'e': stderr_path.assign (option_arg); break;
+ case 'i': stdin_path.assign (option_arg); break;
+ case 'o': stdout_path.assign (option_arg); break;
+ case 'p': plugin_name.assign (option_arg); break;
+ case 'n': no_stdio = true; break;
+ case 'w': working_dir.assign (option_arg); break;
case 't':
if (option_arg && option_arg[0])
tty_name.assign (option_arg);
@@ -87,6 +88,7 @@ public:
stdout_path.clear();
stderr_path.clear();
plugin_name.clear();
+ working_dir.clear();
no_stdio = false;
}
@@ -110,6 +112,7 @@ public:
std::string stdin_path;
std::string stdout_path;
std::string plugin_name;
+ std::string working_dir;
};
@@ -249,6 +252,9 @@ public:
const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Error error;
+ const char *working_dir = NULL;
+ if (!m_options.working_dir.empty())
+ working_dir = m_options.working_dir.c_str();
if (m_options.in_new_tty)
{
@@ -256,6 +262,7 @@ public:
lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
inferior_argv,
inferior_envp,
+ working_dir,
&exe_module->GetArchitecture(),
true,
process->GetDisableASLR());
@@ -287,19 +294,13 @@ public:
stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
}
- if (stdin_path == NULL)
- stdin_path = "/dev/null";
- if (stdout_path == NULL)
- stdout_path = "/dev/null";
- if (stderr_path == NULL)
- stderr_path = "/dev/null";
-
error = process->Launch (inferior_argv,
inferior_envp,
launch_flags,
stdin_path,
stdout_path,
- stderr_path);
+ stderr_path,
+ working_dir);
}
if (error.Success())
@@ -363,6 +364,7 @@ CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
{ SET2 , false, "tty", 't', optional_argument, NULL, 0, eArgTypePath, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
+{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/lldb/source/Core/UserSettingsController.cpp b/lldb/source/Core/UserSettingsController.cpp
index 6cd1f3ccfd8..ea7d84e9494 100644
--- a/lldb/source/Core/UserSettingsController.cpp
+++ b/lldb/source/Core/UserSettingsController.cpp
@@ -1946,9 +1946,17 @@ UserSettingsController::UpdateStringVariable (lldb::VarSetOperationType op,
Error &err)
{
if (op == lldb::eVarSetOperationAssign)
- string_var = new_value;
+ {
+ if (new_value && new_value[0])
+ string_var.assign (new_value);
+ else
+ string_var.clear();
+ }
else if (op == lldb::eVarSetOperationAppend)
- string_var.append (new_value);
+ {
+ if (new_value && new_value[0])
+ string_var.append (new_value);
+ }
else if (op == lldb::eVarSetOperationClear)
string_var.clear();
else
@@ -1964,19 +1972,25 @@ UserSettingsController::UpdateBooleanVariable (lldb::VarSetOperationType op,
if (op != lldb::eVarSetOperationAssign)
err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
+ if (new_value && new_value[0])
+ {
+ if ((::strcasecmp(new_value, "true") == 0) ||
+ (::strcasecmp(new_value, "yes") == 0) ||
+ (::strcasecmp(new_value, "on") == 0) ||
+ (::strcasecmp(new_value, "1") == 0))
+ bool_var = true;
+ else
+ if ((::strcasecmp(new_value, "false") == 0) ||
+ (::strcasecmp(new_value, "no") == 0) ||
+ (::strcasecmp(new_value, "off") == 0) ||
+ (::strcasecmp(new_value, "0") == 0))
+ bool_var = false;
+ else
+ err.SetErrorStringWithFormat ("Invalid boolean value '%s'\n", new_value);
+ }
+ else
+ err.SetErrorString ("Invalid value. Cannot perform update.\n");
- if ((new_value == NULL)
- || (new_value[0] == '\0'))
- err.SetErrorString ("Invalid value. Cannot perform update.\n");
-
- std::string bool_val_str (new_value);
-
- std::transform (bool_val_str.begin(), bool_val_str.end(), bool_val_str.begin(), ::tolower);
-
- if (bool_val_str == "true")
- bool_var = true;
- else if (bool_val_str == "false")
- bool_var = false;
}
void
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 5755aa72c6d..ce82694ca2b 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -907,6 +907,7 @@ Host::LaunchInNewTerminal
const char *tty_name,
const char **argv,
const char **envp,
+ const char *working_dir,
const ArchSpec *arch_spec,
bool stop_at_entry,
bool disable_aslr
diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm
index a76ec805c19..08aec38c3ec 100644
--- a/lldb/source/Host/macosx/Host.mm
+++ b/lldb/source/Host/macosx/Host.mm
@@ -226,6 +226,7 @@ LaunchInNewTerminalWithCommandFile
(
const char **argv,
const char **envp,
+ const char *working_dir,
const ArchSpec *arch_spec,
bool stop_at_entry,
bool disable_aslr
@@ -404,6 +405,7 @@ LaunchInNewTerminalWithAppleScript
const char *tty_name,
const char **argv,
const char **envp,
+ const char *working_dir,
const ArchSpec *arch_spec,
bool stop_at_entry,
bool disable_aslr
@@ -440,6 +442,9 @@ LaunchInNewTerminalWithAppleScript
if (arch_spec && arch_spec->IsValid())
command.Printf(" --arch=%s", arch_spec->AsCString());
+ if (working_dir)
+ command.Printf(" --working-dir '%s'", working_dir);
+
if (disable_aslr)
command.PutCString(" --disable-aslr");
@@ -520,15 +525,16 @@ Host::LaunchInNewTerminal
const char *tty_name,
const char **argv,
const char **envp,
+ const char *working_dir,
const ArchSpec *arch_spec,
bool stop_at_entry,
bool disable_aslr
)
{
#if defined (LLDB_HOST_USE_APPLESCRIPT)
- return LaunchInNewTerminalWithAppleScript (tty_name, argv, envp, arch_spec, stop_at_entry, disable_aslr);
+ return LaunchInNewTerminalWithAppleScript (tty_name, argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
#else
- return LaunchInNewTerminalWithCommandFile (argv, envp, arch_spec, stop_at_entry, disable_aslr);
+ return LaunchInNewTerminalWithCommandFile (argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
#endif
}
diff --git a/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp
index ecf8479ddde..fa5b5b70ec3 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp
@@ -122,7 +122,8 @@ ProcessLinux::DoLaunch(Module *module,
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path)
+ const char *stderr_path,
+ const char *working_directory)
{
Error error;
assert(m_monitor == NULL);
diff --git a/lldb/source/Plugins/Process/Linux/ProcessLinux.h b/lldb/source/Plugins/Process/Linux/ProcessLinux.h
index fbf14df1988..6fe05526647 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessLinux.h
+++ b/lldb/source/Plugins/Process/Linux/ProcessLinux.h
@@ -72,7 +72,8 @@ public:
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path);
+ const char *stderr_path,
+ const char *working_directory);
virtual void
DidLaunch();
diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
index c650f5bb622..9aebc8fdec6 100644
--- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
@@ -316,7 +316,8 @@ ProcessMacOSX::DoLaunch
uint32_t flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path
+ const char *stderr_path,
+ const char *working_dir
)
{
// ::LogSetBitMask (PD_LOG_DEFAULT);
diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
index 4f8bdb930b7..c3df2f3a2dc 100644
--- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
+++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
@@ -95,8 +95,9 @@ public:
char const *envp[], // Can be NULL
uint32_t launch_flags,
const char *stdin_path, // Can be NULL
- const char *stdout_path, // Can be NULL
- const char *stderr_path); // Can be NULL
+ const char *stdout_path, // Can be NULL
+ const char *stderr_path, // Can be NULL
+ const char *working_dir); // Can be NULL
virtual void
DidLaunch ();
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index fe4e06820fc..ffec00e6d6f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -375,7 +375,8 @@ ProcessGDBRemote::DoLaunch
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path
+ const char *stderr_path,
+ const char *working_dir
)
{
Error error;
@@ -400,7 +401,10 @@ ProcessGDBRemote::DoLaunch
error = StartDebugserverProcess (host_port,
argv,
envp,
- NULL, //stdin_path,
+ stdin_path,
+ stdout_path,
+ stderr_path,
+ working_dir,
launch_process,
LLDB_INVALID_PROCESS_ID,
NULL, false,
@@ -420,10 +424,14 @@ ProcessGDBRemote::DoLaunch
error = StartDebugserverProcess (host_port,
NULL,
NULL,
- NULL, //stdin_path
+ stdin_path,
+ stdout_path,
+ stderr_path,
+ working_dir,
launch_process,
LLDB_INVALID_PROCESS_ID,
- NULL, false,
+ NULL,
+ false,
launch_flags,
inferior_arch);
if (error.Fail())
@@ -644,6 +652,9 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
NULL, // inferior_argv
NULL, // inferior_envp
NULL, // stdin_path
+ NULL, // stdout_path
+ NULL, // stderr_path
+ NULL, // working_dir
false, // launch_process == false (we are attaching)
LLDB_INVALID_PROCESS_ID, // Don't send any attach to pid options to debugserver
NULL, // Don't send any attach by process name option to debugserver
@@ -746,6 +757,9 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
NULL, // inferior_argv
NULL, // inferior_envp
NULL, // stdin_path
+ NULL, // stdout_path
+ NULL, // stderr_path
+ NULL, // working_dir
false, // launch_process == false (we are attaching)
LLDB_INVALID_PROCESS_ID, // Don't send any attach to pid options to debugserver
NULL, // Don't send any attach by process name option to debugserver
@@ -1732,7 +1746,10 @@ ProcessGDBRemote::StartDebugserverProcess
const char *debugserver_url, // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
char const *inferior_argv[], // Arguments for the inferior program including the path to the inferior itself as the first argument
char const *inferior_envp[], // Environment to pass along to the inferior program
- char const *stdio_path,
+ const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ const char *working_dir,
bool launch_process, // Set to true if we are going to be launching a the process
lldb::pid_t attach_pid, // If inferior inferior_argv == NULL, and attach_pid != LLDB_INVALID_PROCESS_ID send this pid as an argument to debugserver
const char *attach_name, // Wait for the next process to launch whose basename matches "attach_name"
@@ -1824,7 +1841,13 @@ ProcessGDBRemote::StartDebugserverProcess
char arg_cstr[PATH_MAX];
lldb_utility::PseudoTerminal pty;
- if (launch_process && stdio_path == NULL && m_local_debugserver && !no_stdio)
+ const char *stdio_path = NULL;
+ if (launch_process &&
+ stdin_path == NULL &&
+ stdout_path == NULL &&
+ stderr_path == NULL &&
+ m_local_debugserver &&
+ no_stdio == false)
{
if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
stdio_path = pty.GetSlaveName (NULL, 0);
@@ -1843,14 +1866,60 @@ ProcessGDBRemote::StartDebugserverProcess
debugserver_args.AppendArguments("--disable-aslr");
// Only set the inferior
- if (launch_process && stdio_path)
+ if (launch_process)
{
- debugserver_args.AppendArgument("--stdio-path");
- debugserver_args.AppendArgument(stdio_path);
+ if (no_stdio)
+ debugserver_args.AppendArgument("--no-stdio");
+ else
+ {
+ if (stdin_path && stdout_path && stderr_path &&
+ strcmp(stdin_path, stdout_path) == 0 &&
+ strcmp(stdin_path, stderr_path) == 0)
+ {
+ stdio_path = stdin_path;
+ stdin_path = stdout_path = stderr_path = NULL;
+ }
+
+ if (stdio_path)
+ {
+ // All file handles to stdin, stdout, stderr are the same...
+ debugserver_args.AppendArgument("--stdio-path");
+ debugserver_args.AppendArgument(stdio_path);
+ }
+ else
+ {
+ if (stdin_path == NULL && (stdout_path || stderr_path))
+ stdin_path = "/dev/null";
+
+ if (stdout_path == NULL && (stdin_path || stderr_path))
+ stdout_path = "/dev/null";
+
+ if (stderr_path == NULL && (stdin_path || stdout_path))
+ stderr_path = "/dev/null";
+
+ if (stdin_path)
+ {
+ debugserver_args.AppendArgument("--stdin-path");
+ debugserver_args.AppendArgument(stdin_path);
+ }
+ if (stdout_path)
+ {
+ debugserver_args.AppendArgument("--stdout-path");
+ debugserver_args.AppendArgument(stdout_path);
+ }
+ if (stderr_path)
+ {
+ debugserver_args.AppendArgument("--stderr-path");
+ debugserver_args.AppendArgument(stderr_path);
+ }
+ }
+ }
}
- else if (launch_process && no_stdio)
+
+ if (working_dir)
{
- debugserver_args.AppendArgument("--no-stdio");
+ debugserver_args.AppendArgument("--working-dir");
+ debugserver_args.AppendArgument(working_dir);
}
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index d8a2cebbd33..8c8f1a8a9af 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -82,8 +82,9 @@ public:
char const *envp[], // Can be NULL
uint32_t flags,
const char *stdin_path, // Can be NULL
- const char *stdout_path, // Can be NULL
- const char *stderr_path); // Can be NULL
+ const char *stdout_path, // Can be NULL
+ const char *stderr_path, // Can be NULL
+ const char *working_dir); // Can be NULL
virtual void
DidLaunch ();
@@ -295,6 +296,9 @@ protected:
char const *inferior_argv[],
char const *inferior_envp[],
const char *stdin_path,
+ const char *stdout_path,
+ const char *stderr_path,
+ const char *working_dir,
bool launch_process, // Set to true if we are going to be launching a the process
lldb::pid_t attach_pid, // If inferior inferior_argv == NULL, then attach to this pid
const char *attach_pid_name, // Wait for the next process to launch whose basename matches "attach_wait_name"
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index c3b9dfbdd23..f0b79b99ff0 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -1456,7 +1456,8 @@ Process::Launch
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path
+ const char *stderr_path,
+ const char *working_directory
)
{
Error error;
@@ -1507,7 +1508,8 @@ Process::Launch
launch_flags,
stdin_path,
stdout_path,
- stderr_path);
+ stderr_path,
+ working_directory);
if (error.Fail())
{
@@ -3252,10 +3254,10 @@ Process::SettingsController::instance_settings_table[] =
{ "run-args", eSetVarTypeArray, NULL, NULL, false, false, "A list containing all the arguments to be passed to the executable when it is run." },
{ "env-vars", eSetVarTypeDictionary, NULL, NULL, false, false, "A list of all the environment variables to be passed to the executable's environment, and their values." },
{ "inherit-env", eSetVarTypeBoolean, "true", NULL, false, false, "Inherit the environment from the process that is running LLDB." },
- { "input-path", eSetVarTypeString, "/dev/stdin", NULL, false, false, "The file/path to be used by the executable program for reading its input." },
- { "output-path", eSetVarTypeString, "/dev/stdout", NULL, false, false, "The file/path to be used by the executable program for writing its output." },
- { "error-path", eSetVarTypeString, "/dev/stderr", NULL, false, false, "The file/path to be used by the executable program for writings its error messages." },
- { "plugin", eSetVarTypeEnum, NULL , g_plugins, false, false, "The plugin to be used to run the process." },
+ { "input-path", eSetVarTypeString, NULL, NULL, false, false, "The file/path to be used by the executable program for reading its input." },
+ { "output-path", eSetVarTypeString, NULL, NULL, false, false, "The file/path to be used by the executable program for writing its output." },
+ { "error-path", eSetVarTypeString, NULL, NULL, false, false, "The file/path to be used by the executable program for writings its error messages." },
+ { "plugin", eSetVarTypeEnum, NULL, g_plugins, false, false, "The plugin to be used to run the process." },
{ "disable-aslr", eSetVarTypeBoolean, "true", NULL, false, false, "Disable Address Space Layout Randomization (ASLR)" },
{ "disable-stdio", eSetVarTypeBoolean, "false", NULL, false, false, "Disable stdin/stdout for process (e.g. for a GUI application)" },
{ NULL, eSetVarTypeNone, NULL, NULL, false, false, NULL }
diff --git a/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp
index de9b270a18f..689c3864aff 100644
--- a/lldb/tools/darwin-debug/darwin-debug.cpp
+++ b/lldb/tools/darwin-debug/darwin-debug.cpp
@@ -30,8 +30,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/un.h>
#include <string>
@@ -50,6 +51,7 @@ static struct option g_long_options[] =
{ "help", no_argument, NULL, 'h' },
{ "setsid", no_argument, NULL, 's' },
{ "unix-socket", required_argument, NULL, 'u' },
+ { "working-dir", required_argument, NULL, 'w' },
{ NULL, 0, NULL, 0 }
};
@@ -62,7 +64,7 @@ usage()
" for debugging.\n"
"\n"
"SYNOPSIS\n"
-" darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
+" darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] [--working-dir=<PATH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
"\n"
"DESCRIPTION\n"
" darwin-debug will exec itself into a child process <PROGRAM> that is\n"
@@ -95,7 +97,13 @@ exit_with_errno (int err, const char *prefix)
}
pid_t
-posix_spawn_for_debug (char *const *argv, char *const *envp, cpu_type_t cpu_type, int disable_aslr)
+posix_spawn_for_debug
+(
+ char *const *argv,
+ char *const *envp,
+ const char *working_dir,
+ cpu_type_t cpu_type,
+ int disable_aslr)
{
pid_t pid = 0;
@@ -126,6 +134,15 @@ posix_spawn_for_debug (char *const *argv, char *const *envp, cpu_type_t cpu_type
size_t ocount = 0;
exit_with_errno (::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), "posix_spawnattr_setbinpref_np () error: ");
}
+
+ // I wish there was a posix_spawn flag to change the working directory of
+ // the inferior process we will spawn, but there currently isn't. If there
+ // ever is a better way to do this, we should use it. I would rather not
+ // manually fork, chdir in the child process, and then posix_spawn with exec
+ // as the whole reason for doing posix_spawn is to not hose anything up
+ // after the fork and prior to the exec...
+ if (working_dir)
+ ::chdir (working_dir);
exit_with_errno (::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), "posix_spawn() error: ");
@@ -157,6 +174,7 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
int disable_aslr = 0; // By default we disable ASLR
int pass_env = 1;
std::string unix_socket_name;
+ std::string working_dir;
while ((ch = getopt_long(argc, argv, "a:dehsu:?", g_long_options, NULL)) != -1)
{
switch (ch)
@@ -199,6 +217,16 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
unix_socket_name.assign (optarg);
break;
+ case 'w':
+ {
+ struct stat working_dir_stat;
+ if (stat (optarg, &working_dir_stat) == 0)
+ working_dir.assign (optarg);
+ else
+ ::fprintf(stderr, "warning: working directory doesn't exist: '%s'\n", optarg);
+ }
+ break;
+
case 'h':
case '?':
default:
@@ -254,7 +282,15 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
close (s);
system("clear");
- printf ("Launching '%s' for debug with %u arguments:\n", argv[0], argc);
+ if (working_dir.empty())
+ {
+ char cwd[PATH_MAX];
+ const char *cwd_ptr = getcwd(cwd, sizeof(cwd));
+ printf ("Launching '%s' in '%s' for debug with %u arguments:\n", argv[0], cwd_ptr, argc);
+ }
+ else
+ printf ("Launching '%s' in '%s' for debug with %u arguments:\n", argv[0], working_dir.c_str(), argc);
+
for (int i=0; i<argc; ++i)
printf ("argv[%u] = '%s'\n", i, argv[i]);
@@ -262,6 +298,7 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
// to debug.
posix_spawn_for_debug (argv,
pass_env ? envp : NULL,
+ working_dir.empty() ? NULL : working_dir.c_str(),
cpu_type,
disable_aslr);
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index 92cdf582039..fab4741ac10 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -185,8 +185,21 @@ DNBProcessLaunch (const char *path,
char *err_str,
size_t err_len)
{
- DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %zu) called...", __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr, err_str, err_len);
-
+ DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %zu) called...",
+ __FUNCTION__,
+ path,
+ argv,
+ envp,
+ working_directory,
+ stdin_path,
+ stdout_path,
+ stderr_path,
+ no_stdio,
+ launch_flavor,
+ disable_aslr,
+ err_str,
+ err_len);
+
if (err_str && err_len > 0)
err_str[0] = '\0';
struct stat path_stat;
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
index 8b4c61b433b..12c981bccb4 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
@@ -1625,7 +1625,16 @@ MachProcess::PosixSpawnChildForPTraceDebugging
{
posix_spawnattr_t attr;
short flags;
- DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, process )", __FUNCTION__, path, argv, envp);
+ DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, working_dir=%s, stdin=%s, stdout=%s stderr=%s, no-stdio=%i)",
+ __FUNCTION__,
+ path,
+ argv,
+ envp,
+ working_directory,
+ stdin_path,
+ stdout_path,
+ stderr_path,
+ no_stdio);
err.SetError( ::posix_spawnattr_init (&attr), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
@@ -1703,9 +1712,9 @@ MachProcess::PosixSpawnChildForPTraceDebugging
}
else
{
- int slave_fd_err = open (stderr_path ? stderr_path : "/dev/null", O_RDWR , 0);
- int slave_fd_in = open (stdin_path ? stdin_path : "/dev/null", O_RDONLY, 0);
- int slave_fd_out = open (stdout_path ? stdout_path : "/dev/null", O_WRONLY, 0);
+ int slave_fd_err = open (stderr_path ? stderr_path : "/dev/null", O_NOCTTY | O_CREAT | O_RDWR , 0640);
+ int slave_fd_in = open (stdin_path ? stdin_path : "/dev/null", O_NOCTTY | O_RDONLY);
+ int slave_fd_out = open (stdout_path ? stdout_path : "/dev/null", O_NOCTTY | O_CREAT | O_WRONLY , 0640);
err.SetError( ::posix_spawn_file_actions_adddup2(&file_actions, slave_fd_err, STDERR_FILENO), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
@@ -1719,12 +1728,23 @@ MachProcess::PosixSpawnChildForPTraceDebugging
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d, newfiledes = STDOUT_FILENO )", slave_fd_out);
}
+
+ // TODO: Verify if we can set the working directory back immediately
+ // after the posix_spawnp call without creating a race condition???
+ if (working_directory)
+ ::chdir (working_directory);
+
err.SetError( ::posix_spawnp (&pid, path, &file_actions, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, &file_actions, &attr, argv, envp);
}
else
{
+ // TODO: Verify if we can set the working directory back immediately
+ // after the posix_spawnp call without creating a race condition???
+ if (working_directory)
+ ::chdir (working_directory);
+
err.SetError( ::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, NULL, &attr, argv, envp);
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index 49f1f0c9f10..f3a4b69c5e6 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -651,14 +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 (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
+ { "stdio-path", required_argument, NULL, 's' }, // Set the STDIO path to be used when launching applications (STDIN, STDOUT and STDERR) (only if debugserver launches the process)
+ { "stdin-path", required_argument, NULL, 'I' }, // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
+ { "stdout-path", required_argument, NULL, 'O' }, // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
+ { "stderr-path", required_argument, NULL, 'E' }, // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
+ { "no-stdio", no_argument, NULL, 'n' }, // Do not set up any stdio (perhaps the program is a GUI program) (only if debugserver launches the process)
+ { "setsid", no_argument, NULL, 'S' }, // call setsid() to make debugserver run in its own session
{ "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
+ { "working-dir", required_argument, NULL, 'W' }, // The working directory that the inferior process should have (only if debugserver launches the process)
{ NULL, 0, NULL, 0 }
};
@@ -699,7 +699,7 @@ main (int argc, char *argv[])
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
+ std::string working_dir; // 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;
@@ -785,9 +785,9 @@ main (int argc, char *argv[])
}
break;
- case 'c':
+ case 'W':
if (optarg && optarg[0])
- working_directory.assign(optarg);
+ working_dir.assign(optarg);
break;
case 'x':
@@ -826,7 +826,7 @@ main (int argc, char *argv[])
else if (strcasecmp(optarg, "stderr") == 0)
log_file = stderr;
else
- log_file = fopen(optarg, "w+");
+ log_file = fopen(optarg, "w");
if (log_file == NULL)
{
@@ -938,11 +938,11 @@ main (int argc, char *argv[])
return -1;
}
- if (!working_directory.empty())
+ if (!working_dir.empty())
{
- if (remote->Context().SetWorkingDirectory (working_directory.c_str()) == false)
+ if (remote->Context().SetWorkingDirectory (working_dir.c_str()) == false)
{
- RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_directory.c_str());
+ RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_dir.c_str());
exit (8);
}
}
OpenPOWER on IntegriCloud