diff options
| -rw-r--r-- | lldb/include/lldb/Interpreter/Args.h | 7 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/Process.h | 150 | ||||
| -rw-r--r-- | lldb/include/lldb/lldb-enumerations.h | 3 | ||||
| -rw-r--r-- | lldb/source/API/SBProcess.cpp | 16 | ||||
| -rw-r--r-- | lldb/source/API/SBTarget.cpp | 12 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectPlatform.cpp | 6 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectProcess.cpp | 337 | ||||
| -rw-r--r-- | lldb/source/Interpreter/Args.cpp | 38 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp | 10 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h | 10 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 59 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 10 | ||||
| -rw-r--r-- | lldb/source/Target/Process.cpp | 83 |
13 files changed, 424 insertions, 317 deletions
diff --git a/lldb/include/lldb/Interpreter/Args.h b/lldb/include/lldb/Interpreter/Args.h index ee0b65d2c2e..580ebafba8f 100644 --- a/lldb/include/lldb/Interpreter/Args.h +++ b/lldb/include/lldb/Interpreter/Args.h @@ -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. diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index b2e63c0c95d..325fc4dd857 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -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. diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 9c31daf179c..bf653922c70 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -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; //---------------------------------------------------------------------- diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index 7e04d5af159..4c415f5c1d9 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -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 { diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index d32215e274c..59863ed6f6d 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -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! diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index e868f27c32d..7c7762c60a7 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -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); } } diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index 615bf3ce7c2..2c8a0dd022d 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -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) + { + m_options.launch_info.GetArguments().AppendArguments (launch_args); + } + else { - if (process->GetRunArguments().GetArgumentCount() > 0) - launch_args = process->GetRunArguments(); + 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; - - if (m_options.in_new_tty) - launch_flags |= eLaunchFlagLaunchInTTY; + m_options.launch_info.GetFlags().Set (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()) + 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; - - 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; + 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); + } - // 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(); + 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; - 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 diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp index 592b0ef9a23..50b43b1678c 100644 --- a/lldb/source/Interpreter/Args.cpp +++ b/lldb/source/Interpreter/Args.cpp @@ -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) diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index d2d8dc6a1bd..df01e94cb14 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -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"); diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index 85ed7b3c73b..7ecd2fffef7 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -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); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 7f842c2ecc1..dbe81aea2ff 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -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; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index ed3aeb80d94..be0f95a7dc9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -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 (); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 671084de424..64fe399726d 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -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()) { |

