forked from OSchip/llvm-project
Add '-no-stdio' option to 'process launch' command, which causes the
inferior to be launched without setting up terminal stdin/stdout for it (leaving the lldb command line accessible while the program is executing). Also add a user settings variable, 'target.process.disable-stdio' to allow the user to set this globally rather than having to use the command option each time the process is launched. llvm-svn: 120825
This commit is contained in:
parent
6423c29e14
commit
f8da863196
|
@ -176,6 +176,18 @@ public:
|
|||
{
|
||||
m_disable_aslr = b;
|
||||
}
|
||||
|
||||
bool
|
||||
GetDisableSTDIO () const
|
||||
{
|
||||
return m_disable_stdio;
|
||||
}
|
||||
|
||||
void
|
||||
SetDisableSTDIO (bool b)
|
||||
{
|
||||
m_disable_stdio = b;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -207,7 +219,9 @@ protected:
|
|||
static const ConstString &
|
||||
DisableASLRVarName();
|
||||
|
||||
|
||||
static const ConstString &
|
||||
DisableSTDIOVarName ();
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map<std::string, std::string> dictionary;
|
||||
|
@ -218,6 +232,7 @@ private:
|
|||
std::string m_error_path;
|
||||
ProcessPlugins m_plugin;
|
||||
bool m_disable_aslr;
|
||||
bool m_disable_stdio;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ typedef enum StepType
|
|||
typedef enum LaunchFlags
|
||||
{
|
||||
eLaunchFlagNone = 0u,
|
||||
eLaunchFlagDisableASLR = (1u << 0) ///< Disable Address Space Layout Randomization
|
||||
eLaunchFlagDisableASLR = (1u << 0), ///< Disable Address Space Layout Randomization
|
||||
eLaunchFlagDisableSTDIO = (1u << 1) /// Disable stdio for inferior process (e.g. for a GUI app)
|
||||
} LaunchFlags;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
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 't':
|
||||
if (option_arg && option_arg[0])
|
||||
tty_name.assign (option_arg);
|
||||
|
@ -86,6 +87,7 @@ public:
|
|||
stdout_path.clear();
|
||||
stderr_path.clear();
|
||||
plugin_name.clear();
|
||||
no_stdio = false;
|
||||
}
|
||||
|
||||
const lldb::OptionDefinition*
|
||||
|
@ -102,6 +104,7 @@ public:
|
|||
|
||||
bool stop_at_entry;
|
||||
bool in_new_tty;
|
||||
bool no_stdio;
|
||||
std::string tty_name;
|
||||
std::string stderr_path;
|
||||
std::string stdin_path;
|
||||
|
@ -214,6 +217,18 @@ public:
|
|||
if (process->GetDisableASLR())
|
||||
launch_flags |= eLaunchFlagDisableASLR;
|
||||
|
||||
if (m_options.no_stdio)
|
||||
launch_flags |= eLaunchFlagDisableSTDIO;
|
||||
else if (!m_options.in_new_tty
|
||||
&& m_options.stdin_path.empty()
|
||||
&& m_options.stdout_path.empty()
|
||||
&& m_options.stderr_path.empty())
|
||||
{
|
||||
// Only use the settings value if the user hasn't specified any options that would override it.
|
||||
if (process->GetDisableSTDIO())
|
||||
launch_flags |= eLaunchFlagDisableSTDIO;
|
||||
}
|
||||
|
||||
const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
|
||||
const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
|
||||
|
||||
|
@ -320,21 +335,24 @@ protected:
|
|||
|
||||
#define SET1 LLDB_OPT_SET_1
|
||||
#define SET2 LLDB_OPT_SET_2
|
||||
#define SET3 LLDB_OPT_SET_3
|
||||
|
||||
lldb::OptionDefinition
|
||||
CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ SET1 | SET2, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
|
||||
{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
|
||||
{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
|
||||
{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
|
||||
{ SET1 | SET2, 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."},
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||
{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
|
||||
{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
|
||||
{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
|
||||
{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
|
||||
{ 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."},
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||
};
|
||||
|
||||
#undef SET1
|
||||
#undef SET2
|
||||
#undef SET3
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectProcessAttach
|
||||
|
|
|
@ -404,7 +404,7 @@ ProcessGDBRemote::DoLaunch
|
|||
launch_process,
|
||||
LLDB_INVALID_PROCESS_ID,
|
||||
NULL, false,
|
||||
(launch_flags & eLaunchFlagDisableASLR) != 0,
|
||||
launch_flags,
|
||||
inferior_arch);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
@ -424,7 +424,7 @@ ProcessGDBRemote::DoLaunch
|
|||
launch_process,
|
||||
LLDB_INVALID_PROCESS_ID,
|
||||
NULL, false,
|
||||
(launch_flags & eLaunchFlagDisableASLR) != 0,
|
||||
launch_flags,
|
||||
inferior_arch);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
@ -647,7 +647,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
|
|||
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
|
||||
false, // Don't send any attach wait_for_launch flag as an option to debugserver
|
||||
false, // disable_aslr
|
||||
0, // launch_flags
|
||||
arch_spec);
|
||||
|
||||
if (error.Fail())
|
||||
|
@ -749,7 +749,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
|
|||
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
|
||||
false, // Don't send any attach wait_for_launch flag as an option to debugserver
|
||||
false, // disable_aslr
|
||||
0, // launch_flags
|
||||
arch_spec);
|
||||
if (error.Fail())
|
||||
{
|
||||
|
@ -1659,11 +1659,13 @@ ProcessGDBRemote::StartDebugserverProcess
|
|||
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"
|
||||
bool wait_for_launch, // Wait for the process named "attach_name" to launch
|
||||
bool disable_aslr, // Disable ASLR
|
||||
uint32_t launch_flags, // Launch flags
|
||||
ArchSpec& inferior_arch // The arch of the inferior that we will launch
|
||||
)
|
||||
{
|
||||
Error error;
|
||||
bool disable_aslr = (launch_flags & eLaunchFlagDisableASLR) != 0;
|
||||
bool no_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
|
||||
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
|
||||
{
|
||||
// If we locate debugserver, keep that located version around
|
||||
|
@ -1744,7 +1746,7 @@ ProcessGDBRemote::StartDebugserverProcess
|
|||
char arg_cstr[PATH_MAX];
|
||||
|
||||
lldb_utility::PseudoTerminal pty;
|
||||
if (launch_process && stdio_path == NULL && m_local_debugserver)
|
||||
if (launch_process && stdio_path == NULL && m_local_debugserver && !no_stdio)
|
||||
{
|
||||
if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
|
||||
stdio_path = pty.GetSlaveName (NULL, 0);
|
||||
|
@ -1768,6 +1770,10 @@ ProcessGDBRemote::StartDebugserverProcess
|
|||
debugserver_args.AppendArgument("--stdio-path");
|
||||
debugserver_args.AppendArgument(stdio_path);
|
||||
}
|
||||
else if (launch_process && no_stdio)
|
||||
{
|
||||
debugserver_args.AppendArgument("--no-stdio");
|
||||
}
|
||||
|
||||
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
|
||||
if (env_debugserver_log_file)
|
||||
|
@ -1859,7 +1865,7 @@ ProcessGDBRemote::StartDebugserverProcess
|
|||
if (error.Fail() || log)
|
||||
error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", m_debugserver_pid, debugserver_path, NULL, &attr, inferior_argv, inferior_envp);
|
||||
|
||||
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
|
||||
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID && !no_stdio)
|
||||
{
|
||||
if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
|
||||
SetUpProcessInputReader (pty.ReleaseMasterFileDescriptor());
|
||||
|
|
|
@ -291,7 +291,7 @@ protected:
|
|||
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"
|
||||
bool wait_for_launch, // Wait for the process named "attach_wait_name" to launch
|
||||
bool disable_aslr, // Disable ASLR
|
||||
uint32_t launch_flags,
|
||||
lldb_private::ArchSpec& arch_spec);
|
||||
|
||||
void
|
||||
|
|
|
@ -2600,7 +2600,8 @@ ProcessInstanceSettings::ProcessInstanceSettings (UserSettingsController &owner,
|
|||
m_output_path (),
|
||||
m_error_path (),
|
||||
m_plugin (),
|
||||
m_disable_aslr (true)
|
||||
m_disable_aslr (true),
|
||||
m_disable_stdio (false)
|
||||
{
|
||||
// CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
|
||||
// until the vtables for ProcessInstanceSettings are properly set up, i.e. AFTER all the initializers.
|
||||
|
@ -2629,7 +2630,8 @@ ProcessInstanceSettings::ProcessInstanceSettings (const ProcessInstanceSettings
|
|||
m_output_path (rhs.m_output_path),
|
||||
m_error_path (rhs.m_error_path),
|
||||
m_plugin (rhs.m_plugin),
|
||||
m_disable_aslr (rhs.m_disable_aslr)
|
||||
m_disable_aslr (rhs.m_disable_aslr),
|
||||
m_disable_stdio (rhs.m_disable_stdio)
|
||||
{
|
||||
if (m_instance_name != InstanceSettings::GetDefaultName())
|
||||
{
|
||||
|
@ -2655,6 +2657,7 @@ ProcessInstanceSettings::operator= (const ProcessInstanceSettings &rhs)
|
|||
m_error_path = rhs.m_error_path;
|
||||
m_plugin = rhs.m_plugin;
|
||||
m_disable_aslr = rhs.m_disable_aslr;
|
||||
m_disable_stdio = rhs.m_disable_stdio;
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -2685,6 +2688,8 @@ ProcessInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_
|
|||
UserSettingsController::UpdateEnumVariable (entry.enum_values, (int *) &m_plugin, value, err);
|
||||
else if (var_name == DisableASLRVarName())
|
||||
UserSettingsController::UpdateBooleanVariable (op, m_disable_aslr, value, err);
|
||||
else if (var_name == DisableSTDIOVarName ())
|
||||
UserSettingsController::UpdateBooleanVariable (op, m_disable_stdio, value, err);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2703,6 +2708,7 @@ ProcessInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &n
|
|||
m_error_path = new_process_settings->m_error_path;
|
||||
m_plugin = new_process_settings->m_plugin;
|
||||
m_disable_aslr = new_process_settings->m_disable_aslr;
|
||||
m_disable_stdio = new_process_settings->m_disable_stdio;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2755,6 +2761,13 @@ ProcessInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
|
|||
else
|
||||
value.AppendString ("false");
|
||||
}
|
||||
else if (var_name == DisableSTDIOVarName())
|
||||
{
|
||||
if (m_disable_stdio)
|
||||
value.AppendString ("true");
|
||||
else
|
||||
value.AppendString ("false");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (err)
|
||||
|
@ -2834,6 +2847,13 @@ ProcessInstanceSettings::DisableASLRVarName ()
|
|||
return disable_aslr_var_name;
|
||||
}
|
||||
|
||||
const ConstString &
|
||||
ProcessInstanceSettings::DisableSTDIOVarName ()
|
||||
{
|
||||
static ConstString disable_stdio_var_name ("disable-stdio");
|
||||
|
||||
return disable_stdio_var_name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// SettingsController Variable Tables
|
||||
|
@ -2864,8 +2884,9 @@ Process::SettingsController::instance_settings_table[] =
|
|||
{ "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." },
|
||||
{ "disable-aslr", eSetVarTypeBoolean, "true", NULL, false, false, "Disable Address Space Layout Randomization (ASLR)" },
|
||||
{ "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, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ DNBProcessLaunch (const char *path,
|
|||
char const *argv[],
|
||||
const char *envp[],
|
||||
const char *stdio_path,
|
||||
bool no_stdio,
|
||||
nub_launch_flavor_t launch_flavor,
|
||||
int disable_aslr,
|
||||
char *err_str,
|
||||
|
@ -198,7 +199,7 @@ DNBProcessLaunch (const char *path,
|
|||
if (processSP.get())
|
||||
{
|
||||
DNBError launch_err;
|
||||
pid_t pid = processSP->LaunchForDebug(path, argv, envp, stdio_path, launch_flavor, disable_aslr, launch_err);
|
||||
pid_t pid = processSP->LaunchForDebug(path, argv, envp, stdio_path, no_stdio, launch_flavor, disable_aslr, launch_err);
|
||||
if (err_str)
|
||||
{
|
||||
*err_str = '\0';
|
||||
|
|
|
@ -33,7 +33,7 @@ nub_bool_t DNBSetArchitecture (const char *arch);
|
|||
//----------------------------------------------------------------------
|
||||
// Process control
|
||||
//----------------------------------------------------------------------
|
||||
nub_process_t DNBProcessLaunch (const char *path, char const *argv[], const char *envp[], const char *stdio_path, nub_launch_flavor_t launch_flavor, int disable_aslr, char *err_str, size_t err_len) DNB_EXPORT;
|
||||
nub_process_t DNBProcessLaunch (const char *path, char const *argv[], const char *envp[], const char *stdio_path, bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, char *err_str, size_t err_len) DNB_EXPORT;
|
||||
nub_process_t DNBProcessAttach (nub_process_t pid, struct timespec *timeout, char *err_str, size_t err_len) DNB_EXPORT;
|
||||
nub_process_t DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len) DNB_EXPORT;
|
||||
nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavor_t launch_flavor, struct timespec *timeout, useconds_t interval, char *err_str, size_t err_len, DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL) DNB_EXPORT;
|
||||
|
|
|
@ -1495,6 +1495,7 @@ MachProcess::LaunchForDebug
|
|||
char const *argv[],
|
||||
char const *envp[],
|
||||
const char *stdio_path,
|
||||
bool no_stdio,
|
||||
nub_launch_flavor_t launch_flavor,
|
||||
int disable_aslr,
|
||||
DNBError &launch_err
|
||||
|
@ -1519,7 +1520,8 @@ MachProcess::LaunchForDebug
|
|||
DNBArchProtocol::GetArchitecture (),
|
||||
argv,
|
||||
envp,
|
||||
stdio_path,
|
||||
stdio_path,
|
||||
no_stdio,
|
||||
this,
|
||||
disable_aslr,
|
||||
launch_err);
|
||||
|
@ -1533,7 +1535,7 @@ MachProcess::LaunchForDebug
|
|||
if (app_ext != NULL)
|
||||
{
|
||||
std::string app_bundle_path(path, app_ext + strlen(".app"));
|
||||
return SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, launch_err);
|
||||
return SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, launch_err);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1609,6 +1611,7 @@ MachProcess::PosixSpawnChildForPTraceDebugging
|
|||
char const *argv[],
|
||||
char const *envp[],
|
||||
const char *stdio_path,
|
||||
bool no_stdio,
|
||||
MachProcess* process,
|
||||
int disable_aslr,
|
||||
DNBError& err
|
||||
|
@ -1665,7 +1668,7 @@ MachProcess::PosixSpawnChildForPTraceDebugging
|
|||
pid_t pid = INVALID_NUB_PROCESS;
|
||||
if (file_actions_valid)
|
||||
{
|
||||
if (stdio_path == NULL)
|
||||
if (stdio_path == NULL && !no_stdio)
|
||||
{
|
||||
pty_error = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
|
||||
if (pty_error == PseudoTerminal::success)
|
||||
|
@ -1675,7 +1678,25 @@ MachProcess::PosixSpawnChildForPTraceDebugging
|
|||
stdio_path = "/dev/null";
|
||||
}
|
||||
|
||||
if (stdio_path != NULL)
|
||||
// if no_stdio, then do open file actions, opening /dev/null.
|
||||
if (no_stdio)
|
||||
{
|
||||
err.SetError( ::posix_spawn_file_actions_addopen (&file_actions, STDIN_FILENO, "/dev/null",
|
||||
O_RDONLY | O_NOCTTY, 0), DNBError::POSIX);
|
||||
if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS))
|
||||
err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDIN_FILENO, path=/dev/null)");
|
||||
|
||||
err.SetError( ::posix_spawn_file_actions_addopen (&file_actions, STDOUT_FILENO, "/dev/null",
|
||||
O_WRONLY | O_NOCTTY, 0), DNBError::POSIX);
|
||||
if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS))
|
||||
err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDOUT_FILENO, path=/dev/null)");
|
||||
|
||||
err.SetError( ::posix_spawn_file_actions_addopen (&file_actions, STDERR_FILENO, "/dev/null",
|
||||
O_RDWR | O_NOCTTY, 0), DNBError::POSIX);
|
||||
if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS))
|
||||
err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDERR_FILENO, path=/dev/null)");
|
||||
}
|
||||
else if (stdio_path != NULL)
|
||||
{
|
||||
int slave_fd_err = open (stdio_path, O_RDWR, 0);
|
||||
int slave_fd_in = open (stdio_path, O_RDONLY, 0);
|
||||
|
@ -1807,7 +1828,7 @@ MachProcess::ForkChildForPTraceDebugging
|
|||
#if defined (__arm__)
|
||||
|
||||
pid_t
|
||||
MachProcess::SBLaunchForDebug (const char *path, char const *argv[], char const *envp[], DNBError &launch_err)
|
||||
MachProcess::SBLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, DNBError &launch_err)
|
||||
{
|
||||
// Clear out and clean up from any current state
|
||||
Clear();
|
||||
|
@ -1816,7 +1837,7 @@ MachProcess::SBLaunchForDebug (const char *path, char const *argv[], char const
|
|||
|
||||
// Fork a child process for debugging
|
||||
SetState(eStateLaunching);
|
||||
m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, this, launch_err);
|
||||
m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, no_stdio, this, launch_err);
|
||||
if (m_pid != 0)
|
||||
{
|
||||
m_flags |= eMachProcessFlagsUsingSBS;
|
||||
|
@ -1892,7 +1913,7 @@ CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str)
|
|||
}
|
||||
|
||||
pid_t
|
||||
MachProcess::SBForkChildForPTraceDebugging (const char *app_bundle_path, char const *argv[], char const *envp[], MachProcess* process, DNBError &launch_err)
|
||||
MachProcess::SBForkChildForPTraceDebugging (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err)
|
||||
{
|
||||
DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, process);
|
||||
CFAllocatorRef alloc = kCFAllocatorDefault;
|
||||
|
@ -1961,18 +1982,21 @@ MachProcess::SBForkChildForPTraceDebugging (const char *app_bundle_path, char co
|
|||
CFString stdio_path;
|
||||
|
||||
PseudoTerminal pty;
|
||||
PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
|
||||
if (pty_err == PseudoTerminal::success)
|
||||
if (!no_stdio)
|
||||
{
|
||||
const char* slave_name = pty.SlaveName();
|
||||
DNBLogThreadedIf(LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name);
|
||||
if (slave_name && slave_name[0])
|
||||
PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY);
|
||||
if (pty_err == PseudoTerminal::success)
|
||||
{
|
||||
::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
stdio_path.SetFileSystemRepresentation (slave_name);
|
||||
const char* slave_name = pty.SlaveName();
|
||||
DNBLogThreadedIf(LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name);
|
||||
if (slave_name && slave_name[0])
|
||||
{
|
||||
::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
stdio_path.SetFileSystemRepresentation (slave_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (stdio_path.get() == NULL)
|
||||
{
|
||||
stdio_path.SetFileSystemRepresentation ("/dev/null");
|
||||
|
|
|
@ -46,16 +46,16 @@ public:
|
|||
// Child process control
|
||||
//----------------------------------------------------------------------
|
||||
pid_t AttachForDebug (pid_t pid, char *err_str, size_t err_len);
|
||||
pid_t LaunchForDebug (const char *path, char const *argv[], char const *envp[], const char *stdio_path, nub_launch_flavor_t launch_flavor, int disable_aslr, DNBError &err);
|
||||
pid_t LaunchForDebug (const char *path, char const *argv[], char const *envp[], const char *stdio_path, bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, DNBError &err);
|
||||
static pid_t ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err);
|
||||
static pid_t PosixSpawnChildForPTraceDebugging (const char *path, cpu_type_t cpu_type, char const *argv[], char const *envp[], const char *stdio_path, MachProcess* process, int disable_aslr, DNBError& err);
|
||||
static pid_t PosixSpawnChildForPTraceDebugging (const char *path, cpu_type_t cpu_type, char const *argv[], char const *envp[], const char *stdio_path, bool no_stdio, MachProcess* process, int disable_aslr, DNBError& err);
|
||||
nub_addr_t GetDYLDAllImageInfosAddress ();
|
||||
static const void * PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str);
|
||||
static void CleanupAfterAttach (const void *attach_token, bool success, DNBError &err_str);
|
||||
static nub_process_t CheckForProcess (const void *attach_token);
|
||||
#if defined (__arm__)
|
||||
pid_t SBLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], DNBError &launch_err);
|
||||
static pid_t SBForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &launch_err);
|
||||
pid_t SBLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, DNBError &launch_err);
|
||||
static pid_t SBForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err);
|
||||
#endif
|
||||
nub_addr_t LookupSymbol (const char *name, const char *shlib);
|
||||
void SetNameToAddressCallback (DNBCallbackNameToAddress callback, void *baton)
|
||||
|
|
|
@ -151,7 +151,7 @@ RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remoteSP)
|
|||
// or crash process state.
|
||||
//----------------------------------------------------------------------
|
||||
RNBRunLoopMode
|
||||
RNBRunLoopLaunchInferior (RNBRemoteSP &remote, const char *stdio_path)
|
||||
RNBRunLoopLaunchInferior (RNBRemoteSP &remote, const char *stdio_path, bool no_stdio)
|
||||
{
|
||||
RNBContext& ctx = remote->Context();
|
||||
|
||||
|
@ -209,6 +209,7 @@ RNBRunLoopLaunchInferior (RNBRemoteSP &remote, const char *stdio_path)
|
|||
&inferior_argv[0],
|
||||
&inferior_envp[0],
|
||||
stdio_path,
|
||||
no_stdio,
|
||||
launch_flavor,
|
||||
g_disable_aslr,
|
||||
launch_err_str,
|
||||
|
@ -656,6 +657,7 @@ static struct option g_long_options[] =
|
|||
{ "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
|
||||
{ "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
|
||||
{ NULL, 0, NULL, 0 }
|
||||
|
@ -698,6 +700,7 @@ main (int argc, char *argv[])
|
|||
std::string arch_name;
|
||||
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;
|
||||
|
||||
#if !defined (DNBLOG_ENABLED)
|
||||
compile_options += "(no-logging) ";
|
||||
|
@ -705,7 +708,7 @@ main (int argc, char *argv[])
|
|||
|
||||
RNBRunLoopMode start_mode = eRNBRunLoopModeExit;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:", g_long_options, &long_option_index)) != -1)
|
||||
while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:n", g_long_options, &long_option_index)) != -1)
|
||||
{
|
||||
DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
|
||||
ch, (uint8_t)ch,
|
||||
|
@ -856,6 +859,10 @@ main (int argc, char *argv[])
|
|||
stdio_path = optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
no_stdio = true;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
// Put debugserver into a new session. Terminals group processes
|
||||
// into sessions and when a special terminal key sequences
|
||||
|
@ -1208,7 +1215,7 @@ main (int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case eRNBRunLoopModeInferiorLaunching:
|
||||
mode = RNBRunLoopLaunchInferior (g_remoteSP, stdio_path.empty() ? NULL : stdio_path.c_str());
|
||||
mode = RNBRunLoopLaunchInferior (g_remoteSP, stdio_path.empty() ? NULL : stdio_path.c_str(), no_stdio);
|
||||
|
||||
if (mode == eRNBRunLoopModeInferiorExecuting)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue