[Lldb-commits] [lldb] r144615 - in /lldb/trunk: include/lldb/ include/lldb/Interpreter/ include/lldb/Target/ source/API/ source/Commands/ source/Host/macosx/ source/Interpreter/ source/Plugins/Platform/MacOSX/ source/Plugins/Platform/gdb-server/ source/Plugins/Process/gdb-remote/ source/Target/

Greg Clayton gclayton at apple.com
Mon Nov 14 19:53:30 PST 2011


Author: gclayton
Date: Mon Nov 14 21:53:30 2011
New Revision: 144615

URL: http://llvm.org/viewvc/llvm-project?rev=144615&view=rev
Log:
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.


Modified:
    lldb/trunk/include/lldb/Interpreter/Args.h
    lldb/trunk/include/lldb/Interpreter/CommandReturnObject.h
    lldb/trunk/include/lldb/Target/Platform.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/source/API/SBProcess.cpp
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Commands/CommandObjectPlatform.cpp
    lldb/trunk/source/Commands/CommandObjectProcess.cpp
    lldb/trunk/source/Host/macosx/Host.mm
    lldb/trunk/source/Interpreter/Args.cpp
    lldb/trunk/source/Interpreter/CommandReturnObject.cpp
    lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
    lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h
    lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
    lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
    lldb/trunk/source/Target/Platform.cpp
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/include/lldb/Interpreter/Args.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/Args.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/Args.h (original)
+++ lldb/trunk/include/lldb/Interpreter/Args.h Mon Nov 14 21:53:30 2011
@@ -401,6 +401,9 @@
     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

Modified: lldb/trunk/include/lldb/Interpreter/CommandReturnObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandReturnObject.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandReturnObject.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandReturnObject.h Mon Nov 14 21:53:30 2011
@@ -141,6 +141,10 @@
     void
     AppendErrorWithFormat (const char *format, ...)  __attribute__ ((format (printf, 2, 3)));
 
+    void
+    SetError (const Error &error, 
+              const char *fallback_error_cstr);
+
     lldb::ReturnStatus
     GetStatus();
 

Modified: lldb/trunk/include/lldb/Target/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Platform.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Platform.h (original)
+++ lldb/trunk/include/lldb/Target/Platform.h Mon Nov 14 21:53:30 2011
@@ -305,7 +305,7 @@
         ///     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,

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Mon Nov 14 21:53:30 2011
@@ -148,12 +148,6 @@
         return m_executable.GetFilename().GetLength();
     }
     
-    void
-    SetName (const char *name)
-    {
-        m_executable.GetFilename().SetCString (name);
-    }
-    
     FileSpec &
     GetExecutableFile ()
     {
@@ -591,7 +585,7 @@
     }
     
     void
-    FinalizeFileActions (Target *target, Process *process);
+    FinalizeFileActions (Target *target);
 
     size_t
     GetNumFileActions () const
@@ -671,21 +665,158 @@
             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 @@
     }
 
     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 @@
     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 @@
     ///     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);
 

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Mon Nov 14 21:53:30 2011
@@ -112,6 +112,7 @@
 class   PathMappingList;
 class   Platform;
 class   Process;
+class   ProcessAttachInfo;
 class   ProcessModID;
 class   ProcessInfo;
 class   ProcessInstanceInfo;
@@ -128,7 +129,7 @@
 #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   SyntheticChildrenFrontEnd;
 #ifndef LLDB_DISABLE_PYTHON
 class   SyntheticScriptProvider;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif
 class   Target;
 class   TargetList;
 class   Thread;

Modified: lldb/trunk/source/API/SBProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBProcess.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/API/SBProcess.cpp (original)
+++ lldb/trunk/source/API/SBProcess.cpp Mon Nov 14 21:53:30 2011
@@ -169,7 +169,9 @@
         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
         {

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Mon Nov 14 21:53:30 2011
@@ -337,7 +337,9 @@
 
         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 @@
 
         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)

Modified: lldb/trunk/source/Commands/CommandObjectPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectPlatform.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectPlatform.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectPlatform.cpp Mon Nov 14 21:53:30 2011
@@ -653,27 +653,27 @@
                     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;
 

Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Mon Nov 14 21:53:30 2011
@@ -212,12 +212,32 @@
             }
         }
         
-        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 @@
         }
         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 @@
                             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 @@
                     }
                     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 @@
             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 @@
         void
         OptionParsingStarting ()
         {
-            pid = LLDB_INVALID_PROCESS_ID;
-            name.clear();
-            waitfor = false;
+            attach_info.Clear();
         }
 
         const OptionDefinition*
@@ -497,7 +461,7 @@
                     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 @@
 
         // 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 @@
         {
             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 @@
                     // 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);
-                    
-                    }
-                }
             }
         }
         

Modified: lldb/trunk/source/Host/macosx/Host.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Host.mm?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Host/macosx/Host.mm (original)
+++ lldb/trunk/source/Host/macosx/Host.mm Mon Nov 14 21:53:30 2011
@@ -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 @@
 	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 @@
     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 @@
                                                   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 @@
     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 @@
     }
 
 
+    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 @@
                            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

Modified: lldb/trunk/source/Interpreter/Args.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Args.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Args.cpp (original)
+++ lldb/trunk/source/Interpreter/Args.cpp Mon Nov 14 21:53:30 2011
@@ -864,6 +864,26 @@
     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)

Modified: lldb/trunk/source/Interpreter/CommandReturnObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandReturnObject.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandReturnObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandReturnObject.cpp Mon Nov 14 21:53:30 2011
@@ -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 @@
     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.
 

Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp Mon Nov 14 21:53:30 2011
@@ -395,8 +395,15 @@
 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 @@
 }
 
 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 @@
         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");
     }

Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h Mon Nov 14 21:53:30 2011
@@ -79,7 +79,7 @@
     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, 

Modified: lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp Mon Nov 14 21:53:30 2011
@@ -337,7 +337,7 @@
 }
 
 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 @@
                         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);
                     }
                 }
             }

Modified: lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h (original)
+++ lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h Mon Nov 14 21:53:30 2011
@@ -94,7 +94,7 @@
     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,

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Mon Nov 14 21:53:30 2011
@@ -1243,7 +1243,7 @@
                 extractor.GetStringRef().swap(value);
                 extractor.SetFilePos(0);
                 extractor.GetHexByteString (value);
-                process_info.SetName (value.c_str());
+                process_info.GetExecutableFile().SetFile (value.c_str(), false);
             }
         }
         

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Mon Nov 14 21:53:30 2011
@@ -335,7 +335,7 @@
                 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)
             {

Modified: lldb/trunk/source/Target/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Platform.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Target/Platform.cpp (original)
+++ lldb/trunk/source/Target/Platform.cpp Mon Nov 14 21:53:30 2011
@@ -577,16 +577,10 @@
     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;

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=144615&r1=144614&r2=144615&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Mon Nov 14 21:53:30 2011
@@ -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 ()
 {





More information about the lldb-commits mailing list