Unicode support on Win32.

Win32 API calls that are Unicode aware require wide character
strings, but LLDB uses UTF8 everywhere.  This patch does conversions
wherever necessary when passing strings into and out of Win32 API
calls.

Patch by Cameron
Differential Revision: http://reviews.llvm.org/D17107
Reviewed By: zturner, amccarth

llvm-svn: 264074
This commit is contained in:
Zachary Turner 2016-03-22 17:58:09 +00:00
parent 6feeb6554e
commit 190fadcdb2
29 changed files with 538 additions and 234 deletions

View File

@ -245,6 +245,11 @@ if( MSVC )
)
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})

View File

@ -11,6 +11,8 @@
#define liblldb_Host_FileSystem_h
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include "lldb/lldb-types.h"
@ -23,6 +25,7 @@ class FileSystem
{
public:
static const char *DEV_NULL;
static const char *PATH_CONVERSION_ERROR;
static FileSpec::PathSyntax GetNativePathSyntax();
@ -59,6 +62,15 @@ class FileSystem
/// Return \b true if \a spec is on a locally mounted file system, \b false otherwise.
static bool IsLocal(const FileSpec &spec);
/// Wraps ::fopen in a platform-independent way. Once opened, FILEs can be
/// manipulated and closed with the normal ::fread, ::fclose, etc. functions.
static FILE *
Fopen(const char *path, const char *mode);
/// Wraps ::stat in a platform-independent way.
static int
Stat(const char *path, struct stat *stats);
};
}

View File

@ -33,7 +33,10 @@ class HostInfoPosix : public HostInfoBase
static FileSpec GetDefaultShell();
protected:
static bool
GetEnvironmentVar(const std::string &var_name, std::string &var);
protected:
static bool ComputeSupportExeDirectory(FileSpec &file_spec);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
static bool ComputePythonDirectory(FileSpec &file_spec);

View File

@ -47,6 +47,9 @@ class HostInfoWindows : public HostInfoBase
static FileSpec
GetDefaultShell();
static bool
GetEnvironmentVar(const std::string &var_name, std::string &var);
protected:
static bool ComputePythonDirectory(FileSpec &file_spec);

View File

@ -659,7 +659,7 @@ def setupSysPath():
print(" location of LLDB\'s site-packages folder.")
print(" 3) A different version of Python than that which was built against is exported in")
print(" the system\'s PATH environment variable, causing conflicts.")
print(" 4) The executable '%s' could not be found. Please check " % lldbExecutable)
print(" 4) The executable '%s' could not be found. Please check " % lldbtest_config.lldbExec)
print(" that it exists and is executable.")
if lldbPythonDir:

View File

@ -18,10 +18,11 @@
#include "llvm/ADT/SmallString.h"
// Project includes
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@ -31,6 +32,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/CleanUp.h"
#include "llvm/ADT/SmallString.h"
using namespace lldb_private;
CommandCompletions::CommonCompletionElement
@ -160,8 +163,7 @@ FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, F
isa_directory = true;
else if (file_type == FileSpec::eFileTypeSymbolicLink)
{
struct stat stat_buf;
if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
if (FileSpec(partial_name_copy, false).IsDirectory())
isa_directory = true;
}

View File

@ -32,6 +32,8 @@
#include "lldb/Core/Communication.h"
#include "lldb/Core/Log.h"
#include "llvm/Support/ConvertUTF.h"
using namespace lldb;
using namespace lldb_private;
@ -135,18 +137,18 @@ ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error
m_name.assign (name);
#ifdef _WIN32
HANDLE handle;
if (create) {
handle = CreateFileMapping(
INVALID_HANDLE_VALUE,
nullptr,
PAGE_READWRITE,
llvm::Hi_32(size),
llvm::Lo_32(size),
name);
HANDLE handle = INVALID_HANDLE_VALUE;
std::wstring wname;
if (llvm::ConvertUTF8toWide(name, wname))
{
if (create)
{
handle = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, llvm::Hi_32(size),
llvm::Lo_32(size), wname.c_str());
}
else
handle = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, wname.c_str());
}
else
handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
m_fd = _open_osfhandle((intptr_t)handle, 0);
#else

View File

@ -16,16 +16,16 @@
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueArray.h"
#include "lldb/Interpreter/OptionValueDictionary.h"
@ -38,6 +38,7 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/lldb-private.h"
#define DEFAULT_DISASM_BYTE_SIZE 32
@ -849,8 +850,7 @@ Instruction::TestEmulation (Stream *out_stream, const char *file_name)
out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
return false;
}
FILE *test_file = fopen (file_name, "r");
FILE *test_file = FileSystem::Fopen(file_name, "r");
if (!test_file)
{
out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");

View File

@ -14,7 +14,6 @@
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/stat.h>
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
@ -22,6 +21,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"
@ -29,6 +29,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
using namespace lldb;
using namespace lldb_private;
@ -267,7 +268,18 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
do
{
#ifdef _WIN32
std::wstring wpath;
if (!llvm::ConvertUTF8toWide(path, wpath))
{
m_descriptor = -1;
error.SetErrorString("Error converting path to UTF-16");
return error;
}
::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode);
#else
m_descriptor = ::open(path, oflag, mode);
#endif
} while (m_descriptor < 0 && errno == EINTR);
if (!DescriptorIsValid())
@ -287,7 +299,8 @@ File::GetPermissions(const FileSpec &file_spec, Error &error)
if (file_spec)
{
struct stat file_stats;
if (::stat(file_spec.GetCString(), &file_stats) == -1)
int stat_result = FileSystem::Stat(file_spec.GetCString(), &file_stats);
if (stat_result == -1)
error.SetErrorToErrno();
else
{

View File

@ -17,7 +17,6 @@
#ifndef _MSC_VER
#include <libgen.h>
#endif
#include <sys/stat.h>
#include <set>
#include <string.h>
#include <fstream>
@ -40,6 +39,7 @@
#include "lldb/Utility/CleanUp.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
@ -90,7 +90,7 @@ GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr)
{
char resolved_path[PATH_MAX];
if (file_spec->GetPath (resolved_path, sizeof(resolved_path)))
return ::stat (resolved_path, stats_ptr) == 0;
return FileSystem::Stat(resolved_path, stats_ptr) == 0;
return false;
}
@ -206,15 +206,10 @@ FileSpec::Resolve (llvm::SmallVectorImpl<char> &path)
#endif // #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER
// Save a copy of the original path that's passed in
llvm::SmallString<PATH_MAX> original_path(path.begin(), path.end());
llvm::SmallString<128> original_path(path.begin(), path.end());
llvm::sys::fs::make_absolute(path);
path.push_back(0); // Be sure we have a nul terminated string
path.pop_back();
struct stat file_stats;
if (::stat (path.data(), &file_stats) != 0)
if (!llvm::sys::fs::exists(path))
{
path.clear();
path.append(original_path.begin(), original_path.end());
@ -815,7 +810,10 @@ FileSpec::IsSymbolicLink () const
return false;
#ifdef _WIN32
auto attrs = ::GetFileAttributes (resolved_path);
std::wstring wpath;
if (!llvm::ConvertUTF8toWide(resolved_path, wpath))
return false;
auto attrs = ::GetFileAttributesW(wpath.c_str());
if (attrs == INVALID_FILE_ATTRIBUTES)
return false;
@ -1114,12 +1112,18 @@ FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const
{
if (dir_path && dir_path[0])
{
#if _WIN32
#ifdef _WIN32
std::string szDir(dir_path);
szDir += "\\*";
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(szDir.c_str(), &ffd);
std::wstring wszDir;
if (!llvm::ConvertUTF8toWide(szDir, wszDir))
{
return eEnumerateDirectoryResultNext;
}
WIN32_FIND_DATAW ffd;
HANDLE hFind = FindFirstFileW(wszDir.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
@ -1131,12 +1135,12 @@ FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const
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;
@ -1150,12 +1154,19 @@ FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const
file_type = eFileTypeRegular;
}
char child_path[MAX_PATH];
const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, ffd.cFileName);
if (child_path_len < (int)(sizeof(child_path) - 1))
std::string fileName;
if (!llvm::convertWideToUTF8(ffd.cFileName, fileName))
{
continue;
}
std::vector<char> child_path(PATH_MAX);
const int child_path_len =
::snprintf(child_path.data(), child_path.size(), "%s\\%s", dir_path, fileName.c_str());
if (child_path_len < (int)(child_path.size() - 1))
{
// Don't resolve the file type or path
FileSpec child_path_spec (child_path, false);
FileSpec child_path_spec(child_path.data(), false);
EnumerateDirectoryResult result = callback (file_type, child_path_spec);
@ -1168,7 +1179,8 @@ FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const
break;
case eEnumerateDirectoryResultEnter: // Recurse into the current entry if it is a directory or symlink, or next if not
if (FileSpec::ForEachItemInDirectory(child_path, callback) == eEnumerateDirectoryResultQuit)
if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) ==
eEnumerateDirectoryResultQuit)
{
// The subdirectory returned Quit, which means to
// stop all directory enumerations at all levels.
@ -1185,7 +1197,7 @@ FileSpec::ForEachItemInDirectory (const char *dir_path, DirectoryCallback const
return eEnumerateDirectoryResultQuit;
}
}
} while (FindNextFile(hFind, &ffd) != 0);
} while (FindNextFileW(hFind, &ffd) != 0);
FindClose(hFind);
#else

View File

@ -299,3 +299,15 @@ FileSystem::IsLocal(const FileSpec &spec)
return false;
}
#endif
FILE *
FileSystem::Fopen(const char *path, const char *mode)
{
return ::fopen(path, mode);
}
int
FileSystem::Stat(const char *path, struct stat *stats)
{
return ::stat(path, stats);
}

View File

@ -242,3 +242,14 @@ HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec)
return false;
#endif
}
bool
HostInfoPosix::GetEnvironmentVar(const std::string &var_name, std::string &var)
{
if (const char *pvar = ::getenv(var_name.c_str()))
{
var = std::string(pvar);
return true;
}
return false;
}

View File

@ -14,6 +14,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
using namespace lldb;
using namespace lldb_private;
@ -138,7 +139,15 @@ ConnectionGenericFile::Connect(const char *s, Error *error_ptr)
// Open the file for overlapped access. If it does not exist, create it. We open it overlapped
// so that we can issue asynchronous reads and then use WaitForMultipleObjects to allow the read
// to be interrupted by an event object.
m_file = ::CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
std::wstring wpath;
if (!llvm::ConvertUTF8toWide(path, wpath))
{
if (error_ptr)
error_ptr->SetError(1, eErrorTypeGeneric);
return eConnectionStatusError;
}
m_file = ::CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED, NULL);
if (m_file == INVALID_HANDLE_VALUE)
{
if (error_ptr)

View File

@ -15,6 +15,8 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/windows/AutoHandle.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
using namespace lldb_private;
@ -22,6 +24,8 @@ using namespace lldb_private;
const char *
FileSystem::DEV_NULL = "nul";
const char *FileSystem::PATH_CONVERSION_ERROR = "Error converting path between UTF-8 and native encoding";
FileSpec::PathSyntax
FileSystem::GetNativePathSyntax()
{
@ -47,25 +51,32 @@ Error
FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
{
Error error;
std::wstring path_buffer;
if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer))
{
error.SetErrorString(PATH_CONVERSION_ERROR);
return error;
}
if (!recurse)
{
BOOL result = ::RemoveDirectory(file_spec.GetCString());
BOOL result = ::RemoveDirectoryW(path_buffer.c_str());
if (!result)
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
}
else
{
// SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
// indicate the end of the list.
std::string path_buffer{file_spec.GetPath()};
// indicate the end of the list. The first null terminator is there only in the backing
// store but not the actual vector contents, and so we need to push twice.
path_buffer.push_back(0);
path_buffer.push_back(0);
SHFILEOPSTRUCT shfos = {0};
SHFILEOPSTRUCTW shfos = {0};
shfos.wFunc = FO_DELETE;
shfos.pFrom = path_buffer.c_str();
shfos.pFrom = (LPCWSTR)path_buffer.data();
shfos.fFlags = FOF_NO_UI;
int result = ::SHFileOperation(&shfos);
int result = ::SHFileOperationW(&shfos);
// TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
if (result != 0)
error.SetErrorStringWithFormat("SHFileOperation failed");
@ -121,7 +132,10 @@ Error
FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
{
Error error;
if (!::CreateHardLink(src.GetCString(), dst.GetCString(), nullptr))
std::wstring wsrc, wdst;
if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
error.SetErrorString(PATH_CONVERSION_ERROR);
else if (!::CreateHardLinkW(wsrc.c_str(), wdst.c_str(), nullptr))
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
return error;
}
@ -129,13 +143,12 @@ FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
int
FileSystem::GetHardlinkCount(const FileSpec &file_spec)
{
HANDLE file_handle = ::CreateFile(file_spec.GetCString(),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr);
std::wstring path;
if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
return -1;
HANDLE file_handle = ::CreateFileW(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (file_handle == INVALID_HANDLE_VALUE)
return -1;
@ -152,7 +165,12 @@ Error
FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
{
Error error;
DWORD attrib = ::GetFileAttributes(dst.GetCString());
std::wstring wsrc, wdst;
if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc) || !llvm::ConvertUTF8toWide(dst.GetCString(), wdst))
error.SetErrorString(PATH_CONVERSION_ERROR);
if (error.Fail())
return error;
DWORD attrib = ::GetFileAttributesW(wdst.c_str());
if (attrib == INVALID_FILE_ATTRIBUTES)
{
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
@ -160,7 +178,7 @@ FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
}
bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
BOOL result = ::CreateSymbolicLink(src.GetCString(), dst.GetCString(), flag);
BOOL result = ::CreateSymbolicLinkW(wsrc.c_str(), wdst.c_str(), flag);
if (!result)
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
return error;
@ -170,7 +188,13 @@ Error
FileSystem::Unlink(const FileSpec &file_spec)
{
Error error;
BOOL result = ::DeleteFile(file_spec.GetCString());
std::wstring path;
if (!llvm::ConvertUTF8toWide(file_spec.GetCString(), path))
{
error.SetErrorString(PATH_CONVERSION_ERROR);
return error;
}
BOOL result = ::DeleteFileW(path.c_str());
if (!result)
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
return error;
@ -180,23 +204,31 @@ Error
FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
{
Error error;
HANDLE h = ::CreateFile(src.GetCString(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT, NULL);
std::wstring wsrc;
if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc))
{
error.SetErrorString(PATH_CONVERSION_ERROR);
return error;
}
HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (h == INVALID_HANDLE_VALUE)
{
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
return error;
}
char buf[PATH_MAX];
std::vector<wchar_t> buf(PATH_MAX + 1);
// Subtract 1 from the path length since this function does not add a null terminator.
DWORD result = ::GetFinalPathNameByHandle(h, buf, sizeof(buf) - 1,
FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
DWORD result = ::GetFinalPathNameByHandleW(h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
std::string path;
if (result == 0)
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
else if (!llvm::convertWideToUTF8(buf.data(), path))
error.SetErrorString(PATH_CONVERSION_ERROR);
else
dst.SetFile(buf, false);
dst.SetFile(path, false);
::CloseHandle(h);
return error;
@ -219,3 +251,43 @@ FileSystem::IsLocal(const FileSpec &spec)
return false;
}
FILE *
FileSystem::Fopen(const char *path, const char *mode)
{
std::wstring wpath, wmode;
if (!llvm::ConvertUTF8toWide(path, wpath))
return nullptr;
if (!llvm::ConvertUTF8toWide(mode, wmode))
return nullptr;
FILE *file;
if (_wfopen_s(&file, wpath.c_str(), wmode.c_str()) != 0)
return nullptr;
return file;
}
int
FileSystem::Stat(const char *path, struct stat *stats)
{
std::wstring wpath;
if (!llvm::ConvertUTF8toWide(path, wpath))
{
errno = EINVAL;
return -EINVAL;
}
int stat_result;
#ifdef _USE_32BIT_TIME_T
struct _stat32 file_stats;
stat_result = ::_wstat32(wpath.c_str(), &file_stats);
#else
struct _stat64i32 file_stats;
stat_result = ::_wstat64i32(wpath.c_str(), &file_stats);
#endif
if (stat_result == 0)
{
static_assert(sizeof(struct stat) == sizeof(file_stats),
"stat and _stat32/_stat64i32 must have the same layout");
*stats = *reinterpret_cast<struct stat *>(&file_stats);
}
return stat_result;
}

View File

@ -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 @@ namespace
bool GetExecutableForProcess(const AutoHandle &handle, std::string &path)
{
// Get the process image path. MAX_PATH isn't long enough, paths can actually be up to 32KB.
std::vector<char> buffer(32768);
std::vector<wchar_t> buffer(PATH_MAX);
DWORD dwSize = buffer.size();
if (!::QueryFullProcessImageNameA(handle.get(), 0, &buffer[0], &dwSize))
if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize))
return false;
path.assign(&buffer[0]);
return true;
return llvm::convertWideToUTF8(buffer.data(), path);
}
void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process)
@ -156,15 +157,17 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
return module_filespec;
std::vector<char> buffer(MAX_PATH);
std::vector<wchar_t> buffer(PATH_MAX);
DWORD chars_copied = 0;
do {
chars_copied = ::GetModuleFileName(hmodule, &buffer[0], buffer.size());
chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size());
if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
buffer.resize(buffer.size() * 2);
} while (chars_copied >= buffer.size());
module_filespec.SetFile(&buffer[0], false);
std::string path;
if (!llvm::convertWideToUTF8(buffer.data(), path))
return module_filespec;
module_filespec.SetFile(path, false);
return module_filespec;
}
@ -177,23 +180,25 @@ Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstance
if (!snapshot.IsValid())
return 0;
PROCESSENTRY32 pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(snapshot.get(), &pe))
PROCESSENTRY32W pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32W);
if (Process32FirstW(snapshot.get(), &pe))
{
do
{
AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
ProcessInstanceInfo process;
process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
std::string exeFile;
llvm::convertWideToUTF8(pe.szExeFile, exeFile);
process.SetExecutableFile(FileSpec(exeFile, false), true);
process.SetProcessID(pe.th32ProcessID);
process.SetParentProcessID(pe.th32ParentProcessID);
GetProcessExecutableAndTriple(handle, process);
if (match_info.MatchAllProcesses() || match_info.Matches(process))
process_infos.Append(process);
} while (Process32Next(snapshot.get(), &pe));
} while (Process32NextW(snapshot.get(), &pe));
}
return process_infos.GetSize();
}
@ -312,15 +317,21 @@ Host::GetEnvironment(StringList &env)
{
// The environment block on Windows is a contiguous buffer of NULL terminated strings,
// where the end of the environment block is indicated by two consecutive NULLs.
LPCH environment_block = ::GetEnvironmentStrings();
LPWCH environment_block = ::GetEnvironmentStringsW();
env.Clear();
while (*environment_block != '\0')
while (*environment_block != L'\0')
{
llvm::StringRef current_var(environment_block);
std::string current_var;
auto current_var_size = wcslen(environment_block) + 1;
if (!llvm::convertWideToUTF8(environment_block, current_var))
{
environment_block += current_var_size;
continue;
}
if (current_var[0] != '=')
env.AppendString(current_var);
environment_block += current_var.size()+1;
environment_block += current_var_size;
}
return env.GetSize();
}

View File

@ -15,9 +15,10 @@
#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"
#include "llvm/Support/raw_ostream.h"
using namespace lldb_private;
@ -92,23 +93,24 @@ HostInfoWindows::GetOSKernelDescription(std::string &s)
bool
HostInfoWindows::GetHostname(std::string &s)
{
char buffer[MAX_COMPUTERNAME_LENGTH + 1];
wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
if (!::GetComputerName(buffer, &dwSize))
if (!::GetComputerNameW(buffer, &dwSize))
return false;
s.assign(buffer, buffer + dwSize);
return true;
return llvm::convertWideToUTF8(buffer, s);
}
FileSpec
HostInfoWindows::GetProgramFileSpec()
{
static std::once_flag g_once_flag;
std::call_once(g_once_flag, []() {
char buffer[PATH_MAX];
::GetModuleFileName(NULL, buffer, sizeof(buffer));
m_program_filespec.SetFile(buffer, false);
std::call_once(g_once_flag, []() {
std::vector<wchar_t> buffer(PATH_MAX);
::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
std::string path;
llvm::convertWideToUTF8(buffer.data(), path);
m_program_filespec.SetFile(path, false);
});
return m_program_filespec;
}
@ -116,7 +118,9 @@ HostInfoWindows::GetProgramFileSpec()
FileSpec
HostInfoWindows::GetDefaultShell()
{
return FileSpec(::getenv("ComSpec"), false);
std::string shell;
GetEnvironmentVar("ComSpec", shell);
return FileSpec(shell, false);
}
bool
@ -132,3 +136,15 @@ HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec)
file_spec.GetDirectory().SetString(path.c_str());
return true;
}
bool
HostInfoWindows::GetEnvironmentVar(const std::string &var_name, std::string &var)
{
std::wstring wvar_name;
if (!llvm::ConvertUTF8toWide(var_name, wvar_name))
return false;
if (const wchar_t *wvar = _wgetenv(wvar_name.c_str()))
return llvm::convertWideToUTF8(wvar, var);
return false;
}

View File

@ -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 @@ Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const
if (m_process == nullptr)
error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
char path[MAX_PATH] = { 0 };
if (::GetProcessImageFileName(m_process, path, llvm::array_lengthof(path)))
file_spec.SetFile(path, false);
std::vector<wchar_t> wpath(PATH_MAX);
if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size()))
{
std::string path;
if (llvm::convertWideToUTF8(wpath.data(), path))
file_spec.SetFile(path, false);
else
error.SetErrorString("Error converting path to UTF-8");
}
else
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);

View File

@ -73,8 +73,8 @@ PipeWindows::CreateNew(llvm::StringRef name, bool child_process_inherit)
// 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);
m_read = ::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,8 @@ PipeWindows::OpenNamedPipe(llvm::StringRef name, bool child_process_inherit, boo
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 +165,8 @@ PipeWindows::OpenNamedPipe(llvm::StringRef name, bool child_process_inherit, boo
}
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);

View File

@ -11,6 +11,9 @@
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ConvertUTF.h"
#include <string>
#include <vector>
@ -25,20 +28,18 @@ CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer)
if (env.GetArgumentCount() == 0)
return;
int bytes = 0;
for (int i = 0; i < env.GetArgumentCount(); ++i)
bytes += strlen(env.GetArgumentAtIndex(i)) + sizeof(char);
bytes += sizeof(char);
buffer.resize(bytes);
char *cur_entry = &buffer[0];
// Environment buffer is a null terminated list of null terminated strings
for (int i = 0; i < env.GetArgumentCount(); ++i)
{
::strcpy(cur_entry, env.GetArgumentAtIndex(i));
cur_entry += strlen(cur_entry) + sizeof(char);
std::wstring warg;
if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg))
{
buffer.insert(buffer.end(), (char *)warg.c_str(), (char *)(warg.c_str() + warg.size() + 1));
}
}
// Environment buffer is a null terminated list of null terminated
// strings, so it is terminated by two null bytes.
buffer.back() = 0;
// One null wchar_t (to end the block) is two null bytes
buffer.push_back(0);
buffer.push_back(0);
}
}
@ -70,7 +71,7 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Erro
startupinfo.wShowWindow = SW_HIDE;
}
DWORD flags = CREATE_NEW_CONSOLE;
DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
if (launch_info.GetFlags().Test(eLaunchFlagDebug))
flags |= DEBUG_ONLY_THIS_PROCESS;
@ -82,8 +83,15 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Erro
executable = launch_info.GetExecutableFile().GetPath();
launch_info.GetArguments().GetQuotedCommandString(commandLine);
BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags,
env_block, launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi);
std::wstring wexecutable, wcommandLine, wworkingDirectory;
llvm::ConvertUTF8toWide(executable, wexecutable);
llvm::ConvertUTF8toWide(commandLine, wcommandLine);
llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory);
wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because CreateProcessW can modify it
BOOL result = ::CreateProcessW(wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block,
wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi);
if (result)
{
// Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
@ -131,6 +139,8 @@ ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int
flags = FILE_FLAG_WRITE_THROUGH;
}
HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
std::wstring wpath;
llvm::ConvertUTF8toWide(path, wpath);
HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, flags, NULL);
return (result == INVALID_HANDLE_VALUE) ? NULL : result;
}

View File

@ -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,29 @@ extern "C"
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 +100,90 @@ char* strcasestr(const char *s, const char* find)
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.
*/
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);
}
/* 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 == NULL)
errno = ENOMEM;
/* 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;
errno = EINVAL;
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.
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.
*/
if (retname != NULL)
if ((retname = resolved) == NULL)
{
// 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);
/* 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.
*/
// Force drive to be upper case
if (retname[1] == ':')
retname[0] = toupper(retname[0]);
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.
*/
wchar_t wideFullPathBuffer[PATH_MAX];
wchar_t *wideFullPath;
if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL)
{
errno = ENAMETOOLONG;
return NULL;
}
// 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);
// Convert back to UTF-8
if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX))
{
errno = EINVAL;
return NULL;
}
// Force drive to be upper case
if (retname[1] == ':')
retname[0] = toupper(retname[0]);
return retname;
}
@ -167,7 +201,27 @@ char* basename(char *path)
// use _getcwd() instead of GetCurrentDirectory() because it updates errno
char* getcwd(char* path, int max)
{
return _getcwd(path, max);
assert(path == NULL || max <= PATH_MAX);
wchar_t wpath[PATH_MAX];
if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX))
{
// Caller is allowed to pass in NULL for `path`.
// In that case, we're supposed to allocate a
// buffer on the caller's behalf.
if (path == NULL)
{
max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
path = (char *)malloc(max);
if (path == NULL)
{
errno = ENOMEM;
return NULL;
}
}
if (wideToUtf8(wresult, path, max))
return path;
}
return NULL;
}
// use _chdir() instead of SetCurrentDirectory() because it updates errno

View File

@ -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 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread
return DBG_CONTINUE;
}
std::vector<char> buffer(1);
DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
std::vector<wchar_t> buffer(1);
DWORD required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
if (required_size > 0)
{
buffer.resize(required_size + 1);
required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
llvm::StringRef path_str(&buffer[0]);
required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], required_size, VOLUME_NAME_DOS);
std::string path_str_utf8;
llvm::convertWideToUTF8(buffer.data(), path_str_utf8);
llvm::StringRef path_str = path_str_utf8;
const char *path = path_str.data();
if (path_str.startswith("\\\\?\\"))
path += 4;

View File

@ -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 @@ namespace
std::string
GetProcessExecutableName(HANDLE process_handle)
{
std::vector<char> file_name;
std::vector<wchar_t> file_name;
DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit
DWORD copied = 0;
do
{
file_name_size *= 2;
file_name.resize(file_name_size);
copied = ::GetModuleFileNameEx(process_handle, NULL, file_name.data(), file_name_size);
copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), file_name_size);
} while (copied >= file_name_size);
file_name.resize(copied);
return std::string(file_name.begin(), file_name.end());
std::string result;
llvm::convertWideToUTF8(file_name.data(), result);
return result;
}
std::string

View File

@ -370,14 +370,21 @@ ProcessWinMiniDump::Impl::MapMiniDumpIntoMemory()
{
Error error;
const char *file = m_core_file.GetCString();
m_dump_file = ::CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
std::wstring wfile;
if (!llvm::ConvertUTF8toWide(file, wfile))
{
error.SetErrorString("Error converting path to UTF-16");
return error;
}
m_dump_file =
::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_dump_file == INVALID_HANDLE_VALUE)
{
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
return error;
}
m_mapping = ::CreateFileMapping(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL);
m_mapping = ::CreateFileMappingW(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL);
if (m_mapping == NULL)
{
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
@ -509,7 +516,7 @@ ProcessWinMiniDump::Impl::GetMiniDumpString(RVA rva) const
auto source_start = reinterpret_cast<const UTF16 *>(md_string->Buffer);
const auto source_length = ::wcslen(md_string->Buffer);
const auto source_end = source_start + source_length;
result.resize(4 * source_length); // worst case length
result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length); // worst case length
auto result_start = reinterpret_cast<UTF8 *>(&result[0]);
const auto result_end = result_start + result.size();
ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion);

View File

@ -19,8 +19,11 @@
#include "lldb/Core/Stream.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "llvm/Support/ConvertUTF.h"
#include <stdio.h>
#include "llvm/ADT/StringSwitch.h"
@ -1162,9 +1165,7 @@ PythonFile::PythonFile(File &file, const char *mode)
PythonFile::PythonFile(const char *path, const char *mode)
{
FILE *fp = nullptr;
fp = fopen(path, mode);
lldb_private::File file(fp, true);
lldb_private::File file(path, GetOptionsFromMode(mode));
Reset(file, mode);
}

View File

@ -13,14 +13,21 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/Config.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Target.h"
#include "llvm/Support/ConvertUTF.h"
#if !defined(_WIN32)
#include <limits.h>
#endif
using namespace lldb;
using namespace lldb_private;
@ -449,8 +456,8 @@ ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error,
if (cwd && cwd[0])
new_path += cwd;
}
const char *curr_path = getenv("PATH");
if (curr_path)
std::string curr_path;
if (HostInfo::GetEnvironmentVar("PATH", curr_path))
{
if (new_path.size() > empty_path_len)
new_path += ':';

View File

@ -27,7 +27,6 @@
#include <string>
#include <thread>
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
@ -37,11 +36,13 @@
#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBLanguageRuntime.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBProcess.h"
#include "llvm/Support/ConvertUTF.h"
#include <thread>
#if !defined(__APPLE__)
#include "llvm/Support/DataTypes.h"
@ -1298,7 +1299,11 @@ sigcont_handler (int signo)
}
int
main (int argc, char const *argv[], const char *envp[])
#ifdef WIN32
wmain(int argc, wchar_t const *wargv[])
#else
main(int argc, char const *argv[])
#endif
{
#ifdef _MSC_VER
// disable buffering on windows
@ -1306,37 +1311,49 @@ main (int argc, char const *argv[], const char *envp[])
setvbuf(stdin , NULL, _IONBF, 0);
#endif
SBDebugger::Initialize();
SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
signal(SIGINT, sigint_handler);
#ifndef _MSC_VER
signal (SIGPIPE, SIG_IGN);
signal (SIGWINCH, sigwinch_handler);
signal (SIGTSTP, sigtstp_handler);
signal (SIGCONT, sigcont_handler);
#ifdef _WIN32
// Convert wide arguments to UTF-8
std::vector<std::string> argvStrings(argc);
std::vector<const char *> argvPointers(argc);
for (int i = 0; i != argc; ++i)
{
llvm::convertWideToUTF8(wargv[i], argvStrings[i]);
argvPointers[i] = argvStrings[i].c_str();
}
const char **argv = argvPointers.data();
#endif
// Create a scope for driver so that the driver object will destroy itself
// before SBDebugger::Terminate() is called.
{
Driver driver;
SBDebugger::Initialize();
bool exiting = false;
SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
if (error.Fail())
{
const char *error_cstr = error.GetCString ();
if (error_cstr)
::fprintf (stderr, "error: %s\n", error_cstr);
}
else if (!exiting)
{
driver.MainLoop ();
}
}
SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
SBDebugger::Terminate();
return 0;
signal(SIGINT, sigint_handler);
#if !defined(_MSC_VER)
signal(SIGPIPE, SIG_IGN);
signal(SIGWINCH, sigwinch_handler);
signal(SIGTSTP, sigtstp_handler);
signal(SIGCONT, sigcont_handler);
#endif
// Create a scope for driver so that the driver object will destroy itself
// before SBDebugger::Terminate() is called.
{
Driver driver;
bool exiting = false;
SBError error(driver.ParseArgs(argc, argv, stdout, exiting));
if (error.Fail())
{
const char *error_cstr = error.GetCString();
if (error_cstr)
::fprintf(stderr, "error: %s\n", error_cstr);
}
else if (!exiting)
{
driver.MainLoop();
}
}
SBDebugger::Terminate();
return 0;
}

View File

@ -18,15 +18,16 @@
#include "lldb/API/SBBreakpointLocation.h"
// In-house headers:
#include "MICmdData.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnLLDBDebugger.h"
#include "MICmnResources.h"
#include "MICmnLLDBUtilSBValue.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
#include "MICmdData.h"
#include "MICmnLLDBUtilSBValue.h"
#include "MICmnResources.h"
#include "Platform.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBDebugSessionInfo constructor.
@ -614,7 +615,7 @@ CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::add
{
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]);

View File

@ -14,8 +14,11 @@
#include <cerrno>
// In-house headers:
#include "MIUtilFileStd.h"
#include "MICmnResources.h"
#include "MIUtilFileStd.h"
#include "lldb/Host/FileSystem.h"
#include "llvm/Support/ConvertUTF.h"
//++ ------------------------------------------------------------------------------------
// Details: CMIUtilFileStd constructor.
@ -82,7 +85,14 @@ CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCre
m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb");
#else
// Open a file with exclusive write and shared read permissions
m_pFileHandle = ::_fsopen(vFileNamePath.c_str(), "wb", _SH_DENYWR);
std::wstring path;
if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path))
m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR);
else
{
errno = EINVAL;
m_pFileHandle = nullptr;
}
#endif // !defined( _MSC_VER )
if (m_pFileHandle == nullptr)
@ -221,8 +231,7 @@ CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const
if (vFileNamePath.empty())
return false;
FILE *pTmp = nullptr;
pTmp = ::fopen(vFileNamePath.c_str(), "wb");
FILE *pTmp = lldb_private::FileSystem::Fopen(vFileNamePath.c_str(), "wb");
if (pTmp != nullptr)
{
::fclose(pTmp);

View File

@ -58,7 +58,7 @@ struct termios
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, ...);