diff --git a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs index a8b6717a3c3..cb6f9935c4c 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs @@ -134,7 +134,7 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args) SetSynchronizationContext (); } - [DllImport ("xamarin-app")] + [DllImport (RuntimeConstants.InternalDllName, CallingConvention = CallingConvention.Cdecl)] static extern unsafe void xamarin_app_init (IntPtr env, delegate* unmanaged get_function_pointer); static void SetSynchronizationContext () => diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index fee7a6054e2..380fb63516b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -342,6 +342,7 @@ void AddEnvironment () JniRemappingReplacementTypeCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementTypeCount, JniRemappingReplacementMethodIndexEntryCount = jniRemappingNativeCodeInfo == null ? 0 : jniRemappingNativeCodeInfo.ReplacementMethodIndexEntryCount, MarshalMethodsEnabled = EnableMarshalMethods, + ManagedMarshalMethodsLookupEnabled = EnableManagedMarshalMethodsLookup, IgnoreSplitConfigs = ShouldIgnoreSplitConfigs (), }; } else { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs index 249efc6c031..0efed3ccc3c 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs @@ -49,4 +49,5 @@ sealed class ApplicationConfigCLR public uint jni_remapping_replacement_type_count; public uint jni_remapping_replacement_method_index_entry_count; public string android_package_name = String.Empty; + public bool managed_marshal_methods_lookup_enabled; } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs index 92440adfc42..b61ab28eabd 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGeneratorCLR.cs @@ -207,6 +207,7 @@ sealed class XamarinAndroidBundledAssembly public PackageNamingPolicy PackageNamingPolicy { get; set; } public List NativeLibraries { get; set; } public bool MarshalMethodsEnabled { get; set; } + public bool ManagedMarshalMethodsLookupEnabled { get; set; } public bool IgnoreSplitConfigs { get; set; } public ApplicationConfigNativeAssemblyGeneratorCLR (IDictionary environmentVariables, IDictionary systemProperties, @@ -256,6 +257,7 @@ protected override void Construct (LlvmIrModule module) uses_assembly_preload = UsesAssemblyPreload, jni_add_native_method_registration_attribute_present = JniAddNativeMethodRegistrationAttributePresent, marshal_methods_enabled = MarshalMethodsEnabled, + managed_marshal_methods_lookup_enabled = ManagedMarshalMethodsLookupEnabled, ignore_split_configs = IgnoreSplitConfigs, number_of_runtime_properties = (uint)(runtimeProperties == null ? 0 : runtimeProperties.Count), package_naming_policy = (uint)PackageNamingPolicy, diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsAssemblyRewriter.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsAssemblyRewriter.cs index 5de2f6392d8..335cdadfb6e 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsAssemblyRewriter.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsAssemblyRewriter.cs @@ -6,6 +6,7 @@ using Microsoft.Build.Utilities; using Mono.Cecil; using Mono.Cecil.Cil; +using Java.Interop.Tools.Cecil; using Xamarin.Android.Tools; namespace Xamarin.Android.Tasks @@ -82,6 +83,12 @@ public void Rewrite (bool brokenExceptionTransitions) continue; } + if (HasUnmanagedCallersOnlyAttribute (method.NativeCallback)) { + log.LogDebugMessage ($"[{targetArch}] Method '{method.NativeCallback.FullName}' does not need a wrapper, it already has UnmanagedCallersOnlyAttribute"); + method.NativeCallbackWrapper = method.NativeCallback; + continue; + } + method.NativeCallbackWrapper = GenerateWrapper (method, assemblyImports, brokenExceptionTransitions); if (method.Connector != null) { if (method.Connector.IsStatic && method.Connector.IsPrivate) { @@ -186,6 +193,17 @@ void RemoveFile (string? path) log.LogDebugMessage ($"[{targetArch}] {ex.ToString ()}"); } } + + static bool HasUnmanagedCallersOnlyAttribute (MethodDefinition method) + { + foreach (CustomAttribute ca in method.CustomAttributes) { + if (ca.Constructor.DeclaringType.FullName == "System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute") { + return true; + } + } + + return false; + } } MethodDefinition GenerateWrapper (MarshalMethodEntry method, Dictionary assemblyImports, bool brokenExceptionTransitions) diff --git a/src/native/clr/host/generate-pinvoke-tables.cc b/src/native/clr/host/generate-pinvoke-tables.cc index e2055f45763..9e8e14377cb 100644 --- a/src/native/clr/host/generate-pinvoke-tables.cc +++ b/src/native/clr/host/generate-pinvoke-tables.cc @@ -79,6 +79,7 @@ const std::vector internal_pinvoke_names = { // "recv_uninterrupted", // "send_uninterrupted", // "set_world_accessable", + "xamarin_app_init", // We can treat liblog as "internal", since we link against it "__android_log_print", diff --git a/src/native/clr/host/host.cc b/src/native/clr/host/host.cc index a2eedaa2d6d..74836f670ae 100644 --- a/src/native/clr/host/host.cc +++ b/src/native/clr/host/host.cc @@ -253,6 +253,9 @@ void Host::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass runtimeCl init.jniAddNativeMethodRegistrationAttributePresent = application_config.jni_add_native_method_registration_attribute_present ? 1 : 0; init.jniRemappingInUse = application_config.jni_remapping_replacement_type_count > 0 || application_config.jni_remapping_replacement_method_index_entry_count > 0; init.marshalMethodsEnabled = application_config.marshal_methods_enabled; + init.managedMarshalMethodsLookupEnabled = application_config.managed_marshal_methods_lookup_enabled; + abort_unless (!init.marshalMethodsEnabled || init.managedMarshalMethodsLookupEnabled, + "Managed marshal methods lookup must be enabled if marshal methods are enabled"); // GC threshold is 90% of the max GREF count init.grefGcThreshold = static_cast(AndroidSystem::get_gref_gc_threshold ()); diff --git a/src/native/clr/host/pinvoke-override.cc b/src/native/clr/host/pinvoke-override.cc index d1467e4eda1..3eec4e53ff0 100644 --- a/src/native/clr/host/pinvoke-override.cc +++ b/src/native/clr/host/pinvoke-override.cc @@ -4,6 +4,10 @@ using namespace xamarin::android; +#if defined (DEBUG) +void xamarin_app_init ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] get_function_pointer_fn fn) noexcept {} +#endif + #include "pinvoke-tables.include" [[gnu::flatten]] diff --git a/src/native/clr/host/pinvoke-tables.include b/src/native/clr/host/pinvoke-tables.include index 73d07f125c6..4d7a6b8ef60 100644 --- a/src/native/clr/host/pinvoke-tables.include +++ b/src/native/clr/host/pinvoke-tables.include @@ -11,7 +11,7 @@ namespace { #if INTPTR_MAX == INT64_MAX //64-bit internal p/invoke table - std::array internal_pinvokes {{ + std::array internal_pinvokes {{ {0x4310c1531ddddc14, "__android_log_print", reinterpret_cast(&__android_log_print)}, {0x4b1956138764939a, "_monodroid_gref_log_new", reinterpret_cast(&_monodroid_gref_log_new)}, {0x9187e6bc6294cacf, "clr_typemap_managed_to_java", reinterpret_cast(&clr_typemap_managed_to_java)}, @@ -19,6 +19,7 @@ namespace { {0xa7f58f3ee428cc6b, "_monodroid_gref_log_delete", reinterpret_cast(&_monodroid_gref_log_delete)}, {0xae3df96dda0143bd, "_monodroid_gref_log", reinterpret_cast(&_monodroid_gref_log)}, {0xb8306f71b963cd3d, "monodroid_log", reinterpret_cast(&monodroid_log)}, + {0xb9bae9c43fb05089, "xamarin_app_init", reinterpret_cast(&xamarin_app_init)}, {0xd1e121b94ea63f2e, "_monodroid_gref_get", reinterpret_cast(&_monodroid_gref_get)}, {0xd5151b00eb33d85e, "monodroid_TypeManager_get_java_class_name", reinterpret_cast(&monodroid_TypeManager_get_java_class_name)}, {0xf41c48df6f9be476, "monodroid_free", reinterpret_cast(&monodroid_free)}, @@ -515,7 +516,7 @@ constexpr hash_t system_security_cryptography_native_android_library_hash = 0x18 constexpr hash_t system_globalization_native_library_hash = 0x28b5c8fca080abd5; #else //32-bit internal p/invoke table - std::array internal_pinvokes {{ + std::array internal_pinvokes {{ {0xb7a486a, "monodroid_TypeManager_get_java_class_name", reinterpret_cast(&monodroid_TypeManager_get_java_class_name)}, {0x39e5b5d4, "__android_log_print", reinterpret_cast(&__android_log_print)}, {0x656e00bd, "clr_typemap_managed_to_java", reinterpret_cast(&clr_typemap_managed_to_java)}, @@ -525,6 +526,7 @@ constexpr hash_t system_globalization_native_library_hash = 0x28b5c8fca080abd5; {0xbe8d7701, "_monodroid_gref_log_new", reinterpret_cast(&_monodroid_gref_log_new)}, {0xc5146c54, "_monodroid_gref_log_delete", reinterpret_cast(&_monodroid_gref_log_delete)}, {0xe7e77ca5, "_monodroid_gref_log", reinterpret_cast(&_monodroid_gref_log)}, + {0xeac7f6e3, "xamarin_app_init", reinterpret_cast(&xamarin_app_init)}, {0xfa4e32ca, "monodroid_log", reinterpret_cast(&monodroid_log)}, }}; @@ -1019,6 +1021,6 @@ constexpr hash_t system_security_cryptography_native_android_library_hash = 0x93 constexpr hash_t system_globalization_native_library_hash = 0xa66f1e5a; #endif -constexpr size_t internal_pinvokes_count = 10; +constexpr size_t internal_pinvokes_count = 11; constexpr size_t dotnet_pinvokes_count = 477; } // end of anonymous namespace diff --git a/src/native/clr/include/runtime-base/internal-pinvokes.hh b/src/native/clr/include/runtime-base/internal-pinvokes.hh index 44ba6fb99cb..13aed40f310 100644 --- a/src/native/clr/include/runtime-base/internal-pinvokes.hh +++ b/src/native/clr/include/runtime-base/internal-pinvokes.hh @@ -3,6 +3,7 @@ #include #include "logger.hh" +#include "xamarin-app.hh" int _monodroid_gref_get () noexcept; void _monodroid_gref_log (const char *message) noexcept; diff --git a/src/native/clr/include/xamarin-app.hh b/src/native/clr/include/xamarin-app.hh index 2b42ba9582b..72a2b225b23 100644 --- a/src/native/clr/include/xamarin-app.hh +++ b/src/native/clr/include/xamarin-app.hh @@ -215,7 +215,7 @@ struct AssemblyStoreSingleAssemblyRuntimeData final }; // Keep in strict sync with: -// src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfig.cs +// src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigCLR.cs // src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs struct ApplicationConfig { @@ -394,8 +394,7 @@ struct MarshalMethodName [[gnu::visibility("default")]] extern const char* const mm_class_names[]; [[gnu::visibility("default")]] extern const MarshalMethodName mm_method_names[]; +#endif // def RELEASE using get_function_pointer_fn = void(*)(uint32_t mono_image_index, uint32_t class_index, uint32_t method_token, void*& target_ptr); - -[[gnu::visibility("default")]] extern void xamarin_app_init (JNIEnv *env, get_function_pointer_fn fn) noexcept; -#endif // def RELEASE +extern "C" [[gnu::visibility("default")]] extern void xamarin_app_init (JNIEnv *env, get_function_pointer_fn fn) noexcept; diff --git a/src/native/mono/pinvoke-override/generate-pinvoke-tables.cc b/src/native/mono/pinvoke-override/generate-pinvoke-tables.cc index 082c672e22c..6b5066d3fb1 100644 --- a/src/native/mono/pinvoke-override/generate-pinvoke-tables.cc +++ b/src/native/mono/pinvoke-override/generate-pinvoke-tables.cc @@ -77,6 +77,7 @@ const std::vector internal_pinvoke_names = { "recv_uninterrupted", "send_uninterrupted", "set_world_accessable", + "xamarin_app_init", }; const std::vector dotnet_pinvoke_names = { diff --git a/src/native/mono/pinvoke-override/pinvoke-tables.include b/src/native/mono/pinvoke-override/pinvoke-tables.include index 8b38d425190..211c752a730 100644 --- a/src/native/mono/pinvoke-override/pinvoke-tables.include +++ b/src/native/mono/pinvoke-override/pinvoke-tables.include @@ -11,7 +11,7 @@ namespace { #if INTPTR_MAX == INT64_MAX //64-bit internal p/invoke table - std::array internal_pinvokes {{ + std::array internal_pinvokes {{ {0xa50ce5de13bf8b5, "_monodroid_timezone_get_default_id", reinterpret_cast(&_monodroid_timezone_get_default_id)}, {0x19055d65edfd668e, "_monodroid_get_network_interface_up_state", reinterpret_cast(&_monodroid_get_network_interface_up_state)}, {0x2b3b0ca1d14076da, "monodroid_get_dylib", reinterpret_cast(&monodroid_get_dylib)}, @@ -35,6 +35,7 @@ namespace { {0xae3df96dda0143bd, "_monodroid_gref_log", reinterpret_cast(&_monodroid_gref_log)}, {0xb6222d90af401865, "_monodroid_weak_gref_get", reinterpret_cast(&_monodroid_weak_gref_get)}, {0xb8306f71b963cd3d, "monodroid_log", reinterpret_cast(&monodroid_log)}, + {0xb9bae9c43fb05089, "xamarin_app_init", reinterpret_cast(&xamarin_app_init)}, {0xbc90bafd5ff9c99e, "_monodroid_get_dns_servers", reinterpret_cast(&_monodroid_get_dns_servers)}, {0xbe5a300beec69c35, "monodroid_get_system_property", reinterpret_cast(&monodroid_get_system_property)}, {0xbfbb924fbe190616, "monodroid_dylib_mono_free", reinterpret_cast(&monodroid_dylib_mono_free)}, @@ -549,7 +550,7 @@ constexpr hash_t system_security_cryptography_native_android_library_hash = 0x18 constexpr hash_t system_globalization_native_library_hash = 0x28b5c8fca080abd5; #else //32-bit internal p/invoke table - std::array internal_pinvokes {{ + std::array internal_pinvokes {{ {0xb7a486a, "monodroid_TypeManager_get_java_class_name", reinterpret_cast(&monodroid_TypeManager_get_java_class_name)}, {0xf562bd9, "monodroid_embedded_assemblies_set_assemblies_prefix", reinterpret_cast(&monodroid_embedded_assemblies_set_assemblies_prefix)}, {0x227a2636, "monodroid_get_namespaced_system_property", reinterpret_cast(&monodroid_get_namespaced_system_property)}, @@ -588,6 +589,7 @@ constexpr hash_t system_globalization_native_library_hash = 0x28b5c8fca080abd5; {0xe4c3ee19, "monodroid_log_traces", reinterpret_cast(&monodroid_log_traces)}, {0xe7e77ca5, "_monodroid_gref_log", reinterpret_cast(&_monodroid_gref_log)}, {0xea2184e3, "_monodroid_gc_wait_for_bridge_processing", reinterpret_cast(&_monodroid_gc_wait_for_bridge_processing)}, + {0xeac7f6e3, "xamarin_app_init", reinterpret_cast(&xamarin_app_init)}, {0xf4079b4a, "monodroid_dylib_mono_new", reinterpret_cast(&monodroid_dylib_mono_new)}, {0xf5a0ac55, "set_world_accessable", reinterpret_cast(&set_world_accessable)}, {0xf61941c3, "recv_uninterrupted", reinterpret_cast(&recv_uninterrupted)}, @@ -1087,6 +1089,6 @@ constexpr hash_t system_security_cryptography_native_android_library_hash = 0x93 constexpr hash_t system_globalization_native_library_hash = 0xa66f1e5a; #endif -constexpr size_t internal_pinvokes_count = 45; +constexpr size_t internal_pinvokes_count = 46; constexpr size_t dotnet_pinvokes_count = 477; } // end of anonymous namespace diff --git a/src/native/mono/pinvoke-override/precompiled.cc b/src/native/mono/pinvoke-override/precompiled.cc index 29ac736e433..0edb0a0f453 100644 --- a/src/native/mono/pinvoke-override/precompiled.cc +++ b/src/native/mono/pinvoke-override/precompiled.cc @@ -5,6 +5,10 @@ using namespace xamarin::android; +#if defined (DEBUG) +void xamarin_app_init ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] get_function_pointer_fn fn) noexcept {} +#endif + #include "pinvoke-tables.include" [[gnu::flatten]] diff --git a/src/native/mono/xamarin-app-stub/xamarin-app.hh b/src/native/mono/xamarin-app-stub/xamarin-app.hh index 365df553c7b..5b058a99d2d 100644 --- a/src/native/mono/xamarin-app-stub/xamarin-app.hh +++ b/src/native/mono/xamarin-app-stub/xamarin-app.hh @@ -392,9 +392,9 @@ struct MarshalMethodName MONO_API MONO_API_EXPORT const char* const mm_class_names[]; MONO_API MONO_API_EXPORT const MarshalMethodName mm_method_names[]; -using get_function_pointer_fn = void(*)(uint32_t mono_image_index, uint32_t class_index, uint32_t method_token, void*& target_ptr); +#endif // def RELEASE +using get_function_pointer_fn = void(*)(uint32_t mono_image_index, uint32_t class_index, uint32_t method_token, void*& target_ptr); MONO_API MONO_API_EXPORT void xamarin_app_init (JNIEnv *env, get_function_pointer_fn fn) noexcept; -#endif // def RELEASE #endif // __XAMARIN_ANDROID_TYPEMAP_H