It looks like msvcp doesn't export anything for the std::bad_function_call exception construction and if std::bad_function_call is constructed directly from the app the corresponding class data is generated in the application binary.
I am attaching an ad-hoc test program I used to test it (using MSVC 2022 community edition). [msvcp_except.cpp](/uploads/558f0911366525d05af4ac69552c4aae/msvcp_except.cpp)
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msvcp110/msvcp110.spec | 2 +- dlls/msvcp120/msvcp120.spec | 2 +- dlls/msvcp120_app/msvcp120_app.spec | 2 +- dlls/msvcp140/msvcp140.spec | 2 +- dlls/msvcp90/exception.c | 85 +++++++++++++++++++++++++++++ dlls/msvcp_win/msvcp_win.spec | 2 +- 6 files changed, 90 insertions(+), 5 deletions(-)
diff --git a/dlls/msvcp110/msvcp110.spec b/dlls/msvcp110/msvcp110.spec index 9c61f57a4de..bc73bd57a54 100644 --- a/dlls/msvcp110/msvcp110.spec +++ b/dlls/msvcp110/msvcp110.spec @@ -1833,7 +1833,7 @@ @ cdecl ?_XLgamma@std@@YANN@Z(double) std__XLgamma_double @ cdecl ?_XLgamma@std@@YAOO@Z(double) std__XLgamma_double @ cdecl ?_Xbad_alloc@std@@YAXXZ() _Xmem -@ stub ?_Xbad_function_call@std@@YAXXZ +@ cdecl ?_Xbad_function_call@std@@YAXXZ() _Xbad_function_call @ cdecl -arch=win32 ?_Xinvalid_argument@std@@YAXPBD@Z(str) _Xinvalid_argument @ cdecl -arch=win64 ?_Xinvalid_argument@std@@YAXPEBD@Z(str) _Xinvalid_argument @ cdecl -arch=win32 ?_Xlength_error@std@@YAXPBD@Z(str) _Xlength_error diff --git a/dlls/msvcp120/msvcp120.spec b/dlls/msvcp120/msvcp120.spec index 835d37d3bf4..dc00344c92f 100644 --- a/dlls/msvcp120/msvcp120.spec +++ b/dlls/msvcp120/msvcp120.spec @@ -1794,7 +1794,7 @@ @ cdecl ?_XLgamma@std@@YANN@Z(double) std__XLgamma_double @ cdecl ?_XLgamma@std@@YAOO@Z(double) std__XLgamma_double @ cdecl ?_Xbad_alloc@std@@YAXXZ() _Xmem -@ stub ?_Xbad_function_call@std@@YAXXZ +@ cdecl ?_Xbad_function_call@std@@YAXXZ() _Xbad_function_call @ cdecl -arch=win32 ?_Xinvalid_argument@std@@YAXPBD@Z(str) _Xinvalid_argument @ cdecl -arch=win64 ?_Xinvalid_argument@std@@YAXPEBD@Z(str) _Xinvalid_argument @ cdecl -arch=win32 ?_Xlength_error@std@@YAXPBD@Z(str) _Xlength_error diff --git a/dlls/msvcp120_app/msvcp120_app.spec b/dlls/msvcp120_app/msvcp120_app.spec index c6778841ffb..dc69df9ce6a 100644 --- a/dlls/msvcp120_app/msvcp120_app.spec +++ b/dlls/msvcp120_app/msvcp120_app.spec @@ -1794,7 +1794,7 @@ @ cdecl ?_XLgamma@std@@YANN@Z(double) msvcp120.?_XLgamma@std@@YANN@Z @ cdecl ?_XLgamma@std@@YAOO@Z(double) msvcp120.?_XLgamma@std@@YAOO@Z @ cdecl ?_Xbad_alloc@std@@YAXXZ() msvcp120.?_Xbad_alloc@std@@YAXXZ -@ stub ?_Xbad_function_call@std@@YAXXZ +@ cdecl ?_Xbad_function_call@std@@YAXXZ() msvcp120.?_Xbad_function_call@std@@YAXXZ @ cdecl -arch=win32 ?_Xinvalid_argument@std@@YAXPBD@Z(str) msvcp120.?_Xinvalid_argument@std@@YAXPBD@Z @ cdecl -arch=win64 ?_Xinvalid_argument@std@@YAXPEBD@Z(str) msvcp120.?_Xinvalid_argument@std@@YAXPEBD@Z @ cdecl -arch=win32 ?_Xlength_error@std@@YAXPBD@Z(str) msvcp120.?_Xlength_error@std@@YAXPBD@Z diff --git a/dlls/msvcp140/msvcp140.spec b/dlls/msvcp140/msvcp140.spec index e3d01a9326f..ea2e7798a1d 100644 --- a/dlls/msvcp140/msvcp140.spec +++ b/dlls/msvcp140/msvcp140.spec @@ -1677,7 +1677,7 @@ @ cdecl ?_XLgamma@std@@YANN@Z(double) std__XLgamma_double @ cdecl ?_XLgamma@std@@YAOO@Z(double) std__XLgamma_double @ cdecl ?_Xbad_alloc@std@@YAXXZ() _Xmem -@ stub ?_Xbad_function_call@std@@YAXXZ +@ cdecl ?_Xbad_function_call@std@@YAXXZ() _Xbad_function_call @ cdecl -arch=win32 ?_Xinvalid_argument@std@@YAXPBD@Z(str) _Xinvalid_argument @ cdecl -arch=win64 ?_Xinvalid_argument@std@@YAXPEBD@Z(str) _Xinvalid_argument @ cdecl -arch=win32 ?_Xlength_error@std@@YAXPBD@Z(str) _Xlength_error diff --git a/dlls/msvcp90/exception.c b/dlls/msvcp90/exception.c index ee59dbf2112..7b4c52440b5 100644 --- a/dlls/msvcp90/exception.c +++ b/dlls/msvcp90/exception.c @@ -68,6 +68,8 @@ extern const vtable_ptr failure_vtable; extern const vtable_ptr bad_cast_vtable; /* ??_7range_error@std@@6B@ */ extern const vtable_ptr range_error_vtable; +/* ??_7bad_function_call@std@@6B@ */ +extern const vtable_ptr bad_function_call_vtable;
/* ??0exception@@QAE@ABQBD@Z */ /* ??0exception@@QEAA@AEBQEBD@Z */ @@ -875,6 +877,68 @@ range_error* __thiscall MSVCP_range_error_assign(range_error *this, const range_ DEFINE_RTTI_DATA2(range_error, 0, &runtime_error_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AVrange_error@std@@") DEFINE_CXX_DATA2(range_error, &runtime_error_cxx_type_info, &exception_cxx_type_info, MSVCP_runtime_error_dtor)
+#if _MSVCP_VER > 90 +/* bad_function_call class data */ +typedef exception bad_function_call; + +static bad_function_call* MSVCP_bad_function_call_default_ctor(bad_function_call *this) +{ + static const char *name = "bad function call"; + + TRACE("%p\n", this); + MSVCP_exception_ctor(this, EXCEPTION_NAME(name)); + this->vtable = &bad_function_call_vtable; + return this; +} + +DEFINE_THISCALL_WRAPPER(bad_function_call_copy_ctor, 8) +bad_function_call* __thiscall bad_function_call_copy_ctor(bad_function_call *this, const bad_function_call *rhs) +{ + TRACE("%p %p\n", this, rhs); + exception_copy_ctor(this, rhs); + this->vtable = &bad_function_call_vtable; + return this; +} + +DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_dtor, 4) +void __thiscall MSVCP_bad_function_call_dtor(bad_function_call *this) +{ + TRACE("%p\n", this); + MSVCP_exception_dtor(this); +} + +DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_vector_dtor, 8) +void * __thiscall MSVCP_bad_function_call_vector_dtor(bad_function_call *this, unsigned int flags) +{ + TRACE("%p %x\n", this, flags); + if(flags & 2) { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)this-1; + + for(i=*ptr-1; i>=0; i--) + MSVCP_bad_function_call_dtor(this+i); + operator_delete(ptr); + } else { + MSVCP_bad_function_call_dtor(this); + if(flags & 1) + operator_delete(this); + } + + return this; +} + +DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_what, 4) +const char* __thiscall MSVCP_bad_function_call_what(bad_function_call *this) +{ + TRACE("%p\n", this); + + return MSVCP_exception_what( this ); +} + +DEFINE_RTTI_DATA1(bad_function_call, 0, &exception_rtti_base_descriptor, ".?AVbad_function_call@std@@") +DEFINE_CXX_DATA1(bad_function_call, &exception_cxx_type_info, MSVCP_bad_function_call_dtor) +#endif + /* ?_Nomemory@std@@YAXXZ */ void __cdecl DECLSPEC_NORETURN _Nomemory(void) { @@ -949,6 +1013,19 @@ void __cdecl DECLSPEC_NORETURN _Xruntime_error(const char *str) _CxxThrowException(&e, &runtime_error_cxx_type); }
+#if _MSVCP_VER > 90 +/* ?_Xbad_function_call@std@@YAXXZ() */ +void __cdecl _Xbad_function_call(void) +{ + exception e; + + TRACE("()\n"); + + MSVCP_bad_function_call_default_ctor(&e); + _CxxThrowException(&e, &bad_function_call_cxx_type); +} +#endif + /* ?uncaught_exception@std@@YA_NXZ */ bool __cdecl MSVCP__uncaught_exception(void) { @@ -1476,6 +1553,9 @@ __ASM_BLOCK_BEGIN(exception_vtables) EXCEPTION_VTABLE(system_error, VTABLE_ADD_FUNC(MSVCP_failure_vector_dtor) VTABLE_ADD_FUNC(MSVCP_failure_what)); + EXCEPTION_VTABLE(bad_function_call, + VTABLE_ADD_FUNC(MSVCP_bad_function_call_vector_dtor) + VTABLE_ADD_FUNC(MSVCP_bad_function_call_what)); #endif EXCEPTION_VTABLE(failure, VTABLE_ADD_FUNC(MSVCP_failure_vector_dtor) @@ -1486,6 +1566,7 @@ __ASM_BLOCK_BEGIN(exception_vtables) EXCEPTION_VTABLE(range_error, VTABLE_ADD_FUNC(MSVCP_runtime_error_vector_dtor) VTABLE_ADD_FUNC(MSVCP_runtime_error_what)); + __ASM_BLOCK_END
/* Internal: throws exception */ @@ -1537,6 +1618,7 @@ void init_exception(void *base) #endif #if _MSVCP_VER > 90 init_system_error_rtti(base); + init_bad_function_call_rtti(base); #endif init_failure_rtti(base); init_bad_cast_rtti(base); @@ -1559,6 +1641,9 @@ void init_exception(void *base) init_system_error_cxx_type_info(base); #elif _MSVCP_VER > 100 init_system_error_cxx(base); +#endif +#if _MSVCP_VER > 90 + init_bad_function_call_cxx(base); #endif init_failure_cxx(base); init_range_error_cxx(base); diff --git a/dlls/msvcp_win/msvcp_win.spec b/dlls/msvcp_win/msvcp_win.spec index c8107094d31..9f4d8581cf3 100644 --- a/dlls/msvcp_win/msvcp_win.spec +++ b/dlls/msvcp_win/msvcp_win.spec @@ -1677,7 +1677,7 @@ @ cdecl ?_XLgamma@std@@YANN@Z(double) msvcp140.?_XLgamma@std@@YANN@Z @ cdecl ?_XLgamma@std@@YAOO@Z(double) msvcp140.?_XLgamma@std@@YAOO@Z @ cdecl ?_Xbad_alloc@std@@YAXXZ() msvcp140.?_Xbad_alloc@std@@YAXXZ -@ stub ?_Xbad_function_call@std@@YAXXZ +@ cdecl ?_Xbad_function_call@std@@YAXXZ() msvcp140.?_Xbad_function_call@std@@YAXXZ @ cdecl -arch=win32 ?_Xinvalid_argument@std@@YAXPBD@Z(str) msvcp140.?_Xinvalid_argument@std@@YAXPBD@Z @ cdecl -arch=win64 ?_Xinvalid_argument@std@@YAXPEBD@Z(str) msvcp140.?_Xinvalid_argument@std@@YAXPEBD@Z @ cdecl -arch=win32 ?_Xlength_error@std@@YAXPBD@Z(str) msvcp140.?_Xlength_error@std@@YAXPBD@Z
Piotr Caban (@piotr) commented about dlls/msvcp90/exception.c:
DEFINE_RTTI_DATA2(range_error, 0, &runtime_error_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AVrange_error@std@@") DEFINE_CXX_DATA2(range_error, &runtime_error_cxx_type_info, &exception_cxx_type_info, MSVCP_runtime_error_dtor)
+#if _MSVCP_VER > 90 +/* bad_function_call class data */ +typedef exception bad_function_call;
+static bad_function_call* MSVCP_bad_function_call_default_ctor(bad_function_call *this)
Could you please rename the function?
```suggestion:-0+0 static bad_function_call* bad_function_call_ctor(bad_function_call *this) ```
Piotr Caban (@piotr) commented about dlls/msvcp90/exception.c:
+DEFINE_THISCALL_WRAPPER(bad_function_call_copy_ctor, 8) +bad_function_call* __thiscall bad_function_call_copy_ctor(bad_function_call *this, const bad_function_call *rhs) +{
- TRACE("%p %p\n", this, rhs);
- exception_copy_ctor(this, rhs);
- this->vtable = &bad_function_call_vtable;
- return this;
+}
+DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_dtor, 4) +void __thiscall MSVCP_bad_function_call_dtor(bad_function_call *this) +{
- TRACE("%p\n", this);
- MSVCP_exception_dtor(this);
+}
This function in not needed, you can call MSVCP_exception_dtor directly.
Piotr Caban (@piotr) commented about dlls/msvcp90/exception.c:
+{
- TRACE("%p %p\n", this, rhs);
- exception_copy_ctor(this, rhs);
- this->vtable = &bad_function_call_vtable;
- return this;
+}
+DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_dtor, 4) +void __thiscall MSVCP_bad_function_call_dtor(bad_function_call *this) +{
- TRACE("%p\n", this);
- MSVCP_exception_dtor(this);
+}
+DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_vector_dtor, 8) +void * __thiscall MSVCP_bad_function_call_vector_dtor(bad_function_call *this, unsigned int flags)
This function is also not needed, MSVCP_exception_vector_dtor can be used instead.
Piotr Caban (@piotr) commented about dlls/msvcp90/exception.c:
INT_PTR i, *ptr = (INT_PTR *)this-1;
for(i=*ptr-1; i>=0; i--)
MSVCP_bad_function_call_dtor(this+i);
operator_delete(ptr);
- } else {
MSVCP_bad_function_call_dtor(this);
if(flags & 1)
operator_delete(this);
- }
- return this;
+}
+DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_what, 4) +const char* __thiscall MSVCP_bad_function_call_what(bad_function_call *this)
This function can also be removed.
Piotr Caban (@piotr) commented about dlls/msvcp90/exception.c:
operator_delete(this);
- }
- return this;
+}
+DEFINE_THISCALL_WRAPPER(MSVCP_bad_function_call_what, 4) +const char* __thiscall MSVCP_bad_function_call_what(bad_function_call *this) +{
- TRACE("%p\n", this);
- return MSVCP_exception_what( this );
+}
+DEFINE_RTTI_DATA1(bad_function_call, 0, &exception_rtti_base_descriptor, ".?AVbad_function_call@std@@") +DEFINE_CXX_DATA1(bad_function_call, &exception_cxx_type_info, MSVCP_bad_function_call_dtor)
```suggestion:-0+0 DEFINE_CXX_DATA1(bad_function_call, &exception_cxx_type_info, MSVCP_exception_dtor) ```
Piotr Caban (@piotr) commented about dlls/msvcp90/exception.c:
EXCEPTION_VTABLE(system_error, VTABLE_ADD_FUNC(MSVCP_failure_vector_dtor) VTABLE_ADD_FUNC(MSVCP_failure_what));
- EXCEPTION_VTABLE(bad_function_call,
VTABLE_ADD_FUNC(MSVCP_bad_function_call_vector_dtor)
VTABLE_ADD_FUNC(MSVCP_bad_function_call_what));
```suggestion:-2+0 EXCEPTION_VTABLE(bad_function_call, VTABLE_ADD_FUNC(MSVCP_exception_vector_dtor) VTABLE_ADD_FUNC(MSVCP_exception_what)); ```