From 10c7fb0d3ddaecb32593c168d3308a78389cb7ef Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Thu, 11 Jul 2019 13:38:03 -0500 Subject: [PATCH] [metadata] Respect unmanaged calling conventions in function signatures. (mono/mono#15363) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit According to ECMA-335 § II.15.3, calling conventions other than "default" and "vararg" describe unmanaged methods. Accordingly they should be treated as pinvokes so that that their calling conventions are respected. Commit migrated from https://github.com/mono/mono/commit/2f1b50bfbf9db129d844dad8e45ec248f0c877e4 --- src/mono/mono/metadata/metadata.c | 13 +++++++++++++ src/mono/mono/tests/Makefile.am | 3 ++- src/mono/mono/tests/calli_native.il | 37 +++++++++++++++++++++++++++++++++++++ src/mono/mono/tests/libtest.c | 12 ++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/mono/mono/tests/calli_native.il diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index aea4a39..65c7fff 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -2251,6 +2251,19 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c method->call_convention = call_convention; method->generic_param_count = gen_param_count; + switch (method->call_convention) { + case MONO_CALL_DEFAULT: + case MONO_CALL_VARARG: + method->pinvoke = 0; + break; + case MONO_CALL_C: + case MONO_CALL_STDCALL: + case MONO_CALL_THISCALL: + case MONO_CALL_FASTCALL: + method->pinvoke = 1; + break; + } + if (call_convention != 0xa) { method->ret = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [0] : 0, FALSE, ptr, &ptr, error); if (!method->ret) { diff --git a/src/mono/mono/tests/Makefile.am b/src/mono/mono/tests/Makefile.am index d9b3665..567c2f7 100755 --- a/src/mono/mono/tests/Makefile.am +++ b/src/mono/mono/tests/Makefile.am @@ -1025,7 +1025,8 @@ TESTS_IL_SRC= \ gh-13056_mono_local_cprop_av.il \ gh-13057_mono_local_emulate_ops_av.il \ module-cctor-entrypoint.il \ - bug-gh-9706.il + bug-gh-9706.il \ + calli_native.il # This test crashes the runtime, even with recent fixes. # incorrect-ldvirtftn-read-behind-for-dup.il diff --git a/src/mono/mono/tests/calli_native.il b/src/mono/mono/tests/calli_native.il new file mode 100644 index 0000000..f258264 --- /dev/null +++ b/src/mono/mono/tests/calli_native.il @@ -0,0 +1,37 @@ +// Test using calli with native methods and ensure that it respects calling convention + +.assembly extern mscorlib{} +.assembly calli_native{} + +.method public static pinvokeimpl ("libtest" winapi) int32 mono_test_has_thiscall_globals() cil managed preservesig {} +.method public static pinvokeimpl ("libtest" winapi) void * mono_test_get_native_thiscall2() cil managed preservesig {} + +.method public static int32 test_0_calli_native () cil managed +{ + .entrypoint + .locals init (void *V_0) + + call int32 mono_test_has_thiscall_globals() + brfalse pass + + call void* mono_test_get_native_thiscall2() + stloc.0 + ldc.i4 268894549 + ldc.i4 1212675791 + ldloc.0 + calli unmanaged thiscall int32 (int32, int32) + ldc.i4 1481570339 + ceq + brtrue pass + + ldstr "FAIL" + call void [mscorlib]System.Console::WriteLine(string) + ldc.i4.1 + ret + +pass: + ldstr "PASS" + call void [mscorlib]System.Console::WriteLine(string) + ldc.i4.0 + ret +} \ No newline at end of file diff --git a/src/mono/mono/tests/libtest.c b/src/mono/mono/tests/libtest.c index ce0834b..3b04f2d 100644 --- a/src/mono/mono/tests/libtest.c +++ b/src/mono/mono/tests/libtest.c @@ -5711,6 +5711,18 @@ _mono_test_native_thiscall3 (int arg, int arg2, int arg3) return arg + (arg2^1) + (arg3^2); } +typedef int ( +#ifndef _MSC_VER +__thiscall +#endif +*ThiscallFunction)(int arg, int arg2); + +LIBTEST_API ThiscallFunction STDCALL +mono_test_get_native_thiscall2 (void) +{ + return _mono_test_native_thiscall2; +} + LIBTEST_API int STDCALL _mono_test_managed_thiscall1 (int (__thiscall*fn)(int), int arg) { -- 2.7.4