cameron314 created this revision. cameron314 added a reviewer: zturner. cameron314 added a subscriber: lldb-commits. cameron314 set the repository for this revision to rL LLVM.
Various fixes for Win32 interop, particularly with regard to paths; paths containing non-ASCII characters now work properly (they are converted to and from UTF-8 internally). Repository: rL LLVM http://reviews.llvm.org/D17107 Files: cfe/trunk/tools/libclang/CIndexer.cpp lldb/trunk/cmake/modules/LLDBConfig.cmake 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/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 llvm/trunk/include/llvm/Support/ConvertUTF.h llvm/trunk/lib/Support/CommandLine.cpp llvm/trunk/lib/Support/ConvertUTFWrapper.cpp llvm/trunk/unittests/Support/ConvertUTFTest.cpp
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,9 @@ #include "MIUtilFileStd.h" #include "MICmnResources.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ConvertUTF.h" + //++ ------------------------------------------------------------------------------------ // Details: CMIUtilFileStd constructor. // Type: Method. @@ -82,7 +85,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); + llvm::SmallVector<UTF16, 128> path; + if (llvm::convertUTF8ToUTF16String(vFileNamePath.c_str(), path)) + m_pFileHandle = ::_wfsopen((const wchar_t *)path.data(), L"wb", _SH_DENYWR); + else + { + errno = EINVAL; + m_pFileHandle = nullptr; + } #endif // !defined( _MSC_VER ) if (m_pFileHandle == nullptr) @@ -222,7 +232,14 @@ return false; FILE *pTmp = nullptr; +#if _WIN32 + llvm::SmallVector<UTF16, 128> path; + if (!llvm::convertUTF8ToUTF16String(vFileNamePath.c_str(), path)) + return false; + pTmp = ::_wfopen((const wchar_t *)path.data(), 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 @@ -41,6 +41,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" @@ -1261,14 +1262,33 @@ } int -main (int argc, char const *argv[], const char *envp[]) +#if defined(_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 +#if defined(_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::convertUTF16ToUTF8String((const UTF16*)wargv[i], argvStrings[i]); + argvPointers[i] = argvStrings[i].c_str(); + } + const char** argv = argvPointers.data(); + + // Indicate that all our output is in UTF-8 + SetConsoleCP(CP_UTF8); +#endif + SBDebugger::Initialize(); SBHostOS::ThreadCreated ("<lldb.driver.main-thread>"); Index: lldb/trunk/source/Target/ProcessLaunchInfo.cpp =================================================================== --- lldb/trunk/source/Target/ProcessLaunchInfo.cpp +++ lldb/trunk/source/Target/ProcessLaunchInfo.cpp @@ -16,6 +16,8 @@ #include "lldb/Target/FileAction.h" #include "lldb/Target/Target.h" +#include "llvm/Support/ConvertUTF.h" + #if !defined(_WIN32) #include <limits.h> #endif @@ -451,7 +453,18 @@ if (cwd && cwd[0]) new_path += cwd; } - const char *curr_path = getenv("PATH"); + const char *curr_path = nullptr; +#ifdef _WIN32 + const wchar_t *wcurr_path = _wgetenv(L"PATH"); + std::string curr_path_buffer; + if (wcurr_path) + { + if (llvm::convertUTF16ToUTF8String((const UTF16 *)wcurr_path, curr_path_buffer)) + curr_path = curr_path_buffer.c_str(); + } +#else + curr_path = getenv("PATH"); +#endif if (curr_path) { if (new_path.size() > empty_path_len) 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 @@ -21,6 +21,9 @@ #include "lldb/Host/File.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ConvertUTF.h" + #include <stdio.h> #include "llvm/ADT/StringSwitch.h" @@ -1163,7 +1166,15 @@ PythonFile::PythonFile(const char *path, const char *mode) { FILE *fp = nullptr; +#if _WIN32 + llvm::SmallVector<UTF16, 128> wpath; + llvm::SmallVector<UTF16, 4> wmode; + llvm::convertUTF8ToUTF16String(path, wpath); + llvm::convertUTF8ToUTF16String(mode, wmode); + fp = _wfopen((const wchar_t *)wpath.data(), (const wchar_t *)wmode.data()); +#else fp = fopen(path, mode); +#endif lldb_private::File file(fp, true); 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 @@ -426,17 +426,22 @@ ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file) { Error error; - - m_data_up->m_dump_file = ::CreateFile(file, GENERIC_READ, FILE_SHARE_READ, + llvm::SmallVector<UTF16, 128> wfile; + if (!llvm::convertUTF8ToUTF16String(file, wfile)) + { + error.SetError(1, lldb::eErrorTypeGeneric); + return error; + } + m_data_up->m_dump_file = ::CreateFileW((LPWSTR)wfile.data(), 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<UTF16> 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, (LPWSTR)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::convertUTF16ToUTF8String(file_name, 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<UTF16> buffer(1); + DWORD required_size = GetFinalPathNameByHandleW(info.hFile, (LPWSTR)&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, (LPWSTR)&buffer[0], required_size, VOLUME_NAME_DOS); + std::string path_str_utf8; + llvm::convertUTF16ToUTF8String(buffer, 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,24 @@ // 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)) + { + 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); + llvm::SmallVector<UTF16, 64> warg; + if (llvm::convertUTF8ToUTF16String(env.GetArgumentAtIndex(i), warg)) + { + buffer.insert(buffer.end(), (char*)warg.data(), + (char*)(warg.data() + wcslen((wchar_t*)warg.data()) + 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; @@ -81,9 +83,18 @@ env_block = environment.data(); executable = launch_info.GetExecutableFile().GetPath(); + llvm::SmallVector<UTF16, 128> wexecutable; + llvm::convertUTF8ToUTF16String(executable, wexecutable); + 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); + llvm::SmallVector<UTF16, 64> wcommandLine; + llvm::convertUTF8ToUTF16String(commandLine, wcommandLine); + + llvm::SmallVector<UTF16, 128> wworkingDirectory; + llvm::convertUTF8ToUTF16String(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory); + + BOOL result = ::CreateProcessW((LPCWSTR)wexecutable.data(), (LPWSTR)wcommandLine.data(), NULL, NULL, TRUE, flags, + env_block, (LPCWSTR)wworkingDirectory.data(), &startupinfo, &pi); if (result) { // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. @@ -131,6 +142,8 @@ flags = FILE_FLAG_WRITE_THROUGH; } - HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL); + llvm::SmallVector<UTF16, 128> wpath; + llvm::convertUTF8ToUTF16String(path, wpath); + HANDLE result = ::CreateFileW((LPCWSTR)wpath.data(), 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); + UTF16 wpath[PATH_MAX] = { 0 }; + if (::GetProcessImageFileNameW(m_process, (LPWSTR)wpath, llvm::array_lengthof(wpath))) + { + std::string path; + if (llvm::convertUTF16ToUTF8String(wpath, path)) + file_spec.SetFile(path, false); + else + error.SetError(1, lldb::eErrorTypeGeneric); + } 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,23 +77,25 @@ bool HostInfoWindows::GetHostname(std::string &s) { - char buffer[MAX_COMPUTERNAME_LENGTH + 1]; + UTF16 buffer[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; - if (!::GetComputerName(buffer, &dwSize)) + if (!::GetComputerNameW((LPWSTR)buffer, &dwSize)) return false; - s.assign(buffer, buffer + dwSize); - return true; + return llvm::convertUTF16ToUTF8String( + llvm::makeArrayRef(buffer, dwSize), 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); + UTF16 buffer[PATH_MAX]; + ::GetModuleFileNameW(NULL, (LPWSTR)buffer, PATH_MAX); + std::string path; + llvm::convertUTF16ToUTF8String(buffer, path); + m_program_filespec.SetFile(path, false); }); return m_program_filespec; } 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<UTF16> buffer(PATH_MAX); DWORD dwSize = buffer.size(); - if (!::QueryFullProcessImageNameA(handle.get(), 0, &buffer[0], &dwSize)) + if (!::QueryFullProcessImageNameW(handle.get(), 0, (LPWSTR)&buffer[0], &dwSize)) return false; - path.assign(&buffer[0]); - return true; + return llvm::convertUTF16ToUTF8String(buffer.data(), path); } void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process) @@ -156,15 +157,16 @@ 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; + llvm::convertUTF16ToUTF8String((const UTF16*)buffer.data(), path); + module_filespec.SetFile(path, false); return module_filespec; } @@ -177,23 +179,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::convertUTF16ToUTF8String((const UTF16 *)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,11 +316,16 @@ { // 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; + if (!llvm::convertUTF16ToUTF8String((const UTF16 *)environment_block, current_var)) + { + environment_block += wcslen(environment_block) + 1; + continue; + } if (current_var[0] != '=') env.AppendString(current_var); Index: lldb/trunk/source/Host/windows/FileSystem.cpp =================================================================== --- lldb/trunk/source/Host/windows/FileSystem.cpp +++ lldb/trunk/source/Host/windows/FileSystem.cpp @@ -15,6 +15,9 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/windows/AutoHandle.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" using namespace lldb_private; @@ -47,25 +50,32 @@ FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { Error error; + llvm::SmallVector<UTF16, 128> path_buffer; + if (!llvm::convertUTF8ToUTF16String(file_spec.GetPath(), path_buffer)) + { + error.SetError(1, lldb::eErrorTypeGeneric); + return error; + } if (!recurse) { - BOOL result = ::RemoveDirectory(file_spec.GetCString()); + BOOL result = ::RemoveDirectoryW((LPCWSTR)path_buffer.data()); 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 +131,24 @@ FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { Error error; - if (!::CreateHardLink(src.GetCString(), dst.GetCString(), nullptr)) + llvm::SmallVector<UTF16, 128> srcBuffer, dstBuffer; + if (!llvm::convertUTF8ToUTF16String(src.GetCString(), srcBuffer)) + error.SetError(1, lldb::eErrorTypeGeneric); + else if (!llvm::convertUTF8ToUTF16String(dst.GetCString(), dstBuffer)) + error.SetError(1, lldb::eErrorTypeGeneric); + else if (!::CreateHardLinkW((LPCWSTR)srcBuffer.data(), (LPCWSTR)dstBuffer.data(), nullptr)) error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; } int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { - HANDLE file_handle = ::CreateFile(file_spec.GetCString(), + llvm::SmallVector<UTF16, 128> path; + if (!llvm::convertUTF8ToUTF16String(file_spec.GetCString(), path)) + return -1; + + HANDLE file_handle = ::CreateFileW((LPCWSTR)path.data(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr, @@ -152,15 +171,22 @@ FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { Error error; - DWORD attrib = ::GetFileAttributes(dst.GetCString()); + llvm::SmallVector<UTF16, 128> srcBuffer, dstBuffer; + if (!llvm::convertUTF8ToUTF16String(src.GetCString(), srcBuffer)) + error.SetError(1, lldb::eErrorTypeGeneric); + else if (!llvm::convertUTF8ToUTF16String(dst.GetCString(), dstBuffer)) + error.SetError(1, lldb::eErrorTypeGeneric); + if (error.Fail()) + return error; + DWORD attrib = ::GetFileAttributesW((LPCWSTR)dstBuffer.data()); 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((LPCWSTR)srcBuffer.data(), (LPCWSTR)dstBuffer.data(), 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()); + llvm::SmallVector<UTF16, 128> path; + if (!llvm::convertUTF8ToUTF16String(file_spec.GetCString(), path)) + { + error.SetError(1, lldb::eErrorTypeGeneric); + return error; + } + BOOL result = ::DeleteFileW((LPCWSTR)path.data()); 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, + llvm::SmallVector<UTF16, 128> srcBuffer; + if (!llvm::convertUTF8ToUTF16String(src.GetCString(), srcBuffer)) + { + error.SetError(1, lldb::eErrorTypeGeneric); + return error; + } + + HANDLE h = ::CreateFileW((LPCWSTR)srcBuffer.data(), 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]; + 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, PATH_MAX, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + std::string path; if (result == 0) error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + else if (!llvm::convertUTF16ToUTF8String((UTF16*)buf, path)) + error.SetError(1, lldb::eErrorTypeGeneric); else - dst.SetFile(buf, false); + dst.SetFile(path, false); ::CloseHandle(h); return error; Index: lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp =================================================================== --- lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp +++ lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp @@ -12,8 +12,10 @@ #include "lldb/Host/TimeValue.h" #include "lldb/Host/windows/ConnectionGenericFileWindows.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ConvertUTF.h" using namespace lldb; using namespace lldb_private; @@ -138,7 +140,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); + llvm::SmallVector<UTF16, 128> wpath; + if (!llvm::convertUTF8ToUTF16String(path, wpath)) + { + if (error_ptr) + error_ptr->SetError(1, eErrorTypeGeneric); + return eConnectionStatusError; + } + m_file = ::CreateFileW((LPCWSTR)wpath.data(), 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/common/FileSpec.cpp =================================================================== --- lldb/trunk/source/Host/common/FileSpec.cpp +++ lldb/trunk/source/Host/common/FileSpec.cpp @@ -40,6 +40,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 +91,26 @@ { char resolved_path[PATH_MAX]; if (file_spec->GetPath (resolved_path, sizeof(resolved_path))) + { +#ifdef _WIN32 + llvm::SmallVector<UTF16, 128> wresolved_path; + if (!llvm::convertUTF8ToUTF16String(resolved_path, wresolved_path)) + return false; + int stat_result; +#ifdef _USE_32BIT_TIME_T + struct _stat32 file_stats; + stat_result = ::_wstat32((const wchar_t *)wresolved_path.data(), &file_stats); +#else + struct _stat64i32 file_stats; + stat_result = ::_wstat64i32((const wchar_t *)wresolved_path.data(), &file_stats); +#endif + if (stat_result == 0) + *stats_ptr = *reinterpret_cast<struct stat *>(&file_stats); + return stat_result == 0; +#else return ::stat (resolved_path, stats_ptr) == 0; +#endif + } return false; } @@ -213,8 +233,17 @@ path.push_back(0); // Be sure we have a nul terminated string path.pop_back(); + int stat_result; +#ifdef _WIN32 + llvm::SmallVector<UTF16, 128> wpath; + llvm::convertUTF8ToUTF16String(path.data(), wpath); + struct _stat32 file_stats; + stat_result = ::_wstat32((const wchar_t *)wpath.data(), &file_stats); +#else struct stat file_stats; - if (::stat (path.data(), &file_stats) != 0) + stat_result = ::stat(file_spec.GetCString(), &file_stats); +#endif + if (stat_result != 0) { path.clear(); path.append(original_path.begin(), original_path.end()); @@ -797,7 +826,10 @@ return false; #ifdef _WIN32 - auto attrs = ::GetFileAttributes (resolved_path); + llvm::SmallVector<UTF16, 128> wpath; + if (!llvm::convertUTF8ToUTF16String (resolved_path, wpath)) + return false; + auto attrs = ::GetFileAttributesW ((LPCWSTR)wpath.data()); if (attrs == INVALID_FILE_ATTRIBUTES) return false; @@ -1100,8 +1132,14 @@ std::string szDir(dir_path); szDir += "\\*"; + llvm::SmallVector<UTF16, 128> wszDir; + if (!llvm::convertUTF8ToUTF16String(szDir, wszDir)) + { + return eEnumerateDirectoryResultNext; + } + WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile(szDir.c_str(), &ffd); + HANDLE hFind = FindFirstFileW((LPCWSTR)wszDir.data(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { @@ -1113,12 +1151,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,8 +1170,14 @@ 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); + std::string fileName; + if (!llvm::convertUTF16ToUTF8String((const UTF16*)ffd.cFileName, fileName)) + { + continue; + } + + char child_path[PATH_MAX]; + const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, fileName.c_str()); if (child_path_len < (int)(sizeof(child_path) - 1)) { // Don't resolve the file type or path @@ -1167,7 +1211,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 + llvm::SmallVector<UTF16, 128> wpath; + if (!llvm::convertUTF8ToUTF16String(path, wpath)) + { + m_descriptor = -1; + error.SetErrorString("Error converting path to UTF-16"); + return error; + } + m_descriptor = ::_wopen((const wchar_t *)wpath.data(), oflag, 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 + llvm::SmallVector<UTF16, 128> wpath; + if (!llvm::convertUTF8ToUTF16String(file_spec.GetCString(), wpath)) + { + error.SetError(1, lldb::eErrorTypeGeneric); + return 0; + } + struct _stat32 file_stats; + stat_result = ::_wstat32((const wchar_t *)wpath.data(), &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 @@ -36,6 +36,8 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" +#include "llvm/Support/ConvertUTF.h" + #define DEFAULT_DISASM_BYTE_SIZE 32 using namespace lldb; @@ -876,8 +878,14 @@ out_stream->Printf ("Instruction::TestEmulation: Missing file_name."); return false; } - - FILE *test_file = fopen (file_name, "r"); + FILE *test_file = nullptr; +#if _WIN32 + llvm::SmallVector<UTF16, 128> wfile_name; + if (llvm::convertUTF8ToUTF16String (file_name, wfile_name)) + test_file = _wfopen ((const wchar_t *)wfile_name.data(), L"r"); +#else + test_file = fopen (file_name, "r"); +#endif 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,9 @@ #include "lldb/Core/Communication.h" #include "lldb/Core/Log.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ConvertUTF.h" + using namespace lldb; using namespace lldb_private; @@ -132,18 +135,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; + llvm::SmallVector<UTF16, 128> wname; + if (llvm::convertUTF8ToUTF16String(name, wname)) + { + if (create) { + handle = CreateFileMappingW( + INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + llvm::Hi_32(size), + llvm::Lo_32(size), + (LPCWSTR)wname.data()); + } + else + handle = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, (LPCWSTR)wname.data()); } - 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 @@ -30,6 +30,8 @@ #include "lldb/Utility/CleanUp.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ConvertUTF.h" using namespace lldb_private; @@ -166,9 +168,20 @@ isa_directory = true; else if (file_type == FileSpec::eFileTypeSymbolicLink) { +#ifdef _WIN32 + llvm::SmallVector<UTF16, 128> wpartial_name_copy; + if (llvm::convertUTF8ToUTF16String(partial_name_copy, wpartial_name_copy)) + { + struct _stat32 stat_buf; + if (_wstat32((const wchar_t *)wpartial_name_copy.data(), &stat_buf) == 0 && + S_ISDIR(stat_buf.st_mode)) + isa_directory = true; + } +#else struct stat stat_buf; if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) isa_directory = true; +#endif } if (isa_directory) 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}) Index: cfe/trunk/tools/libclang/CIndexer.cpp =================================================================== --- cfe/trunk/tools/libclang/CIndexer.cpp +++ cfe/trunk/tools/libclang/CIndexer.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" @@ -53,20 +54,12 @@ // Find the location where this library lives (libclang.dylib). #ifdef LLVM_ON_WIN32 MEMORY_BASIC_INFORMATION mbi; - char path[MAX_PATH]; + wchar_t wpath[MAX_PATH]; VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi, sizeof(mbi)); - GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH); - -#ifdef __CYGWIN__ - char w32path[MAX_PATH]; - strcpy(w32path, path); -#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181 - cygwin_conv_path(CCP_WIN_A_TO_POSIX, w32path, path, MAX_PATH); -#else - cygwin_conv_to_full_posix_path(w32path, path); -#endif -#endif + GetModuleFileNameW((HINSTANCE)mbi.AllocationBase, wpath, MAX_PATH); + std::string path; + llvm::convertUTF16ToUTF8String((const UTF16 *)wpath, path); LibClangPath += llvm::sys::path::parent_path(path); #else Index: llvm/trunk/unittests/Support/ConvertUTFTest.cpp =================================================================== --- llvm/trunk/unittests/Support/ConvertUTFTest.cpp +++ llvm/trunk/unittests/Support/ConvertUTFTest.cpp @@ -59,7 +59,7 @@ TEST(ConvertUTFTest, Empty) { std::string Result; - bool Success = convertUTF16ToUTF8String(None, Result); + bool Success = convertUTF16ToUTF8String(llvm::ArrayRef<char>(None), Result); EXPECT_TRUE(Success); EXPECT_TRUE(Result.empty()); } Index: llvm/trunk/lib/Support/ConvertUTFWrapper.cpp =================================================================== --- llvm/trunk/lib/Support/ConvertUTFWrapper.cpp +++ llvm/trunk/lib/Support/ConvertUTFWrapper.cpp @@ -36,7 +36,7 @@ ConversionFlags flags = strictConversion; result = ConvertUTF8toUTF16( &sourceStart, sourceStart + Source.size(), - &targetStart, targetStart + 2*Source.size(), flags); + &targetStart, targetStart + Source.size(), flags); if (result == conversionOK) ResultPtr = reinterpret_cast<char*>(targetStart); else @@ -49,7 +49,7 @@ ConversionFlags flags = strictConversion; result = ConvertUTF8toUTF32( &sourceStart, sourceStart + Source.size(), - &targetStart, targetStart + 4*Source.size(), flags); + &targetStart, targetStart + Source.size(), flags); if (result == conversionOK) ResultPtr = reinterpret_cast<char*>(targetStart); else @@ -130,6 +130,20 @@ return true; } +bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out) +{ + return convertUTF16ToUTF8String( + llvm::ArrayRef<char>(reinterpret_cast<const char *>(Src.data()), + Src.size() * sizeof(UTF16)), Out); +} + +bool convertUTF16ToUTF8String(const UTF16 *Src, std::string &Out) +{ + const UTF16 *End = Src; + while (*End) ++End; + return convertUTF16ToUTF8String(llvm::makeArrayRef(Src, End), Out); +} + bool convertUTF8ToUTF16String(StringRef SrcUTF8, SmallVectorImpl<UTF16> &DstUTF16) { assert(DstUTF16.empty()); Index: llvm/trunk/lib/Support/CommandLine.cpp =================================================================== --- llvm/trunk/lib/Support/CommandLine.cpp +++ llvm/trunk/lib/Support/CommandLine.cpp @@ -787,9 +787,22 @@ assert(envVar && "Environment variable name missing"); // Get the environment variable they want us to parse options out of. +#ifdef _WIN32 + llvm::SmallVector<UTF16, 32> wenvVar; + if (!llvm::convertUTF8ToUTF16String(envVar, wenvVar)) + return; + const wchar_t *wenvValue = _wgetenv((const wchar_t *)wenvVar.data()); + if (!wenvValue) + return; + std::string envValueBuffer; + if (!llvm::convertUTF16ToUTF8String((const UTF16 *)wenvValue, envValueBuffer)) + return; + const char *envValue = envValueBuffer.c_str(); +#else const char *envValue = getenv(envVar); if (!envValue) return; +#endif // Get program's "name", which we wouldn't know without the caller // telling us. Index: llvm/trunk/include/llvm/Support/ConvertUTF.h =================================================================== --- llvm/trunk/include/llvm/Support/ConvertUTF.h +++ llvm/trunk/include/llvm/Support/ConvertUTF.h @@ -252,6 +252,24 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out); /** +* Converts a UTF16 string into a UTF8 std::string. +* +* \param [in] Src A buffer of UTF-16 encoded text. +* \param [out] Out Converted UTF-8 is stored here on success. +* \returns true on success +*/ +bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out); + +/** +* Converts a UTF16 string into a UTF8 std::string. +* +* \param [in] Src A pointer to a null-terminated UTF-16 encoded string. +* \param [out] Out Converted UTF-8 is stored here on success. +* \returns true on success +*/ +bool convertUTF16ToUTF8String(const UTF16 *Src, std::string &Out); + +/** * Converts a UTF-8 string into a UTF-16 string with native endianness. * * \returns true on success
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits