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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits