cameron314 updated this revision to Diff 49185.

http://reviews.llvm.org/D17107

Files:
  lldb/trunk/cmake/modules/LLDBConfig.cmake
  lldb/trunk/include/lldb/Host/FileSystem.h
  lldb/trunk/include/lldb/Host/posix/HostInfoPosix.h
  lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h
  lldb/trunk/packages/Python/lldbsuite/test/dotest.py
  lldb/trunk/source/Commands/CommandCompletions.cpp
  lldb/trunk/source/Core/ConnectionSharedMemory.cpp
  lldb/trunk/source/Core/Disassembler.cpp
  lldb/trunk/source/Host/common/File.cpp
  lldb/trunk/source/Host/common/FileSpec.cpp
  lldb/trunk/source/Host/posix/FileSystem.cpp
  lldb/trunk/source/Host/posix/HostInfoPosix.cpp
  lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
  lldb/trunk/source/Host/windows/FileSystem.cpp
  lldb/trunk/source/Host/windows/Host.cpp
  lldb/trunk/source/Host/windows/HostInfoWindows.cpp
  lldb/trunk/source/Host/windows/HostProcessWindows.cpp
  lldb/trunk/source/Host/windows/PipeWindows.cpp
  lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
  lldb/trunk/source/Host/windows/Windows.cpp
  lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
  lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
  lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
  lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
  lldb/trunk/source/Target/ProcessLaunchInfo.cpp
  lldb/trunk/tools/driver/Driver.cpp
  lldb/trunk/tools/driver/Platform.h
  lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
  lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
  lldb/trunk/tools/lldb-mi/Platform.h

Index: lldb/trunk/tools/lldb-mi/Platform.h
===================================================================
--- lldb/trunk/tools/lldb-mi/Platform.h
+++ lldb/trunk/tools/lldb-mi/Platform.h
@@ -60,7 +60,7 @@
 typedef long pid_t;
 
 #define STDIN_FILENO 0
-#define PATH_MAX MAX_PATH
+#define PATH_MAX 32768
 #define snprintf _snprintf
 
 extern int ioctl(int d, int request, ...);
Index: lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
===================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
+++ lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
@@ -17,6 +17,8 @@
 #include "MIUtilFileStd.h"
 #include "MICmnResources.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 //++ ------------------------------------------------------------------------------------
 // Details: CMIUtilFileStd constructor.
 // Type:    Method.
@@ -82,7 +84,14 @@
     m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb");
 #else
     // Open a file with exclusive write and shared read permissions
-    m_pFileHandle = ::_fsopen(vFileNamePath.c_str(), "wb", _SH_DENYWR);
+    std::wstring path;
+    if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path))
+        m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR);
+    else
+    {
+        errno = EINVAL;
+        m_pFileHandle = nullptr;
+    }
 #endif // !defined( _MSC_VER )
 
     if (m_pFileHandle == nullptr)
@@ -222,7 +231,14 @@
         return false;
 
     FILE *pTmp = nullptr;
+#if _WIN32
+    std::wstring path;
+    if (!llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path))
+        return false;
+    pTmp = ::_wfopen(path.c_str(), L"wb");
+#else
     pTmp = ::fopen(vFileNamePath.c_str(), "wb");
+#endif
     if (pTmp != nullptr)
     {
         ::fclose(pTmp);
Index: lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
===================================================================
--- lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -27,6 +27,7 @@
 #include "MICmnMIValueTuple.h"
 #include "MICmdData.h"
 #include "MICmnLLDBUtilSBValue.h"
+#include "Platform.h"
 
 //++ ------------------------------------------------------------------------------------
 // Details: CMICmnLLDBDebugSessionInfo constructor.
@@ -614,7 +615,7 @@
 {
     lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
 
-    static char pBuffer[MAX_PATH];
+    static char pBuffer[PATH_MAX];
     const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer));
     MIunused(nBytes);
     CMIUtilString strResolvedPath(&pBuffer[0]);
Index: lldb/trunk/tools/driver/Platform.h
===================================================================
--- lldb/trunk/tools/driver/Platform.h
+++ lldb/trunk/tools/driver/Platform.h
@@ -81,7 +81,7 @@
     typedef long pid_t;
     #define snprintf _snprintf
     extern sighandler_t signal( int sig, sighandler_t );
-    #define PATH_MAX MAX_PATH
+    #define PATH_MAX 32768
 #endif
 
     #define STDIN_FILENO 0
Index: lldb/trunk/tools/driver/Driver.cpp
===================================================================
--- lldb/trunk/tools/driver/Driver.cpp
+++ lldb/trunk/tools/driver/Driver.cpp
@@ -42,6 +42,7 @@
 #include "lldb/API/SBTarget.h"
 #include "lldb/API/SBThread.h"
 #include "lldb/API/SBProcess.h"
+#include "llvm/Support/ConvertUTF.h"
 
 #if !defined(__APPLE__)
 #include "llvm/Support/DataTypes.h"
@@ -1298,14 +1299,36 @@
 }
 
 int
-main (int argc, char const *argv[], const char *envp[])
+#ifdef WIN32
+wmain(int argc, wchar_t const *wargv[])
+#else
+main (int argc, char const *argv[])
+#endif
 {
 #ifdef _MSC_VER
 	// disable buffering on windows
 	setvbuf(stdout, NULL, _IONBF, 0);
 	setvbuf(stdin , NULL, _IONBF, 0);
 #endif
 
+#ifdef _WIN32
+    // Convert wide arguments to UTF-8
+    std::vector<std::string> argvStrings(argc);
+    std::vector<const char*> argvPointers(argc);
+    for (int i = 0; i != argc; ++i)
+    {
+        llvm::convertWideToUTF8(wargv[i], argvStrings[i]);
+        argvPointers[i] = argvStrings[i].c_str();
+    }
+    const char** argv = argvPointers.data();
+
+    // Indicate that all our I/O is in UTF-8
+    UINT prevInputCP = GetConsoleCP();
+    UINT prevOutputCP = GetConsoleOutputCP();
+    SetConsoleCP(CP_UTF8);
+    SetConsoleOutputCP(CP_UTF8);
+#endif
+
     SBDebugger::Initialize();
     
     SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
@@ -1336,5 +1359,10 @@
     }
 
     SBDebugger::Terminate();
+
+#ifdef _WIN32
+    SetConsoleCP(prevInputCP);
+    SetConsoleOutputCP(prevOutputCP);
+#endif
     return 0;
 }
Index: lldb/trunk/source/Target/ProcessLaunchInfo.cpp
===================================================================
--- lldb/trunk/source/Target/ProcessLaunchInfo.cpp
+++ lldb/trunk/source/Target/ProcessLaunchInfo.cpp
@@ -16,11 +16,18 @@
 #include "lldb/Host/Config.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Host/HostInfo.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Target/ProcessLaunchInfo.h"
 #include "lldb/Target/FileAction.h"
 #include "lldb/Target/Target.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
+#if !defined(_WIN32)
+#include <limits.h>
+#endif
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -449,8 +456,8 @@
                         if (cwd && cwd[0])
                             new_path += cwd;
                     }
-                    const char *curr_path = getenv("PATH");
-                    if (curr_path)
+                    std::string curr_path;
+                    if (HostInfo::GetEnvironmentVar("PATH", curr_path))
                     {
                         if (new_path.size() > empty_path_len)
                             new_path += ':';
Index: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
===================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -19,8 +19,11 @@
 
 #include "lldb/Core/Stream.h"
 #include "lldb/Host/File.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Interpreter/ScriptInterpreter.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 #include <stdio.h>
 
 #include "llvm/ADT/StringSwitch.h"
@@ -1162,9 +1165,7 @@
 
 PythonFile::PythonFile(const char *path, const char *mode)
 {
-    FILE *fp = nullptr;
-    fp = fopen(path, mode);
-    lldb_private::File file(fp, true);
+    lldb_private::File file(path, GetOptionsFromMode(mode));
     Reset(file, mode);
 }
 
Index: lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
@@ -59,7 +59,7 @@
     auto source_start = reinterpret_cast<const UTF16 *>(md_string->Buffer);
     const auto source_length = ::wcslen(md_string->Buffer);
     const auto source_end = source_start + source_length;
-    result.resize(4*source_length);  // worst case length
+    result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT*source_length);  // worst case length
     auto result_start = reinterpret_cast<UTF8 *>(&result[0]);
     const auto result_end = result_start + result.size();
     ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion);
@@ -426,17 +426,22 @@
 ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file)
 {
     Error error;
-
-    m_data_up->m_dump_file = ::CreateFile(file, GENERIC_READ, FILE_SHARE_READ,
+    std::wstring wfile;
+    if (!llvm::ConvertUTF8toWide(file, wfile))
+    {
+        error.SetErrorString("Error converting path to UTF-16");
+        return error;
+    }
+    m_data_up->m_dump_file = ::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ,
                                           NULL, OPEN_EXISTING,
                                           FILE_ATTRIBUTE_NORMAL, NULL);
     if (m_data_up->m_dump_file == INVALID_HANDLE_VALUE)
     {
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
         return error;
     }
 
-    m_data_up->m_mapping = ::CreateFileMapping(m_data_up->m_dump_file, NULL,
+    m_data_up->m_mapping = ::CreateFileMappingW(m_data_up->m_dump_file, NULL,
                                                PAGE_READONLY, 0, 0, NULL);
     if (m_data_up->m_mapping == NULL)
     {
Index: lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
@@ -47,6 +47,7 @@
 #include "ProcessWindowsLive.h"
 #include "TargetThreadWindowsLive.h"
 
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -61,17 +62,19 @@
 std::string
 GetProcessExecutableName(HANDLE process_handle)
 {
-    std::vector<char> file_name;
+    std::vector<wchar_t> file_name;
     DWORD file_name_size = MAX_PATH;  // first guess, not an absolute limit
     DWORD copied = 0;
     do
     {
         file_name_size *= 2;
         file_name.resize(file_name_size);
-        copied = ::GetModuleFileNameEx(process_handle, NULL, file_name.data(), file_name_size);
+        copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), file_name_size);
     } while (copied >= file_name_size);
     file_name.resize(copied);
-    return std::string(file_name.begin(), file_name.end());
+    std::string result;
+    llvm::convertWideToUTF8(file_name.data(), result);
+    return result;
 }
 
 std::string
Index: lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
@@ -27,6 +27,7 @@
 #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace lldb;
@@ -484,13 +485,15 @@
         return DBG_CONTINUE;
     }
 
-    std::vector<char> buffer(1);
-    DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
+    std::vector<wchar_t> buffer(1);
+    DWORD required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
     if (required_size > 0)
     {
         buffer.resize(required_size + 1);
-        required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
-        llvm::StringRef path_str(&buffer[0]);
+        required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], required_size, VOLUME_NAME_DOS);
+        std::string path_str_utf8;
+        llvm::convertWideToUTF8(buffer.data(), path_str_utf8);
+        llvm::StringRef path_str = path_str_utf8;
         const char *path = path_str.data();
         if (path_str.startswith("\\\\?\\"))
             path += 4;
Index: lldb/trunk/source/Host/windows/Windows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/Windows.cpp
+++ lldb/trunk/source/Host/windows/Windows.cpp
@@ -12,6 +12,8 @@
 #include "lldb/Host/windows/windows.h"
 #include "lldb/Host/windows/win32.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
@@ -27,6 +29,33 @@
     int _chdir(const char *path);
 }
 
+namespace
+{
+    bool utf8ToWide(const char* utf8, wchar_t* buf, size_t bufSize)
+    {
+        const UTF8* sourceStart = reinterpret_cast<const UTF8*>(utf8);
+        size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
+        UTF16* target = reinterpret_cast<UTF16*>(buf);
+        ConversionFlags flags = strictConversion;
+        return ConvertUTF8toUTF16(
+            &sourceStart, sourceStart + sourceLen,
+            &target, target + bufSize, flags) ==
+            conversionOK;
+    }
+
+    bool wideToUtf8(const wchar_t* wide, char* buf, size_t bufSize)
+    {
+        const UTF16* sourceStart = reinterpret_cast<const UTF16*>(wide);
+        size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
+        UTF8* target = reinterpret_cast<UTF8*>(buf);
+        ConversionFlags flags = strictConversion;
+        return ConvertUTF16toUTF8(
+            &sourceStart, sourceStart + sourceLen,
+            &target, target + bufSize, flags) ==
+            conversionOK;
+    }
+}
+
 int vasprintf(char **ret, const char *fmt, va_list ap)
 {
     char *buf;
@@ -75,81 +104,90 @@
 
 char* realpath(const char * name, char * resolved)
 {
-    char *retname = NULL;  /* we will return this, if we fail */
+    char *retname = NULL;
 
     /* SUSv3 says we must set `errno = EINVAL', and return NULL,
     * if `name' is passed as a NULL pointer.
     */
-
     if (name == NULL)
+    {
         errno = EINVAL;
+        return NULL;
+    }
 
     /* Otherwise, `name' must refer to a readable filesystem object,
     * if we are going to resolve its absolute path name.
     */
-
-    else if (access(name, 4) == 0)
+    wchar_t wideNameBuffer[PATH_MAX];
+    wchar_t* wideName = wideNameBuffer;
+    if (!utf8ToWide(name, wideName, PATH_MAX))
     {
-        /* If `name' didn't point to an existing entity,
-        * then we don't get to here; we simply fall past this block,
-        * returning NULL, with `errno' appropriately set by `access'.
-        *
-        * When we _do_ get to here, then we can use `_fullpath' to
-        * resolve the full path for `name' into `resolved', but first,
-        * check that we have a suitable buffer, in which to return it.
-        */
+        errno = EINVAL;
+        return NULL;
+    }
 
-        if ((retname = resolved) == NULL)
-        {
-            /* Caller didn't give us a buffer, so we'll exercise the
-            * option granted by SUSv3, and allocate one.
-            *
-            * `_fullpath' would do this for us, but it uses `malloc', and
-            * Microsoft's implementation doesn't set `errno' on failure.
-            * If we don't do this explicitly ourselves, then we will not
-            * know if `_fullpath' fails on `malloc' failure, or for some
-            * other reason, and we want to set `errno = ENOMEM' for the
-            * `malloc' failure case.
-            */
-
-            retname = (char*) malloc(_MAX_PATH);
-        }
+    if (_waccess(wideName, 4) != 0)
+        return NULL;
+
+    /* If `name' didn't point to an existing entity,
+    * then we don't get to here; we simply fall past this block,
+    * returning NULL, with `errno' appropriately set by `access'.
+    *
+    * When we _do_ get to here, then we can use `_fullpath' to
+    * resolve the full path for `name' into `resolved', but first,
+    * check that we have a suitable buffer, in which to return it.
+    */
 
-        /* By now, we should have a valid buffer.
-        * If we don't, then we know that `malloc' failed,
-        * so we can set `errno = ENOMEM' appropriately.
+    if ((retname = resolved) == NULL)
+    {
+        /* Caller didn't give us a buffer, so we'll exercise the
+        * option granted by SUSv3, and allocate one.
+        *
+        * `_fullpath' would do this for us, but it uses `malloc', and
+        * Microsoft's implementation doesn't set `errno' on failure.
+        * If we don't do this explicitly ourselves, then we will not
+        * know if `_fullpath' fails on `malloc' failure, or for some
+        * other reason, and we want to set `errno = ENOMEM' for the
+        * `malloc' failure case.
         */
 
+        retname = (char*) malloc(PATH_MAX);
         if (retname == NULL)
+        {
             errno = ENOMEM;
+            return NULL;
+        }
+    }
 
-        /* Otherwise, when we do have a valid buffer,
-        * `_fullpath' should only fail if the path name is too long.
-        */
+    /* Otherwise, when we do have a valid buffer,
+    * `_fullpath' should only fail if the path name is too long.
+    */
 
-        else if ((retname = _fullpath(retname, name, _MAX_PATH)) == NULL)
-            errno = ENAMETOOLONG;
+    wchar_t wideFullPathBuffer[PATH_MAX];
+    wchar_t* wideFullPath;
+    if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL)
+    {
+        errno = ENAMETOOLONG;
+        return NULL;
     }
 
-    /* By the time we get to here,
-    * `retname' either points to the required resolved path name,
-    * or it is NULL, with `errno' set appropriately, either of which
-    * is our required return condition.
-    */
+    // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
+    // FIXME: Check for failure
+    size_t initialLength = wcslen(wideFullPath);
+    GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
+    GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
 
-    if (retname != NULL)
+    // Convert back to UTF-8
+    if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX))
     {
-        // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
-        int initialLength = strlen(retname);
-        TCHAR buffer[MAX_PATH];
-        GetShortPathName(retname, buffer, MAX_PATH);
-        GetLongPathName(buffer, retname, initialLength + 1);
-
-        // Force drive to be upper case
-        if (retname[1] == ':')
-            retname[0] = toupper(retname[0]);
+        errno = EINVAL;
+        return NULL;
     }
 
+    // Force drive to be upper case
+    if (retname[1] == ':')
+        retname[0] = toupper(retname[0]);
+
     return retname;
 }
 
@@ -167,7 +205,27 @@
 // use _getcwd() instead of GetCurrentDirectory() because it updates errno
 char* getcwd(char* path, int max)
 {
-    return _getcwd(path, max);
+    assert(path == NULL || max <= PATH_MAX);
+    wchar_t wpath[PATH_MAX];
+    if (wchar_t* wresult = _wgetcwd(wpath, PATH_MAX))
+    {
+        // Caller is allowed to pass in NULL for `path`.
+        // In that case, we're supposed to allocate a
+        // buffer on the caller's behalf.
+        if (path == NULL)
+        {
+            max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
+            path = (char*)malloc(max);
+            if (path == NULL)
+            {
+                errno = ENOMEM;
+                return NULL;
+            }
+        }
+        if (wideToUtf8(wresult, path, max))
+            return path;
+    }
+    return NULL;
 }
 
 // use _chdir() instead of SetCurrentDirectory() because it updates errno
Index: lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
+++ lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
@@ -11,6 +11,9 @@
 #include "lldb/Host/windows/ProcessLauncherWindows.h"
 #include "lldb/Target/ProcessLaunchInfo.h"
 
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/ADT/SmallVector.h"
+
 #include <string>
 #include <vector>
 
@@ -25,20 +28,19 @@
     if (env.GetArgumentCount() == 0)
         return;
 
-    int bytes = 0;
-    for (int i = 0; i < env.GetArgumentCount(); ++i)
-        bytes += strlen(env.GetArgumentAtIndex(i)) + sizeof(char);
-    bytes += sizeof(char);
-    buffer.resize(bytes);
-    char *cur_entry = &buffer[0];
+    // Environment buffer is a null terminated list of null terminated strings
     for (int i = 0; i < env.GetArgumentCount(); ++i)
     {
-        ::strcpy(cur_entry, env.GetArgumentAtIndex(i));
-        cur_entry += strlen(cur_entry) + sizeof(char);
+        std::wstring warg;
+        if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg))
+        {
+            buffer.insert(buffer.end(), (char*)warg.c_str(),
+                (char*)(warg.c_str() + warg.size() + 1));
+        }
     }
-    // Environment buffer is a null terminated list of null terminated
-    // strings, so it is terminated by two null bytes.
-    buffer.back() = 0;
+    // One null wchar_t (to end the block) is two null bytes
+    buffer.push_back(0);
+    buffer.push_back(0);
 }
 }
 
@@ -70,7 +72,7 @@
         startupinfo.wShowWindow = SW_HIDE;
     }
 
-    DWORD flags = CREATE_NEW_CONSOLE;
+    DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
     if (launch_info.GetFlags().Test(eLaunchFlagDebug))
         flags |= DEBUG_ONLY_THIS_PROCESS;
 
@@ -82,8 +84,16 @@
 
     executable = launch_info.GetExecutableFile().GetPath();
     launch_info.GetArguments().GetQuotedCommandString(commandLine);
-    BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags,
-                                   env_block, launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi);
+
+    std::wstring wexecutable, wcommandLine, wworkingDirectory;
+    llvm::ConvertUTF8toWide(executable, wexecutable);
+    llvm::ConvertUTF8toWide(commandLine, wcommandLine);
+    llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory);
+
+    wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because CreateProcessW can modify it
+    BOOL result = ::CreateProcessW(wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags,
+                                   env_block, wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
+                                   &startupinfo, &pi);
     if (result)
     {
         // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
@@ -131,6 +141,8 @@
             flags = FILE_FLAG_WRITE_THROUGH;
     }
 
-    HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
+    std::wstring wpath;
+    llvm::ConvertUTF8toWide(path, wpath);
+    HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, flags, NULL);
     return (result == INVALID_HANDLE_VALUE) ? NULL : result;
 }
Index: lldb/trunk/source/Host/windows/PipeWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/PipeWindows.cpp
+++ lldb/trunk/source/Host/windows/PipeWindows.cpp
@@ -74,7 +74,7 @@
     // Always open for overlapped i/o.  We implement blocking manually in Read and Write.
     DWORD read_mode = FILE_FLAG_OVERLAPPED;
     m_read =
-        ::CreateNamedPipe(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
+        ::CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
     if (INVALID_HANDLE_VALUE == m_read)
         return Error(::GetLastError(), eErrorTypeWin32);
     m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
@@ -153,7 +153,7 @@
 
     if (is_read)
     {
-        m_read = ::CreateFile(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+        m_read = ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
         if (INVALID_HANDLE_VALUE == m_read)
             return Error(::GetLastError(), eErrorTypeWin32);
 
@@ -164,7 +164,7 @@
     }
     else
     {
-        m_write = ::CreateFile(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+        m_write = ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
         if (INVALID_HANDLE_VALUE == m_write)
             return Error(::GetLastError(), eErrorTypeWin32);
 
Index: lldb/trunk/source/Host/windows/HostProcessWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/HostProcessWindows.cpp
+++ lldb/trunk/source/Host/windows/HostProcessWindows.cpp
@@ -14,6 +14,7 @@
 #include "lldb/Host/windows/HostProcessWindows.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ConvertUTF.h"
 
 #include <Psapi.h>
 
@@ -70,9 +71,15 @@
     if (m_process == nullptr)
         error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
 
-    char path[MAX_PATH] = { 0 };
-    if (::GetProcessImageFileName(m_process, path, llvm::array_lengthof(path)))
-        file_spec.SetFile(path, false);
+    std::vector<wchar_t> wpath(PATH_MAX);
+    if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size()))
+    {
+        std::string path;
+        if (llvm::convertWideToUTF8(wpath.data(), path))
+            file_spec.SetFile(path, false);
+        else
+            error.SetErrorString("Error converting path to UTF-8");
+    }
     else
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
 
Index: lldb/trunk/source/Host/windows/HostInfoWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/HostInfoWindows.cpp
+++ lldb/trunk/source/Host/windows/HostInfoWindows.cpp
@@ -13,6 +13,7 @@
 
 #include "lldb/Host/windows/HostInfoWindows.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Path.h"
@@ -76,31 +77,34 @@
 bool
 HostInfoWindows::GetHostname(std::string &s)
 {
-    char buffer[MAX_COMPUTERNAME_LENGTH + 1];
+    wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
     DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
-    if (!::GetComputerName(buffer, &dwSize))
+    if (!::GetComputerNameW(buffer, &dwSize))
         return false;
 
-    s.assign(buffer, buffer + dwSize);
-    return true;
+    return llvm::convertWideToUTF8(buffer, s);
 }
 
 FileSpec
 HostInfoWindows::GetProgramFileSpec()
 {
     static std::once_flag g_once_flag;
     std::call_once(g_once_flag,  []() {
-        char buffer[PATH_MAX];
-        ::GetModuleFileName(NULL, buffer, sizeof(buffer));
-        m_program_filespec.SetFile(buffer, false);
+        std::vector<wchar_t> buffer(PATH_MAX);
+        ::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
+        std::string path;
+        llvm::convertWideToUTF8(buffer.data(), path);
+        m_program_filespec.SetFile(path, false);
     });
     return m_program_filespec;
 }
 
 FileSpec
 HostInfoWindows::GetDefaultShell()
 {
-    return FileSpec(::getenv("ComSpec"), false);
+    std::string shell;
+    GetEnvironmentVar("ComSpec", shell);
+    return FileSpec(shell, false);
 }
 
 bool
@@ -116,3 +120,15 @@
     file_spec.GetDirectory().SetString(path.c_str());
     return true;
 }
+
+bool
+HostInfoWindows::GetEnvironmentVar(const std::string &var_name, std::string &var)
+{
+    std::wstring wvar_name;
+    if (!llvm::ConvertUTF8toWide(var_name, wvar_name))
+        return false;
+
+    if (const wchar_t *wvar = _wgetenv(wvar_name.c_str()))
+        return llvm::convertWideToUTF8(wvar, var);
+    return false;
+}
Index: lldb/trunk/source/Host/windows/Host.cpp
===================================================================
--- lldb/trunk/source/Host/windows/Host.cpp
+++ lldb/trunk/source/Host/windows/Host.cpp
@@ -26,6 +26,8 @@
 #include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StructuredData.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 // Windows includes
 #include <TlHelp32.h>
 
@@ -68,12 +70,11 @@
     bool GetExecutableForProcess(const AutoHandle &handle, std::string &path)
     {
         // Get the process image path.  MAX_PATH isn't long enough, paths can actually be up to 32KB.
-        std::vector<char> buffer(32768);
+        std::vector<wchar_t> buffer(PATH_MAX);
         DWORD dwSize = buffer.size();
-        if (!::QueryFullProcessImageNameA(handle.get(), 0, &buffer[0], &dwSize))
+        if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize))
             return false;
-        path.assign(&buffer[0]);
-        return true;
+        return llvm::convertWideToUTF8(buffer.data(), path);
     }
 
     void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process)
@@ -156,15 +157,17 @@
     if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
         return module_filespec;
 
-    std::vector<char> buffer(MAX_PATH);
+    std::vector<wchar_t> buffer(PATH_MAX);
     DWORD chars_copied = 0;
     do {
-        chars_copied = ::GetModuleFileName(hmodule, &buffer[0], buffer.size());
+        chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size());
         if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
             buffer.resize(buffer.size() * 2);
     } while (chars_copied >= buffer.size());
-
-    module_filespec.SetFile(&buffer[0], false);
+    std::string path;
+    if (!llvm::convertWideToUTF8(buffer.data(), path))
+        return module_filespec;
+    module_filespec.SetFile(path, false);
     return module_filespec;
 }
 
@@ -177,23 +180,25 @@
     if (!snapshot.IsValid())
         return 0;
 
-    PROCESSENTRY32 pe = {0};
-    pe.dwSize = sizeof(PROCESSENTRY32);
-    if (Process32First(snapshot.get(), &pe))
+    PROCESSENTRY32W pe = {0};
+    pe.dwSize = sizeof(PROCESSENTRY32W);
+    if (Process32FirstW(snapshot.get(), &pe))
     {
         do
         {
             AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
 
             ProcessInstanceInfo process;
-            process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
+            std::string exeFile;
+            llvm::convertWideToUTF8(pe.szExeFile, exeFile);
+            process.SetExecutableFile(FileSpec(exeFile, false), true);
             process.SetProcessID(pe.th32ProcessID);
             process.SetParentProcessID(pe.th32ParentProcessID);
             GetProcessExecutableAndTriple(handle, process);
 
             if (match_info.MatchAllProcesses() || match_info.Matches(process))
                 process_infos.Append(process);
-        } while (Process32Next(snapshot.get(), &pe));
+        } while (Process32NextW(snapshot.get(), &pe));
     }
     return process_infos.GetSize();
 }
@@ -312,15 +317,21 @@
 {
     // The environment block on Windows is a contiguous buffer of NULL terminated strings,
     // where the end of the environment block is indicated by two consecutive NULLs.
-    LPCH environment_block = ::GetEnvironmentStrings();
+    LPWCH environment_block = ::GetEnvironmentStringsW();
     env.Clear();
-    while (*environment_block != '\0')
+    while (*environment_block != L'\0')
     {
-        llvm::StringRef current_var(environment_block);
+        std::string current_var;
+        auto current_var_size = wcslen(environment_block) + 1;
+        if (!llvm::convertWideToUTF8(environment_block, current_var))
+        {
+            environment_block += current_var_size;
+            continue;
+        }
         if (current_var[0] != '=')
             env.AppendString(current_var);
 
-        environment_block += current_var.size()+1;
+        environment_block += current_var_size;
     }
     return env.GetSize();
 }
Index: lldb/trunk/source/Host/windows/FileSystem.cpp
===================================================================
--- lldb/trunk/source/Host/windows/FileSystem.cpp
+++ lldb/trunk/source/Host/windows/FileSystem.cpp
@@ -15,13 +15,18 @@
 
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/windows/AutoHandle.h"
+
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 
 using namespace lldb_private;
 
 const char *
 FileSystem::DEV_NULL = "nul";
 
+const char *
+FileSystem::PATH_CONVERSION_ERROR = "Error converting path between UTF-8 and native encoding";
+
 FileSpec::PathSyntax
 FileSystem::GetNativePathSyntax()
 {
@@ -47,25 +52,32 @@
 FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
 {
     Error error;
+    std::wstring path_buffer;
+    if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer))
+    {
+        error.SetErrorString(PATH_CONVERSION_ERROR);
+        return error;
+    }
     if (!recurse)
     {
-        BOOL result = ::RemoveDirectory(file_spec.GetCString());
+        BOOL result = ::RemoveDirectoryW(path_buffer.c_str());
         if (!result)
             error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     }
     else
     {
         // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
-        // indicate the end of the list.
-        std::string path_buffer{file_spec.GetPath()};
+        // indicate the end of the list. The first null terminator is there only in the backing
+        // store but not the actual vector contents, and so we need to push twice.
+        path_buffer.push_back(0);
         path_buffer.push_back(0);
 
-        SHFILEOPSTRUCT shfos = {0};
+        SHFILEOPSTRUCTW shfos = {0};
         shfos.wFunc = FO_DELETE;
-        shfos.pFrom = path_buffer.c_str();
+        shfos.pFrom = (LPCWSTR)path_buffer.data();
         shfos.fFlags = FOF_NO_UI;
 
-        int result = ::SHFileOperation(&shfos);
+        int result = ::SHFileOperationW(&shfos);
         // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
         if (result != 0)
             error.SetErrorStringWithFormat("SHFileOperation failed");
@@ -121,15 +133,23 @@
 FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
 {
     Error error;
-    if (!::CreateHardLink(src.GetCString(), dst.GetCString(), nullptr))
+    std::wstring wsrc, wdst;
+    if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) ||
+        !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
+        error.SetErrorString(PATH_CONVERSION_ERROR);
+    else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr))
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     return error;
 }
 
 int
 FileSystem::GetHardlinkCount(const FileSpec &file_spec)
 {
-    HANDLE file_handle = ::CreateFile(file_spec.GetCString(),
+    std::wstring path;
+    if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
+        return -1;
+
+    HANDLE file_handle = ::CreateFileW(path.c_str(),
                                       FILE_READ_ATTRIBUTES,
                                       FILE_SHARE_READ,
                                       nullptr,
@@ -152,15 +172,21 @@
 FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
 {
     Error error;
-    DWORD attrib = ::GetFileAttributes(dst.GetCString());
+    std::wstring wsrc, wdst;
+    if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) ||
+        !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
+        error.SetErrorString(PATH_CONVERSION_ERROR);
+    if (error.Fail())
+        return error;
+    DWORD attrib = ::GetFileAttributesW(wdst.c_str());
     if (attrib == INVALID_FILE_ATTRIBUTES)
     {
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
         return error;
     }
     bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
     DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
-    BOOL result = ::CreateSymbolicLink(src.GetCString(), dst.GetCString(), flag);
+    BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag);
     if (!result)
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     return error;
@@ -170,7 +196,13 @@
 FileSystem::Unlink(const FileSpec &file_spec)
 {
     Error error;
-    BOOL result = ::DeleteFile(file_spec.GetCString());
+    std::wstring path;
+    if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
+    {
+        error.SetErrorString(PATH_CONVERSION_ERROR);
+        return error;
+    }
+    BOOL result = ::DeleteFileW(path.c_str());
     if (!result)
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     return error;
@@ -180,23 +212,33 @@
 FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
 {
     Error error;
-    HANDLE h = ::CreateFile(src.GetCString(), GENERIC_READ,
+    std::wstring wsrc;
+    if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc))
+    {
+        error.SetErrorString(PATH_CONVERSION_ERROR);
+        return error;
+    }
+
+    HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ,
             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
             FILE_FLAG_OPEN_REPARSE_POINT, NULL);
     if (h == INVALID_HANDLE_VALUE)
     {
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
         return error;
     }
 
-    char buf[PATH_MAX];
+    std::vector<wchar_t> buf(PATH_MAX + 1);
     // Subtract 1 from the path length since this function does not add a null terminator.
-    DWORD result = ::GetFinalPathNameByHandle(h, buf, sizeof(buf) - 1,
+    DWORD result = ::GetFinalPathNameByHandleW(h, buf.data(), buf.size() - 1,
             FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+    std::string path;
     if (result == 0)
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+    else if (!llvm::convertWideToUTF8(buf.data(), path))
+        error.SetErrorString(PATH_CONVERSION_ERROR);
     else
-        dst.SetFile(buf, false);
+        dst.SetFile(path, false);
 
     ::CloseHandle(h);
     return error;
@@ -219,3 +261,17 @@
 
     return false;
 }
+
+FILE*
+FileSystem::Fopen(const char *path, const char *mode)
+{
+    std::wstring wpath, wmode;
+    if (!llvm::ConvertUTF8toWide(path, wpath))
+        return nullptr;
+    if (!llvm::ConvertUTF8toWide(mode, wmode))
+        return nullptr;
+    FILE* file;
+    if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0)
+        return nullptr;
+    return file;
+}
Index: lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
+++ lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
@@ -14,6 +14,7 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -138,7 +139,14 @@
     // Open the file for overlapped access.  If it does not exist, create it.  We open it overlapped
     // so that we can issue asynchronous reads and then use WaitForMultipleObjects to allow the read
     // to be interrupted by an event object.
-    m_file = ::CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
+    std::wstring wpath;
+    if (!llvm::ConvertUTF8toWide(path, wpath))
+    {
+        if (error_ptr)
+            error_ptr->SetError(1, eErrorTypeGeneric);
+        return eConnectionStatusError;
+    }
+    m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
     if (m_file == INVALID_HANDLE_VALUE)
     {
         if (error_ptr)
Index: lldb/trunk/source/Host/posix/HostInfoPosix.cpp
===================================================================
--- lldb/trunk/source/Host/posix/HostInfoPosix.cpp
+++ lldb/trunk/source/Host/posix/HostInfoPosix.cpp
@@ -242,3 +242,14 @@
     return false;
 #endif
 }
+
+bool
+HostInfoPosix::GetEnvironmentVar(const std::string &var_name, std::string &var)
+{
+    if (const char *pvar = ::getenv(var_name.c_str()))
+    {
+        var = std::string(pvar);
+        return true;
+    }
+    return false;
+}
Index: lldb/trunk/source/Host/posix/FileSystem.cpp
===================================================================
--- lldb/trunk/source/Host/posix/FileSystem.cpp
+++ lldb/trunk/source/Host/posix/FileSystem.cpp
@@ -297,3 +297,9 @@
     return false;
 }
 #endif
+
+FILE*
+FileSystem::Fopen(const char *path, const char *mode)
+{
+    return ::fopen(path, mode);
+}
Index: lldb/trunk/source/Host/common/FileSpec.cpp
===================================================================
--- lldb/trunk/source/Host/common/FileSpec.cpp
+++ lldb/trunk/source/Host/common/FileSpec.cpp
@@ -17,7 +17,6 @@
 #ifndef _MSC_VER
 #include <libgen.h>
 #endif
-#include <sys/stat.h>
 #include <set>
 #include <string.h>
 #include <fstream>
@@ -40,6 +39,7 @@
 #include "lldb/Utility/CleanUp.h"
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
@@ -90,7 +90,29 @@
 {
     char resolved_path[PATH_MAX];
     if (file_spec->GetPath (resolved_path, sizeof(resolved_path)))
+    {
+#ifdef _WIN32
+        std::wstring wresolved_path;
+        if (!llvm::ConvertUTF8toWide(resolved_path, wresolved_path))
+            return false;
+        int stat_result;
+#ifdef _USE_32BIT_TIME_T
+        struct _stat32 file_stats;
+        stat_result = ::_wstat32(wresolved_path.c_str(), &file_stats);
+#else
+        struct _stat64i32 file_stats;
+        stat_result = ::_wstat64i32(wresolved_path.c_str(), &file_stats);
+#endif
+        if (stat_result == 0)
+        {
+            static_assert(sizeof(struct stat) == sizeof(file_stats), "stat and _stat32/_stat64i32 must have the same layout");
+            *stats_ptr = *reinterpret_cast<struct stat *>(&file_stats);
+        }
+        return stat_result == 0;
+#else
         return ::stat (resolved_path, stats_ptr) == 0;
+#endif
+    }
     return false;
 }
 
@@ -206,15 +228,10 @@
 #endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
 
     // Save a copy of the original path that's passed in
-    llvm::SmallString<PATH_MAX> original_path(path.begin(), path.end());
+    llvm::SmallString<128> original_path(path.begin(), path.end());
 
     llvm::sys::fs::make_absolute(path);
-
-    
-    path.push_back(0);  // Be sure we have a nul terminated string
-    path.pop_back();
-    struct stat file_stats;
-    if (::stat (path.data(), &file_stats) != 0)
+    if (!llvm::sys::fs::exists(path))
     {
         path.clear();
         path.append(original_path.begin(), original_path.end());
@@ -797,7 +814,10 @@
         return false;
 
 #ifdef _WIN32
-    auto attrs = ::GetFileAttributes (resolved_path);
+    std::wstring wpath;
+    if (!llvm::ConvertUTF8toWide (resolved_path, wpath))
+        return false;
+    auto attrs = ::GetFileAttributesW (wpath.c_str());
     if (attrs == INVALID_FILE_ATTRIBUTES)
         return false;
 
@@ -1096,12 +1116,18 @@
 {
     if (dir_path && dir_path[0])
     {
-#if _WIN32
+#ifdef _WIN32
         std::string szDir(dir_path);
         szDir += "\\*";
 
-        WIN32_FIND_DATA ffd;
-        HANDLE hFind = FindFirstFile(szDir.c_str(), &ffd);
+        std::wstring wszDir;
+        if (!llvm::ConvertUTF8toWide(szDir, wszDir))
+        {
+            return eEnumerateDirectoryResultNext;
+        }
+
+        WIN32_FIND_DATAW ffd;
+        HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd);
 
         if (hFind == INVALID_HANDLE_VALUE)
         {
@@ -1113,12 +1139,12 @@
             FileSpec::FileType file_type = eFileTypeUnknown;
             if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
             {
-                size_t len = strlen(ffd.cFileName);
+                size_t len = wcslen(ffd.cFileName);
 
-                if (len == 1 && ffd.cFileName[0] == '.')
+                if (len == 1 && ffd.cFileName[0] == L'.')
                     continue;
 
-                if (len == 2 && ffd.cFileName[0] == '.' && ffd.cFileName[1] == '.')
+                if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.')
                     continue;
 
                 file_type = eFileTypeDirectory;
@@ -1132,12 +1158,18 @@
                 file_type = eFileTypeRegular;
             }
 
-            char child_path[MAX_PATH];
-            const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, ffd.cFileName);
-            if (child_path_len < (int)(sizeof(child_path) - 1))
+            std::string fileName;
+            if (!llvm::convertWideToUTF8(ffd.cFileName, fileName))
+            {
+                continue;
+            }
+
+            std::vector<char> child_path(PATH_MAX);
+            const int child_path_len = ::snprintf (child_path.data(), child_path.size(), "%s\\%s", dir_path, fileName.c_str());
+            if (child_path_len < (int)(child_path.size() - 1))
             {
                 // Don't resolve the file type or path
-                FileSpec child_path_spec (child_path, false);
+                FileSpec child_path_spec (child_path.data(), false);
 
                 EnumerateDirectoryResult result = callback (file_type, child_path_spec);
 
@@ -1150,7 +1182,7 @@
                         break;
 
                     case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not
-                        if (FileSpec::ForEachItemInDirectory(child_path, callback) == eEnumerateDirectoryResultQuit)
+                        if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == eEnumerateDirectoryResultQuit)
                         {
                             // The subdirectory returned Quit, which means to
                             // stop all directory enumerations at all levels.
@@ -1167,7 +1199,7 @@
                         return eEnumerateDirectoryResultQuit;
                 }
             }
-        } while (FindNextFile(hFind, &ffd) != 0);
+        } while (FindNextFileW(hFind, &ffd) != 0);
 
         FindClose(hFind);
 #else
Index: lldb/trunk/source/Host/common/File.cpp
===================================================================
--- lldb/trunk/source/Host/common/File.cpp
+++ lldb/trunk/source/Host/common/File.cpp
@@ -22,6 +22,7 @@
 #include <sys/ioctl.h>
 #endif
 
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
 
 #include "lldb/Core/DataBufferHeap.h"
@@ -318,7 +319,18 @@
 
     do
     {
+#ifdef _WIN32
+        std::wstring wpath;
+        if (!llvm::ConvertUTF8toWide(path, wpath))
+        {
+            m_descriptor = -1;
+            error.SetErrorString("Error converting path to UTF-16");
+            return error;
+        }
+        ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYWR, mode);
+#else
         m_descriptor = ::open(path, oflag, mode);
+#endif
     } while (m_descriptor < 0 && errno == EINTR);
 
     if (!DescriptorIsValid())
@@ -337,8 +349,21 @@
 {
     if (file_spec)
     {
+        int stat_result;
+#ifdef _WIN32
+        std::wstring wpath;
+        if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), wpath))
+        {
+            error.SetErrorString("Error converting path to UTF-16");
+            return 0;
+        }
+        struct _stat32 file_stats;
+        stat_result = ::_wstat32(wpath.c_str(), &file_stats);
+#else
         struct stat file_stats;
-        if (::stat(file_spec.GetCString(), &file_stats) == -1)
+        stat_result = ::stat(file_spec.GetCString(), &file_stats);
+#endif
+        if (stat_result == -1)
             error.SetErrorToErrno();
         else
         {
Index: lldb/trunk/source/Core/Disassembler.cpp
===================================================================
--- lldb/trunk/source/Core/Disassembler.cpp
+++ lldb/trunk/source/Core/Disassembler.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/Timer.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Interpreter/OptionValue.h"
 #include "lldb/Interpreter/OptionValueArray.h"
 #include "lldb/Interpreter/OptionValueDictionary.h"
@@ -876,8 +877,7 @@
         out_stream->Printf ("Instruction::TestEmulation:  Missing file_name.");
         return false;
     }
-        
-    FILE *test_file = fopen (file_name, "r");
+    FILE *test_file = FileSystem::Fopen ( file_name, "r");
     if (!test_file)
     {
         out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Index: lldb/trunk/source/Core/ConnectionSharedMemory.cpp
===================================================================
--- lldb/trunk/source/Core/ConnectionSharedMemory.cpp
+++ lldb/trunk/source/Core/ConnectionSharedMemory.cpp
@@ -29,6 +29,8 @@
 #include "lldb/Core/Communication.h"
 #include "lldb/Core/Log.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -132,18 +134,22 @@
     m_name.assign (name);
 
 #ifdef _WIN32
-    HANDLE handle;
-    if (create) {
-        handle = CreateFileMapping(
-            INVALID_HANDLE_VALUE,
-            NULL,
-            PAGE_READWRITE,
-            llvm::Hi_32(size),
-            llvm::Lo_32(size),
-            name);
+    HANDLE handle = INVALID_HANDLE_VALUE;
+    std::wstring wname;
+    if (llvm::ConvertUTF8toWide(name, wname))
+    {
+        if (create) {
+            handle = CreateFileMappingW(
+                INVALID_HANDLE_VALUE,
+                NULL,
+                PAGE_READWRITE,
+                llvm::Hi_32(size),
+                llvm::Lo_32(size),
+                wname.c_str());
+        }
+        else
+            handle = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, wname.c_str());
     }
-    else
-        handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
 
     m_fd = _open_osfhandle((intptr_t)handle, 0);
 #else
Index: lldb/trunk/source/Commands/CommandCompletions.cpp
===================================================================
--- lldb/trunk/source/Commands/CommandCompletions.cpp
+++ lldb/trunk/source/Commands/CommandCompletions.cpp
@@ -19,6 +19,7 @@
 
 // Project includes
 #include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Core/FileSpecList.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Module.h"
@@ -31,6 +32,8 @@
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/CleanUp.h"
 
+#include "llvm/ADT/SmallString.h"
+
 using namespace lldb_private;
 
 CommandCompletions::CommonCompletionElement
@@ -160,8 +163,7 @@
             isa_directory = true;
         else if (file_type == FileSpec::eFileTypeSymbolicLink)
         {
-            struct stat stat_buf;
-            if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
+            if (FileSpec(partial_name_copy, false).IsDirectory())
                 isa_directory = true;
         }
 
Index: lldb/trunk/packages/Python/lldbsuite/test/dotest.py
===================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/dotest.py
+++ lldb/trunk/packages/Python/lldbsuite/test/dotest.py
@@ -659,7 +659,7 @@
                 print("     location of LLDB\'s site-packages folder.")
                 print("  3) A different version of Python than that which was built against is exported in")
                 print("     the system\'s PATH environment variable, causing conflicts.")
-                print("  4) The executable '%s' could not be found.  Please check " % lldbExecutable)
+                print("  4) The executable '%s' could not be found.  Please check " % lldbtest_config.lldbExec)
                 print("     that it exists and is executable.")
 
     if lldbPythonDir:
Index: lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h
===================================================================
--- lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h
+++ lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h
@@ -35,6 +35,8 @@
     static FileSpec GetProgramFileSpec();
     static FileSpec GetDefaultShell();
 
+    static bool GetEnvironmentVar(const std::string &var_name, std::string &var);
+
   protected:
     static bool ComputePythonDirectory(FileSpec &file_spec);
 
Index: lldb/trunk/include/lldb/Host/posix/HostInfoPosix.h
===================================================================
--- lldb/trunk/include/lldb/Host/posix/HostInfoPosix.h
+++ lldb/trunk/include/lldb/Host/posix/HostInfoPosix.h
@@ -33,6 +33,8 @@
 
     static FileSpec GetDefaultShell();
 
+    static bool GetEnvironmentVar(const std::string &var_name, std::string &var);
+
   protected:
     static bool ComputeSupportExeDirectory(FileSpec &file_spec);
     static bool ComputeHeaderDirectory(FileSpec &file_spec);
Index: lldb/trunk/include/lldb/Host/FileSystem.h
===================================================================
--- lldb/trunk/include/lldb/Host/FileSystem.h
+++ lldb/trunk/include/lldb/Host/FileSystem.h
@@ -11,6 +11,8 @@
 #define liblldb_Host_FileSystem_h
 
 #include <stdint.h>
+#include <stdio.h>
+#include <sys/stat.h>
 
 #include "lldb/lldb-types.h"
 
@@ -23,6 +25,7 @@
 {
   public:
     static const char *DEV_NULL;
+    static const char *PATH_CONVERSION_ERROR;
 
     static FileSpec::PathSyntax GetNativePathSyntax();
 
@@ -59,6 +62,10 @@
 
     /// Return \b true if \a spec is on a locally mounted file system, \b false otherwise.
     static bool IsLocal(const FileSpec &spec);
+
+    /// Wraps ::fopen in a platform-independent way. Once opened, FILEs can be
+    /// manipulated and closed with the normal ::fread, ::fclose, etc. functions.
+    static FILE* Fopen(const char *path, const char *mode);
 };
 }
 
Index: lldb/trunk/cmake/modules/LLDBConfig.cmake
===================================================================
--- lldb/trunk/cmake/modules/LLDBConfig.cmake
+++ lldb/trunk/cmake/modules/LLDBConfig.cmake
@@ -245,6 +245,11 @@
   )
 endif()
 
+# Use the Unicode (UTF-16) APIs by default on Win32
+if (CMAKE_SYSTEM_NAME MATCHES "Windows")
+	add_definitions( /D _UNICODE /D UNICODE )
+endif()
+
 set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to