mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-24 10:07:48 +00:00
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:
parent
6feeb6554e
commit
190fadcdb2
@ -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})
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.");
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 += ':';
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
@ -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, ...);
|
||||
|
Loading…
x
Reference in New Issue
Block a user