Modified all Process::Launch() calls to use a ProcessLaunchInfo structure

on internal only (public API hasn't changed) to simplify the paramter list
to the launch calls down into just one argument. Also all of the argument,
envronment and stdio things are now handled in a much more centralized fashion.

llvm-svn: 143656
This commit is contained in:
Greg Clayton
2011-11-03 21:22:33 +00:00
parent 9f01a0db7d
commit 982c9762a2
13 changed files with 424 additions and 317 deletions

View File

@@ -205,6 +205,10 @@ public:
void
AppendArguments (const Args &rhs);
void
AppendArguments (const char **argv);
//------------------------------------------------------------------
/// Insert the argument value at index \a idx to \a arg_cstr.
///
@@ -266,6 +270,9 @@ public:
void
SetArguments (int argc, const char **argv);
void
SetArguments (const char **argv);
//------------------------------------------------------------------
/// Shifts the first argument C string value of the array off the
/// argument array.

View File

@@ -300,7 +300,29 @@ public:
{
return m_executable;
}
void
SetExecutableFile (const FileSpec &exe_file, bool add_exe_file_as_first_arg)
{
if (exe_file)
{
m_executable = exe_file;
if (add_exe_file_as_first_arg)
{
m_arguments.Clear();
char filename[PATH_MAX];
if (exe_file.GetPath(filename, sizeof(filename)))
m_arguments.AppendArgument (filename);
}
}
else
{
m_executable.Clear();
if (add_exe_file_as_first_arg)
m_arguments.Clear();
}
}
const FileSpec &
GetExecutableFile () const
{
@@ -389,10 +411,15 @@ public:
}
void
SetArgumentsFromArgs (const Args& args,
bool first_arg_is_executable,
bool first_arg_is_executable_and_argument);
SetArguments (const Args& args,
bool first_arg_is_executable,
bool first_arg_is_executable_and_argument);
void
SetArguments (char const **argv,
bool first_arg_is_executable,
bool first_arg_is_executable_and_argument);
Args &
GetEnvironmentEntries ()
{
@@ -534,6 +561,14 @@ public:
class FileAction
{
public:
enum Action
{
eFileActionNone,
eFileActionClose,
eFileActionDuplicate,
eFileActionOpen
};
FileAction () :
m_action (eFileActionNone),
@@ -567,15 +602,33 @@ public:
Log *log,
Error& error);
protected:
enum Action
int
GetFD () const
{
eFileActionNone,
eFileActionClose,
eFileActionDuplicate,
eFileActionOpen
};
return m_fd;
}
Action
GetAction () const
{
return m_action;
}
int
GetActionArgument () const
{
return m_arg;
}
const char *
GetPath () const
{
if (m_path.empty())
return NULL;
return m_path.c_str();
}
protected:
Action m_action; // The action for this file
int m_fd; // An existing file descriptor
int m_arg; // oflag for eFileActionOpen*, dup_fd for eFileActionDuplicate
@@ -584,13 +637,45 @@ public:
ProcessLaunchInfo () :
ProcessInfo(),
m_flags (),
m_stdin_info (),
m_stdout_info (),
m_stderr_info ()
m_flags ()
{
}
ProcessLaunchInfo (const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_directory,
uint32_t launch_flags) :
ProcessInfo(),
m_flags (launch_flags)
{
if (stderr_path)
{
ProcessLaunchInfo::FileAction file_action;
const bool read = true;
const bool write = true;
if (file_action.Open(STDERR_FILENO, stderr_path, read, write))
AppendFileAction (file_action);
}
if (stdout_path)
{
ProcessLaunchInfo::FileAction file_action;
const bool read = false;
const bool write = true;
if (file_action.Open(STDOUT_FILENO, stdout_path, read, write))
AppendFileAction (file_action);
}
if (stdin_path)
{
ProcessLaunchInfo::FileAction file_action;
const bool read = true;
const bool write = false;
if (file_action.Open(STDIN_FILENO, stdin_path, read, write))
AppendFileAction (file_action);
}
if (working_directory)
SetWorkingDirectory(working_directory);
}
void
AppendFileAction (const FileAction &info)
{
@@ -643,6 +728,17 @@ public:
return NULL;
}
const FileAction *
GetFileActionForFD (int fd) const
{
for (uint32_t idx=0, count=m_file_actions.size(); idx < count; ++idx)
{
if (m_file_actions[idx].GetFD () == fd)
return &m_file_actions[idx];
}
return NULL;
}
Flags &
GetFlags ()
{
@@ -703,9 +799,6 @@ public:
m_working_dir.clear();
m_plugin_name.clear();
m_flags.Clear();
m_stdin_info.Clear();
m_stdout_info.Clear();
m_stderr_info.Clear();
m_file_actions.clear();
}
@@ -713,9 +806,6 @@ protected:
std::string m_working_dir;
std::string m_plugin_name;
Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags
FileAction m_stdin_info; // File action for stdin
FileAction m_stdout_info; // File action for stdout
FileAction m_stderr_info; // File action for stderr
std::vector<FileAction> m_file_actions; // File actions for any other files
};
@@ -1316,13 +1406,7 @@ public:
/// the error object is success.
//------------------------------------------------------------------
virtual Error
Launch (char const *argv[],
char const *envp[],
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_directory);
Launch (const ProcessLaunchInfo &launch_info);
//------------------------------------------------------------------
/// Attach to an existing process using a process ID.
@@ -1688,14 +1772,8 @@ public:
/// launching fails.
//------------------------------------------------------------------
virtual Error
DoLaunch (Module* module,
char const *argv[],
char const *envp[],
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_directory) = 0;
DoLaunch (Module *exe_module,
const ProcessLaunchInfo &launch_info) = 0;
//------------------------------------------------------------------
/// Called after launching a process.

View File

@@ -44,7 +44,8 @@ namespace lldb {
eLaunchFlagStopAtEntry = (1u << 2), ///< Stop at the program entry point instead of auto-continuing when launching or attaching at entry point
eLaunchFlagDisableASLR = (1u << 3), ///< Disable Address Space Layout Randomization
eLaunchFlagDisableSTDIO = (1u << 4), ///< Disable stdio for inferior process (e.g. for a GUI app)
eLaunchFlagLaunchInTTY = (1u << 5) ///< Launch the process in a new TTY if supported by the host
eLaunchFlagLaunchInTTY = (1u << 5), ///< Launch the process in a new TTY if supported by the host
eLaunchFlagLaunchInShell= (1u << 6) ///< Launch the process inside a shell to get shell expansion
} LaunchFlags;
//----------------------------------------------------------------------

View File

@@ -126,7 +126,21 @@ SBProcess::RemoteLaunch (char const **argv,
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
if (m_opaque_sp->GetState() == eStateConnected)
{
error.SetError (m_opaque_sp->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory));
if (stop_at_entry)
launch_flags |= eLaunchFlagStopAtEntry;
ProcessLaunchInfo launch_info (stdin_path,
stdout_path,
stderr_path,
working_directory,
launch_flags);
Module *exe_module = m_opaque_sp->GetTarget().GetExecutableModulePointer();
if (exe_module)
launch_info.SetExecutableFile(exe_module->GetFileSpec(), true);
if (argv)
launch_info.GetArguments().AppendArguments (argv);
if (envp)
launch_info.GetEnvironmentEntries ().SetArguments (envp);
error.SetError (m_opaque_sp->Launch (launch_info));
}
else
{

View File

@@ -231,7 +231,17 @@ SBTarget::Launch
if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO"))
launch_flags |= eLaunchFlagDisableSTDIO;
error.SetError (sb_process->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory));
ProcessLaunchInfo launch_info (stdin_path, stdout_path, stderr_path, working_directory, launch_flags);
Module *exe_module = m_opaque_sp->GetExecutableModulePointer();
if (exe_module)
launch_info.SetExecutableFile(exe_module->GetFileSpec(), true);
if (argv)
launch_info.GetArguments().AppendArguments (argv);
if (envp)
launch_info.GetEnvironmentEntries ().SetArguments (envp);
error.SetError (sb_process->Launch (launch_info));
if (error.Success())
{
// We we are stopping at the entry point, we can return now!

View File

@@ -400,9 +400,9 @@ public:
// We don't have any file yet, so the first argument is our
// executable, and the rest are program arguments
const bool first_arg_is_executable = true;
m_options.launch_info.SetArgumentsFromArgs (args,
first_arg_is_executable,
first_arg_is_executable);
m_options.launch_info.SetArguments (args,
first_arg_is_executable,
first_arg_is_executable);
}
}

View File

@@ -35,86 +35,86 @@ class CommandObjectProcessLaunch : public CommandObject
{
public:
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter)
{
// Keep default values of all options in one place: OptionParsingStarting ()
OptionParsingStarting ();
}
~CommandOptions ()
{
}
Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
switch (short_option)
{
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);
in_new_tty = true;
break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
stop_at_entry = false;
in_new_tty = false;
tty_name.clear();
stdin_path.clear();
stdout_path.clear();
stderr_path.clear();
plugin_name.clear();
working_dir.clear();
no_stdio = false;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
bool stop_at_entry;
bool in_new_tty;
bool no_stdio;
std::string tty_name;
std::string stderr_path;
std::string stdin_path;
std::string stdout_path;
std::string plugin_name;
std::string working_dir;
};
// class CommandOptions : public Options
// {
// public:
//
// CommandOptions (CommandInterpreter &interpreter) :
// Options(interpreter)
// {
// // Keep default values of all options in one place: OptionParsingStarting ()
// OptionParsingStarting ();
// }
//
// ~CommandOptions ()
// {
// }
//
// Error
// SetOptionValue (uint32_t option_idx, const char *option_arg)
// {
// Error error;
// char short_option = (char) m_getopt_table[option_idx].val;
//
// switch (short_option)
// {
// 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);
// in_new_tty = true;
// break;
// default:
// error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
// break;
//
// }
// return error;
// }
//
// void
// OptionParsingStarting ()
// {
// stop_at_entry = false;
// in_new_tty = false;
// tty_name.clear();
// stdin_path.clear();
// stdout_path.clear();
// stderr_path.clear();
// plugin_name.clear();
// working_dir.clear();
// no_stdio = false;
// }
//
// const OptionDefinition*
// GetDefinitions ()
// {
// return g_option_table;
// }
//
// // Options table: Required for subclasses of Options.
//
// static OptionDefinition g_option_table[];
//
// // Instance variables to hold the values for command options.
//
// bool stop_at_entry;
// bool in_new_tty;
// bool no_stdio;
// std::string tty_name;
// std::string stderr_path;
// std::string stdin_path;
// std::string stdout_path;
// std::string plugin_name;
// std::string working_dir;
//
// };
CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
CommandObject (interpreter,
@@ -171,8 +171,11 @@ public:
return false;
}
exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
exe_module->GetFileSpec().GetPath (filename, sizeof(filename));
const bool add_exe_file_as_first_arg = true;
m_options.launch_info.SetExecutableFile(exe_module->GetFileSpec(), add_exe_file_as_first_arg);
StateType state = eStateInvalid;
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process)
@@ -210,11 +213,7 @@ public:
if (state != eStateConnected)
{
const char *plugin_name;
if (!m_options.plugin_name.empty())
plugin_name = m_options.plugin_name.c_str();
else
plugin_name = NULL;
const char *plugin_name = m_options.launch_info.GetProcessPluginName();
process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
if (process == NULL)
@@ -225,99 +224,74 @@ public:
}
}
// If no launch args were given on the command line, then use any that
// might have been set using the "run-args" set variable.
if (launch_args.GetArgumentCount() == 0)
if (launch_args.GetArgumentCount() > 0)
{
if (process->GetRunArguments().GetArgumentCount() > 0)
launch_args = process->GetRunArguments();
m_options.launch_info.GetArguments().AppendArguments (launch_args);
}
else
{
const Args &process_args = process->GetRunArguments();
if (process_args.GetArgumentCount() > 0)
m_options.launch_info.GetArguments().AppendArguments (process_args);
}
if (m_options.in_new_tty)
if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
{
if (state == eStateConnected)
{
result.AppendWarning("launch in tty option is ignored when launching through a remote connection");
m_options.in_new_tty = false;
}
else
{
char exec_file_path[PATH_MAX];
if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
{
launch_args.InsertArgumentAtIndex(0, exec_file_path);
}
else
{
result.AppendError("invalid executable");
result.SetStatus (eReturnStatusFailed);
return false;
}
m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
}
}
Args environment;
process->GetEnvironmentAsArgs (environment);
uint32_t launch_flags = eLaunchFlagNone;
m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
if (process->GetDisableASLR())
launch_flags |= eLaunchFlagDisableASLR;
m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
if (m_options.in_new_tty)
launch_flags |= eLaunchFlagLaunchInTTY;
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())
if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY) == false &&
m_options.launch_info.GetNumFileActions() == 0)
{
// 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;
m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
const char *path;
path = process->GetStandardErrorPath();
if (path)
{
ProcessLaunchInfo::FileAction file_action;
const bool read = true;
const bool write = true;
if (file_action.Open(STDERR_FILENO, path, read, write))
m_options.launch_info.AppendFileAction (file_action);
}
path = process->GetStandardInputPath();
if (path)
{
ProcessLaunchInfo::FileAction file_action;
const bool read = true;
const bool write = false;
if (file_action.Open(STDIN_FILENO, path, read, write))
m_options.launch_info.AppendFileAction (file_action);
}
path = process->GetStandardOutputPath();
if (path)
{
ProcessLaunchInfo::FileAction file_action;
const bool read = false;
const bool write = true;
if (file_action.Open(STDOUT_FILENO, path, read, write))
m_options.launch_info.AppendFileAction (file_action);
}
}
Error error;
const char *working_dir = NULL;
if (!m_options.working_dir.empty())
working_dir = m_options.working_dir.c_str();
const char * stdin_path = NULL;
const char * stdout_path = NULL;
const char * stderr_path = NULL;
// Were any standard input/output/error paths given on the command line?
if (m_options.stdin_path.empty() &&
m_options.stdout_path.empty() &&
m_options.stderr_path.empty())
{
// No standard file handles were given on the command line, check
// with the process object in case they were give using "set settings"
stdin_path = process->GetStandardInputPath();
stdout_path = process->GetStandardOutputPath();
stderr_path = process->GetStandardErrorPath();
}
else
{
stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
}
error = process->Launch (inferior_argv,
inferior_envp,
launch_flags,
stdin_path,
stdout_path,
stderr_path,
working_dir);
error = process->Launch (m_options.launch_info);
if (error.Success())
{
@@ -325,7 +299,7 @@ public:
result.AppendMessageWithFormat ("Process %llu launched: '%s' (%s)\n", process->GetID(), filename, archname);
result.SetDidChangeProcessState (true);
if (m_options.stop_at_entry == false)
if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
StateType state = process->WaitForProcessToStop (NULL);
@@ -380,32 +354,31 @@ public:
}
protected:
CommandOptions m_options;
ProcessLaunchCommandOptions m_options;
};
#define SET1 LLDB_OPT_SET_1
#define SET2 LLDB_OPT_SET_2
#define SET3 LLDB_OPT_SET_3
OptionDefinition
CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
{
{ 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."},
{ 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 }
};
#undef SET1
#undef SET2
#undef SET3
//#define SET1 LLDB_OPT_SET_1
//#define SET2 LLDB_OPT_SET_2
//#define SET3 LLDB_OPT_SET_3
//
//OptionDefinition
//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
//{
//{ 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."},
//{ 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 }
//};
//
//#undef SET1
//#undef SET2
//#undef SET3
//-------------------------------------------------------------------------
// CommandObjectProcessAttach

View File

@@ -476,6 +476,16 @@ Args::AppendArguments (const Args &rhs)
AppendArgument(rhs.GetArgumentAtIndex(i));
}
void
Args::AppendArguments (const char **argv)
{
if (argv)
{
for (uint32_t i=0; argv[i]; ++i)
AppendArgument(argv[i]);
}
}
const char *
Args::AppendArgument (const char *arg_cstr, char quote_char)
{
@@ -560,10 +570,8 @@ Args::SetArguments (int argc, const char **argv)
m_args.clear();
m_args_quote_char.clear();
// Make a copy of the arguments in our internal buffer
size_t i;
// First copy each string
for (i=0; i<argc; ++i)
for (size_t i=0; i<argc; ++i)
{
m_args.push_back (argv[i]);
if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
@@ -575,6 +583,30 @@ Args::SetArguments (int argc, const char **argv)
UpdateArgvFromArgs();
}
void
Args::SetArguments (const char **argv)
{
// m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
// no need to clear it here.
m_args.clear();
m_args_quote_char.clear();
if (argv)
{
// First copy each string
for (size_t i=0; argv[i]; ++i)
{
m_args.push_back (argv[i]);
if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
m_args_quote_char.push_back (argv[i][0]);
else
m_args_quote_char.push_back ('\0');
}
}
UpdateArgvFromArgs();
}
Error
Args::ParseOptions (Options &options)

View File

@@ -230,14 +230,8 @@ ProcessKDP::DoConnectRemote (const char *remote_url)
// Process Control
//----------------------------------------------------------------------
Error
ProcessKDP::DoLaunch (Module* module,
char const *argv[],
char const *envp[],
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_dir)
ProcessKDP::DoLaunch (Module *exe_module,
const ProcessLaunchInfo &launch_info)
{
Error error;
error.SetErrorString ("launching not supported in kdp-remote plug-in");

View File

@@ -78,14 +78,8 @@ public:
WillLaunch (lldb_private::Module* module);
virtual lldb_private::Error
DoLaunch (lldb_private::Module* module,
char const *argv[], // Can be NULL
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 *working_dir); // Can be NULL
DoLaunch (lldb_private::Module *exe_module,
const lldb_private::ProcessLaunchInfo &launch_info);
virtual lldb_private::Error
WillAttachToProcessWithID (lldb::pid_t pid);

View File

@@ -437,25 +437,42 @@ ProcessGDBRemote::WillLaunchOrAttach ()
// Process Control
//----------------------------------------------------------------------
Error
ProcessGDBRemote::DoLaunch
(
Module* module,
char const *argv[],
char const *envp[],
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_dir
)
ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_info)
{
Error error;
uint32_t launch_flags = launch_info.GetFlags().Get();
const char *stdin_path = NULL;
const char *stdout_path = NULL;
const char *stderr_path = NULL;
const char *working_dir = launch_info.GetWorkingDirectory();
const ProcessLaunchInfo::FileAction *file_action;
file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
if (file_action)
{
if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
stdin_path = file_action->GetPath();
}
file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
if (file_action)
{
if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
stdout_path = file_action->GetPath();
}
file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
if (file_action)
{
if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
stderr_path = file_action->GetPath();
}
// ::LogSetBitMask (GDBR_LOG_DEFAULT);
// ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
// ::LogSetLogFile ("/dev/stdout");
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
ObjectFile * object_file = module->GetObjectFile();
ObjectFile * object_file = exe_module->GetObjectFile();
if (object_file)
{
char host_port[128];
@@ -537,18 +554,20 @@ ProcessGDBRemote::DoLaunch
}
// Send the environment and the program + arguments after we connect
if (envp)
const Args &environment = launch_info.GetEnvironmentEntries();
if (environment.GetArgumentCount())
{
const char *env_entry;
for (int i=0; (env_entry = envp[i]); ++i)
size_t num_environment_entries = environment.GetArgumentCount();
for (size_t i=0; i<num_environment_entries; ++i)
{
if (m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
const char *env_entry = environment.GetArgumentAtIndex(i);
if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
break;
}
}
const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (10);
int arg_packet_err = m_gdb_comm.SendArgumentsPacket (argv);
int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info.GetArguments().GetConstArgumentVector());
if (arg_packet_err == 0)
{
std::string error_str;
@@ -597,9 +616,9 @@ ProcessGDBRemote::DoLaunch
{
// Set our user ID to an invalid process ID.
SetID(LLDB_INVALID_PROCESS_ID);
error.SetErrorStringWithFormat("failed to get object file from '%s' for arch %s",
module->GetFileSpec().GetFilename().AsCString(),
module->GetArchitecture().GetArchitectureName());
error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s",
exe_module->GetFileSpec().GetFilename().AsCString(),
exe_module->GetArchitecture().GetArchitectureName());
}
return error;

View File

@@ -79,14 +79,8 @@ public:
WillLaunch (lldb_private::Module* module);
virtual lldb_private::Error
DoLaunch (lldb_private::Module* module,
char const *argv[], // Can be NULL
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 *working_dir); // Can be NULL
DoLaunch (lldb_private::Module *exe_module,
const lldb_private::ProcessLaunchInfo &launch_info);
virtual void
DidLaunch ();

View File

@@ -197,9 +197,35 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar
void
ProcessInfo::SetArgumentsFromArgs (const Args& args,
bool first_arg_is_executable,
bool first_arg_is_executable_and_argument)
ProcessInfo::SetArguments (char const **argv,
bool first_arg_is_executable,
bool first_arg_is_executable_and_argument)
{
m_arguments.SetArguments (argv);
// Is the first argument the executable?
if (first_arg_is_executable)
{
const char *first_arg = m_arguments.GetArgumentAtIndex (0);
if (first_arg)
{
// Yes the first argument is an executable, set it as the executable
// in the launch options. Don't resolve the file path as the path
// could be a remote platform path
const bool resolve = false;
m_executable.SetFile(first_arg, resolve);
// If argument zero is an executable and shouldn't be included
// in the arguments, remove it from the front of the arguments
if (first_arg_is_executable_and_argument == false)
m_arguments.DeleteArgumentAtIndex (0);
}
}
}
void
ProcessInfo::SetArguments (const Args& args,
bool first_arg_is_executable,
bool first_arg_is_executable_and_argument)
{
// Copy all arguments
m_arguments = args;
@@ -207,7 +233,7 @@ ProcessInfo::SetArgumentsFromArgs (const Args& args,
// Is the first argument the executable?
if (first_arg_is_executable)
{
const char *first_arg = args.GetArgumentAtIndex (0);
const char *first_arg = m_arguments.GetArgumentAtIndex (0);
if (first_arg)
{
// Yes the first argument is an executable, set it as the executable
@@ -415,6 +441,10 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
break;
case 'c':
launch_info.GetFlags().Set (eLaunchFlagLaunchInShell);
break;
case 'v':
launch_info.GetEnvironmentEntries().AppendArgument(option_arg);
break;
@@ -445,6 +475,7 @@ ProcessLaunchCommandOptions::g_option_table[] =
{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
{ LLDB_OPT_SET_4 , false, "shell", 'c', no_argument, NULL, 0, eArgTypeNone, "Run the process in a shell (not supported on all platforms)."},
{ 0 , false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -2037,16 +2068,7 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp)
}
Error
Process::Launch
(
char const *argv[],
char const *envp[],
uint32_t launch_flags,
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
const char *working_directory
)
Process::Launch (const ProcessLaunchInfo &launch_info)
{
Error error;
m_abi_sp.reset();
@@ -2070,40 +2092,9 @@ Process::Launch
if (error.Success())
{
SetPublicState (eStateLaunching);
// The args coming in should not contain the application name, the
// lldb_private::Process class will add this in case the executable
// gets resolved to a different file than was given on the command
// line (like when an applicaiton bundle is specified and will
// resolve to the contained exectuable file, or the file given was
// a symlink or other file system link that resolves to a different
// file).
// Get the resolved exectuable path
// Make a new argument vector
std::vector<const char *> exec_path_plus_argv;
// Append the resolved executable path
exec_path_plus_argv.push_back (platform_exec_file_path);
// Push all args if there are any
if (argv)
{
for (int i = 0; argv[i]; ++i)
exec_path_plus_argv.push_back(argv[i]);
}
// Push a NULL to terminate the args.
exec_path_plus_argv.push_back(NULL);
// Now launch using these arguments.
error = DoLaunch (exe_module,
exec_path_plus_argv.empty() ? NULL : &exec_path_plus_argv.front(),
envp,
launch_flags,
stdin_path,
stdout_path,
stderr_path,
working_directory);
error = DoLaunch (exe_module, launch_info);
if (error.Fail())
{