Allow clients to control the exact path that is used to launch processes by adding new calls to SBLaunchInfo.

The new calls are:

SBFileSpec
SBLaunchInfo::GetExecutableFile ();

void
SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg);

<rdar://problem/16833939>

llvm-svn: 208245
diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index bcb9fc5..e0ac4f8 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -47,6 +47,35 @@
     void
     SetGroupID (uint32_t gid);
     
+    SBFileSpec
+    GetExecutableFile ();
+    
+    //----------------------------------------------------------------------
+    /// Set the executable file that will be used to launch the process and
+    /// optionally set it as the first argument in the argument vector.
+    ///
+    /// This only needs to be specified if clients wish to carefully control
+    /// the exact path will be used to launch a binary. If you create a
+    /// target with a symlink, that simlink will get resolved in the target
+    /// and the resolved path will get used to launch the process. Calling
+    /// this function can help you still launch your process using the
+    /// path of your choice.
+    ///
+    /// If this function is not called prior to launching with
+    /// SBTarget::Launch(...), the target will use the resolved executable
+    /// path that was used to create the target.
+    ///
+    /// @param[in] exe_file
+    ///     The override path to use when launching the executable.
+    ///
+    /// @param[in] add_as_first_arg
+    ///     If true, then the path will be inserted into the argument vector
+    ///     prior to launching. Otherwise the argument vector will be left
+    ///     alone.
+    //----------------------------------------------------------------------
+    void
+    SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg);
+    
     uint32_t
     GetNumArguments ();
     
diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i
index 87d5c5b..1f697ba 100644
--- a/lldb/scripts/Python/interface/SBTarget.i
+++ b/lldb/scripts/Python/interface/SBTarget.i
@@ -32,6 +32,12 @@
     void
     SetGroupID (uint32_t gid);
     
+    lldb::SBFileSpec
+    GetExecutableFile ();
+    
+    void
+    SetExecutableFile (lldb::SBFileSpec exe_file, bool add_as_first_arg);
+
     uint32_t
     GetNumArguments ();
     
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 8faf504..27a492d 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -120,6 +120,18 @@
     m_opaque_sp->SetGroupID (gid);
 }
 
+SBFileSpec
+SBLaunchInfo::GetExecutableFile ()
+{
+    return SBFileSpec (m_opaque_sp->GetExecutableFile());
+}
+
+void
+SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg)
+{
+    m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg);
+}
+
 uint32_t
 SBLaunchInfo::GetNumArguments ()
 {
@@ -747,27 +759,30 @@
         Mutex::Locker api_locker (target_sp->GetAPIMutex());
         StateType state = eStateInvalid;
         {
-        ProcessSP process_sp = target_sp->GetProcessSP();
-        if (process_sp)
-        {
-            state = process_sp->GetState();
-
-            if (process_sp->IsAlive() && state != eStateConnected)
+            ProcessSP process_sp = target_sp->GetProcessSP();
+            if (process_sp)
             {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
-                else
-                    error.SetErrorString ("a process is already being debugged");
-                return sb_process;
+                state = process_sp->GetState();
+                
+                if (process_sp->IsAlive() && state != eStateConnected)
+                {
+                    if (state == eStateAttaching)
+                        error.SetErrorString ("process attach is in progress");
+                    else
+                        error.SetErrorString ("a process is already being debugged");
+                    return sb_process;
+                }
             }
         }
-        }
 
         lldb_private::ProcessLaunchInfo &launch_info = sb_launch_info.ref();
 
-        Module *exe_module = target_sp->GetExecutableModulePointer();
-        if (exe_module)
-            launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
+        if (!launch_info.GetExecutableFile())
+        {
+            Module *exe_module = target_sp->GetExecutableModulePointer();
+            if (exe_module)
+                launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
+        }
 
         const ArchSpec &arch_spec = target_sp->GetArchitecture();
         if (arch_spec.IsValid())