Refactor many file functions to use FileSpec over strings.

Summary:
This should solve the issue of sending denormalized paths over gdb-remote
if we stick to GetPath(false) in GDBRemoteCommunicationClient, and let the
server handle any denormalization.

Reviewers: ovyalov, zturner, vharron, clayborg

Reviewed By: clayborg

Subscribers: tberghammer, emaste, lldb-commits

Differential Revision: http://reviews.llvm.org/D9728

llvm-svn: 238604
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index b3956eb..210888b 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -954,17 +954,17 @@
 NativeProcessLinux::LaunchArgs::LaunchArgs(Module *module,
                                        char const **argv,
                                        char const **envp,
-                                       const std::string &stdin_path,
-                                       const std::string &stdout_path,
-                                       const std::string &stderr_path,
-                                       const char *working_dir,
+                                       const FileSpec &stdin_file_spec,
+                                       const FileSpec &stdout_file_spec,
+                                       const FileSpec &stderr_file_spec,
+                                       const FileSpec &working_dir,
                                        const ProcessLaunchInfo &launch_info)
     : m_module(module),
       m_argv(argv),
       m_envp(envp),
-      m_stdin_path(stdin_path),
-      m_stdout_path(stdout_path),
-      m_stderr_path(stderr_path),
+      m_stdin_file_spec(stdin_file_spec),
+      m_stdout_file_spec(stdout_file_spec),
+      m_stderr_file_spec(stderr_file_spec),
       m_working_dir(working_dir),
       m_launch_info(launch_info)
 {
@@ -989,50 +989,52 @@
     Error error;
 
     // Verify the working directory is valid if one was specified.
-    const char* working_dir = launch_info.GetWorkingDirectory ();
-    if (working_dir)
+    FileSpec working_dir{launch_info.GetWorkingDirectory()};
+    if (working_dir &&
+            (!working_dir.ResolvePath() ||
+             working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
     {
-      FileSpec working_dir_fs (working_dir, true);
-      if (!working_dir_fs || working_dir_fs.GetFileType () != FileSpec::eFileTypeDirectory)
-      {
-          error.SetErrorStringWithFormat ("No such file or directory: %s", working_dir);
-          return error;
-      }
+        error.SetErrorStringWithFormat ("No such file or directory: %s",
+                working_dir.GetCString());
+        return error;
     }
 
     const FileAction *file_action;
 
-    // Default of NULL will mean to use existing open file descriptors.
-    std::string stdin_path;
-    std::string stdout_path;
-    std::string stderr_path;
+    // Default of empty will mean to use existing open file descriptors.
+    FileSpec stdin_file_spec{};
+    FileSpec stdout_file_spec{};
+    FileSpec stderr_file_spec{};
 
     file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
     if (file_action)
-        stdin_path = file_action->GetPath ();
+        stdin_file_spec = file_action->GetFileSpec();
 
     file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
     if (file_action)
-        stdout_path = file_action->GetPath ();
+        stdout_file_spec = file_action->GetFileSpec();
 
     file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
     if (file_action)
-        stderr_path = file_action->GetPath ();
+        stderr_file_spec = file_action->GetFileSpec();
 
     if (log)
     {
-        if (!stdin_path.empty ())
-            log->Printf ("NativeProcessLinux::%s setting STDIN to '%s'", __FUNCTION__, stdin_path.c_str ());
+        if (stdin_file_spec)
+            log->Printf ("NativeProcessLinux::%s setting STDIN to '%s'",
+                    __FUNCTION__, stdin_file_spec.GetCString());
         else
             log->Printf ("NativeProcessLinux::%s leaving STDIN as is", __FUNCTION__);
 
-        if (!stdout_path.empty ())
-            log->Printf ("NativeProcessLinux::%s setting STDOUT to '%s'", __FUNCTION__, stdout_path.c_str ());
+        if (stdout_file_spec)
+            log->Printf ("NativeProcessLinux::%s setting STDOUT to '%s'",
+                    __FUNCTION__, stdout_file_spec.GetCString());
         else
             log->Printf ("NativeProcessLinux::%s leaving STDOUT as is", __FUNCTION__);
 
-        if (!stderr_path.empty ())
-            log->Printf ("NativeProcessLinux::%s setting STDERR to '%s'", __FUNCTION__, stderr_path.c_str ());
+        if (stderr_file_spec)
+            log->Printf ("NativeProcessLinux::%s setting STDERR to '%s'",
+                    __FUNCTION__, stderr_file_spec.GetCString());
         else
             log->Printf ("NativeProcessLinux::%s leaving STDERR as is", __FUNCTION__);
     }
@@ -1061,9 +1063,9 @@
             exe_module,
             launch_info.GetArguments ().GetConstArgumentVector (),
             launch_info.GetEnvironmentEntries ().GetConstArgumentVector (),
-            stdin_path,
-            stdout_path,
-            stderr_path,
+            stdin_file_spec,
+            stdout_file_spec,
+            stderr_file_spec,
             working_dir,
             launch_info,
             error);
@@ -1141,10 +1143,10 @@
     Module *module,
     const char *argv[],
     const char *envp[],
-    const std::string &stdin_path,
-    const std::string &stdout_path,
-    const std::string &stderr_path,
-    const char *working_dir,
+    const FileSpec &stdin_file_spec,
+    const FileSpec &stdout_file_spec,
+    const FileSpec &stderr_file_spec,
+    const FileSpec &working_dir,
     const ProcessLaunchInfo &launch_info,
     Error &error)
 {
@@ -1154,10 +1156,12 @@
     SetState (eStateLaunching);
 
     std::unique_ptr<LaunchArgs> args(
-        new LaunchArgs(
-            module, argv, envp,
-            stdin_path, stdout_path, stderr_path,
-            working_dir, launch_info));
+        new LaunchArgs(module, argv, envp,
+                       stdin_file_spec,
+                       stdout_file_spec,
+                       stderr_file_spec,
+                       working_dir,
+                       launch_info));
 
     StartMonitorThread ([&] (Error &e) { return Launch(args.get(), e); }, error);
     if (!error.Success ())
@@ -1226,7 +1230,7 @@
 
     const char **argv = args->m_argv;
     const char **envp = args->m_envp;
-    const char *working_dir = args->m_working_dir;
+    const FileSpec working_dir = args->m_working_dir;
 
     lldb_utility::PseudoTerminal terminal;
     const size_t err_len = 1024;
@@ -1286,16 +1290,16 @@
         }
 
         // Dup file descriptors if needed.
-        if (!args->m_stdin_path.empty ())
-            if (!DupDescriptor(args->m_stdin_path.c_str (), STDIN_FILENO, O_RDONLY))
+        if (args->m_stdin_file_spec)
+            if (!DupDescriptor(args->m_stdin_file_spec, STDIN_FILENO, O_RDONLY))
                 exit(eDupStdinFailed);
 
-        if (!args->m_stdout_path.empty ())
-            if (!DupDescriptor(args->m_stdout_path.c_str (), STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
+        if (args->m_stdout_file_spec)
+            if (!DupDescriptor(args->m_stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
                 exit(eDupStdoutFailed);
 
-        if (!args->m_stderr_path.empty ())
-            if (!DupDescriptor(args->m_stderr_path.c_str (), STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
+        if (args->m_stderr_file_spec)
+            if (!DupDescriptor(args->m_stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC))
                 exit(eDupStderrFailed);
 
         // Close everything besides stdin, stdout, and stderr that has no file
@@ -1305,8 +1309,7 @@
                 close(fd);
 
         // Change working directory
-        if (working_dir != NULL && working_dir[0])
-          if (0 != ::chdir(working_dir))
+        if (working_dir && 0 != ::chdir(working_dir.GetCString()))
               exit(eChdirFailed);
 
         // Disable ASLR if requested.
@@ -3310,9 +3313,9 @@
 }
 
 bool
-NativeProcessLinux::DupDescriptor(const char *path, int fd, int flags)
+NativeProcessLinux::DupDescriptor(const FileSpec &file_spec, int fd, int flags)
 {
-    int target_fd = open(path, flags, 0666);
+    int target_fd = open(file_spec.GetCString(), flags, 0666);
 
     if (target_fd == -1)
         return false;
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
index 71482e6..137f7fd 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -17,6 +17,7 @@
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/lldb-types.h"
 #include "lldb/Host/Debug.h"
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Host/HostThread.h"
 #include "lldb/Host/Mutex.h"
 #include "lldb/Target/MemoryRegionInfo.h"
@@ -195,21 +196,21 @@
             LaunchArgs(Module *module,
                     char const **argv,
                     char const **envp,
-                    const std::string &stdin_path,
-                    const std::string &stdout_path,
-                    const std::string &stderr_path,
-                    const char *working_dir,
+                    const FileSpec &stdin_file_spec,
+                    const FileSpec &stdout_file_spec,
+                    const FileSpec &stderr_file_spec,
+                    const FileSpec &working_dir,
                     const ProcessLaunchInfo &launch_info);
 
             ~LaunchArgs();
 
-            Module *m_module;                 // The executable image to launch.
-            char const **m_argv;              // Process arguments.
-            char const **m_envp;              // Process environment.
-            const std::string &m_stdin_path;  // Redirect stdin if not empty.
-            const std::string &m_stdout_path; // Redirect stdout if not empty.
-            const std::string &m_stderr_path; // Redirect stderr if not empty.
-            const char *m_working_dir;        // Working directory or NULL.
+            Module *m_module;                  // The executable image to launch.
+            char const **m_argv;               // Process arguments.
+            char const **m_envp;               // Process environment.
+            const FileSpec m_stdin_file_spec;  // Redirect stdin if not empty.
+            const FileSpec m_stdout_file_spec; // Redirect stdout if not empty.
+            const FileSpec m_stderr_file_spec; // Redirect stderr if not empty.
+            const FileSpec m_working_dir;      // Working directory or empty.
             const ProcessLaunchInfo &m_launch_info;
         };
 
@@ -227,10 +228,10 @@
             Module *module,
             char const *argv[],
             char const *envp[],
-            const std::string &stdin_path,
-            const std::string &stdout_path,
-            const std::string &stderr_path,
-            const char *working_dir,
+            const FileSpec &stdin_file_spec,
+            const FileSpec &stdout_file_spec,
+            const FileSpec &stderr_file_spec,
+            const FileSpec &working_dir,
             const ProcessLaunchInfo &launch_info,
             Error &error);
 
@@ -252,7 +253,7 @@
         SetDefaultPtraceOpts(const lldb::pid_t);
 
         static bool
-        DupDescriptor(const char *path, int fd, int flags);
+        DupDescriptor(const FileSpec &file_spec, int fd, int flags);
 
         static void *
         MonitorThread(void *baton);
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
index a4063e5..d5341f1 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -1185,18 +1185,18 @@
                                        lldb_private::Module *module,
                                        char const **argv,
                                        char const **envp,
-                                       const char *stdin_path,
-                                       const char *stdout_path,
-                                       const char *stderr_path,
-                                       const char *working_dir,
+                                       const FileSpec &stdin_file_spec,
+                                       const FileSpec &stdout_file_spec,
+                                       const FileSpec &stderr_file_spec,
+                                       const FileSpec &working_dir,
                                        const lldb_private::ProcessLaunchInfo &launch_info)
     : OperationArgs(monitor),
       m_module(module),
       m_argv(argv),
       m_envp(envp),
-      m_stdin_path(stdin_path),
-      m_stdout_path(stdout_path),
-      m_stderr_path(stderr_path),
+      m_stdin_file_spec(stdin_file_spec),
+      m_stdout_file_spec(stdout_file_spec),
+      m_stderr_file_spec(stderr_file_spec),
       m_working_dir(working_dir),
       m_launch_info(launch_info)
 {
@@ -1228,10 +1228,10 @@
                                Module *module,
                                const char *argv[],
                                const char *envp[],
-                               const char *stdin_path,
-                               const char *stdout_path,
-                               const char *stderr_path,
-                               const char *working_dir,
+                               const FileSpec &stdin_file_spec,
+                               const FileSpec &stdout_file_spec,
+                               const FileSpec &stderr_file_spec,
+                               const FileSpec &working_dir,
                                const lldb_private::ProcessLaunchInfo &launch_info,
                                lldb_private::Error &error)
     : m_process(static_cast<ProcessLinux *>(process)),
@@ -1242,8 +1242,11 @@
       m_operation(0)
 {
     std::unique_ptr<LaunchArgs> args(new LaunchArgs(this, module, argv, envp,
-                                     stdin_path, stdout_path, stderr_path,
-                                     working_dir, launch_info));
+                                                    stdin_file_spec,
+                                                    stdout_file_spec,
+                                                    stderr_file_spec,
+                                                    working_dir,
+                                                    launch_info));
 
     sem_init(&m_operation_pending, 0, 0);
     sem_init(&m_operation_done, 0, 0);
@@ -1378,10 +1381,10 @@
     ProcessLinux &process = monitor->GetProcess();
     const char **argv = args->m_argv;
     const char **envp = args->m_envp;
-    const char *stdin_path = args->m_stdin_path;
-    const char *stdout_path = args->m_stdout_path;
-    const char *stderr_path = args->m_stderr_path;
-    const char *working_dir = args->m_working_dir;
+    const FileSpec &stdin_file_spec = args->m_stdin_file_spec;
+    const FileSpec &stdout_file_spec = args->m_stdout_file_spec;
+    const FileSpec &stderr_file_spec = args->m_stderr_file_spec;
+    const FileSpec &working_dir = args->m_working_dir;
 
     lldb_utility::PseudoTerminal terminal;
     const size_t err_len = 1024;
@@ -1436,22 +1439,21 @@
         //
         // FIXME: If two or more of the paths are the same we needlessly open
         // the same file multiple times.
-        if (stdin_path != NULL && stdin_path[0])
-            if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY))
+        if (stdin_file_spec)
+            if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY))
                 exit(eDupStdinFailed);
 
-        if (stdout_path != NULL && stdout_path[0])
-            if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT))
+        if (stdout_file_spec)
+            if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT))
                 exit(eDupStdoutFailed);
 
-        if (stderr_path != NULL && stderr_path[0])
-            if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
+        if (stderr_file_spec)
+            if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT))
                 exit(eDupStderrFailed);
 
         // Change working directory
-        if (working_dir != NULL && working_dir[0])
-          if (0 != ::chdir(working_dir))
-              exit(eChdirFailed);
+        if (working_dir && 0 != ::chdir(working_dir.GetCString()))
+            exit(eChdirFailed);
 
         // Disable ASLR if requested.
         if (args->m_launch_info.GetFlags ().Test (lldb::eLaunchFlagDisableASLR))
@@ -2402,9 +2404,9 @@
 }
 
 bool
-ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
+ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, int flags)
 {
-    int target_fd = open(path, flags, 0666);
+    int target_fd = open(file_spec.GetCString(), flags, 0666);
 
     if (target_fd == -1)
         return false;
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
index a399856..8fc97bc 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
@@ -17,6 +17,7 @@
 // C++ Includes
 // Other libraries and framework includes
 #include "lldb/lldb-types.h"
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Host/HostThread.h"
 #include "lldb/Host/Mutex.h"
 
@@ -58,10 +59,10 @@
                    lldb_private::Module *module,
                    char const *argv[],
                    char const *envp[],
-                   const char *stdin_path,
-                   const char *stdout_path,
-                   const char *stderr_path,
-                   const char *working_dir,
+                   const lldb_private::FileSpec &stdin_file_spec,
+                   const lldb_private::FileSpec &stdout_file_spec,
+                   const lldb_private::FileSpec &stderr_file_spec,
+                   const lldb_private::FileSpec &working_dir,
                    const lldb_private::ProcessLaunchInfo &launch_info,
                    lldb_private::Error &error);
 
@@ -251,21 +252,21 @@
                    lldb_private::Module *module,
                    char const **argv,
                    char const **envp,
-                   const char *stdin_path,
-                   const char *stdout_path,
-                   const char *stderr_path,
-                   const char *working_dir,
+                   const lldb_private::FileSpec &stdin_file_spec,
+                   const lldb_private::FileSpec &stdout_file_spec,
+                   const lldb_private::FileSpec &stderr_file_spec,
+                   const lldb_private::FileSpec &working_dir,
                    const lldb_private::ProcessLaunchInfo &launch_info);
 
         ~LaunchArgs();
 
-        lldb_private::Module *m_module; // The executable image to launch.
-        char const **m_argv;            // Process arguments.
-        char const **m_envp;            // Process environment.
-        const char *m_stdin_path;       // Redirect stdin or NULL.
-        const char *m_stdout_path;      // Redirect stdout or NULL.
-        const char *m_stderr_path;      // Redirect stderr or NULL.
-        const char *m_working_dir;      // Working directory or NULL.
+        lldb_private::Module *m_module;                  // The executable image to launch.
+        char const **m_argv;                             // Process arguments.
+        char const **m_envp;                             // Process environment.
+        const lldb_private::FileSpec m_stdin_file_spec;  // Redirect stdin or empty.
+        const lldb_private::FileSpec m_stdout_file_spec; // Redirect stdout or empty.
+        const lldb_private::FileSpec m_stderr_file_spec; // Redirect stderr or empty.
+        const lldb_private::FileSpec m_working_dir;      // Working directory or empty.
         const lldb_private::ProcessLaunchInfo &m_launch_info;
     };
 
@@ -304,7 +305,7 @@
     ServeOperation(OperationArgs *args);
 
     static bool
-    DupDescriptor(const char *path, int fd, int flags);
+    DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, int flags);
 
     static bool
     MonitorCallback(void *callback_baton,
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 82ce0c7..4b4080d 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -50,9 +50,9 @@
 {
     // FIXME: Putting this code in the ctor and saving the byte order in a
     // member variable is a hack to avoid const qual issues in GetByteOrder.
-	lldb::ModuleSP module = GetTarget().GetExecutableModule();
-	if (module && module->GetObjectFile())
-		m_byte_order = module->GetObjectFile()->GetByteOrder();
+    lldb::ModuleSP module = GetTarget().GetExecutableModule();
+    if (module && module->GetObjectFile())
+        m_byte_order = module->GetObjectFile()->GetByteOrder();
 }
 
 ProcessPOSIX::~ProcessPOSIX()
@@ -138,27 +138,24 @@
     return error;
 }
 
-const char *
-ProcessPOSIX::GetFilePath(const lldb_private::FileAction *file_action, const char *default_path,
-                          const char *dbg_pts_path)
+FileSpec
+ProcessPOSIX::GetFileSpec(const lldb_private::FileAction *file_action,
+                          const FileSpec &default_file_spec,
+                          const FileSpec &dbg_pts_file_spec)
 {
-    const char *path = NULL;
+    FileSpec file_spec{};
 
-    if (file_action)
+    if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
     {
-        if (file_action->GetAction() == FileAction::eFileActionOpen)
-        {
-            path = file_action->GetPath();
-            // By default the stdio paths passed in will be pseudo-terminal
-            // (/dev/pts). If so, convert to using a different default path
-            // instead to redirect I/O to the debugger console. This should
-            //  also handle user overrides to /dev/null or a different file.
-            if (!path || (dbg_pts_path &&
-                          ::strncmp(path, dbg_pts_path, ::strlen(dbg_pts_path)) == 0))
-                path = default_path;
-        }
+        file_spec = file_action->GetFileSpec();
+        // By default the stdio paths passed in will be pseudo-terminal
+        // (/dev/pts). If so, convert to using a different default path
+        // instead to redirect I/O to the debugger console. This should
+        // also handle user overrides to /dev/null or a different file.
+        if (!file_spec || file_spec == dbg_pts_file_spec)
+            file_spec = default_file_spec;
     }
-    return path;
+    return file_spec;
 }
 
 Error
@@ -168,46 +165,46 @@
     Error error;
     assert(m_monitor == NULL);
 
-    const char* working_dir = launch_info.GetWorkingDirectory();
-    if (working_dir) {
-      FileSpec WorkingDir(working_dir, true);
-      if (!WorkingDir || WorkingDir.GetFileType() != FileSpec::eFileTypeDirectory)
-      {
-          error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
-          return error;
-      }
+    FileSpec working_dir = launch_info.GetWorkingDirectory();
+    if (working_dir &&
+            (!working_dir.ResolvePath() ||
+             working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
+    {
+        error.SetErrorStringWithFormat("No such file or directory: %s",
+                working_dir.GetCString());
+        return error;
     }
 
     SetPrivateState(eStateLaunching);
 
     const lldb_private::FileAction *file_action;
 
-    // Default of NULL will mean to use existing open file descriptors
-    const char *stdin_path = NULL;
-    const char *stdout_path = NULL;
-    const char *stderr_path = NULL;
+    // Default of empty will mean to use existing open file descriptors
+    FileSpec stdin_file_spec{};
+    FileSpec stdout_file_spec{};
+    FileSpec stderr_file_spec{};
 
-    const char * dbg_pts_path = launch_info.GetPTY().GetSlaveName(NULL,0);
+    const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};
 
     file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
-    stdin_path = GetFilePath(file_action, stdin_path, dbg_pts_path);
+    stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
 
     file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
-    stdout_path = GetFilePath(file_action, stdout_path, dbg_pts_path);
+    stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
 
     file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
-    stderr_path = GetFilePath(file_action, stderr_path, dbg_pts_path);
+    stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
 
-    m_monitor = new ProcessMonitor (this, 
-                                    module,
-                                    launch_info.GetArguments().GetConstArgumentVector(), 
-                                    launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
-                                    stdin_path, 
-                                    stdout_path, 
-                                    stderr_path,
-                                    working_dir,
-                                    launch_info,
-                                    error);
+    m_monitor = new ProcessMonitor(this,
+                                   module,
+                                   launch_info.GetArguments().GetConstArgumentVector(),
+                                   launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
+                                   stdin_file_spec,
+                                   stdout_file_spec,
+                                   stderr_file_spec,
+                                   working_dir,
+                                   launch_info,
+                                   error);
 
     m_module = module;
 
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
index 2e8f46e..7d5ec68 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -151,8 +151,10 @@
     ProcessMonitor &
     GetMonitor() { assert(m_monitor); return *m_monitor; }
 
-    const char *GetFilePath(const lldb_private::FileAction *file_action, const char *default_path,
-                            const char *dbg_pts_path);
+    lldb_private::FileSpec
+    GetFileSpec(const lldb_private::FileAction *file_action,
+                const lldb_private::FileSpec &default_file_spec,
+                const lldb_private::FileSpec &dbg_pts_file_spec);
 
     /// Stops all threads in the process.
     /// The \p stop_tid parameter indicates the thread which initiated the stop.
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 3e92788..0a1ec3f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1325,7 +1325,7 @@
     const char *arg = NULL;
     const Args &launch_args = launch_info.GetArguments();
     if (exe_file)
-        exe_path = exe_file.GetPath();
+        exe_path = exe_file.GetPath(false);
     else
     {
         arg = launch_args.GetArgumentAtIndex(0);
@@ -2221,13 +2221,14 @@
 }
 
 int
-GDBRemoteCommunicationClient::SetSTDIN (char const *path)
+GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec)
 {
-    if (path && path[0])
+    if (file_spec)
     {
+        std::string path{file_spec.GetPath(false)};
         StreamString packet;
         packet.PutCString("QSetSTDIN:");
-        packet.PutBytesAsRawHex8(path, strlen(path));
+        packet.PutCStringAsRawHex8(path.c_str());
 
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
@@ -2243,14 +2244,15 @@
 }
 
 int
-GDBRemoteCommunicationClient::SetSTDOUT (char const *path)
+GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec)
 {
-    if (path && path[0])
+    if (file_spec)
     {
+        std::string path{file_spec.GetPath(false)};
         StreamString packet;
         packet.PutCString("QSetSTDOUT:");
-        packet.PutBytesAsRawHex8(path, strlen(path));
-        
+        packet.PutCStringAsRawHex8(path.c_str());
+
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
         {
@@ -2265,14 +2267,15 @@
 }
 
 int
-GDBRemoteCommunicationClient::SetSTDERR (char const *path)
+GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec)
 {
-    if (path && path[0])
+    if (file_spec)
     {
+        std::string path{file_spec.GetPath(false)};
         StreamString packet;
         packet.PutCString("QSetSTDERR:");
-        packet.PutBytesAsRawHex8(path, strlen(path));
-        
+        packet.PutCStringAsRawHex8(path.c_str());
+
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
         {
@@ -2287,7 +2290,7 @@
 }
 
 bool
-GDBRemoteCommunicationClient::GetWorkingDir (std::string &cwd)
+GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir)
 {
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse ("qGetWorkingDir", response, false) == PacketResult::Success)
@@ -2296,21 +2299,24 @@
             return false;
         if (response.IsErrorResponse())
             return false;
-        response.GetHexByteString (cwd);
+        std::string cwd;
+        response.GetHexByteString(cwd);
+        working_dir.SetFile(cwd, false);
         return !cwd.empty();
     }
     return false;
 }
 
 int
-GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
+GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir)
 {
-    if (path && path[0])
+    if (working_dir)
     {
+        std::string path{working_dir.GetPath(false)};
         StreamString packet;
         packet.PutCString("QSetWorkingDir:");
-        packet.PutBytesAsRawHex8(path, strlen(path));
-        
+        packet.PutCStringAsRawHex8(path.c_str());
+
         StringExtractorGDBRemote response;
         if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
         {
@@ -3262,22 +3268,23 @@
 }
 
 lldb_private::Error
-GDBRemoteCommunicationClient::RunShellCommand (const char *command,           // Shouldn't be NULL
-                                               const char *working_dir,       // Pass NULL to use the current working directory
-                                               int *status_ptr,               // Pass NULL if you don't want the process exit status
-                                               int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
-                                               std::string *command_output,   // Pass NULL if you don't want the command output
-                                               uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
+GDBRemoteCommunicationClient::RunShellCommand(const char *command,           // Shouldn't be NULL
+                                              const FileSpec &working_dir,   // Pass empty FileSpec to use the current working directory
+                                              int *status_ptr,               // Pass NULL if you don't want the process exit status
+                                              int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
+                                              std::string *command_output,   // Pass NULL if you don't want the command output
+                                              uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
 {
     lldb_private::StreamString stream;
     stream.PutCString("qPlatform_shell:");
     stream.PutBytesAsRawHex8(command, strlen(command));
     stream.PutChar(',');
     stream.PutHex32(timeout_sec);
-    if (working_dir && *working_dir)
+    if (working_dir)
     {
+        std::string path{working_dir.GetPath(false)};
         stream.PutChar(',');
-        stream.PutBytesAsRawHex8(working_dir, strlen(working_dir));
+        stream.PutCStringAsRawHex8(path.c_str());
     }
     const char *packet = stream.GetData();
     int packet_len = stream.GetSize();
@@ -3310,14 +3317,15 @@
 }
 
 Error
-GDBRemoteCommunicationClient::MakeDirectory (const char *path,
-                                             uint32_t file_permissions)
+GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
+                                            uint32_t file_permissions)
 {
+    std::string path{file_spec.GetPath(false)};
     lldb_private::StreamString stream;
     stream.PutCString("qPlatform_mkdir:");
     stream.PutHex32(file_permissions);
     stream.PutChar(',');
-    stream.PutBytesAsRawHex8(path, strlen(path));
+    stream.PutCStringAsRawHex8(path.c_str());
     const char *packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
@@ -3332,14 +3340,15 @@
 }
 
 Error
-GDBRemoteCommunicationClient::SetFilePermissions (const char *path,
-                                                  uint32_t file_permissions)
+GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
+                                                 uint32_t file_permissions)
 {
+    std::string path{file_spec.GetPath(false)};
     lldb_private::StreamString stream;
     stream.PutCString("qPlatform_chmod:");
     stream.PutHex32(file_permissions);
     stream.PutChar(',');
-    stream.PutBytesAsRawHex8(path, strlen(path));
+    stream.PutCStringAsRawHex8(path.c_str());
     const char *packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
@@ -3382,9 +3391,9 @@
                                         mode_t mode,
                                         Error &error)
 {
+    std::string path(file_spec.GetPath(false));
     lldb_private::StreamString stream;
     stream.PutCString("vFile:open:");
-    std::string path (file_spec.GetPath(false));
     if (path.empty())
         return UINT64_MAX;
     stream.PutCStringAsRawHex8(path.c_str());
@@ -3422,9 +3431,9 @@
 lldb::user_id_t
 GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_spec)
 {
+    std::string path(file_spec.GetPath(false));
     lldb_private::StreamString stream;
     stream.PutCString("vFile:size:");
-    std::string path (file_spec.GetPath());
     stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
@@ -3440,12 +3449,14 @@
 }
 
 Error
-GDBRemoteCommunicationClient::GetFilePermissions(const char *path, uint32_t &file_permissions)
+GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
+                                                 uint32_t &file_permissions)
 {
+    std::string path{file_spec.GetPath(false)};
     Error error;
     lldb_private::StreamString stream;
     stream.PutCString("vFile:mode:");
-    stream.PutCStringAsRawHex8(path);
+    stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
@@ -3564,16 +3575,18 @@
 }
 
 Error
-GDBRemoteCommunicationClient::CreateSymlink (const char *src, const char *dst)
+GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, const FileSpec &dst)
 {
+    std::string src_path{src.GetPath(false)},
+                dst_path{dst.GetPath(false)};
     Error error;
     lldb_private::StreamGDBRemote stream;
     stream.PutCString("vFile:symlink:");
     // the unix symlink() command reverses its parameters where the dst if first,
     // so we follow suit here
-    stream.PutCStringAsRawHex8(dst);
+    stream.PutCStringAsRawHex8(dst_path.c_str());
     stream.PutChar(',');
-    stream.PutCStringAsRawHex8(src);
+    stream.PutCStringAsRawHex8(src_path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
@@ -3607,14 +3620,15 @@
 }
 
 Error
-GDBRemoteCommunicationClient::Unlink (const char *path)
+GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec)
 {
+    std::string path{file_spec.GetPath(false)};
     Error error;
     lldb_private::StreamGDBRemote stream;
     stream.PutCString("vFile:unlink:");
     // the unix symlink() command reverses its parameters where the dst if first,
     // so we follow suit here
-    stream.PutCStringAsRawHex8(path);
+    stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
     StringExtractorGDBRemote response;
@@ -3651,9 +3665,9 @@
 bool
 GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec)
 {
+    std::string path(file_spec.GetPath(false));
     lldb_private::StreamString stream;
     stream.PutCString("vFile:exists:");
-    std::string path (file_spec.GetPath());
     stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
@@ -3675,9 +3689,9 @@
                                             uint64_t &high,
                                             uint64_t &low)
 {
+    std::string path(file_spec.GetPath(false));
     lldb_private::StreamString stream;
     stream.PutCString("vFile:MD5:");
-    std::string path (file_spec.GetPath());
     stream.PutCStringAsRawHex8(path.c_str());
     const char* packet = stream.GetData();
     int packet_len = stream.GetSize();
@@ -3874,7 +3888,7 @@
     packet.PutCStringAsRawHex8(module_path.c_str());
     packet.PutCString(";");
     const auto& triple = arch_spec.GetTriple().getTriple();
-    packet.PutBytesAsRawHex8(triple.c_str(), triple.size());
+    packet.PutCStringAsRawHex8(triple.c_str());
 
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) != PacketResult::Success)
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 23b5d38..726bc57 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -205,11 +205,11 @@
     ///     Zero if the for success, or an error code for failure.
     //------------------------------------------------------------------
     int
-    SetSTDIN (char const *path);
+    SetSTDIN(const FileSpec &file_spec);
     int
-    SetSTDOUT (char const *path);
+    SetSTDOUT(const FileSpec &file_spec);
     int
-    SetSTDERR (char const *path);
+    SetSTDERR(const FileSpec &file_spec);
 
     //------------------------------------------------------------------
     /// Sets the disable ASLR flag to \a enable for a process that will 
@@ -243,27 +243,27 @@
     /// implements the platform, it will change the current working
     /// directory for the platform process.
     ///
-    /// @param[in] path
+    /// @param[in] working_dir
     ///     The path to a directory to use when launching our process
     ///
     /// @return
     ///     Zero if the for success, or an error code for failure.
     //------------------------------------------------------------------
     int
-    SetWorkingDir (char const *path);
+    SetWorkingDir(const FileSpec &working_dir);
 
     //------------------------------------------------------------------
     /// Gets the current working directory of a remote platform GDB
     /// server.
     ///
-    /// @param[out] cwd
+    /// @param[out] working_dir
     ///     The current working directory on the remote platform.
     ///
     /// @return
     ///     Boolean for success
     //------------------------------------------------------------------
     bool
-    GetWorkingDir (std::string &cwd);
+    GetWorkingDir(FileSpec &working_dir);
 
     lldb::addr_t
     AllocateMemory (size_t size, uint32_t permissions);
@@ -466,10 +466,10 @@
     GetFileSize (const FileSpec& file_spec);
     
     Error
-    GetFilePermissions(const char *path, uint32_t &file_permissions);
+    GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions);
 
     Error
-    SetFilePermissions(const char *path, uint32_t file_permissions);
+    SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions);
 
     uint64_t
     ReadFile (lldb::user_id_t fd,
@@ -486,26 +486,26 @@
                Error &error);
     
     Error
-    CreateSymlink (const char *src,
-                   const char *dst);
+    CreateSymlink(const FileSpec &src,
+                  const FileSpec &dst);
     
     Error
-    Unlink (const char *path);
+    Unlink(const FileSpec &file_spec);
 
     Error
-    MakeDirectory (const char *path, uint32_t mode);
-    
+    MakeDirectory(const FileSpec &file_spec, uint32_t mode);
+
     bool
     GetFileExists (const FileSpec& file_spec);
     
     Error
-    RunShellCommand (const char *command,           // Shouldn't be NULL
-                     const char *working_dir,       // Pass NULL to use the current working directory
-                     int *status_ptr,               // Pass NULL if you don't want the process exit status
-                     int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
-                     std::string *command_output,   // Pass NULL if you don't want the command output
-                     uint32_t timeout_sec);         // Timeout in seconds to wait for shell program to finish
-    
+    RunShellCommand(const char *command,           // Shouldn't be NULL
+                    const FileSpec &working_dir,   // Pass empty FileSpec to use the current working directory
+                    int *status_ptr,               // Pass NULL if you don't want the process exit status
+                    int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
+                    std::string *command_output,   // Pass NULL if you don't want the command output
+                    uint32_t timeout_sec);         // Timeout in seconds to wait for shell program to finish
+
     bool
     CalculateMD5 (const FileSpec& file_spec, uint64_t &high, uint64_t &low);
     
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index c61d9f4..18e8118 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -584,8 +584,8 @@
             {
                 mode_t mode = packet.GetHexMaxU32(false, 0600);
                 Error error;
-                const FileSpec path_spec(path.c_str(), true);
-                int fd = ::open (path_spec.GetPath().c_str(), flags, mode);
+                const FileSpec path_spec{path, true};
+                int fd = ::open(path_spec.GetCString(), flags, mode);
                 const int save_errno = fd == -1 ? errno : 0;
                 StreamString response;
                 response.PutChar('F');
@@ -734,7 +734,7 @@
     if (!path.empty())
     {
         Error error;
-        const uint32_t mode = File::GetPermissions(path.c_str(), error);
+        const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error);
         StreamString response;
         response.Printf("F%u", mode);
         if (mode == 0 || error.Fail())
@@ -773,7 +773,7 @@
     packet.GetHexByteStringTerminatedBy(dst, ',');
     packet.GetChar(); // Skip ',' char
     packet.GetHexByteString(src);
-    Error error = FileSystem::Symlink(src.c_str(), dst.c_str());
+    Error error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false});
     StreamString response;
     response.Printf("F%u,%u", error.GetError(), error.GetError());
     return SendPacketNoLock(response.GetData(), response.GetSize());
@@ -785,7 +785,7 @@
     packet.SetFilePos(::strlen("vFile:unlink:"));
     std::string path;
     packet.GetHexByteString(path);
-    Error error = FileSystem::Unlink(path.c_str());
+    Error error = FileSystem::Unlink(FileSpec{path, true});
     StreamString response;
     response.Printf("F%u,%u", error.GetError(), error.GetError());
     return SendPacketNoLock(response.GetData(), response.GetSize());
@@ -810,7 +810,7 @@
             int status, signo;
             std::string output;
             Error err = Host::RunShellCommand(path.c_str(),
-                                              working_dir.empty() ? NULL : working_dir.c_str(),
+                                              FileSpec{working_dir, true},
                                               &status, &signo, &output, timeout);
             StreamGDBRemote response;
             if (err.Fail())
@@ -875,8 +875,8 @@
     {
         std::string path;
         packet.GetHexByteString(path);
-        Error error = FileSystem::MakeDirectory(path.c_str(), mode);
-        
+        Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode);
+
         StreamGDBRemote response;
         response.Printf("F%u", error.GetError());
 
@@ -895,7 +895,7 @@
     {
         std::string path;
         packet.GetHexByteString(path);
-        Error error = FileSystem::SetFilePermissions(path.c_str(), mode);
+        Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode);
 
         StreamGDBRemote response;
         response.Printf("F%u", error.GetError());
@@ -968,7 +968,7 @@
     packet.GetHexByteString(path);
     const bool read = false;
     const bool write = true;
-    if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
+    if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write))
     {
         m_process_launch_info.AppendFileAction(file_action);
         return SendOKResponse ();
@@ -985,7 +985,7 @@
     packet.GetHexByteString(path);
     const bool read = true;
     const bool write = false;
-    if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
+    if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write))
     {
         m_process_launch_info.AppendFileAction(file_action);
         return SendOKResponse ();
@@ -1002,7 +1002,7 @@
     packet.GetHexByteString(path);
     const bool read = true;
     const bool write = false;
-    if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
+    if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write))
     {
         m_process_launch_info.AppendFileAction(file_action);
         return SendOKResponse ();
@@ -1217,7 +1217,7 @@
     response.PutChar(';');
 
     response.PutCString("file_path:");
-    response.PutCStringAsRawHex8(module_path_spec.GetPath().c_str());
+    response.PutCStringAsRawHex8(module_path_spec.GetCString());
     response.PutChar(';');
     response.PutCString("file_offset:");
     response.PutHex64(file_offset);
@@ -1241,7 +1241,7 @@
                      proc_info.GetEffectiveUserID(),
                      proc_info.GetEffectiveGroupID());
     response.PutCString ("name:");
-    response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetPath().c_str());
+    response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString());
     response.PutChar(';');
     const ArchSpec &proc_arch = proc_info.GetArchitecture();
     if (proc_arch.IsValid())
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 5ffd1e9..8b31dbe 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -950,18 +950,18 @@
     packet.SetFilePos (::strlen ("QSetWorkingDir:"));
     std::string path;
     packet.GetHexByteString (path);
-    m_process_launch_info.SwapWorkingDirectory (path);
+    m_process_launch_info.SetWorkingDirectory(FileSpec{path, true});
     return SendOKResponse ();
 }
 
 GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
 {
-    const char *working_dir = m_process_launch_info.GetWorkingDirectory();
-    if (working_dir && working_dir[0])
+    FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
+    if (working_dir)
     {
         StreamString response;
-        response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
+        response.PutCStringAsRawHex8(working_dir.GetCString());
         return SendPacketNoLock(response.GetData(), response.GetSize());
     }
 
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 3c825c7..7100163 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -878,45 +878,45 @@
         log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__);
 
     uint32_t launch_flags = launch_info.GetFlags().Get();
-    const char *stdin_path = NULL;
-    const char *stdout_path = NULL;
-    const char *stderr_path = NULL;
-    const char *working_dir = launch_info.GetWorkingDirectory();
+    FileSpec stdin_file_spec{};
+    FileSpec stdout_file_spec{};
+    FileSpec stderr_file_spec{};
+    FileSpec working_dir = launch_info.GetWorkingDirectory();
 
     const FileAction *file_action;
     file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
     if (file_action)
     {
         if (file_action->GetAction() == FileAction::eFileActionOpen)
-            stdin_path = file_action->GetPath();
+            stdin_file_spec = file_action->GetFileSpec();
     }
     file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
     if (file_action)
     {
         if (file_action->GetAction() == FileAction::eFileActionOpen)
-            stdout_path = file_action->GetPath();
+            stdout_file_spec = file_action->GetFileSpec();
     }
     file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
     if (file_action)
     {
         if (file_action->GetAction() == FileAction::eFileActionOpen)
-            stderr_path = file_action->GetPath();
+            stderr_file_spec = file_action->GetFileSpec();
     }
 
     if (log)
     {
-        if (stdin_path || stdout_path || stderr_path)
+        if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
             log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stderr=%s",
                          __FUNCTION__,
-                         stdin_path ? stdin_path : "<null>",
-                         stdout_path ? stdout_path : "<null>",
-                         stderr_path ? stderr_path : "<null>");
+                          stdin_file_spec ?  stdin_file_spec.GetCString() : "<null>",
+                         stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+                         stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
         else
             log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__);
     }
 
     const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
-    if (stdin_path || disable_stdio)
+    if (stdin_file_spec || disable_stdio)
     {
         // the inferior will be reading stdin from the specified file
         // or stdio is completely disabled
@@ -949,12 +949,12 @@
             if (disable_stdio)
             {
                 // set to /dev/null unless redirected to a file above
-                if (!stdin_path)
-                    stdin_path = "/dev/null";
-                if (!stdout_path)
-                    stdout_path = "/dev/null";
-                if (!stderr_path)
-                    stderr_path = "/dev/null";
+                if (!stdin_file_spec)
+                    stdin_file_spec.SetFile("/dev/null", false);
+                if (!stdout_file_spec)
+                    stdout_file_spec.SetFile("/dev/null", false);
+                if (!stderr_file_spec)
+                    stderr_file_spec.SetFile("/dev/null", false);
             }
             else if (platform_sp && platform_sp->IsHost())
             {
@@ -962,42 +962,41 @@
                 // a pseudo terminal to instead of relying on the 'O' packets for stdio
                 // since 'O' packets can really slow down debugging if the inferior
                 // does a lot of output.
-                const char *slave_name = NULL;
-                if (stdin_path == NULL || stdout_path == NULL || stderr_path == NULL)
+                if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
+                        pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
                 {
-                    if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
-                        slave_name = pty.GetSlaveName (NULL, 0);
+                    FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};
+
+                    if (!stdin_file_spec)
+                        stdin_file_spec = slave_name;
+
+                    if (!stdout_file_spec)
+                        stdout_file_spec = slave_name;
+
+                    if (!stderr_file_spec)
+                        stderr_file_spec = slave_name;
                 }
-                if (stdin_path == NULL) 
-                    stdin_path = slave_name;
-
-                if (stdout_path == NULL)
-                    stdout_path = slave_name;
-
-                if (stderr_path == NULL)
-                    stderr_path = slave_name;
-
                 if (log)
                     log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
                                  __FUNCTION__,
-                                 stdin_path ? stdin_path : "<null>",
-                                 stdout_path ? stdout_path : "<null>",
-                                 stderr_path ? stderr_path : "<null>");
+                                  stdin_file_spec ?  stdin_file_spec.GetCString() : "<null>",
+                                 stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+                                 stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
             }
 
             if (log)
                 log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stderr=%s",
                              __FUNCTION__,
-                             stdin_path ? stdin_path : "<null>",
-                             stdout_path ? stdout_path : "<null>",
-                             stderr_path ? stderr_path : "<null>");
+                              stdin_file_spec ?  stdin_file_spec.GetCString() : "<null>",
+                             stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+                             stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
 
-            if (stdin_path)
-                m_gdb_comm.SetSTDIN (stdin_path);
-            if (stdout_path)
-                m_gdb_comm.SetSTDOUT (stdout_path);
-            if (stderr_path)
-                m_gdb_comm.SetSTDERR (stderr_path);
+            if (stdin_file_spec)
+                m_gdb_comm.SetSTDIN(stdin_file_spec);
+            if (stdout_file_spec)
+                m_gdb_comm.SetSTDOUT(stdout_file_spec);
+            if (stderr_file_spec)
+                m_gdb_comm.SetSTDERR(stderr_file_spec);
 
             m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
             m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
@@ -1008,7 +1007,7 @@
             if (launch_event_data != NULL && *launch_event_data != '\0')
                 m_gdb_comm.SendLaunchEventDataPacket (launch_event_data);
             
-            if (working_dir && working_dir[0])
+            if (working_dir)
             {
                 m_gdb_comm.SetWorkingDir (working_dir);
             }