From a31b1c54fa0a584ce60c52324b7d31959016de36 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Thu, 15 Dec 2022 13:03:30 +0000 Subject: [PATCH 1/5] Centralise code to map between UTF-8 and UTF-16 on Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In various places we need to call the Windows API, and because Swift uses UTF-8 for its string representation, we can’t call the ANSI API functions (because the code page used for the ANSI functions varies depending on the system locale setting). Instead, we need to use the wide character APIs. This means that we need to convert UTF-8 to wide character and vice-versa in various places in the runtime. rdar://103397975 --- include/swift/Runtime/Win32.h | 55 ++++++++++++ .../public/CommandLineSupport/CommandLine.cpp | 45 +--------- stdlib/public/runtime/CMakeLists.txt | 3 +- stdlib/public/runtime/Win32.cpp | 87 +++++++++++++++++++ 4 files changed, 146 insertions(+), 44 deletions(-) create mode 100644 include/swift/Runtime/Win32.h create mode 100644 stdlib/public/runtime/Win32.cpp diff --git a/include/swift/Runtime/Win32.h b/include/swift/Runtime/Win32.h new file mode 100644 index 0000000000000..3f1f01b590948 --- /dev/null +++ b/include/swift/Runtime/Win32.h @@ -0,0 +1,55 @@ +//===--- Win32.h - Win32 utility functions ----------------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Utility functions that are specific to the Windows port. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_RUNTIME_WIN32_H +#define SWIFT_RUNTIME_WIN32_H + +#ifdef _WIN32 + +#include "swift/shims/Visibility.h" + +#include + +namespace swift { +namespace win32 { + +/// Convert a wide string to UTF-8. +/// +/// @param str The string to convert. +/// +/// @returns The string, converted to UTF-8. The caller is responsible +/// for freeing this string with @c free() when done with it. +/// +/// If @a str cannot be converted to UTF-8, a fatal error occurs. +SWIFT_RUNTIME_STDLIB_INTERNAL +char *copyUTF8FromWide(const wchar_t *str); + +/// Convert a UTF-8 string to a wide string. +/// +/// @param str The string to convert. +/// +/// @returns The string, converted to UTF-16. The caller is responsible +/// for freeing this string with @c free() when done with it. +/// +/// If @a str cannot be converted to UTF-16, a fatal error occurs. +SWIFT_RUNTIME_STDLIB_INTERNAL +wchar_t *copyWideFromUTF8(const char *str); + +} +} +#endif // defined(_WIN32) + +#endif // SWIFT_RUNTIME_WIN32_H diff --git a/stdlib/public/CommandLineSupport/CommandLine.cpp b/stdlib/public/CommandLineSupport/CommandLine.cpp index d06b21971f404..e32224fc750c5 100644 --- a/stdlib/public/CommandLineSupport/CommandLine.cpp +++ b/stdlib/public/CommandLineSupport/CommandLine.cpp @@ -25,6 +25,7 @@ #include #include "swift/Runtime/Debug.h" +#include "swift/Runtime/Win32.h" #include "swift/shims/GlobalObjects.h" #include "swift/shims/RuntimeStubs.h" @@ -193,48 +194,6 @@ static void swift::enumerateUnsafeArgv(const F& body) { #elif defined(_WIN32) #include -namespace swift { - /// Convert an argument, represented by a wide string, to UTF-8. - /// - /// @param str The string to convert. - /// - /// @returns The string, converted to UTF-8. The caller is responsible for - /// freeing this string when done with it. - /// - /// If @a str cannot be converted to UTF-8, a fatal error occurs. - static char *copyUTF8FromWide(wchar_t *str) { - char *result = nullptr; - - int resultLength = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, - -1, nullptr, 0, nullptr, nullptr); - if (resultLength <= 0) { - swift::fatalError(0, - "Fatal error: Could not get length of commandline " - "argument '%ls': %lu\n", - str, GetLastError()); - } - - result = reinterpret_cast(malloc(resultLength)); - if (!result) { - swift::fatalError(0, - "Fatal error: Could not allocate space for commandline " - "argument '%ls': %d\n", - str, errno); - } - - resultLength = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, -1, - result, resultLength, nullptr, nullptr); - if (resultLength <= 0) { - swift::fatalError(0, - "Fatal error: Conversion to UTF-8 failed for " - "commandline argument '%ls': %lu\n", - str, GetLastError()); - } - - return result; - } -} - static char **swift::getUnsafeArgvArgc(int *outArgLen) { return nullptr; } @@ -244,7 +203,7 @@ static void swift::enumerateUnsafeArgv(const F& body) { int argc = 0; if (LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &argc)) { std::for_each(wargv, wargv + argc, [=] (wchar_t *warg) { - auto arg = copyUTF8FromWide(warg); + auto arg = swift::win32::copyUTF8FromWide(warg); body(argc, arg); free(arg); }); diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index c6a32d004a8ea..3aacf32cb352d 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -70,7 +70,8 @@ set(swift_runtime_sources SwiftTLSContext.cpp ThreadingError.cpp AccessibleFunction.cpp - RuntimeAttribute.cpp) + RuntimeAttribute.cpp + Win32.cpp) # Acknowledge that the following sources are known. set(LLVM_OPTIONAL_SOURCES diff --git a/stdlib/public/runtime/Win32.cpp b/stdlib/public/runtime/Win32.cpp new file mode 100644 index 0000000000000..ca4656fc585d5 --- /dev/null +++ b/stdlib/public/runtime/Win32.cpp @@ -0,0 +1,87 @@ +//===--- Win32.cpp - Win32 utility functions --------------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Utility functions that are specific to the Windows port. +// +//===----------------------------------------------------------------------===// + +#include "swift/Runtime/Debug.h" +#include "swift/Runtime/Win32.h" + +#ifdef _WIN32 + +#include + +char * +swift::win32::copyUTF8FromWide(const wchar_t *str) { + char *result = nullptr; + int len = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, + str, -1, + nullptr, 0, + nullptr, nullptr); + if (len <= 0) { + swift::fatalError(0, "failed to convert string '%ls' " + "from wide to UTF-8: %lx\n", + str, ::GetLastError()); + } + + result = reinterpret_cast(std::malloc(len)); + if (!result) { + swift::fatalError(0, "unable to allocate space to convert '%ls': %d\n", + str, errno); + } + + len = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, + str, -1, + result, len, + nullptr, nullptr); + + if (len <= 0) { + swift::fatalError(0, "failed to convert string '%ls' " + "from wide to UTF-8: %lx\n", + str, ::GetLastError()); + } + + return result; +} + +wchar_t * +swift::win32::copyWideFromUTF8(const char *str) { + wchar_t *result = nullptr; + int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str, -1, + nullptr, 0); + if (len <= 0) { + swift::fatalError(0, "failed to convert string '%s' " + "from UTF-8 to wide: %lx\n", + str, ::GetLastError()); + } + + result = reinterpret_cast(std::malloc(len * sizeof(wchar_t))); + if (!result) { + swift::fatalError(0, "unable to allocate space to convert '%s': %d\n", + str, errno); + } + + len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str, -1, + result, len); + if (len <= 0) { + swift::fatalError(0, "failed to convert string '%s' " + "from UTF-8 to wide: %lx\n", + str, ::GetLastError()); + } + + return result; +} + +#endif // defined(_WIN32) From ca771c4d1d37b16c33197d0a5183e639771fd58e Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Thu, 15 Dec 2022 16:30:53 +0000 Subject: [PATCH 2/5] Change to returning `nullptr` rather than triggering a fatal error. Instead of triggering a fatal error on failure, return `nullptr` and let the caller decide what to do about it. The CommandLine code should trigger a fatal error, of course. rdar://103397975 --- include/swift/Runtime/Win32.h | 4 +- .../public/CommandLineSupport/CommandLine.cpp | 9 ++++ stdlib/public/runtime/Win32.cpp | 47 +++++++------------ 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/include/swift/Runtime/Win32.h b/include/swift/Runtime/Win32.h index 3f1f01b590948..1856eb1e726d1 100644 --- a/include/swift/Runtime/Win32.h +++ b/include/swift/Runtime/Win32.h @@ -33,7 +33,7 @@ namespace win32 { /// @returns The string, converted to UTF-8. The caller is responsible /// for freeing this string with @c free() when done with it. /// -/// If @a str cannot be converted to UTF-8, a fatal error occurs. +/// If @a str cannot be converted to UTF-8, @c nullptr is returned. SWIFT_RUNTIME_STDLIB_INTERNAL char *copyUTF8FromWide(const wchar_t *str); @@ -44,7 +44,7 @@ char *copyUTF8FromWide(const wchar_t *str); /// @returns The string, converted to UTF-16. The caller is responsible /// for freeing this string with @c free() when done with it. /// -/// If @a str cannot be converted to UTF-16, a fatal error occurs. +/// If @a str cannot be converted to UTF-16, @c nullptr is returned. SWIFT_RUNTIME_STDLIB_INTERNAL wchar_t *copyWideFromUTF8(const char *str); diff --git a/stdlib/public/CommandLineSupport/CommandLine.cpp b/stdlib/public/CommandLineSupport/CommandLine.cpp index e32224fc750c5..1867ca1c2fe82 100644 --- a/stdlib/public/CommandLineSupport/CommandLine.cpp +++ b/stdlib/public/CommandLineSupport/CommandLine.cpp @@ -204,6 +204,15 @@ static void swift::enumerateUnsafeArgv(const F& body) { if (LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &argc)) { std::for_each(wargv, wargv + argc, [=] (wchar_t *warg) { auto arg = swift::win32::copyUTF8FromWide(warg); + if (!arg) { + // Note that GetLastError() and errno may not be so useful here, + // as in the error case we may have called free(), which might reset + // either or both of them. + swift::fatalError(0, + "Fatal error: Unable to convert argument '%ls' to " + "UTF-8: %lx, %d.\n", + warg, ::GetLastError(), errno); + } body(argc, arg); free(arg); }); diff --git a/stdlib/public/runtime/Win32.cpp b/stdlib/public/runtime/Win32.cpp index ca4656fc585d5..1a06acef42ecc 100644 --- a/stdlib/public/runtime/Win32.cpp +++ b/stdlib/public/runtime/Win32.cpp @@ -28,30 +28,23 @@ swift::win32::copyUTF8FromWide(const wchar_t *str) { str, -1, nullptr, 0, nullptr, nullptr); - if (len <= 0) { - swift::fatalError(0, "failed to convert string '%ls' " - "from wide to UTF-8: %lx\n", - str, ::GetLastError()); - } + if (len <= 0) + return nullptr; result = reinterpret_cast(std::malloc(len)); - if (!result) { - swift::fatalError(0, "unable to allocate space to convert '%ls': %d\n", - str, errno); - } + if (!result) + return nullptr; len = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, -1, result, len, nullptr, nullptr); - if (len <= 0) { - swift::fatalError(0, "failed to convert string '%ls' " - "from wide to UTF-8: %lx\n", - str, ::GetLastError()); - } + if (len) + return result; - return result; + free(result); + return nullptr; } wchar_t * @@ -60,28 +53,22 @@ swift::win32::copyWideFromUTF8(const char *str) { int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nullptr, 0); - if (len <= 0) { - swift::fatalError(0, "failed to convert string '%s' " - "from UTF-8 to wide: %lx\n", - str, ::GetLastError()); - } + if (len <= 0) + return nullptr; result = reinterpret_cast(std::malloc(len * sizeof(wchar_t))); - if (!result) { - swift::fatalError(0, "unable to allocate space to convert '%s': %d\n", - str, errno); - } + if (!result) + return nullptr; len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, result, len); - if (len <= 0) { - swift::fatalError(0, "failed to convert string '%s' " - "from UTF-8 to wide: %lx\n", - str, ::GetLastError()); - } - return result; + if (len) + return result; + + free(result); + return nullptr; } #endif // defined(_WIN32) From fb1211e3fa73eccfbe8b4292da25155266aa6a63 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 16 Dec 2022 12:25:44 +0000 Subject: [PATCH 3/5] Rename the functions as they're exported as C APIs. `SWIFT_RUNTIME_STDLIB_INTERNAL` does `extern "C"`, so we can't put these in a namespace and have to use a C-style prefix instead. Also slightly rearrange the code in `CommandLine.cpp`. rdar://103397975 --- include/swift/Runtime/Win32.h | 9 ++------- stdlib/public/CommandLineSupport/CommandLine.cpp | 8 ++++---- stdlib/public/runtime/Win32.cpp | 4 ++-- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/include/swift/Runtime/Win32.h b/include/swift/Runtime/Win32.h index 1856eb1e726d1..58e556e834c43 100644 --- a/include/swift/Runtime/Win32.h +++ b/include/swift/Runtime/Win32.h @@ -23,9 +23,6 @@ #include -namespace swift { -namespace win32 { - /// Convert a wide string to UTF-8. /// /// @param str The string to convert. @@ -35,7 +32,7 @@ namespace win32 { /// /// If @a str cannot be converted to UTF-8, @c nullptr is returned. SWIFT_RUNTIME_STDLIB_INTERNAL -char *copyUTF8FromWide(const wchar_t *str); +char *_swift_win32_copyUTF8FromWide(const wchar_t *str); /// Convert a UTF-8 string to a wide string. /// @@ -46,10 +43,8 @@ char *copyUTF8FromWide(const wchar_t *str); /// /// If @a str cannot be converted to UTF-16, @c nullptr is returned. SWIFT_RUNTIME_STDLIB_INTERNAL -wchar_t *copyWideFromUTF8(const char *str); +wchar_t *_swift_win32_copyWideFromUTF8(const char *str); -} -} #endif // defined(_WIN32) #endif // SWIFT_RUNTIME_WIN32_H diff --git a/stdlib/public/CommandLineSupport/CommandLine.cpp b/stdlib/public/CommandLineSupport/CommandLine.cpp index 1867ca1c2fe82..18efd62f76415 100644 --- a/stdlib/public/CommandLineSupport/CommandLine.cpp +++ b/stdlib/public/CommandLineSupport/CommandLine.cpp @@ -203,8 +203,10 @@ static void swift::enumerateUnsafeArgv(const F& body) { int argc = 0; if (LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &argc)) { std::for_each(wargv, wargv + argc, [=] (wchar_t *warg) { - auto arg = swift::win32::copyUTF8FromWide(warg); - if (!arg) { + if (char *arg = _swift_win32_copyUTF8FromWide(warg)) { + body(argc, arg); + free(arg); + } else { // Note that GetLastError() and errno may not be so useful here, // as in the error case we may have called free(), which might reset // either or both of them. @@ -213,8 +215,6 @@ static void swift::enumerateUnsafeArgv(const F& body) { "UTF-8: %lx, %d.\n", warg, ::GetLastError(), errno); } - body(argc, arg); - free(arg); }); LocalFree(wargv); diff --git a/stdlib/public/runtime/Win32.cpp b/stdlib/public/runtime/Win32.cpp index 1a06acef42ecc..14eb627d052a1 100644 --- a/stdlib/public/runtime/Win32.cpp +++ b/stdlib/public/runtime/Win32.cpp @@ -22,7 +22,7 @@ #include char * -swift::win32::copyUTF8FromWide(const wchar_t *str) { +_swift_win32_copyUTF8FromWide(const wchar_t *str) { char *result = nullptr; int len = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, str, -1, @@ -48,7 +48,7 @@ swift::win32::copyUTF8FromWide(const wchar_t *str) { } wchar_t * -swift::win32::copyWideFromUTF8(const char *str) { +_swift_win32_copyWideFromUTF8(const char *str) { wchar_t *result = nullptr; int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, From e73de539b849e1a7b152f0bfb303cf5a2ff2d3ed Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 16 Dec 2022 12:26:51 +0000 Subject: [PATCH 4/5] Move _swift_win32_withDbgHelpLibrary into the new header. It makes sense to move this function into the new Win32 header. rdar://103397975 --- include/swift/Runtime/Win32.h | 83 +++++++++++++++++++ stdlib/public/runtime/Errors.cpp | 1 + stdlib/public/runtime/ImageInspection.h | 77 ----------------- stdlib/public/runtime/ImageInspectionCOFF.cpp | 3 +- stdlib/public/runtime/SymbolInfo.cpp | 2 + 5 files changed, 88 insertions(+), 78 deletions(-) diff --git a/include/swift/Runtime/Win32.h b/include/swift/Runtime/Win32.h index 58e556e834c43..3f81f12f164aa 100644 --- a/include/swift/Runtime/Win32.h +++ b/include/swift/Runtime/Win32.h @@ -21,6 +21,14 @@ #include "swift/shims/Visibility.h" +#include +#include + +// For HANDLE +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include + #include /// Convert a wide string to UTF-8. @@ -45,6 +53,81 @@ char *_swift_win32_copyUTF8FromWide(const wchar_t *str); SWIFT_RUNTIME_STDLIB_INTERNAL wchar_t *_swift_win32_copyWideFromUTF8(const char *str); +/// Configure the environment to allow calling into the Debug Help library. +/// +/// \param body A function to invoke. This function attempts to first initialize +/// the Debug Help library. If it did so successfully, the handle used during +/// initialization is passed to this function and should be used with +/// subsequent calls to the Debug Help library. Do not close this handle. +/// \param context A caller-supplied value to pass to \a body. +/// +/// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All +/// calls into it from the Swift runtime and stdlib should route through this +/// function. +/// +/// This function sets the Debug Help library's options by calling +/// \c SymSetOptions() before \a body is invoked, and then resets them back to +/// their old value before returning. \a body can also call \c SymSetOptions() +/// if needed. +SWIFT_RUNTIME_STDLIB_SPI +void _swift_win32_withDbgHelpLibrary( + void (* body)(HANDLE hProcess, void *context), void *context); + +/// Configure the environment to allow calling into the Debug Help library. +/// +/// \param body A function to invoke. This function attempts to first initialize +/// the Debug Help library. If it did so successfully, the handle used during +/// initialization is passed to this function and should be used with +/// subsequent calls to the Debug Help library. Do not close this handle. +/// +/// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All +/// calls into it from the Swift runtime and stdlib should route through this +/// function. +/// +/// This function sets the Debug Help library's options by calling +/// \c SymSetOptions() before \a body is invoked, and then resets them back to +/// their old value before returning. \a body can also call \c SymSetOptions() +/// if needed. +static inline void _swift_win32_withDbgHelpLibrary( + const std::function &body) { + _swift_win32_withDbgHelpLibrary([](HANDLE hProcess, void *context) { + auto bodyp = reinterpret_cast *>(context); + (* bodyp)(hProcess); + }, const_cast(reinterpret_cast(&body))); +} + +/// Configure the environment to allow calling into the Debug Help library. +/// +/// \param body A function to invoke. This function attempts to first initialize +/// the Debug Help library. If it did so successfully, the handle used during +/// initialization is passed to this function and should be used with +/// subsequent calls to the Debug Help library. Do not close this handle. +/// +/// \returns Whatever is returned from \a body. +/// +/// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All +/// calls into it from the Swift runtime and stdlib should route through this +/// function. +/// +/// This function sets the Debug Help library's options by calling +/// \c SymSetOptions() before \a body is invoked, and then resets them back to +/// their old value before returning. \a body can also call \c SymSetOptions() +/// if needed. +template < + typename F, + typename R = typename std::result_of_t, + typename = typename std::enable_if_t::value> +> +static inline R _swift_win32_withDbgHelpLibrary(const F& body) { + R result; + + _swift_win32_withDbgHelpLibrary([&body, &result] (HANDLE hProcess) { + result = body(hProcess); + }); + + return result; +} + #endif // defined(_WIN32) #endif // SWIFT_RUNTIME_WIN32_H diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp index 221e2b0712a6d..b126245d14bbe 100644 --- a/stdlib/public/runtime/Errors.cpp +++ b/stdlib/public/runtime/Errors.cpp @@ -36,6 +36,7 @@ #include "swift/Demangling/Demangle.h" #include "swift/Runtime/Debug.h" #include "swift/Runtime/Portability.h" +#include "swift/Runtime/Win32.h" #include "swift/Threading/Errors.h" #include "swift/Threading/Mutex.h" #include "llvm/ADT/StringRef.h" diff --git a/stdlib/public/runtime/ImageInspection.h b/stdlib/public/runtime/ImageInspection.h index f7d730d34ca46..f06694c7ab17d 100644 --- a/stdlib/public/runtime/ImageInspection.h +++ b/stdlib/public/runtime/ImageInspection.h @@ -92,83 +92,6 @@ void addImageRuntimeAttributesBlockCallbackUnsafe(const void *baseAddress, const void *start, uintptr_t size); -#if defined(_WIN32) -/// Configure the environment to allow calling into the Debug Help library. -/// -/// \param body A function to invoke. This function attempts to first initialize -/// the Debug Help library. If it did so successfully, the handle used during -/// initialization is passed to this function and should be used with -/// subsequent calls to the Debug Help library. Do not close this handle. -/// \param context A caller-supplied value to pass to \a body. -/// -/// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All -/// calls into it from the Swift runtime and stdlib should route through this -/// function. -/// -/// This function sets the Debug Help library's options by calling -/// \c SymSetOptions() before \a body is invoked, and then resets them back to -/// their old value before returning. \a body can also call \c SymSetOptions() -/// if needed. -SWIFT_RUNTIME_STDLIB_SPI -void _swift_win32_withDbgHelpLibrary( - void (* body)(HANDLE hProcess, void *context), void *context); - -/// Configure the environment to allow calling into the Debug Help library. -/// -/// \param body A function to invoke. This function attempts to first initialize -/// the Debug Help library. If it did so successfully, the handle used during -/// initialization is passed to this function and should be used with -/// subsequent calls to the Debug Help library. Do not close this handle. -/// -/// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All -/// calls into it from the Swift runtime and stdlib should route through this -/// function. -/// -/// This function sets the Debug Help library's options by calling -/// \c SymSetOptions() before \a body is invoked, and then resets them back to -/// their old value before returning. \a body can also call \c SymSetOptions() -/// if needed. -static inline void _swift_win32_withDbgHelpLibrary( - const std::function &body) { - _swift_win32_withDbgHelpLibrary([](HANDLE hProcess, void *context) { - auto bodyp = reinterpret_cast *>(context); - (* bodyp)(hProcess); - }, const_cast(reinterpret_cast(&body))); -} - -/// Configure the environment to allow calling into the Debug Help library. -/// -/// \param body A function to invoke. This function attempts to first initialize -/// the Debug Help library. If it did so successfully, the handle used during -/// initialization is passed to this function and should be used with -/// subsequent calls to the Debug Help library. Do not close this handle. -/// -/// \returns Whatever is returned from \a body. -/// -/// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All -/// calls into it from the Swift runtime and stdlib should route through this -/// function. -/// -/// This function sets the Debug Help library's options by calling -/// \c SymSetOptions() before \a body is invoked, and then resets them back to -/// their old value before returning. \a body can also call \c SymSetOptions() -/// if needed. -template < - typename F, - typename R = typename std::result_of_t, - typename = typename std::enable_if_t::value> -> -static inline R _swift_win32_withDbgHelpLibrary(const F& body) { - R result; - - _swift_win32_withDbgHelpLibrary([&body, &result] (HANDLE hProcess) { - result = body(hProcess); - }); - - return result; -} -#endif - } // end namespace swift #endif diff --git a/stdlib/public/runtime/ImageInspectionCOFF.cpp b/stdlib/public/runtime/ImageInspectionCOFF.cpp index 7277c863557b2..f9803345ff747 100644 --- a/stdlib/public/runtime/ImageInspectionCOFF.cpp +++ b/stdlib/public/runtime/ImageInspectionCOFF.cpp @@ -23,6 +23,7 @@ #include #endif +#include "swift/Runtime/Win32.h" #include "swift/Threading/Mutex.h" using namespace swift; @@ -31,7 +32,7 @@ using namespace swift; static LazyMutex mutex; static HANDLE dbgHelpHandle = nullptr; -void swift::_swift_win32_withDbgHelpLibrary( +void _swift_win32_withDbgHelpLibrary( void (* body)(HANDLE hProcess, void *context), void *context) { mutex.withLock([=] () { // If we have not previously created a handle to use with the library, do so diff --git a/stdlib/public/runtime/SymbolInfo.cpp b/stdlib/public/runtime/SymbolInfo.cpp index ebcccf71e79b2..f51e46b02aa95 100644 --- a/stdlib/public/runtime/SymbolInfo.cpp +++ b/stdlib/public/runtime/SymbolInfo.cpp @@ -21,6 +21,8 @@ #include #endif +#include "swift/Runtime/Win32.h" + #include "ImageInspection.h" using namespace swift; From a13d67758c1176c630272f091673b8947a916723 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Wed, 21 Dec 2022 15:27:21 +0000 Subject: [PATCH 5/5] Make the UTF8-to-wide functions into SPI rather than internal. They're useful functions to have; I don't think we want them to be API, but having them as SPI is conceivably useful for other purposes, and avoids everyone rolling their own copy. rdar://103397975 --- include/swift/Runtime/Win32.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/swift/Runtime/Win32.h b/include/swift/Runtime/Win32.h index 3f81f12f164aa..ee9729b05ca35 100644 --- a/include/swift/Runtime/Win32.h +++ b/include/swift/Runtime/Win32.h @@ -39,7 +39,7 @@ /// for freeing this string with @c free() when done with it. /// /// If @a str cannot be converted to UTF-8, @c nullptr is returned. -SWIFT_RUNTIME_STDLIB_INTERNAL +SWIFT_RUNTIME_STDLIB_SPI char *_swift_win32_copyUTF8FromWide(const wchar_t *str); /// Convert a UTF-8 string to a wide string. @@ -50,7 +50,7 @@ char *_swift_win32_copyUTF8FromWide(const wchar_t *str); /// for freeing this string with @c free() when done with it. /// /// If @a str cannot be converted to UTF-16, @c nullptr is returned. -SWIFT_RUNTIME_STDLIB_INTERNAL +SWIFT_RUNTIME_STDLIB_SPI wchar_t *_swift_win32_copyWideFromUTF8(const char *str); /// Configure the environment to allow calling into the Debug Help library.