summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2011-11-15 03:53:30 +0000
committerGreg Clayton <gclayton@apple.com>2011-11-15 03:53:30 +0000
commit144f3a9c90f8434b51b544042397718a3f09ac1f (patch)
tree781ac0d9a76d930a490277849774e129c0a64e37
parent9c0de9bb6b5158e8e45876e978370bed9519c01c (diff)
downloadbcm5719-llvm-144f3a9c90f8434b51b544042397718a3f09ac1f.tar.gz
bcm5719-llvm-144f3a9c90f8434b51b544042397718a3f09ac1f.zip
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
-rw-r--r--lldb/include/lldb/Interpreter/Args.h3
-rw-r--r--lldb/include/lldb/Interpreter/CommandReturnObject.h4
-rw-r--r--lldb/include/lldb/Target/Platform.h2
-rw-r--r--lldb/include/lldb/Target/Process.h178
-rw-r--r--lldb/include/lldb/lldb-forward.h5
-rw-r--r--lldb/source/API/SBProcess.cpp4
-rw-r--r--lldb/source/API/SBTarget.cpp9
-rw-r--r--lldb/source/Commands/CommandObjectPlatform.cpp10
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp238
-rw-r--r--lldb/source/Host/macosx/Host.mm89
-rw-r--r--lldb/source/Interpreter/Args.cpp20
-rw-r--r--lldb/source/Interpreter/CommandReturnObject.cpp10
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp19
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h2
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp4
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h2
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp2
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp2
-rw-r--r--lldb/source/Target/Platform.cpp12
-rw-r--r--lldb/source/Target/Process.cpp312
20 files changed, 558 insertions, 369 deletions
diff --git a/lldb/include/lldb/Interpreter/Args.h b/lldb/include/lldb/Interpreter/Args.h
index 580ebafba8f..a5b66ac387c 100644
--- a/lldb/include/lldb/Interpreter/Args.h
+++ b/lldb/include/lldb/Interpreter/Args.h
@@ -401,6 +401,9 @@ public:
static const char *
StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update);
+ static const char *
+ GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg);
+
// This one isn't really relevant to Arguments per se, but we're using the Args as a
// general strings container, so...
void
diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h
index 8b44cb7ea18..ce062d38845 100644
--- a/lldb/include/lldb/Interpreter/CommandReturnObject.h
+++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h
@@ -141,6 +141,10 @@ public:
void
AppendErrorWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+ void
+ SetError (const Error &error,
+ const char *fallback_error_cstr);
+
lldb::ReturnStatus
GetStatus();
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 9d2e6ca2acb..76659b69914 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -305,7 +305,7 @@ namespace lldb_private {
/// appriopriate error fill into the \a error object.
//------------------------------------------------------------------
virtual lldb::ProcessSP
- Attach (lldb::pid_t pid,
+ Attach (ProcessAttachInfo &attach_info,
Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use existing one
Listener &listener,
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index e002932750a..95a41f45bc0 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -148,12 +148,6 @@ public:
return m_executable.GetFilename().GetLength();
}
- void
- SetName (const char *name)
- {
- m_executable.GetFilename().SetCString (name);
- }
-
FileSpec &
GetExecutableFile ()
{
@@ -591,7 +585,7 @@ public:
}
void
- FinalizeFileActions (Target *target, Process *process);
+ FinalizeFileActions (Target *target);
size_t
GetNumFileActions () const
@@ -671,21 +665,158 @@ public:
m_plugin_name.clear();
}
+ const char *
+ GetShell () const
+ {
+ if (m_shell.empty())
+ return NULL;
+ return m_shell.c_str();
+ }
+
+ void
+ SetShell (const char * path)
+ {
+ if (path && path[0])
+ {
+ m_shell.assign (path);
+ m_flags.Set (lldb::eLaunchFlagLaunchInShell);
+ }
+ else
+ {
+ m_shell.clear();
+ m_flags.Clear (lldb::eLaunchFlagLaunchInShell);
+ }
+ }
+
+ uint32_t
+ GetResumeCount () const
+ {
+ return m_resume_count;
+ }
+
+ void
+ SetResumeCount (uint32_t c)
+ {
+ m_resume_count = c;
+ }
+
void
Clear ()
{
ProcessInfo::Clear();
m_working_dir.clear();
m_plugin_name.clear();
+ m_shell.clear();
m_flags.Clear();
m_file_actions.clear();
+ m_resume_count = 0;
}
+ bool
+ ConvertArgumentsForLaunchingInShell (Error &error, bool localhost);
+
protected:
std::string m_working_dir;
std::string m_plugin_name;
+ std::string m_shell;
Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags
std::vector<FileAction> m_file_actions; // File actions for any other files
+ uint32_t m_resume_count; // How many times do we resume after launching
+};
+
+//----------------------------------------------------------------------
+// ProcessLaunchInfo
+//
+// Describes any information that is required to launch a process.
+//----------------------------------------------------------------------
+
+class ProcessAttachInfo : public ProcessInstanceInfo
+{
+public:
+ ProcessAttachInfo() :
+ ProcessInstanceInfo(),
+ m_plugin_name (),
+ m_resume_count (0),
+ m_wait_for_launch (false)
+ {
+ }
+
+ ProcessAttachInfo (const ProcessLaunchInfo &launch_info) :
+ ProcessInstanceInfo(),
+ m_plugin_name (),
+ m_resume_count (0),
+ m_wait_for_launch (false)
+ {
+ ProcessInfo::operator= (launch_info);
+ SetProcessPluginName (launch_info.GetProcessPluginName());
+ SetResumeCount (launch_info.GetResumeCount());
+ }
+
+ bool
+ GetWaitForLaunch () const
+ {
+ return m_wait_for_launch;
+ }
+
+ void
+ SetWaitForLaunch (bool b)
+ {
+ m_wait_for_launch = b;
+ }
+
+ uint32_t
+ GetResumeCount () const
+ {
+ return m_resume_count;
+ }
+
+ void
+ SetResumeCount (uint32_t c)
+ {
+ m_resume_count = c;
+ }
+
+ const char *
+ GetProcessPluginName () const
+ {
+ if (m_plugin_name.empty())
+ return NULL;
+ return m_plugin_name.c_str();
+ }
+
+ void
+ SetProcessPluginName (const char *plugin)
+ {
+ if (plugin && plugin[0])
+ m_plugin_name.assign (plugin);
+ else
+ m_plugin_name.clear();
+ }
+
+ void
+ Clear ()
+ {
+ ProcessInstanceInfo::Clear();
+ m_plugin_name.clear();
+ m_resume_count = 0;
+ m_wait_for_launch = false;
+ }
+
+ bool
+ ProcessInfoSpecified () const
+ {
+ if (GetExecutableFile())
+ return true;
+ if (GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ return true;
+ if (GetParentProcessID() != LLDB_INVALID_PROCESS_ID)
+ return true;
+ return false;
+ }
+protected:
+ std::string m_plugin_name;
+ uint32_t m_resume_count; // How many times do we resume after launching
+ bool m_wait_for_launch;
};
class ProcessLaunchCommandOptions : public Options
@@ -744,12 +875,12 @@ public:
}
ProcessInstanceInfoMatch (const char *process_name,
- lldb_private::NameMatchType process_name_match_type) :
+ lldb_private::NameMatchType process_name_match_type) :
m_match_info (),
m_name_match_type (process_name_match_type),
m_match_all_users (false)
{
- m_match_info.SetName (process_name);
+ m_match_info.GetExecutableFile().SetFile(process_name, false);
}
ProcessInstanceInfo &
@@ -1316,11 +1447,12 @@ public:
Launch (const ProcessLaunchInfo &launch_info);
//------------------------------------------------------------------
- /// Attach to an existing process using a process ID.
+ /// Attach to an existing process using the process attach info.
///
/// This function is not meant to be overridden by Process
- /// subclasses. It will first call Process::WillAttach (lldb::pid_t)
- /// and if that returns \b true, Process::DoAttach (lldb::pid_t) will
+ /// subclasses. It will first call WillAttach (lldb::pid_t)
+ /// or WillAttach (const char *), and if that returns \b
+ /// true, DoAttach (lldb::pid_t) or DoAttach (const char *) will
/// be called to actually do the attach. If DoAttach returns \b
/// true, then Process::DidAttach() will be called.
///
@@ -1332,28 +1464,8 @@ public:
/// LLDB_INVALID_PROCESS_ID if attaching fails.
//------------------------------------------------------------------
virtual Error
- Attach (lldb::pid_t pid, uint32_t exec_count);
+ Attach (ProcessAttachInfo &attach_info);
- //------------------------------------------------------------------
- /// Attach to an existing process by process name.
- ///
- /// This function is not meant to be overridden by Process
- /// subclasses. It will first call
- /// Process::WillAttach (const char *) and if that returns \b
- /// true, Process::DoAttach (const char *) will be called to
- /// actually do the attach. If DoAttach returns \b true, then
- /// Process::DidAttach() will be called.
- ///
- /// @param[in] process_name
- /// A process name to match against the current process list.
- ///
- /// @return
- /// Returns \a pid if attaching was successful, or
- /// LLDB_INVALID_PROCESS_ID if attaching fails.
- //------------------------------------------------------------------
- virtual Error
- Attach (const char *process_name, bool wait_for_launch);
-
virtual Error
ConnectRemote (const char *remote_url);
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index fb23b43e4e8..c75f75fe02d 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -112,6 +112,7 @@ class NamedOption;
class PathMappingList;
class Platform;
class Process;
+class ProcessAttachInfo;
class ProcessModID;
class ProcessInfo;
class ProcessInstanceInfo;
@@ -128,7 +129,7 @@ class ScriptInterpreter;
#ifndef LLDB_DISABLE_PYTHON
class ScriptInterpreterPython;
struct ScriptSummaryFormat;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif
class SearchFilter;
class Section;
class SectionImpl;
@@ -161,7 +162,7 @@ class SyntheticChildren;
class SyntheticChildrenFrontEnd;
#ifndef LLDB_DISABLE_PYTHON
class SyntheticScriptProvider;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif
class Target;
class TargetList;
class Thread;
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 66abd086c40..5a98c9f96d6 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -169,7 +169,9 @@ SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error)
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
if (m_opaque_sp->GetState() == eStateConnected)
{
- error.SetError (m_opaque_sp->Attach (pid, 0));
+ ProcessAttachInfo attach_info;
+ attach_info.SetProcessID (pid);
+ error.SetError (m_opaque_sp->Attach (attach_info));
}
else
{
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 58d89b197ae..c393635c3c6 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -337,7 +337,9 @@ SBTarget::AttachToProcessWithID
if (sb_process.IsValid())
{
- error.SetError (sb_process->Attach (pid, 0));
+ ProcessAttachInfo attach_info;
+ attach_info.SetProcessID (pid);
+ error.SetError (sb_process->Attach (attach_info));
// If we are doing synchronous mode, then wait for the
// process to stop!
if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false)
@@ -409,7 +411,10 @@ SBTarget::AttachToProcessWithName
if (sb_process.IsValid())
{
- error.SetError (sb_process->Attach (name, wait_for));
+ ProcessAttachInfo attach_info;
+ attach_info.GetExecutableFile().SetFile(name, false);
+ attach_info.SetWaitForLaunch(wait_for);
+ error.SetError (sb_process->Attach (attach_info));
// If we are doing synchronous mode, then wait for the
// process to stop!
if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false)
diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index e2136d32cac..c9f776ed7ee 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -653,27 +653,27 @@ protected:
break;
case 'n':
- match_info.GetProcessInfo().SetName (option_arg);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
match_info.SetNameMatchType (eNameMatchEquals);
break;
case 'e':
- match_info.GetProcessInfo().SetName (option_arg);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
match_info.SetNameMatchType (eNameMatchEndsWith);
break;
case 's':
- match_info.GetProcessInfo().SetName (option_arg);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
match_info.SetNameMatchType (eNameMatchStartsWith);
break;
case 'c':
- match_info.GetProcessInfo().SetName (option_arg);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
match_info.SetNameMatchType (eNameMatchContains);
break;
case 'r':
- match_info.GetProcessInfo().SetName (option_arg);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
match_info.SetNameMatchType (eNameMatchRegularExpression);
break;
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index e7d392da030..e048182d04b 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -212,12 +212,32 @@ public:
}
}
- if (launch_args.GetArgumentCount() > 0)
+ if (launch_args.GetArgumentCount() == 0)
+ {
+ const Args &process_args = target->GetRunArguments();
+ if (process_args.GetArgumentCount() > 0)
+ m_options.launch_info.GetArguments().AppendArguments (process_args);
+ }
+ else
{
m_options.launch_info.GetArguments().AppendArguments (launch_args);
}
-
+ if (target->GetDisableASLR())
+ m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+
+ if (target->GetDisableSTDIO())
+ m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
+
+ m_options.launch_info.GetFlags().Set (eLaunchFlagDebug);
+
+ Args environment;
+ target->GetEnvironmentAsArgs (environment);
+ if (environment.GetArgumentCount() > 0)
+ m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
+
+ m_options.launch_info.FinalizeFileActions (target);
+
if (state == eStateConnected)
{
if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
@@ -228,78 +248,18 @@ public:
}
else
{
- const char *plugin_name = m_options.launch_info.GetProcessPluginName();
-
- if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
- {
+ if (!m_options.launch_info.GetArchitecture().IsValid())
m_options.launch_info.GetArchitecture() = target->GetArchitecture();
- process = target->GetPlatform()->DebugProcess (m_options.launch_info,
- debugger,
- target,
- debugger.GetListener(),
- error).get();
- }
- else
- {
- process = target->CreateProcess (debugger.GetListener(), plugin_name).get();
-
- if (launch_args.GetArgumentCount() == 0)
- {
- const Args &process_args = target->GetRunArguments();
- if (process_args.GetArgumentCount() > 0)
- m_options.launch_info.GetArguments().AppendArguments (process_args);
- }
-
- Args environment;
- target->GetEnvironmentAsArgs (environment);
- m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
-
- if (target->GetDisableASLR())
- m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
-
- if (m_options.launch_info.GetNumFileActions() == 0)
- {
- // Only use the settings value if the user hasn't specified any options that would override it.
- if (target->GetDisableSTDIO())
- m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
-
- const char *path;
- path = target->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 = target->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);
- }
+ process = target->GetPlatform()->DebugProcess (m_options.launch_info,
+ debugger,
+ target,
+ debugger.GetListener(),
+ error).get();
- path = target->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 = process->Launch (m_options.launch_info);
- }
if (process == NULL)
{
- result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
- result.SetStatus (eReturnStatusFailed);
+ result.SetError (error, "failed to launch or debug process");
return false;
}
}
@@ -326,7 +286,7 @@ public:
state = process->WaitForProcessToStop (NULL);
if (!StateIsStoppedState(state))
{
- result.AppendErrorWithFormat ("Process isn't stopped: %s", StateAsCString(state));
+ result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state));
}
result.SetDidChangeProcessState (true);
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -338,13 +298,13 @@ public:
}
else
{
- result.AppendErrorWithFormat ("Process resume at entry point failed: %s", error.AsCString());
+ result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString());
result.SetStatus (eReturnStatusFailed);
}
}
else
{
- result.AppendErrorWithFormat ("Initial process state wasn't stopped: %s", StateAsCString(state));
+ result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
result.SetStatus (eReturnStatusFailed);
}
}
@@ -423,23 +383,29 @@ public:
switch (short_option)
{
case 'p':
- pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
- if (!success || pid == LLDB_INVALID_PROCESS_ID)
{
- error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
+ lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
+ if (!success || pid == LLDB_INVALID_PROCESS_ID)
+ {
+ error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
+ }
+ else
+ {
+ attach_info.SetProcessID (pid);
+ }
}
break;
case 'P':
- plugin_name = option_arg;
+ attach_info.SetProcessPluginName (option_arg);
break;
case 'n':
- name.assign(option_arg);
+ attach_info.GetExecutableFile().SetFile(option_arg, false);
break;
case 'w':
- waitfor = true;
+ attach_info.SetWaitForLaunch(true);
break;
default:
@@ -452,9 +418,7 @@ public:
void
OptionParsingStarting ()
{
- pid = LLDB_INVALID_PROCESS_ID;
- name.clear();
- waitfor = false;
+ attach_info.Clear();
}
const OptionDefinition*
@@ -497,7 +461,7 @@ public:
ProcessInstanceInfoMatch match_info;
if (partial_name)
{
- match_info.GetProcessInfo().SetName(partial_name);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
match_info.SetNameMatchType(eNameMatchStartsWith);
}
platform_sp->FindProcesses (match_info, process_infos);
@@ -522,10 +486,7 @@ public:
// Instance variables to hold the values for command options.
- lldb::pid_t pid;
- std::string plugin_name;
- std::string name;
- bool waitfor;
+ ProcessAttachInfo attach_info;
};
CommandObjectProcessAttach (CommandInterpreter &interpreter) :
@@ -601,55 +562,37 @@ public:
{
if (state != eStateConnected)
{
- const char *plugin_name = NULL;
-
- if (!m_options.plugin_name.empty())
- plugin_name = m_options.plugin_name.c_str();
-
+ const char *plugin_name = m_options.attach_info.GetProcessPluginName();
process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
}
if (process)
{
Error error;
- int attach_pid = m_options.pid;
-
- const char *wait_name = NULL;
-
- if (m_options.name.empty())
+ // If no process info was specified, then use the target executable
+ // name as the process to attach to by default
+ if (!m_options.attach_info.ProcessInfoSpecified ())
{
if (old_exec_module_sp)
+ m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetFileSpec().GetFilename();
+
+ if (!m_options.attach_info.ProcessInfoSpecified ())
{
- wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
+ error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
}
}
- else
- {
- wait_name = m_options.name.c_str();
- }
-
- // If we are waiting for a process with this name to show up, do that first.
- if (m_options.waitfor)
- {
-
- if (wait_name == NULL)
- {
- result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name);
- error = process->Attach (wait_name, m_options.waitfor);
+ if (error.Success())
+ {
+ error = process->Attach (m_options.attach_info);
+
if (error.Success())
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
}
else
{
- result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
- wait_name,
- error.AsCString());
+ result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
result.SetStatus (eReturnStatusFailed);
return false;
}
@@ -658,70 +601,11 @@ public:
// FIXME: in the async case it will now be possible to get to the command
// interpreter with a state eStateAttaching. Make sure we handle that correctly.
StateType state = process->WaitForProcessToStop (NULL);
-
+
result.SetDidChangeProcessState (true);
result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
- else
- {
- // If the process was specified by name look it up, so we can warn if there are multiple
- // processes with this pid.
-
- if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
- {
- ProcessInstanceInfoList process_infos;
- PlatformSP platform_sp (m_interpreter.GetPlatform (true));
- if (platform_sp)
- {
- ProcessInstanceInfoMatch match_info (wait_name, eNameMatchEquals);
- platform_sp->FindProcesses (match_info, process_infos);
- }
- if (process_infos.GetSize() > 1)
- {
- result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- else if (process_infos.GetSize() == 0)
- {
- result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- else
- {
- attach_pid = process_infos.GetProcessIDAtIndex (0);
- }
- }
-
- if (attach_pid != LLDB_INVALID_PROCESS_ID)
- {
- error = process->Attach (attach_pid, 0);
- if (error.Success())
- {
- result.SetStatus (eReturnStatusSuccessContinuingNoResult);
- }
- else
- {
- result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
- attach_pid,
- error.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
- StateType state = process->WaitForProcessToStop (NULL);
-
- result.SetDidChangeProcessState (true);
- result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendErrorWithFormat ("No PID specified for attach\n");
- result.SetStatus (eReturnStatusFailed);
-
- }
- }
}
}
diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm
index 048555a4e9c..529525d6ea6 100644
--- a/lldb/source/Host/macosx/Host.mm
+++ b/lldb/source/Host/macosx/Host.mm
@@ -59,6 +59,12 @@
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
#endif
+extern "C"
+{
+ int __pthread_chdir(const char *path);
+ int __pthread_fchdir (int fildes);
+}
+
using namespace lldb;
using namespace lldb_private;
@@ -431,25 +437,6 @@ tell application \"Terminal\"\n\
do script the_shell_script\n\
end tell\n";
-static const char *
-GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
-{
- safe_arg.assign (unsafe_arg);
- size_t prev_pos = 0;
- while (prev_pos < safe_arg.size())
- {
- // Escape spaces and quotes
- size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
- if (pos != std::string::npos)
- {
- safe_arg.insert (pos, 1, '\\');
- prev_pos = pos + 2;
- }
- else
- break;
- }
- return safe_arg.c_str();
-}
static Error
LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &launch_info)
@@ -499,44 +486,22 @@ LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &lau
if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
command.PutCString(" --disable-aslr");
- if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
+ command.PutCString(" -- ");
+
+ const char **argv = launch_info.GetArguments().GetConstArgumentVector ();
+ if (argv)
{
- const char *shell_executable = "/bin/bash"; //getenv("SHELL");
- std::string safe_arg;
- if (launch_info.GetArchitecture().IsValid())
- command.Printf(" -- %s -c 'exec /usr/bin/arch -arch %s", shell_executable, launch_info.GetArchitecture().GetArchitectureName());
- else
- command.Printf(" -- %s -c 'exec ", shell_executable);
- const char **argv = launch_info.GetArguments().GetConstArgumentVector ();
- if (argv)
+ for (size_t i=0; argv[i] != NULL; ++i)
{
- for (size_t i=0; argv[i] != NULL; ++i)
- {
- const char *arg = GetShellSafeArgument (i == 0 ? exe_path : argv[i], safe_arg);
- command.Printf(" %s", arg);
- }
+ if (i==0)
+ command.Printf(" '%s'", exe_path);
+ else
+ command.Printf(" '%s'", argv[i]);
}
- command.PutChar('\'');
}
else
{
- command.PutCString(" -- ");
-
- const char **argv = launch_info.GetArguments().GetConstArgumentVector ();
- if (argv)
- {
- for (size_t i=0; argv[i] != NULL; ++i)
- {
- if (i==0)
- command.Printf(" '%s'", exe_path);
- else
- command.Printf(" '%s'", argv[i]);
- }
- }
- else
- {
- command.Printf(" '%s'", exe_path);
- }
+ command.Printf(" '%s'", exe_path);
}
command.PutCString (" ; echo Process exited with status $?");
@@ -1007,11 +972,11 @@ GetMacOSXProcessName (const ProcessInstanceInfoMatch *match_info_ptr,
match_info_ptr->GetNameMatchType(),
match_info_ptr->GetProcessInfo().GetName()))
{
- process_info.SetName (process_name);
+ process_info.GetExecutableFile().SetFile (process_name, false);
return true;
}
}
- process_info.SetName (NULL);
+ process_info.GetExecutableFile().Clear();
return false;
}
@@ -1306,6 +1271,11 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag
+//#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
+// // Close all files exception those with file actions if this is supported.
+// flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
+//#endif
+
error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
if (error.Fail() || log)
error.PutToLog(log.get(), "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
@@ -1347,6 +1317,13 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
}
+ const char *working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir)
+ {
+ // No more thread specific current working directory
+ __pthread_chdir (working_dir);
+ }
+
const size_t num_file_actions = launch_info.GetNumFileActions ();
if (num_file_actions > 0)
{
@@ -1410,6 +1387,12 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
envp);
}
+ if (working_dir)
+ {
+ // No more thread specific current working directory
+ __pthread_fchdir (-1);
+ }
+
if (pid != LLDB_INVALID_PROCESS_ID)
{
// If all went well, then set the process ID into the launch info
diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp
index 50b43b1678c..f32b25c9127 100644
--- a/lldb/source/Interpreter/Args.cpp
+++ b/lldb/source/Interpreter/Args.cpp
@@ -864,6 +864,26 @@ Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t
return 0;
}
+const char *
+Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
+{
+ safe_arg.assign (unsafe_arg);
+ size_t prev_pos = 0;
+ while (prev_pos < safe_arg.size())
+ {
+ // Escape spaces and quotes
+ size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
+ if (pos != std::string::npos)
+ {
+ safe_arg.insert (pos, 1, '\\');
+ prev_pos = pos + 2;
+ }
+ else
+ break;
+ }
+ return safe_arg.c_str();
+}
+
int32_t
Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp
index eb6fae4ce1b..51e6ee6e5fe 100644
--- a/lldb/source/Interpreter/CommandReturnObject.cpp
+++ b/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -13,6 +13,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Core/Error.h"
#include "lldb/Core/StreamString.h"
using namespace lldb;
@@ -134,6 +135,15 @@ CommandReturnObject::AppendError (const char *in_string, int len)
GetErrorStream().Printf ("error: %*.*s\n", len, len, in_string);
}
+void
+CommandReturnObject::SetError (const Error &error, const char *fallback_error_cstr)
+{
+ const char *error_cstr = error.AsCString();
+ if (error_cstr == NULL)
+ error_cstr = fallback_error_cstr;
+ AppendError (error_cstr);
+ SetStatus (eReturnStatusFailed);
+}
// Similar to AppendError, but do not prepend 'Error: ' to message, and
// don't append "\n" to the end of it.
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 8baaefc929f..408a57f391a 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -395,8 +395,15 @@ Error
PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
{
Error error;
+
if (IsHost())
{
+ if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
+ {
+ const bool is_localhost = true;
+ if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost))
+ return error;
+ }
error = Platform::LaunchProcess (launch_info);
}
else
@@ -410,13 +417,14 @@ PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
}
lldb::ProcessSP
-PlatformDarwin::Attach (lldb::pid_t pid,
+PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
Debugger &debugger,
Target *target,
Listener &listener,
Error &error)
{
lldb::ProcessSP process_sp;
+
if (IsHost())
{
if (target == NULL)
@@ -438,18 +446,17 @@ PlatformDarwin::Attach (lldb::pid_t pid,
if (target && error.Success())
{
debugger.GetTargetList().SetSelectedTarget(target);
- // The darwin always currently uses the GDB remote debugger plug-in
- // so even when debugging locally we are debugging remotely!
- process_sp = target->CreateProcess (listener, "gdb-remote");
+
+ process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName());
if (process_sp)
- error = process_sp->Attach (pid, 2);
+ error = process_sp->Attach (attach_info);
}
}
else
{
if (m_remote_platform_sp)
- process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error);
+ process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
else
error.SetErrorString ("the platform is not currently connected");
}
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index 9b3e771193e..5ed533da3a3 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -79,7 +79,7 @@ public:
LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
virtual lldb::ProcessSP
- Attach (lldb::pid_t pid,
+ Attach (lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
lldb_private::Listener &listener,
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 69fa4487e3e..387737b7ab6 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -337,7 +337,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
}
lldb::ProcessSP
-PlatformRemoteGDBServer::Attach (lldb::pid_t pid,
+PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use existing one
Listener &listener,
@@ -391,7 +391,7 @@ PlatformRemoteGDBServer::Attach (lldb::pid_t pid,
assert (connect_url_len < sizeof(connect_url));
error = process_sp->ConnectRemote (connect_url);
if (error.Success())
- error = process_sp->Attach(pid, 0);
+ error = process_sp->Attach(attach_info);
}
}
}
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 36c48c24b60..e141f7fc080 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -94,7 +94,7 @@ public:
LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
virtual lldb::ProcessSP
- Attach (lldb::pid_t pid,
+ Attach (lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
lldb_private::Listener &listener,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 85f56dd3ffb..5dd4dc68027 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1243,7 +1243,7 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
extractor.GetStringRef().swap(value);
extractor.SetFilePos(0);
extractor.GetHexByteString (value);
- process_info.SetName (value.c_str());
+ process_info.GetExecutableFile().SetFile (value.c_str(), false);
}
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 9712d6f2ccd..2fbac25c933 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -335,7 +335,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
StringExtractor extractor;
extractor.GetStringRef().swap(value);
extractor.GetHexByteString (value);
- match_info.GetProcessInfo().SetName (value.c_str());
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
}
else if (key.compare("name_match") == 0)
{
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 0213ac61485..3b780428836 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -577,16 +577,10 @@ Platform::DebugProcess (ProcessLaunchInfo &launch_info,
error = LaunchProcess (launch_info);
if (error.Success())
{
- lldb::pid_t pid = launch_info.GetProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
+ if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
- process_sp = Attach (pid, debugger, target, listener, error);
-
-// if (process_sp)
-// {
-// if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry))
-// process_sp->Resume();
-// }
+ ProcessAttachInfo attach_info (launch_info);
+ process_sp = Attach (attach_info, debugger, target, listener, error);
}
}
return process_sp;
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 6ee9dbf85de..e70788e93ac 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -251,7 +251,7 @@ ProcessInfo::SetArguments (const Args& args,
}
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 @@ ProcessLaunchInfo::FinalizeFileActions (Target *target, Process *process)
}
}
+
+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 @@ ProcessLaunchInfo::FileAction::Open (int fd, const char *path, bool read, bool w
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 @@ ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions
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 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
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 @@ ProcessLaunchCommandOptions::g_option_table[] =
{ 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 @@ Process::AttachCompletionHandler::GetExitString ()
}
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 @@ Process::Attach (const char *process_name, bool wait_for_launch)
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 ()
{
OpenPOWER on IntegriCloud