Functions _invoke_watson(), _invalid_parameter(), _invalid_parameter_noinfo(),
_invalid_parameter_noinfo_noreturn() are supported since msvcr80.dll.
Function _invalid_parameter_noinfo_noreturn() is supported since msvcr100.dll.
For older CRT import libraries provide simple wrapper around the
_invalid_parameter() and _invoke_watson() calls.
OS system version of msvcrt.dll provides function _invalid_parameter()
since Windows Vista but it is mostly useless. Seems that it does absolutely
nothing. Moreover OS system version of msvcrt.dll does not provide
_set_invalid_parameter_handler() function, so application has no way to
instruct what OS system version of _invalid_parameter() should call.
Therefore threat msvcrt.dll's _invalid_parameter() function as unusable and
disable it in msvcrt.def.in file.
Note that MS WDK 7.1.0 toolchain which allows to link against the Windows 7
OS system msvcrt.dll library, does not use the msvcrt.dll's _invalid_parameter
symbol but rather provides its own code statically linked into executable.
This can indicate the fact that the msvcrt.dll's _invalid_parameter is not
usable or compatible with msvcr80+.
So for pre-msvcr80 CRT import libraries and also for OS system msvcrt.dll
import library provide mingw-w64 implementation of those functions.
_invalid_parameter() implementation uses _get_invalid_parameter_handler()
to retrieve the invalid parameter handler, which is already provided by
mingw-w64 for all CRT import libraries.
Implementation of _invoke_watson() mimics the behavior of msvcr80+ and UCRT.
---
mingw-w64-crt/Makefile.am | 8 ++
mingw-w64-crt/lib-common/msvcrt.def.in | 2 +-
mingw-w64-crt/misc/_invalid_parameter.c | 33 ++++++
.../misc/_invalid_parameter_noinfo.c | 16 +++
.../misc/_invalid_parameter_noinfo_noreturn.c | 15 +++
mingw-w64-crt/misc/_invoke_watson.c | 105 ++++++++++++++++++
6 files changed, 178 insertions(+), 1 deletion(-)
create mode 100644 mingw-w64-crt/misc/_invalid_parameter.c
create mode 100644 mingw-w64-crt/misc/_invalid_parameter_noinfo.c
create mode 100644 mingw-w64-crt/misc/_invalid_parameter_noinfo_noreturn.c
create mode 100644 mingw-w64-crt/misc/_invoke_watson.c
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index c417ed9ebeb5..dc98a298ce1e 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -344,6 +344,10 @@ src_msvcrt=\
misc/_get_timezone.c \
misc/_get_tzname.c \
misc/_get_wpgmptr.c \
+ misc/_invalid_parameter.c \
+ misc/_invalid_parameter_noinfo.c \
+ misc/_invalid_parameter_noinfo_noreturn.c \
+ misc/_invoke_watson.c \
misc/_recalloc.c \
misc/_set_purecall_handler.c \
misc/imaxdiv.c \
@@ -906,6 +910,9 @@ src_pre_msvcr80=\
misc/_get_tzname.c \
misc/_get_wpgmptr.c \
misc/_initterm_e.c \
+ misc/_invalid_parameter.c \
+ misc/_invalid_parameter_noinfo.c \
+ misc/_invoke_watson.c \
misc/_recalloc.c \
misc/_set_doserrno.c \
misc/_set_errno.c \
@@ -926,6 +933,7 @@ src_pre_msvcr80=\
string/wcstok.c
src_pre_msvcr100=\
+ misc/_invalid_parameter_noinfo_noreturn.c \
misc/imaxdiv.c
src_pre_msvcr110=\
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in
b/mingw-w64-crt/lib-common/msvcrt.def.in
index 91430d083407..fefddc5b7229 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1445,7 +1445,7 @@ F_ARM_ANY(_gmtime64_s) ; i386 and x64 _gmtime64_s
replaced by emu
_i64toa_s
_i64tow_s
F_ARM_ANY(_initterm_e) ; i386 and x64 _initterm_e replaced by emu
-_invalid_parameter
+; _invalid_parameter replaced by emu, msvcrt.dll's _invalid_parameter is not
compatible with msvcr80+/UCRT
_isalnum_l
_isalpha_l
_iscntrl_l
diff --git a/mingw-w64-crt/misc/_invalid_parameter.c
b/mingw-w64-crt/misc/_invalid_parameter.c
new file mode 100644
index 000000000000..67578e3c73be
--- /dev/null
+++ b/mingw-w64-crt/misc/_invalid_parameter.c
@@ -0,0 +1,33 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#define _DEBUG /* needed for _invalid_parameter */
+#include <corecrt.h>
+#undef _DEBUG
+#include <stdlib.h>
+
+void __cdecl _invalid_parameter(const wchar_t *expression, const wchar_t
*function_name, const wchar_t *file_name, unsigned int line_number, uintptr_t
reserved)
+{
+ _invalid_parameter_handler handler;
+
+ /* TODO: Enable this code when mingw-w64 has
_get_thread_local_invalid_parameter_handler() support */
+#if 0
+ handler = _get_thread_local_invalid_parameter_handler();
+ if (handler) {
+ handler(expression, function_name, file_name, line_number, reserved);
+ return;
+ }
+#endif
+
+ handler = _get_invalid_parameter_handler();
+ if (handler) {
+ handler(expression, function_name, file_name, line_number, reserved);
+ return;
+ }
+
+ _invoke_watson(expression, function_name, file_name, line_number,
reserved);
+}
+void (__cdecl *__MINGW_IMP_SYMBOL(_invalid_parameter))(const wchar_t *, const
wchar_t *, const wchar_t *, unsigned int, uintptr_t) = _invalid_parameter;
diff --git a/mingw-w64-crt/misc/_invalid_parameter_noinfo.c
b/mingw-w64-crt/misc/_invalid_parameter_noinfo.c
new file mode 100644
index 000000000000..ed68e5b521da
--- /dev/null
+++ b/mingw-w64-crt/misc/_invalid_parameter_noinfo.c
@@ -0,0 +1,16 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#define _DEBUG /* needed for _invalid_parameter */
+#include <corecrt.h>
+#undef _DEBUG
+#include <stddef.h>
+
+void __cdecl _invalid_parameter_noinfo(void)
+{
+ _invalid_parameter(NULL, NULL, NULL, 0, 0);
+}
+void (__cdecl *__MINGW_IMP_SYMBOL(_invalid_parameter_noinfo))(void) =
_invalid_parameter_noinfo;
diff --git a/mingw-w64-crt/misc/_invalid_parameter_noinfo_noreturn.c
b/mingw-w64-crt/misc/_invalid_parameter_noinfo_noreturn.c
new file mode 100644
index 000000000000..500860d3f5b5
--- /dev/null
+++ b/mingw-w64-crt/misc/_invalid_parameter_noinfo_noreturn.c
@@ -0,0 +1,15 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <corecrt.h>
+#include <stddef.h>
+
+__MINGW_ATTRIB_NORETURN void __cdecl _invalid_parameter_noinfo_noreturn(void)
+{
+ _invalid_parameter_noinfo();
+ _invoke_watson(NULL, NULL, NULL, 0, 0);
+}
+__MINGW_ATTRIB_NORETURN void (__cdecl
*__MINGW_IMP_SYMBOL(_invalid_parameter_noinfo_noreturn))(void) =
_invalid_parameter_noinfo_noreturn;
diff --git a/mingw-w64-crt/misc/_invoke_watson.c
b/mingw-w64-crt/misc/_invoke_watson.c
new file mode 100644
index 000000000000..a7fa505024b2
--- /dev/null
+++ b/mingw-w64-crt/misc/_invoke_watson.c
@@ -0,0 +1,105 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <corecrt.h>
+#include <windows.h>
+
+#if defined(__i386__)
+DECLSPEC_NOINLINE /* decrease chance of modifying caller's registers and/or
stack frame */
+#endif
+static BOOL is_fastfail_available(void)
+{
+#if defined(__i386__)
+ HMODULE module = GetModuleHandleA("kernel32.dll");
+ BOOL (WINAPI *func)(DWORD) = module ? (LPVOID)GetProcAddress(module,
"IsProcessorFeaturePresent") : (LPVOID)NULL;
+ return func ? func(PF_FASTFAIL_AVAILABLE) : FALSE;
+#elif defined(__x86_64__)
+ return IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE);
+#elif defined (__arm__) || defined(__aarch64__)
+ /* On ARM is fastfail always available */
+ return TRUE;
+#else
+#error Unsupported platform
+#endif
+}
+
+/* DECLSPEC_NOINLINE is needed for __builtin_return_address() and
__builtin_frame_address() usage */
+DECLSPEC_NOINLINE __MINGW_ATTRIB_NORETURN void __cdecl _invoke_watson(const
wchar_t * __UNUSED_PARAM(expression), const wchar_t *
__UNUSED_PARAM(function_name), const wchar_t * __UNUSED_PARAM(file_name),
unsigned int __UNUSED_PARAM(line_number), uintptr_t __UNUSED_PARAM(reserved))
+{
+ EXCEPTION_RECORD exception_record = { 0, };
+ CONTEXT context = { 0, };
+ EXCEPTION_POINTERS exception_pointers = { &exception_record, &context };
+#if defined(__x86_64__)
+ ULONG64 establisher_frame;
+ ULONG64 image_base;
+ PRUNTIME_FUNCTION function_entry;
+ PVOID handler_data;
+#endif
+
+ if (is_fastfail_available())
+ __fastfail(FAST_FAIL_INVALID_ARG);
+
+ /*
+ * RtlCaptureContext() is available since Windows XP.
+ * UCRT runtime uses inline assemly on 32-bit x86.
+ * For compatibility with UCRT do same thing.
+ */
+#if defined(__i386__)
+ asm volatile(
+ "mov %%eax, %0\n\t"
+ "mov %%ecx, %1\n\t"
+ "mov %%edx, %2\n\t"
+ "mov %%ebx, %3\n\t"
+ "mov %%esi, %4\n\t"
+ "mov %%edi, %5\n\t"
+ "movw %%ss, %w6\n\t"
+ "movw %%cs, %w7\n\t"
+ "movw %%ds, %w8\n\t"
+ "movw %%es, %w9\n\t"
+ "movw %%fs, %w10\n\t"
+ "movw %%gs, %w11\n\t"
+ "pushf\n\t"
+ "pop %12"
+ :
+ /* Specify only "m" (memory) to prevent using registers and clobbering
their content. */
+ "=m" (context.Eax), "=m" (context.Ecx), "=m" (context.Edx),
+ "=m" (context.Ebx), "=m" (context.Esi), "=m" (context.Edi),
+ "=m" (context.SegSs), "=m" (context.SegCs), "=m" (context.SegDs),
+ "=m" (context.SegEs), "=m" (context.SegFs), "=m" (context.SegGs),
+ "=m" (context.EFlags)
+ :
+ :
+ );
+#else
+ RtlCaptureContext(&context);
+#endif
+
+ /* Fill additional platform specific fields of the parent (caller)
function into context. */
+#if defined(__i386__)
+ context.ContextFlags = CONTEXT_CONTROL;
+ context.Eip =
(uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0)); /* msvc
uses _ReturnAddress() */
+ context.Esp = (uintptr_t)__builtin_frame_address(0); /* msvc uses
_AddressOfReturnAddress() */
+ context.Ebp = *((uintptr_t *)__builtin_frame_address(0)-1); /* msvc uses
*((ULONG *)_AddressOfReturnAddress()-1) */
+#elif defined(__x86_64__)
+ function_entry = RtlLookupFunctionEntry(context.Rip, &image_base, NULL);
+ if (function_entry)
+ RtlVirtualUnwind(UNW_FLAG_NHANDLER, image_base, context.Rip,
function_entry, &context, &handler_data, &establisher_frame, NULL);
+ context.Rip =
(uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0)); /* msvc
uses _ReturnAddress() */
+ context.Rsp = (uintptr_t)__builtin_frame_address(0); /* msvc uses
_AddressOfReturnAddress()+8 */
+ context.Rbp = *((uintptr_t *)__builtin_frame_address(0)-1); /* not filled
filled by msvc */
+#endif
+
+ exception_record.ExceptionCode = STATUS_INVALID_CRUNTIME_PARAMETER;
+ exception_record.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ exception_record.ExceptionAddress =
__builtin_extract_return_addr(__builtin_return_address(0)); /* msvc uses
_ReturnAddress() */
+
+ /* Remove all filters, trigger exception and terminate the process. */
+ SetUnhandledExceptionFilter(NULL);
+ UnhandledExceptionFilter(&exception_pointers);
+ TerminateProcess(GetCurrentProcess(), STATUS_INVALID_CRUNTIME_PARAMETER);
+ __builtin_unreachable();
+}
+__MINGW_ATTRIB_NORETURN void (__cdecl
*__MINGW_IMP_SYMBOL(_invoke_watson))(const wchar_t *, const wchar_t *, const
wchar_t *, unsigned int, uintptr_t) = _invoke_watson;
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public