[Lldb-commits] [lldb] r124060 - in /lldb/trunk: include/lldb/API/ include/lldb/Host/ include/lldb/Target/ source/API/ source/Commands/ source/Core/ source/Host/common/ source/Host/macosx/ source/Plugins/Process/Linux/ source/Plugins/Process/MacOSX-User/source/ source/Plugins/Process/gdb-remote/ source/Target/ tools/darwin-debug/ tools/debugserver/source/ tools/debugserver/source/MacOSX/

Greg Clayton gclayton at apple.com
Sat Jan 22 21:56:20 PST 2011


Author: gclayton
Date: Sat Jan 22 23:56:20 2011
New Revision: 124060

URL: http://llvm.org/viewvc/llvm-project?rev=124060&view=rev
Log:
Added a new variant of SBTarget::Launch() that deprectates the old one that
takes separate file handles for stdin, stdout, and stder and also allows for
the working directory to be specified.

Added support to "process launch" to a new option: --working-dir=PATH. We
can now set the working directory. If this is not set, it defaults to that
of the process that has LLDB loaded. Added the working directory to the
host LaunchInNewTerminal function to allows the current working directory 
to be set in processes that are spawned in their own terminal. Also hooked this
up to the lldb_private::Process and all mac plug-ins. The linux plug-in had its
API changed, but nothing is making use of it yet. Modfied "debugserver" and
"darwin-debug" to also handle the current working directory options and modified
the code in LLDB that spawns these tools to pass the info along.

Fixed ProcessGDBRemote to properly pass along all file handles for stdin, stdout
and stderr. 

After clearing the default values for the stdin/out/err file handles for
process to be NULL, we had a crasher in UserSettingsController::UpdateStringVariable
which is now fixed. Also fixed the setting of boolean values to be able to
be set as "true", "yes", "on", "1" for true (case insensitive) and "false", "no",
"off", or "0" for false.

Fixed debugserver to properly handle files for STDIN, STDOUT and STDERR that are not
already opened. Previous to this fix debugserver would only correctly open and dupe
file handles for the slave side of a pseudo terminal. It now correctly handles
getting STDIN for the inferior from a file, and spitting STDOUT and STDERR out to
files. Also made sure the file handles were correctly opened with the NOCTTY flag
for terminals.


Modified:
    lldb/trunk/include/lldb/API/SBTarget.h
    lldb/trunk/include/lldb/Host/Host.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Commands/CommandObjectProcess.cpp
    lldb/trunk/source/Core/UserSettingsController.cpp
    lldb/trunk/source/Host/common/Host.cpp
    lldb/trunk/source/Host/macosx/Host.mm
    lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
    lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
    lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/tools/darwin-debug/darwin-debug.cpp
    lldb/trunk/tools/debugserver/source/DNB.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.cpp
    lldb/trunk/tools/debugserver/source/debugserver.cpp

Modified: lldb/trunk/include/lldb/API/SBTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBTarget.h (original)
+++ lldb/trunk/include/lldb/API/SBTarget.h Sat Jan 22 23:56:20 2011
@@ -55,16 +55,20 @@
     GetProcess ();
 
     lldb::SBProcess
-    LaunchProcess (char const **argv,
-                   char const **envp,
-                   const char *tty,
-                   uint32_t launch_flags,   // See LaunchFlags
-                   bool stop_at_entry);
+    Launch (char const **argv,
+            char const **envp,
+            const char *tty,
+            uint32_t launch_flags,   // See LaunchFlags
+            bool stop_at_entry,
+            lldb::SBError& error);
 
     lldb::SBProcess
     Launch (char const **argv,
             char const **envp,
-            const char *tty,
+            const char *stdin_path,
+            const char *stdout_path,
+            const char *stderr_path,
+            const char *working_directory,
             uint32_t launch_flags,   // See LaunchFlags
             bool stop_at_entry,
             lldb::SBError& error);

Modified: lldb/trunk/include/lldb/Host/Host.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Host.h?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/Host.h (original)
+++ lldb/trunk/include/lldb/Host/Host.h Sat Jan 22 23:56:20 2011
@@ -329,8 +329,9 @@
 
     static lldb::pid_t
     LaunchInNewTerminal (const char *tty_name,  // Optional partial or full tty name ("/dev/ttys000" or "ttys000")
-                         const char **argv,   // argv[0] is executable
-                         const char **envp,
+                         const char **argv,     // argv[0] is executable, argv[1] and on are the arguments
+                         const char **envp,     
+                         const char *working_dir,
                          const ArchSpec *arch_spec,
                          bool stop_at_entry,
                          bool disable_aslr);

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Sat Jan 22 23:56:20 2011
@@ -540,6 +540,9 @@
     ///     process. If all stdXX_path arguments are NULL, a pseudo
     ///     terminal will be used.
     ///
+    /// @param[in] working_directory
+    ///     The working directory to have the child process run in
+    ///
     /// @return
     ///     An error object. Call GetID() to get the process ID if
     ///     the error object is success.
@@ -550,7 +553,8 @@
             uint32_t launch_flags,
             const char *stdin_path,
             const char *stdout_path,
-            const char *stderr_path);
+            const char *stderr_path,
+            const char *working_directory);
 
     //------------------------------------------------------------------
     /// Attach to an existing process using a process ID.
@@ -950,6 +954,9 @@
     ///     process. If all stdXX_path arguments are NULL, a pseudo
     ///     terminal will be used.
     ///
+    /// @param[in] working_directory
+    ///     The working directory to have the child process run in
+    ///
     /// @return
     ///     A new valid process ID, or LLDB_INVALID_PROCESS_ID if
     ///     launching fails.
@@ -961,7 +968,8 @@
               uint32_t launch_flags,
               const char *stdin_path,
               const char *stdout_path,
-              const char *stderr_path) = 0;
+              const char *stderr_path,
+              const char *working_directory) = 0;
     
     //------------------------------------------------------------------
     /// Called after launching a process.

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Sat Jan 22 23:56:20 2011
@@ -117,51 +117,48 @@
 }
 
 SBProcess
-SBTarget::LaunchProcess
+SBTarget::Launch
 (
     char const **argv,
     char const **envp,
     const char *tty,
     uint32_t launch_flags,
-    bool stop_at_entry
+    bool stop_at_entry,
+    SBError &error
 )
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
-
-    if (log)
-        log->Printf ("SBTarget(%p)::LaunchProcess (argv=%p, envp=%p, tty=\"%s\", launch_flags=%d, stop_at_entry=%i)",
-                     m_opaque_sp.get(), argv, envp, tty, launch_flags, stop_at_entry);
-
-    SBError sb_error;    
-    SBProcess sb_process = Launch (argv, envp, tty, launch_flags, stop_at_entry, sb_error);
-
-    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
-    if (log)
-    {
-        log->Printf ("SBTarget(%p)::LaunchProcess (...) => SBProcess(%p)", 
-                     m_opaque_sp.get(), sb_process.get());
-    }
-
-    return sb_process;
+    return Launch (argv, envp, tty, tty, tty, NULL, launch_flags, stop_at_entry, error);
 }
 
 SBProcess
-SBTarget::Launch
+SBTarget::Launch 
 (
     char const **argv,
     char const **envp,
-    const char *tty,
-    uint32_t launch_flags,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    const char *working_directory,
+    uint32_t launch_flags,   // See LaunchFlags
     bool stop_at_entry,
-    SBError &error
+    lldb::SBError& error
 )
 {
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     if (log)
     {
-        log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, tty=\"%s\", launch_flags=%d, stop_at_entry=%i, &error (%p))...",
-                     m_opaque_sp.get(), argv, envp, tty, launch_flags, stop_at_entry, error.get());
+        log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
+                     m_opaque_sp.get(), 
+                     argv, 
+                     envp, 
+                     stdin_path ? stdin_path : "NULL", 
+                     stdout_path ? stdout_path : "NULL", 
+                     stderr_path ? stderr_path : "NULL", 
+                     working_directory ? working_directory : "NULL",
+                     launch_flags, 
+                     stop_at_entry, 
+                     error.get());
     }
     SBProcess sb_process;
     if (m_opaque_sp)
@@ -171,7 +168,7 @@
 
         if (sb_process.IsValid())
         {
-            error.SetError (sb_process->Launch (argv, envp, launch_flags, tty, tty, tty));
+            error.SetError (sb_process->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory));
             if (error.Success())
             {
                 // We we are stopping at the entry point, we can return now!

Modified: lldb/trunk/source/Commands/CommandObjectProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectProcess.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectProcess.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectProcess.cpp Sat Jan 22 23:56:20 2011
@@ -57,12 +57,13 @@
 
             switch (short_option)
             {
-                case 's':   stop_at_entry = true;       break;
-                case 'e':   stderr_path = option_arg;   break;
-                case 'i':   stdin_path  = option_arg;   break;
-                case 'o':   stdout_path = option_arg;   break;
-                case 'p':   plugin_name = option_arg;   break;
-                case 'n':   no_stdio = true;            break;
+                case 's':   stop_at_entry = true;               break;
+                case 'e':   stderr_path.assign (option_arg);    break;
+                case 'i':   stdin_path.assign (option_arg);     break;
+                case 'o':   stdout_path.assign (option_arg);    break;
+                case 'p':   plugin_name.assign (option_arg);    break;
+                case 'n':   no_stdio = true;                    break;
+                case 'w':   working_dir.assign (option_arg);    break;
                 case 't':   
                     if (option_arg && option_arg[0])
                         tty_name.assign (option_arg);
@@ -87,6 +88,7 @@
             stdout_path.clear();
             stderr_path.clear();
             plugin_name.clear();
+            working_dir.clear();
             no_stdio = false;
         }
 
@@ -110,6 +112,7 @@
         std::string stdin_path;
         std::string stdout_path;
         std::string plugin_name;
+        std::string working_dir;
 
     };
 
@@ -249,6 +252,9 @@
         const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
 
         Error error;
+        const char *working_dir = NULL;
+        if (!m_options.working_dir.empty())
+            working_dir = m_options.working_dir.c_str();
 
         if (m_options.in_new_tty)
         {
@@ -256,6 +262,7 @@
             lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
                                                          inferior_argv,
                                                          inferior_envp,
+                                                         working_dir,
                                                          &exe_module->GetArchitecture(),
                                                          true,
                                                          process->GetDisableASLR());
@@ -287,19 +294,13 @@
                 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
             }
 
-            if (stdin_path == NULL)
-                stdin_path = "/dev/null";
-            if (stdout_path == NULL)
-                stdout_path = "/dev/null";
-            if (stderr_path == NULL)
-                stderr_path = "/dev/null";
-
             error = process->Launch (inferior_argv,
                                      inferior_envp,
                                      launch_flags,
                                      stdin_path,
                                      stdout_path,
-                                     stderr_path);
+                                     stderr_path,
+                                     working_dir);
         }
                      
         if (error.Success())
@@ -363,6 +364,7 @@
 { SET1 | SET2 | SET3, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
 {        SET2       , false, "tty",           't', optional_argument, NULL, 0, eArgTypePath,    "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
 {               SET3, false, "no-stdio",      'n', no_argument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
+{ SET1 | SET2 | SET3, false, "working-dir",   'w', required_argument, NULL, 0, eArgTypePath,    "Set the current working directory to <path> when running the inferior."},
 { 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
 };
 

Modified: lldb/trunk/source/Core/UserSettingsController.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/UserSettingsController.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Core/UserSettingsController.cpp (original)
+++ lldb/trunk/source/Core/UserSettingsController.cpp Sat Jan 22 23:56:20 2011
@@ -1946,9 +1946,17 @@
                                               Error &err)
 {
     if (op == lldb::eVarSetOperationAssign)
-        string_var = new_value;
+    {
+        if (new_value && new_value[0])
+            string_var.assign (new_value);
+        else
+            string_var.clear();
+    }
     else if (op == lldb::eVarSetOperationAppend)
-        string_var.append (new_value);
+    {
+        if (new_value && new_value[0])
+            string_var.append (new_value);
+    }
     else if (op == lldb::eVarSetOperationClear)
         string_var.clear();
     else
@@ -1964,19 +1972,25 @@
     if (op != lldb::eVarSetOperationAssign)
         err.SetErrorString ("Invalid operation for Boolean variable.  Cannot update value.\n");
 
+    if (new_value && new_value[0])
+    {
+        if ((::strcasecmp(new_value, "true") == 0) ||
+            (::strcasecmp(new_value, "yes") == 0)  ||
+            (::strcasecmp(new_value, "on") == 0)   ||
+            (::strcasecmp(new_value, "1") == 0))
+            bool_var = true;
+        else 
+        if ((::strcasecmp(new_value, "false") == 0) ||
+            (::strcasecmp(new_value, "no") == 0)    ||
+            (::strcasecmp(new_value, "off") == 0)   ||
+            (::strcasecmp(new_value, "0") == 0))
+            bool_var = false;
+        else
+            err.SetErrorStringWithFormat ("Invalid boolean value '%s'\n", new_value);
+    }
+    else
+        err.SetErrorString ("Invalid value.  Cannot perform update.\n");
 
-    if ((new_value == NULL)
-        || (new_value[0] == '\0'))
-      err.SetErrorString ("Invalid value.  Cannot perform update.\n");
-
-    std::string bool_val_str (new_value);
-
-    std::transform (bool_val_str.begin(), bool_val_str.end(), bool_val_str.begin(), ::tolower);
-
-    if (bool_val_str == "true")
-        bool_var = true;
-    else if (bool_val_str == "false")
-        bool_var = false;
 }
 
 void

Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Sat Jan 22 23:56:20 2011
@@ -907,6 +907,7 @@
     const char *tty_name,
     const char **argv, 
     const char **envp,
+    const char *working_dir,
     const ArchSpec *arch_spec,
     bool stop_at_entry,
     bool disable_aslr

Modified: lldb/trunk/source/Host/macosx/Host.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Host.mm?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Host/macosx/Host.mm (original)
+++ lldb/trunk/source/Host/macosx/Host.mm Sat Jan 22 23:56:20 2011
@@ -226,6 +226,7 @@
 (
     const char **argv, 
     const char **envp,
+    const char *working_dir,
     const ArchSpec *arch_spec,
     bool stop_at_entry,
     bool disable_aslr
@@ -404,6 +405,7 @@
     const char *tty_name,
     const char **argv, 
     const char **envp,
+    const char *working_dir,
     const ArchSpec *arch_spec,
     bool stop_at_entry,
     bool disable_aslr
@@ -440,6 +442,9 @@
     if (arch_spec && arch_spec->IsValid())
         command.Printf(" --arch=%s", arch_spec->AsCString());
 
+    if (working_dir)
+        command.Printf(" --working-dir '%s'", working_dir);
+    
     if (disable_aslr)
         command.PutCString(" --disable-aslr");
         
@@ -520,15 +525,16 @@
     const char *tty_name,
     const char **argv, 
     const char **envp,
+    const char *working_dir,
     const ArchSpec *arch_spec,
     bool stop_at_entry,
     bool disable_aslr
 )
 {
 #if defined (LLDB_HOST_USE_APPLESCRIPT)
-    return LaunchInNewTerminalWithAppleScript (tty_name, argv, envp, arch_spec, stop_at_entry, disable_aslr);
+    return LaunchInNewTerminalWithAppleScript (tty_name, argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
 #else
-    return LaunchInNewTerminalWithCommandFile (argv, envp, arch_spec, stop_at_entry, disable_aslr);
+    return LaunchInNewTerminalWithCommandFile (argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
 #endif
 }
 

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Sat Jan 22 23:56:20 2011
@@ -122,7 +122,8 @@
                        uint32_t launch_flags,
                        const char *stdin_path,
                        const char *stdout_path,
-                       const char *stderr_path)
+                       const char *stderr_path,
+                       const char *working_directory)
 {
     Error error;
     assert(m_monitor == NULL);

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h Sat Jan 22 23:56:20 2011
@@ -72,7 +72,8 @@
              uint32_t launch_flags,
              const char *stdin_path,
              const char *stdout_path,
-             const char *stderr_path);
+             const char *stderr_path,
+             const char *working_directory);
 
     virtual void
     DidLaunch();

Modified: lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp Sat Jan 22 23:56:20 2011
@@ -316,7 +316,8 @@
     uint32_t flags,
     const char *stdin_path,
     const char *stdout_path,
-    const char *stderr_path
+    const char *stderr_path,
+    const char *working_dir
 )
 {
 //  ::LogSetBitMask (PD_LOG_DEFAULT);

Modified: lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h (original)
+++ lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h Sat Jan 22 23:56:20 2011
@@ -95,8 +95,9 @@
               char const *envp[],           // Can be NULL
               uint32_t launch_flags,
               const char *stdin_path,       // Can be NULL
-              const char *stdout_path,  // Can be NULL
-              const char *stderr_path); // Can be NULL
+              const char *stdout_path,      // Can be NULL
+              const char *stderr_path,      // Can be NULL
+              const char *working_dir);     // Can be NULL
 
     virtual void
     DidLaunch ();

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Sat Jan 22 23:56:20 2011
@@ -375,7 +375,8 @@
     uint32_t launch_flags,
     const char *stdin_path,
     const char *stdout_path,
-    const char *stderr_path
+    const char *stderr_path,
+    const char *working_dir
 )
 {
     Error error;
@@ -400,7 +401,10 @@
             error = StartDebugserverProcess (host_port,
                                              argv,
                                              envp,
-                                             NULL, //stdin_path,
+                                             stdin_path,
+                                             stdout_path,
+                                             stderr_path,
+                                             working_dir,
                                              launch_process,
                                              LLDB_INVALID_PROCESS_ID,
                                              NULL, false,
@@ -420,10 +424,14 @@
             error = StartDebugserverProcess (host_port,
                                              NULL,
                                              NULL,
-                                             NULL, //stdin_path
+                                             stdin_path,
+                                             stdout_path,
+                                             stderr_path,
+                                             working_dir,
                                              launch_process,
                                              LLDB_INVALID_PROCESS_ID,
-                                             NULL, false,
+                                             NULL, 
+                                             false,
                                              launch_flags,
                                              inferior_arch);
             if (error.Fail())
@@ -644,6 +652,9 @@
                                          NULL,                      // inferior_argv
                                          NULL,                      // inferior_envp
                                          NULL,                      // stdin_path
+                                         NULL,                      // stdout_path
+                                         NULL,                      // stderr_path
+                                         NULL,                      // working_dir
                                          false,                     // launch_process == false (we are attaching)
                                          LLDB_INVALID_PROCESS_ID,   // Don't send any attach to pid options to debugserver
                                          NULL,                      // Don't send any attach by process name option to debugserver
@@ -746,6 +757,9 @@
                                          NULL,                      // inferior_argv
                                          NULL,                      // inferior_envp
                                          NULL,                      // stdin_path
+                                         NULL,                      // stdout_path
+                                         NULL,                      // stderr_path
+                                         NULL,                      // working_dir
                                          false,                     // launch_process == false (we are attaching)
                                          LLDB_INVALID_PROCESS_ID,   // Don't send any attach to pid options to debugserver
                                          NULL,                      // Don't send any attach by process name option to debugserver
@@ -1732,7 +1746,10 @@
     const char *debugserver_url,    // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
     char const *inferior_argv[],    // Arguments for the inferior program including the path to the inferior itself as the first argument
     char const *inferior_envp[],    // Environment to pass along to the inferior program
-    char const *stdio_path,
+    const char *stdin_path,
+    const char *stdout_path,
+    const char *stderr_path,
+    const char *working_dir,
     bool launch_process,            // Set to true if we are going to be launching a the process
     lldb::pid_t attach_pid,         // If inferior inferior_argv == NULL, and attach_pid != LLDB_INVALID_PROCESS_ID send this pid as an argument to debugserver
     const char *attach_name,        // Wait for the next process to launch whose basename matches "attach_name"
@@ -1824,7 +1841,13 @@
             char arg_cstr[PATH_MAX];
 
             lldb_utility::PseudoTerminal pty;
-            if (launch_process && stdio_path == NULL && m_local_debugserver && !no_stdio)
+            const char *stdio_path = NULL;
+            if (launch_process && 
+                stdin_path == NULL && 
+                stdout_path == NULL && 
+                stderr_path == NULL && 
+                m_local_debugserver &&
+                no_stdio == false)
             {
                 if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
                     stdio_path = pty.GetSlaveName (NULL, 0);
@@ -1843,14 +1866,60 @@
                 debugserver_args.AppendArguments("--disable-aslr");
             
             // Only set the inferior
-            if (launch_process && stdio_path)
+            if (launch_process)
             {
-                debugserver_args.AppendArgument("--stdio-path");
-                debugserver_args.AppendArgument(stdio_path);
+                if (no_stdio)
+                    debugserver_args.AppendArgument("--no-stdio");
+                else
+                {
+                    if (stdin_path && stdout_path && stderr_path && 
+                        strcmp(stdin_path, stdout_path) == 0 &&
+                        strcmp(stdin_path, stderr_path) == 0)
+                    {
+                        stdio_path = stdin_path;
+                        stdin_path = stdout_path = stderr_path = NULL;
+                    }
+
+                    if (stdio_path)
+                    {
+                        // All file handles to stdin, stdout, stderr are the same...
+                        debugserver_args.AppendArgument("--stdio-path");
+                        debugserver_args.AppendArgument(stdio_path);
+                    }
+                    else
+                    {
+                        if (stdin_path == NULL && (stdout_path || stderr_path))
+                            stdin_path = "/dev/null";
+
+                        if (stdout_path == NULL && (stdin_path || stderr_path))
+                            stdout_path = "/dev/null";
+
+                        if (stderr_path == NULL && (stdin_path || stdout_path))
+                            stderr_path = "/dev/null";
+
+                        if (stdin_path)
+                        {
+                            debugserver_args.AppendArgument("--stdin-path");
+                            debugserver_args.AppendArgument(stdin_path);
+                        }
+                        if (stdout_path)
+                        {
+                            debugserver_args.AppendArgument("--stdout-path");
+                            debugserver_args.AppendArgument(stdout_path);
+                        }
+                        if (stderr_path)
+                        {
+                            debugserver_args.AppendArgument("--stderr-path");
+                            debugserver_args.AppendArgument(stderr_path);
+                        }
+                    }
+                }
             }
-            else if (launch_process && no_stdio)
+
+            if (working_dir)
             {
-                debugserver_args.AppendArgument("--no-stdio");
+                debugserver_args.AppendArgument("--working-dir");
+                debugserver_args.AppendArgument(working_dir);
             }
 
             const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Sat Jan 22 23:56:20 2011
@@ -82,8 +82,9 @@
               char const *envp[],           // Can be NULL
               uint32_t flags,
               const char *stdin_path,       // Can be NULL
-              const char *stdout_path,  // Can be NULL
-              const char *stderr_path); // Can be NULL
+              const char *stdout_path,      // Can be NULL
+              const char *stderr_path,      // Can be NULL
+              const char *working_dir);     // Can be NULL
 
     virtual void
     DidLaunch ();
@@ -295,6 +296,9 @@
                              char const *inferior_argv[],
                              char const *inferior_envp[],
                              const char *stdin_path,
+                             const char *stdout_path,
+                             const char *stderr_path,
+                             const char *working_dir,
                              bool launch_process,           // Set to true if we are going to be launching a the process
                              lldb::pid_t attach_pid,        // If inferior inferior_argv == NULL, then attach to this pid
                              const char *attach_pid_name,   // Wait for the next process to launch whose basename matches "attach_wait_name"

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Sat Jan 22 23:56:20 2011
@@ -1456,7 +1456,8 @@
     uint32_t launch_flags,
     const char *stdin_path,
     const char *stdout_path,
-    const char *stderr_path
+    const char *stderr_path,
+    const char *working_directory
 )
 {
     Error error;
@@ -1507,7 +1508,8 @@
                                   launch_flags,
                                   stdin_path, 
                                   stdout_path, 
-                                  stderr_path);
+                                  stderr_path,
+                                  working_directory);
 
                 if (error.Fail())
                 {
@@ -3252,10 +3254,10 @@
     { "run-args",       eSetVarTypeArray,       NULL,           NULL,       false,  false,  "A list containing all the arguments to be passed to the executable when it is run." },
     { "env-vars",       eSetVarTypeDictionary,  NULL,           NULL,       false,  false,  "A list of all the environment variables to be passed to the executable's environment, and their values." },
     { "inherit-env",    eSetVarTypeBoolean,     "true",         NULL,       false,  false,  "Inherit the environment from the process that is running LLDB." },
-    { "input-path",     eSetVarTypeString,      "/dev/stdin",   NULL,       false,  false,  "The file/path to be used by the executable program for reading its input." },
-    { "output-path",    eSetVarTypeString,      "/dev/stdout",  NULL,       false,  false,  "The file/path to be used by the executable program for writing its output." },
-    { "error-path",     eSetVarTypeString,      "/dev/stderr",  NULL,       false,  false,  "The file/path to be used by the executable program for writings its error messages." },
-    { "plugin",         eSetVarTypeEnum,        NULL         ,  g_plugins,  false,  false,  "The plugin to be used to run the process." }, 
+    { "input-path",     eSetVarTypeString,      NULL,           NULL,       false,  false,  "The file/path to be used by the executable program for reading its input." },
+    { "output-path",    eSetVarTypeString,      NULL,           NULL,       false,  false,  "The file/path to be used by the executable program for writing its output." },
+    { "error-path",     eSetVarTypeString,      NULL,           NULL,       false,  false,  "The file/path to be used by the executable program for writings its error messages." },
+    { "plugin",         eSetVarTypeEnum,        NULL,           g_plugins,  false,  false,  "The plugin to be used to run the process." }, 
     { "disable-aslr",   eSetVarTypeBoolean,     "true",         NULL,       false,  false,  "Disable Address Space Layout Randomization (ASLR)" },
     { "disable-stdio",  eSetVarTypeBoolean,     "false",        NULL,       false,  false,  "Disable stdin/stdout for process (e.g. for a GUI application)" },
     {  NULL,            eSetVarTypeNone,        NULL,           NULL,       false,  false,  NULL }

Modified: lldb/trunk/tools/darwin-debug/darwin-debug.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/darwin-debug/darwin-debug.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/tools/darwin-debug/darwin-debug.cpp (original)
+++ lldb/trunk/tools/darwin-debug/darwin-debug.cpp Sat Jan 22 23:56:20 2011
@@ -30,8 +30,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/un.h>
 
 #include <string>
@@ -50,6 +51,7 @@
 	{ "help",           no_argument,		NULL,           'h'		},
 	{ "setsid",         no_argument,		NULL,           's'		},
 	{ "unix-socket",    required_argument,  NULL,           'u'		},
+    { "working-dir",    required_argument,  NULL,           'w'     },
 	{ NULL,				0,					NULL,            0		}
 };
 
@@ -62,7 +64,7 @@
 "                    for debugging.\n"
 "\n"
 "SYNOPSIS\n"
-"    darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
+"    darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] [--working-dir=<PATH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
 "\n"
 "DESCRIPTION\n"
 "    darwin-debug will exec itself into a child process <PROGRAM> that is\n"
@@ -95,7 +97,13 @@
 }
 
 pid_t
-posix_spawn_for_debug (char *const *argv, char *const *envp, cpu_type_t cpu_type, int disable_aslr)
+posix_spawn_for_debug 
+(
+    char *const *argv, 
+    char *const *envp, 
+    const char *working_dir,
+    cpu_type_t cpu_type, 
+    int disable_aslr)
 {
     pid_t pid = 0;
 
@@ -126,6 +134,15 @@
         size_t ocount = 0;
         exit_with_errno (::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), "posix_spawnattr_setbinpref_np () error: ");
     }
+    
+    // I wish there was a posix_spawn flag to change the working directory of
+    // the inferior process we will spawn, but there currently isn't. If there
+    // ever is a better way to do this, we should use it. I would rather not
+    // manually fork, chdir in the child process, and then posix_spawn with exec
+    // as the whole reason for doing posix_spawn is to not hose anything up
+    // after the fork and prior to the exec...
+    if (working_dir)
+        ::chdir (working_dir);
 
     exit_with_errno (::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), "posix_spawn() error: ");
     
@@ -157,6 +174,7 @@
     int disable_aslr = 0; // By default we disable ASLR
     int pass_env = 1;
     std::string unix_socket_name;
+    std::string working_dir;
 	while ((ch = getopt_long(argc, argv, "a:dehsu:?", g_long_options, NULL)) != -1)
 	{
 		switch (ch) 
@@ -199,6 +217,16 @@
             unix_socket_name.assign (optarg);
             break;
 
+        case 'w':
+            {
+                struct stat working_dir_stat;
+                if (stat (optarg, &working_dir_stat) == 0)
+                    working_dir.assign (optarg);
+                else
+                    ::fprintf(stderr, "warning: working directory doesn't exist: '%s'\n", optarg);
+            }
+            break;
+
 		case 'h':
 		case '?':
 		default:
@@ -254,7 +282,15 @@
     close (s);
 
     system("clear");
-    printf ("Launching '%s' for debug with %u arguments:\n", argv[0], argc);
+    if (working_dir.empty())
+    {
+        char cwd[PATH_MAX];
+        const char *cwd_ptr = getcwd(cwd, sizeof(cwd));
+        printf ("Launching '%s' in '%s' for debug with %u arguments:\n", argv[0], cwd_ptr, argc);
+    }
+    else
+        printf ("Launching '%s' in '%s' for debug with %u arguments:\n", argv[0], working_dir.c_str(), argc);
+
     for (int i=0; i<argc; ++i)
         printf ("argv[%u] = '%s'\n", i, argv[i]);
 
@@ -262,6 +298,7 @@
     // to debug.
     posix_spawn_for_debug (argv, 
                            pass_env ? envp : NULL, 
+                           working_dir.empty() ? NULL : working_dir.c_str(),
                            cpu_type, 
                            disable_aslr);
     

Modified: lldb/trunk/tools/debugserver/source/DNB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNB.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNB.cpp (original)
+++ lldb/trunk/tools/debugserver/source/DNB.cpp Sat Jan 22 23:56:20 2011
@@ -185,8 +185,21 @@
                   char *err_str,
                   size_t err_len)
 {
-    DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %zu) called...", __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr, err_str, err_len);
-
+    DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %zu) called...", 
+                     __FUNCTION__, 
+                     path, 
+                     argv, 
+                     envp, 
+                     working_directory,
+                     stdin_path,
+                     stdout_path,
+                     stderr_path,
+                     no_stdio,
+                     launch_flavor, 
+                     disable_aslr, 
+                     err_str, 
+                     err_len);
+    
     if (err_str && err_len > 0)
         err_str[0] = '\0';
     struct stat path_stat;

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachProcess.cpp Sat Jan 22 23:56:20 2011
@@ -1625,7 +1625,16 @@
 {
     posix_spawnattr_t attr;
     short flags;
-    DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, process )", __FUNCTION__, path, argv, envp);
+    DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, working_dir=%s, stdin=%s, stdout=%s stderr=%s, no-stdio=%i)", 
+                     __FUNCTION__, 
+                     path, 
+                     argv, 
+                     envp,
+                     working_directory,
+                     stdin_path,
+                     stdout_path,
+                     stderr_path,
+                     no_stdio);
 
     err.SetError( ::posix_spawnattr_init (&attr), DNBError::POSIX);
     if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
@@ -1703,9 +1712,9 @@
         }
         else
         {
-            int slave_fd_err = open (stderr_path ? stderr_path : "/dev/null", O_RDWR  , 0);
-            int slave_fd_in  = open (stdin_path  ? stdin_path  : "/dev/null", O_RDONLY, 0);
-            int slave_fd_out = open (stdout_path ? stdout_path : "/dev/null", O_WRONLY, 0);
+            int slave_fd_err = open (stderr_path ? stderr_path : "/dev/null", O_NOCTTY | O_CREAT | O_RDWR   , 0640);
+            int slave_fd_in  = open (stdin_path  ? stdin_path  : "/dev/null", O_NOCTTY | O_RDONLY);
+            int slave_fd_out = open (stdout_path ? stdout_path : "/dev/null", O_NOCTTY | O_CREAT | O_WRONLY , 0640);
 
             err.SetError( ::posix_spawn_file_actions_adddup2(&file_actions, slave_fd_err, STDERR_FILENO), DNBError::POSIX);
             if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
@@ -1719,12 +1728,23 @@
             if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
                 err.LogThreaded("::posix_spawn_file_actions_adddup2 ( &file_actions, filedes = %d, newfiledes = STDOUT_FILENO )", slave_fd_out);
         }
+
+        // TODO: Verify if we can set the working directory back immediately
+        // after the posix_spawnp call without creating a race condition???
+        if (working_directory)
+            ::chdir (working_directory);
+        
         err.SetError( ::posix_spawnp (&pid, path, &file_actions, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX);
         if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
             err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, &file_actions, &attr, argv, envp);
     }
     else
     {
+        // TODO: Verify if we can set the working directory back immediately
+        // after the posix_spawnp call without creating a race condition???
+        if (working_directory)
+            ::chdir (working_directory);
+        
         err.SetError( ::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX);
         if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
             err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, NULL, &attr, argv, envp);

Modified: lldb/trunk/tools/debugserver/source/debugserver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/debugserver.cpp?rev=124060&r1=124059&r2=124060&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/debugserver.cpp (original)
+++ lldb/trunk/tools/debugserver/source/debugserver.cpp Sat Jan 22 23:56:20 2011
@@ -651,14 +651,14 @@
     { "waitfor-interval",   required_argument,  NULL,               'i' },  // Time in usecs to wait between sampling the pid list when waiting for a process by name
     { "waitfor-duration",   required_argument,  NULL,               'd' },  // The time in seconds to wait for a process to show up by name
     { "native-regs",        no_argument,        NULL,               'r' },  // Specify to use the native registers instead of the gdb defaults for the architecture.
-    { "stdio-path",         required_argument,  NULL,               's' },  // Set the STDIO path to be used when launching applications (STDIN, STDOUT and STDERR)
-    { "stdin-path",         required_argument,  NULL,               'I' },  // Set the STDIN path to be used when launching applications
-    { "stdout-path",        required_argument,  NULL,               'O' },  // Set the STDIN path to be used when launching applications
-    { "stderr-path",        required_argument,  NULL,               'E' },  // Set the STDIN path to be used when launching applications
-    { "no-stdio",           no_argument,        NULL,               'n' },  // Do not set up any stdio (perhaps the program is a GUI program)
-    { "setsid",             no_argument,        NULL,               'S' },  // call setsid() to make debugserver run in its own sessions
+    { "stdio-path",         required_argument,  NULL,               's' },  // Set the STDIO path to be used when launching applications (STDIN, STDOUT and STDERR) (only if debugserver launches the process)
+    { "stdin-path",         required_argument,  NULL,               'I' },  // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
+    { "stdout-path",        required_argument,  NULL,               'O' },  // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
+    { "stderr-path",        required_argument,  NULL,               'E' },  // Set the STDIN path to be used when launching applications (only if debugserver launches the process)
+    { "no-stdio",           no_argument,        NULL,               'n' },  // Do not set up any stdio (perhaps the program is a GUI program) (only if debugserver launches the process)
+    { "setsid",             no_argument,        NULL,               'S' },  // call setsid() to make debugserver run in its own session
     { "disable-aslr",       no_argument,        NULL,               'D' },  // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
-    { "chdir",              no_argument,        NULL,               'c' },  // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
+    { "working-dir",        required_argument,  NULL,               'W' },  // The working directory that the inferior process should have (only if debugserver launches the process)
     { NULL,                 0,                  NULL,               0   }
 };
 
@@ -699,7 +699,7 @@
     std::string stdout_path;
     std::string stderr_path;
     std::string arch_name;
-    std::string working_directory;          // The new working directory to use for the inferior
+    std::string working_dir;          // The new working directory to use for the inferior
     useconds_t waitfor_interval = 1000;     // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
     useconds_t waitfor_duration = 0;        // Time in seconds to wait for a process by name, 0 means wait forever.
     bool no_stdio = false;
@@ -785,9 +785,9 @@
                 }
                 break;
 
-            case 'c':
+            case 'W':
                 if (optarg && optarg[0])
-                    working_directory.assign(optarg);
+                    working_dir.assign(optarg);
                 break;
 
             case 'x':
@@ -826,7 +826,7 @@
                     else if (strcasecmp(optarg, "stderr") == 0)
                         log_file = stderr;
                     else
-                        log_file = fopen(optarg, "w+");
+                        log_file = fopen(optarg, "w");
 
                     if (log_file == NULL)
                     {
@@ -938,11 +938,11 @@
         return -1;
     }
 
-    if (!working_directory.empty())
+    if (!working_dir.empty())
     {
-        if (remote->Context().SetWorkingDirectory (working_directory.c_str()) == false)
+        if (remote->Context().SetWorkingDirectory (working_dir.c_str()) == false)
         {
-            RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_directory.c_str());
+            RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_dir.c_str());
             exit (8);
         }
     }





More information about the lldb-commits mailing list