Added a new class to Process.h: ProcessAttachInfo. This class contains enough
info for us to attach by pid, or by name and will also allow us to eventually
do a lot more powerful attaches. If you look at the options for the "platform
process list" command, there are many options which we should be able to
specify. This will allow us to do things like "attach to a process named 'tcsh'
that has a parent process ID of 123", or "attach to a process named 'x' which
has an effective user ID of 345".
I finished up the --shell implementation so that it can be used without the
--tty option in "process launch". The "--shell" option now can take an
optional argument which is the path to the shell to use (or a partial name
like "sh" which we will find using the current PATH environment variable).
Modified the Process::Attach to use the new ProcessAttachInfo as the sole
argument and centralized a lot of code that was in the "process attach"
Execute function so that everyone can take advantage of the powerful new
attach functionality.
llvm-svn: 144615
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 6ee9dbf..e70788e 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -251,7 +251,7 @@
}
void
-ProcessLaunchInfo::FinalizeFileActions (Target *target, Process *process)
+ProcessLaunchInfo::FinalizeFileActions (Target *target)
{
// If notthing was specified, then check the process for any default
// settings that were set with "settings set"
@@ -304,6 +304,87 @@
}
}
+
+bool
+ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, bool localhost)
+{
+ error.Clear();
+
+ if (GetFlags().Test (eLaunchFlagLaunchInShell))
+ {
+ const char *shell_executable = GetShell();
+ if (shell_executable)
+ {
+ char shell_resolved_path[PATH_MAX];
+
+ if (localhost)
+ {
+ FileSpec shell_filespec (shell_executable, true);
+
+ if (!shell_filespec.Exists())
+ {
+ // Resolve the path in case we just got "bash", "sh" or "tcsh"
+ if (!shell_filespec.ResolveExecutableLocation ())
+ {
+ error.SetErrorStringWithFormat("invalid shell path '%s'", shell_executable);
+ return false;
+ }
+ }
+ shell_filespec.GetPath (shell_resolved_path, sizeof(shell_resolved_path));
+ shell_executable = shell_resolved_path;
+ }
+
+ Args shell_arguments;
+ std::string safe_arg;
+ shell_arguments.AppendArgument (shell_executable);
+ StreamString shell_command;
+ shell_arguments.AppendArgument ("-c");
+ shell_command.PutCString ("exec");
+ if (GetArchitecture().IsValid())
+ {
+ shell_command.Printf(" /usr/bin/arch -arch %s", GetArchitecture().GetArchitectureName());
+ // Set the resume count to 2:
+ // 1 - stop in shell
+ // 2 - stop in /usr/bin/arch
+ // 3 - then we will stop in our program
+ SetResumeCount(2);
+ }
+ else
+ {
+ // Set the resume count to 1:
+ // 1 - stop in shell
+ // 2 - then we will stop in our program
+ SetResumeCount(1);
+ }
+
+ const char **argv = GetArguments().GetConstArgumentVector ();
+ if (argv)
+ {
+ for (size_t i=0; argv[i] != NULL; ++i)
+ {
+ const char *arg = Args::GetShellSafeArgument (argv[i], safe_arg);
+ shell_command.Printf(" %s", arg);
+ }
+ }
+ shell_arguments.AppendArgument (shell_command.GetString().c_str());
+
+ m_executable.SetFile(shell_executable, false);
+ m_arguments = shell_arguments;
+ return true;
+ }
+ else
+ {
+ error.SetErrorString ("invalid shell path");
+ }
+ }
+ else
+ {
+ error.SetErrorString ("not launching in shell");
+ }
+ return false;
+}
+
+
bool
ProcessLaunchInfo::FileAction::Open (int fd, const char *path, bool read, bool write)
{
@@ -312,11 +393,11 @@
m_action = eFileActionOpen;
m_fd = fd;
if (read && write)
- m_arg = O_RDWR;
+ m_arg = O_NOCTTY | O_CREAT | O_RDWR;
else if (read)
- m_arg = O_RDONLY;
+ m_arg = O_NOCTTY | O_RDONLY;
else
- m_arg = O_WRONLY;
+ m_arg = O_NOCTTY | O_CREAT | O_WRONLY;
m_path.assign (path);
return true;
}
@@ -404,8 +485,12 @@
else
{
int oflag = info->m_arg;
+
mode_t mode = 0;
+ if (oflag & O_CREAT)
+ mode = 0640;
+
error.SetError (::posix_spawn_file_actions_addopen (file_actions,
info->m_fd,
info->m_path.c_str(),
@@ -496,7 +581,10 @@
break;
case 'c':
- launch_info.GetFlags().Set (eLaunchFlagLaunchInShell);
+ if (option_arg && option_arg[0])
+ launch_info.SetShell (option_arg);
+ else
+ launch_info.SetShell ("/bin/bash");
break;
case 'v':
@@ -520,7 +608,7 @@
{ LLDB_OPT_SET_ALL, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
{ LLDB_OPT_SET_ALL, false, "arch", 'a', required_argument, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."},
{ LLDB_OPT_SET_ALL, false, "environment", 'v', required_argument, NULL, 0, eArgTypeNone, "Specify an environment variable name/value stirng (--environement NAME=VALUE). Can be specified multiple times for subsequent environment entries."},
-{ LLDB_OPT_SET_ALL, false, "shell", 'c', no_argument, NULL, 0, eArgTypeNone, "Run the process in a shell (not supported on all platforms)."},
+{ LLDB_OPT_SET_ALL, false, "shell", 'c', optional_argument, NULL, 0, eArgTypePath, "Run the process in a shell (not supported on all platforms)."},
{ LLDB_OPT_SET_1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
{ LLDB_OPT_SET_1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
@@ -2229,91 +2317,103 @@
}
Error
-Process::Attach (lldb::pid_t attach_pid, uint32_t exec_count)
+Process::Attach (ProcessAttachInfo &attach_info)
{
-
m_abi_sp.reset();
m_process_input_reader.reset();
-
m_dyld_ap.reset();
m_os_ap.reset();
-
- Error error (WillAttachToProcessWithID(attach_pid));
- if (error.Success())
- {
- SetPublicState (eStateAttaching);
-
- error = DoAttachToProcessWithID (attach_pid);
- if (error.Success())
- {
-
- SetNextEventAction(new Process::AttachCompletionHandler(this, exec_count));
- StartPrivateStateThread();
- }
- else
- {
- if (GetID() != LLDB_INVALID_PROCESS_ID)
- {
- SetID (LLDB_INVALID_PROCESS_ID);
- const char *error_string = error.AsCString();
- if (error_string == NULL)
- error_string = "attach failed";
-
- SetExitStatus(-1, error_string);
- }
- }
- }
- return error;
-}
-
-Error
-Process::Attach (const char *process_name, bool wait_for_launch)
-{
- m_abi_sp.reset();
- m_process_input_reader.reset();
- // Find the process and its architecture. Make sure it matches the architecture
- // of the current Target, and if not adjust it.
+ lldb::pid_t attach_pid = attach_info.GetProcessID();
Error error;
-
- if (!wait_for_launch)
+ if (attach_pid == LLDB_INVALID_PROCESS_ID)
{
- ProcessInstanceInfoList process_infos;
- PlatformSP platform_sp (m_target.GetPlatform ());
- assert (platform_sp.get());
+ char process_name[PATH_MAX];
- if (platform_sp)
+ if (attach_info.GetExecutableFile().GetPath (process_name, sizeof(process_name)))
{
- ProcessInstanceInfoMatch match_info;
- match_info.GetProcessInfo().SetName(process_name);
- match_info.SetNameMatchType (eNameMatchEquals);
- platform_sp->FindProcesses (match_info, process_infos);
- if (process_infos.GetSize() > 1)
+ const bool wait_for_launch = attach_info.GetWaitForLaunch();
+
+ if (wait_for_launch)
{
- error.SetErrorStringWithFormat ("more than one process named %s", process_name);
+ error = WillAttachToProcessWithName(process_name, wait_for_launch);
+ if (error.Success())
+ {
+ SetPublicState (eStateAttaching);
+ error = DoAttachToProcessWithName (process_name, wait_for_launch);
+ if (error.Fail())
+ {
+ if (GetID() != LLDB_INVALID_PROCESS_ID)
+ {
+ SetID (LLDB_INVALID_PROCESS_ID);
+ if (error.AsCString() == NULL)
+ error.SetErrorString("attach failed");
+
+ SetExitStatus(-1, error.AsCString());
+ }
+ }
+ else
+ {
+ SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount()));
+ StartPrivateStateThread();
+ }
+ return error;
+ }
}
- else if (process_infos.GetSize() == 0)
+ else
{
- error.SetErrorStringWithFormat ("could not find a process named %s", process_name);
+ ProcessInstanceInfoList process_infos;
+ PlatformSP platform_sp (m_target.GetPlatform ());
+
+ if (platform_sp)
+ {
+ ProcessInstanceInfoMatch match_info;
+ match_info.GetProcessInfo() = attach_info;
+ match_info.SetNameMatchType (eNameMatchEquals);
+ platform_sp->FindProcesses (match_info, process_infos);
+ const uint32_t num_matches = process_infos.GetSize();
+ if (num_matches == 1)
+ {
+ attach_pid = process_infos.GetProcessIDAtIndex(0);
+ // Fall through and attach using the above process ID
+ }
+ else
+ {
+ match_info.GetProcessInfo().GetExecutableFile().GetPath (process_name, sizeof(process_name));
+ if (num_matches > 1)
+ error.SetErrorStringWithFormat ("more than one process named %s", process_name);
+ else
+ error.SetErrorStringWithFormat ("could not find a process named %s", process_name);
+ }
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform, can't find processes by name");
+ return error;
+ }
}
}
else
- {
- error.SetErrorString ("invalid platform");
+ {
+ error.SetErrorString ("invalid process name");
}
}
-
- if (error.Success())
+
+ if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
- m_dyld_ap.reset();
- m_os_ap.reset();
-
- error = WillAttachToProcessWithName(process_name, wait_for_launch);
+ error = WillAttachToProcessWithID(attach_pid);
if (error.Success())
{
SetPublicState (eStateAttaching);
- error = DoAttachToProcessWithName (process_name, wait_for_launch);
- if (error.Fail())
+
+ error = DoAttachToProcessWithID (attach_pid);
+ if (error.Success())
+ {
+
+ SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount()));
+ StartPrivateStateThread();
+ }
+ else
{
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
@@ -2325,16 +2425,80 @@
SetExitStatus(-1, error_string);
}
}
- else
- {
- SetNextEventAction(new Process::AttachCompletionHandler(this, 0));
- StartPrivateStateThread();
- }
}
}
return error;
}
+//Error
+//Process::Attach (const char *process_name, bool wait_for_launch)
+//{
+// m_abi_sp.reset();
+// m_process_input_reader.reset();
+//
+// // Find the process and its architecture. Make sure it matches the architecture
+// // of the current Target, and if not adjust it.
+// Error error;
+//
+// if (!wait_for_launch)
+// {
+// ProcessInstanceInfoList process_infos;
+// PlatformSP platform_sp (m_target.GetPlatform ());
+// assert (platform_sp.get());
+//
+// if (platform_sp)
+// {
+// ProcessInstanceInfoMatch match_info;
+// match_info.GetProcessInfo().SetName(process_name);
+// match_info.SetNameMatchType (eNameMatchEquals);
+// platform_sp->FindProcesses (match_info, process_infos);
+// if (process_infos.GetSize() > 1)
+// {
+// error.SetErrorStringWithFormat ("more than one process named %s", process_name);
+// }
+// else if (process_infos.GetSize() == 0)
+// {
+// error.SetErrorStringWithFormat ("could not find a process named %s", process_name);
+// }
+// }
+// else
+// {
+// error.SetErrorString ("invalid platform");
+// }
+// }
+//
+// if (error.Success())
+// {
+// m_dyld_ap.reset();
+// m_os_ap.reset();
+//
+// error = WillAttachToProcessWithName(process_name, wait_for_launch);
+// if (error.Success())
+// {
+// SetPublicState (eStateAttaching);
+// error = DoAttachToProcessWithName (process_name, wait_for_launch);
+// if (error.Fail())
+// {
+// if (GetID() != LLDB_INVALID_PROCESS_ID)
+// {
+// SetID (LLDB_INVALID_PROCESS_ID);
+// const char *error_string = error.AsCString();
+// if (error_string == NULL)
+// error_string = "attach failed";
+//
+// SetExitStatus(-1, error_string);
+// }
+// }
+// else
+// {
+// SetNextEventAction(new Process::AttachCompletionHandler(this, 0));
+// StartPrivateStateThread();
+// }
+// }
+// }
+// return error;
+//}
+
void
Process::CompleteAttach ()
{