From 5c4e97bc3172cc08f52bbd2519cf6dc98f24b731 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 24 Jan 2023 11:25:07 -0500 Subject: [PATCH 1/6] Bump to xamarin/monodroid/main@50faac94 (#7725) Fixes: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1714340 Fixes: https://developercommunity.visualstudio.com/t/Unable-to-debug-XamarinAndroid-system-a/10247269 Changes: https://github.com/xamarin/monodroid/compare/2b9c9d01820c8df4541157f6b6116852eba73350...50faac94c6a0c27864564829ac83f3988c82f8ef * xamarin/monodroid@50faac94c: [tools/msbuild] Review RegisterTaskObject() use (xamarin/monodroid#1281) * xamarin/monodroid@83e997ab5: Bump to xamarin/androidtools/main@f11d1635 (xamarin/monodroid#1286) * xamarin/monodroid@db636fc7a: [tools/msbuild] Fix System App detection (xamarin/monodroid#1284) --- .external | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.external b/.external index 9be67b56e6a..1f60e2f5032 100644 --- a/.external +++ b/.external @@ -1,2 +1,2 @@ -xamarin/monodroid:main@2b9c9d01820c8df4541157f6b6116852eba73350 +xamarin/monodroid:main@50faac94c6a0c27864564829ac83f3988c82f8ef mono/mono:2020-02@6dd9def57ce969ca04a0ecd9ef72c0a8f069112d From 953cd1939d309e0affe610728a79ede865a3bb75 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 24 Jan 2023 17:48:52 +0000 Subject: [PATCH 2/6] [Xamarin.Android.Build.Tasks] fix AndroidGenerateResourceDesigner (#7721) Context: dc3ccf28cdbe9f8c0a705400b83c11a85c81a980 Context: https://github.com/dotnet/maui/pull/12520 When `_Microsoft.Android.Resource.Designer.dll` is used (dc3ccf28) and [`$(AndroidGenerateResourceDesigner)`][0]=False, the `__Microsoft.Android.Resource.Designer.cs` file is still generated, which is *equivalent* to `Resource.designer.cs`. This causes a `Resource` type to be generated. This showed up when attempting to bump MAUI to use xamarin-android for .NET 8 (dotnet/maui#12520), which [introduced][1] *lots* of `*.Resource` types which are *not desirable*. Fix this so that when `$(AndroidGenerateResourceDesigner)`=False the `__Microsoft.Android.Resource.Designer.*` files are *not* created. This prevents `*.Resource` types from being added to the assembly. Note that `_Microsoft.Android.Resource.Designer.dll` is still created at build time. A unit test has been updated to test this change. [0]: https://learn.microsoft.com/en-us/xamarin/android/deploy-test/building-apps/build-properties#androidgenerateresourcedesigner [1]: https://github.com/dotnet/maui/pull/12520/commits/2e4981257c1203a9dea935b4b39979859b770c33 --- .../Xamarin.Android.Resource.Designer.targets | 6 +- ...soft.Android.Sdk.DefaultProperties.targets | 4 +- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 58 ++++++++++++++++++- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets index f5b225179bb..d0943e16bb9 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets @@ -93,7 +93,7 @@ Copyright (C) 2016 Xamarin. All rights reserved. @@ -166,11 +166,11 @@ Copyright (C) 2016 Xamarin. All rights reserved. PreserveNewest - + - + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets index 43ed246a334..51ed5880c64 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets @@ -10,9 +10,9 @@ true Xamarin.Android.Net.AndroidMessageHandler Xamarin.Android.Net.AndroidClientHandler - true - false true + true + false $(AndroidGenerateResourceDesigner) false false diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 062e7fadbca..2ded510c810 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -455,7 +455,54 @@ public void AppWithSingleJar () } [Test] - public void GenerateResourceDesigner_false() + public void GenerateResourceDesigner([Values (false, true)] bool generateResourceDesigner, [Values (false, true)] bool useDesignerAssembly) + { + var path = Path.Combine ("temp", TestName); + var libraryB = new XASdkProject (outputType: "Library") { + ProjectName = "LibraryB", + }; + libraryB.Sources.Clear (); + libraryB.Sources.Add (new BuildItem.Source ("Foo.cs") { + TextContent = () => @"namespace LibraryB; +public class Foo { + public static int foo => Resource.Drawable.foo; +}", + }); + libraryB.Sources.Add (new AndroidItem.AndroidResource (() => "Resources\\drawable\\foo.png") { + BinaryContent = () => XamarinAndroidCommonProject.icon_binary_mdpi, + }); + libraryB.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ()); + var libraryA = new XASdkProject (outputType: "Library") { + ProjectName = "LibraryA", + }; + libraryA.Sources.Clear (); + libraryA.Sources.Add (new BuildItem.Source ("FooA.cs") { + TextContent = () => @"namespace LibraryA; +public class FooA { + public int foo => 0; + public int foo2 => LibraryB.Foo.foo; + public int foo3 => LibraryB.Resource.Drawable.foo; +}", + }); + libraryA.AddReference (libraryB); + libraryA.SetProperty ("AndroidGenerateResourceDesigner", generateResourceDesigner.ToString ()); + if (!useDesignerAssembly) + libraryA.SetProperty ("AndroidUseDesignerAssembly", "False"); + var libraryBBuilder = CreateDotNetBuilder (libraryB, Path.Combine (path, libraryB.ProjectName)); + Assert.IsTrue (libraryBBuilder.Build (), "Build of LibraryB should succeed."); + var libraryABuilder = CreateDotNetBuilder (libraryA, Path.Combine (path, libraryA.ProjectName)); + Assert.IsTrue (libraryABuilder.Build (), "Build of LibraryA should succeed."); + var proj = new XASdkProject () { + ProjectName = "App1", + }; + proj.SetProperty ("AndroidUseDesignerAssembly", useDesignerAssembly.ToString ()); + proj.AddReference (libraryA); + var dotnet = CreateDotNetBuilder (proj, Path.Combine (path, proj.ProjectName)); + Assert.IsTrue (dotnet.Build (), "Build of Proj should succeed."); + } + + [Test] + public void GenerateResourceDesigner_false([Values (false, true)] bool useDesignerAssembly) { var proj = new XASdkProject (outputType: "Library") { Sources = { @@ -466,7 +513,8 @@ public void GenerateResourceDesigner_false() }; // Turn off Resource.designer.cs and remove usage of it proj.SetProperty ("AndroidGenerateResourceDesigner", "false"); - proj.SetProperty ("AndroidUseDesignerAssembly", "false"); + if (!useDesignerAssembly) + proj.SetProperty ("AndroidUseDesignerAssembly", "false"); proj.MainActivity = proj.DefaultMainActivity .Replace ("Resource.Layout.Main", "0") .Replace ("Resource.Id.myButton", "0"); @@ -475,11 +523,15 @@ public void GenerateResourceDesigner_false() Assert.IsTrue (dotnet.Build(target: "CoreCompile", parameters: new string[] { "BuildingInsideVisualStudio=true" }), "Designtime build should succeed."); var intermediate = Path.Combine (FullProjectDirectory, proj.IntermediateOutputPath); var resource_designer_cs = Path.Combine (intermediate, "designtime", "Resource.designer.cs"); + if (useDesignerAssembly) + resource_designer_cs = Path.Combine (intermediate, "__Microsoft.Android.Resource.Designer.cs"); FileAssert.DoesNotExist (resource_designer_cs); Assert.IsTrue (dotnet.Build (), "build should succeed"); - resource_designer_cs = Path.Combine (intermediate, "Resource.designer.cs"); + resource_designer_cs = Path.Combine (intermediate, "Resource.designer.cs"); + if (useDesignerAssembly) + resource_designer_cs = Path.Combine (intermediate, "__Microsoft.Android.Resource.Designer.cs"); FileAssert.DoesNotExist (resource_designer_cs); var assemblyPath = Path.Combine (FullProjectDirectory, proj.OutputPath, $"{proj.ProjectName}.dll"); From 2775ce03e36d82f159e486a4bfbe95e90a6712e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 13:54:55 -0500 Subject: [PATCH 3/6] Bump to xamarin/Java.Interop/main@1366d99 (#7718) Changes: https://github.com/xamarin/java.interop/compare/cf80deb7d2ad3c79abfd0140e4adee4376b41af5...1366d998c5662c2ada9a069c7df4428b13f58175 * xamarin/java.interop@1366d998: [Java.Interop.Tools.JavaCallableWrappers] use less System.Linq for CAs (xamarin/java.interop#1072) * xamarin/java.interop@bde306d5: [Java.Interop.Tools.JavaCallableWrappers] JavaTypeScanner.GetJavaTypes (xamarin/java.interop#1076) * xamarin/java.interop@f03088e7: [Java.Interop.Tools.JavaCallableWrappers] IMetadataResolver redux (xamarin/java.interop#1075) * xamarin/java.interop@e11d0242: [lgtm] Fix LGTM-reported issues. (xamarin/java.interop#1074) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index cf80deb7d2a..1366d998c56 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit cf80deb7d2ad3c79abfd0140e4adee4376b41af5 +Subproject commit 1366d998c5662c2ada9a069c7df4428b13f58175 From b259967696c661587fe9e86d78127b72162bdcc1 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 25 Jan 2023 11:43:55 -0600 Subject: [PATCH 4/6] [build] bump `$(AndroidNet7Version)` (#7737) Context: https://www.nuget.org/packages/Microsoft.NET.Sdk.Android.Manifest-7.0.100/33.0.26 33.0.26 is the version of the latest `android` workload in .NET 7. Bump to this version, so we will rely on those packs in .NET 8. Previously we were using an older build, I noticed the issue when trying to dogfood .NET 8 builds on macOS: Workload installation failed: microsoft.android.sdk.darwin::33.0.1 is not found in NuGet feeds --- Configuration.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration.props b/Configuration.props index 3c15d7e702a..e93828c5fae 100644 --- a/Configuration.props +++ b/Configuration.props @@ -47,7 +47,7 @@ portable True latest - 33.0.1 + 33.0.26 32.0.485 From adcda0386b906da50a5111b6b46486086b9547b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Jan 2023 14:24:25 -0500 Subject: [PATCH 5/6] Bump to xamarin/Java.Interop/main@8a1ae57 (#7738) Changes: https://github.com/xamarin/java.interop/compare/1366d998c5662c2ada9a069c7df4428b13f58175...8a1ae5710ab00f7af3abbb3e7c45479f0d4cfeb5 * xamarin/java.interop@8a1ae571: Bump to xamarin/xamarin-android-tools/main@099fd95f (xamarin/java.interop#1073) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index 1366d998c56..8a1ae5710ab 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 1366d998c5662c2ada9a069c7df4428b13f58175 +Subproject commit 8a1ae5710ab00f7af3abbb3e7c45479f0d4cfeb5 From c990148cb88214cf0941a4ab316a33df22d3c7c4 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Thu, 26 Jan 2023 00:03:05 +0100 Subject: [PATCH 6/6] [monodroid] Replace `exit()` with `abort()` in native code (#7734) Context: https://discord.com/channels/732297728826277939/732297837953679412/1067806732983746621 Context: https://discord.com/channels/732297728826277939/732297837953679412/1067822882274689024 In certain "bad app" scenarios, we would print a message and then **exit**(3) the app. The problem with using `exit()` in this manner is that it *can* result in the app constantly relaunching, "spamming" the UI. Improve this by calling **abort**(3) instead. This prevents Android from constantly re-launching the app, and also prints useful abort information such as registers and a native stack trace to `adb logcat`. Unexpectedly, however, "simply" replacing app calls to `exit()` with calls to `abort()` resulted in `libmonodroid.so` increasing in size by ~16%. For some reason, calling `abort()` caused the compiler to inline much more code and in a weird manner (it repeated essentially identical blocks of code from an inlined function, which were previously folded into a single block when `exit()` was used). We found that consolidating the `abort()` calls into `Helpers::abort_application()` removed the size increase. --- src/monodroid/CMakeLists.txt | 2 ++ src/monodroid/jni/cpp-util.hh | 3 ++- src/monodroid/jni/cxx-abi/terminate.cc | 4 ++- src/monodroid/jni/debug-app-helper.cc | 4 +-- src/monodroid/jni/debug.cc | 4 +-- src/monodroid/jni/embedded-assemblies-zip.cc | 22 ++++++++-------- src/monodroid/jni/embedded-assemblies.cc | 26 +++++++++---------- src/monodroid/jni/helpers.cc | 9 +++++++ src/monodroid/jni/helpers.hh | 9 ++++--- src/monodroid/jni/mono-log-adapter.cc | 2 +- src/monodroid/jni/monodroid-glue.cc | 24 ++++++++--------- src/monodroid/jni/new_delete.cc | 4 ++- src/monodroid/jni/pinvoke-override-api.cc | 2 +- src/monodroid/jni/strings.hh | 6 ++--- src/monodroid/jni/timezones.cc | 2 +- src/monodroid/jni/util.cc | 4 +-- .../jni/xamarin-android-app-context.cc | 4 +-- 17 files changed, 74 insertions(+), 57 deletions(-) create mode 100644 src/monodroid/jni/helpers.cc diff --git a/src/monodroid/CMakeLists.txt b/src/monodroid/CMakeLists.txt index 7f45848792b..8a6951991f9 100644 --- a/src/monodroid/CMakeLists.txt +++ b/src/monodroid/CMakeLists.txt @@ -486,6 +486,7 @@ set(XAMARIN_MONODROID_SOURCES ${SOURCES_DIR}/embedded-assemblies.cc ${SOURCES_DIR}/embedded-assemblies-zip.cc ${SOURCES_DIR}/globals.cc + ${SOURCES_DIR}/helpers.cc ${SOURCES_DIR}/logger.cc ${SOURCES_DIR}/jni-remapping.cc ${SOURCES_DIR}/monodroid-glue.cc @@ -564,6 +565,7 @@ set(XAMARIN_DEBUG_APP_HELPER_SOURCES ${SOURCES_DIR}/basic-utilities.cc ${SOURCES_DIR}/cpu-arch-detect.cc ${SOURCES_DIR}/debug-app-helper.cc + ${SOURCES_DIR}/helpers.cc ${SOURCES_DIR}/new_delete.cc ${SOURCES_DIR}/shared-constants.cc ) diff --git a/src/monodroid/jni/cpp-util.hh b/src/monodroid/jni/cpp-util.hh index 55d4505bb1a..641e506d256 100644 --- a/src/monodroid/jni/cpp-util.hh +++ b/src/monodroid/jni/cpp-util.hh @@ -17,6 +17,7 @@ #include "cppcompat.hh" #include "platform-compat.hh" +#include "helpers.hh" static inline void do_abort_unless (const char* fmt, ...) @@ -32,7 +33,7 @@ do_abort_unless (const char* fmt, ...) #endif // ndef ANDROID va_end (ap); - std::abort (); + xamarin::android::Helpers::abort_application (); } #define abort_unless(_condition_, _fmt_, ...) \ diff --git a/src/monodroid/jni/cxx-abi/terminate.cc b/src/monodroid/jni/cxx-abi/terminate.cc index 3379cbbcaef..e38da64b034 100644 --- a/src/monodroid/jni/cxx-abi/terminate.cc +++ b/src/monodroid/jni/cxx-abi/terminate.cc @@ -6,11 +6,13 @@ #include #include +#include "helpers.hh" + namespace std { [[noreturn]] void terminate () noexcept { __android_log_write (ANDROID_LOG_FATAL, "monodroid", "std::terminate() called. Aborting."); - abort (); + xamarin::android::Helpers::abort_application (); } } diff --git a/src/monodroid/jni/debug-app-helper.cc b/src/monodroid/jni/debug-app-helper.cc index e47daf8bdef..e79c62b238d 100644 --- a/src/monodroid/jni/debug-app-helper.cc +++ b/src/monodroid/jni/debug-app-helper.cc @@ -91,7 +91,7 @@ Java_mono_android_DebugRuntime_init (JNIEnv *env, [[maybe_unused]] jclass klass, void *monosgen = dlopen (monosgen_path, RTLD_LAZY | RTLD_GLOBAL); if (monosgen == nullptr) { log_fatal (LOG_DEFAULT, "Failed to dlopen Mono runtime from %s: %s", monosgen_path, dlerror ()); - exit (FATAL_EXIT_CANNOT_FIND_LIBMONOSGEN); + Helpers::abort_application (); } } @@ -276,7 +276,7 @@ get_libmonosgen_path () log_fatal (LOG_DEFAULT, "Do you have a shared runtime build of your app with AndroidManifest.xml android:minSdkVersion < 10 while running on a 64-bit Android 5.0 target? This combination is not supported."); log_fatal (LOG_DEFAULT, "Please either set android:minSdkVersion >= 10 or use a build without the shared runtime (like default Release configuration)."); - exit (FATAL_EXIT_CANNOT_FIND_LIBMONOSGEN); + Helpers::abort_application (); return libmonoso; } diff --git a/src/monodroid/jni/debug.cc b/src/monodroid/jni/debug.cc index d3959e44033..3b911106a99 100644 --- a/src/monodroid/jni/debug.cc +++ b/src/monodroid/jni/debug.cc @@ -248,7 +248,7 @@ Debug::start_debugging_and_profiling () DebuggerConnectionStatus res = start_connection (connect_args); if (res == DebuggerConnectionStatus::Error) { log_fatal (LOG_DEBUGGER, "Could not start a connection to the debugger with connection args '%s'.", connect_args); - exit (FATAL_EXIT_DEBUGGER_CONNECT); + Helpers::abort_application (); } else if (res == DebuggerConnectionStatus::Connected) { /* Wait for XS to configure debugging/profiling */ gettimeofday(&wait_tv, nullptr); @@ -655,7 +655,7 @@ xamarin::android::conn_thread (void *arg) res = instance->handle_server_connection (); if (res && res != 3) { log_fatal (LOG_DEBUGGER, "Error communicating with the IDE, exiting..."); - exit (FATAL_EXIT_DEBUGGER_CONNECT); + Helpers::abort_application (); } return nullptr; diff --git a/src/monodroid/jni/embedded-assemblies-zip.cc b/src/monodroid/jni/embedded-assemblies-zip.cc index d44a8344f7b..f7be28a631e 100644 --- a/src/monodroid/jni/embedded-assemblies-zip.cc +++ b/src/monodroid/jni/embedded-assemblies-zip.cc @@ -47,12 +47,12 @@ EmbeddedAssemblies::zip_load_entry_common (size_t entry_index, std::vector { if (number_of_mapped_assembly_stores >= application_config.number_of_assembly_store_files) { log_fatal (LOG_ASSEMBLY, "Too many assembly stores. Expected at most %u", application_config.number_of_assembly_store_files); - abort (); + Helpers::abort_application (); } md_mmap_info assembly_store_map = md_mmap_apk_file (state.apk_fd, state.data_offset, state.file_size, entry_name.get ()); @@ -182,12 +182,12 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string if (header->magic != ASSEMBLY_STORE_MAGIC) { log_fatal (LOG_ASSEMBLY, "Assembly store '%s' is not a valid Xamarin.Android assembly store file", entry_name.get ()); - abort (); + Helpers::abort_application (); } if (header->version > ASSEMBLY_STORE_FORMAT_VERSION) { log_fatal (LOG_ASSEMBLY, "Assembly store '%s' uses format v%u which is not understood by this version of Xamarin.Android", entry_name.get (), header->version); - abort (); + Helpers::abort_application (); } if (header->store_id >= application_config.number_of_assembly_store_files) { @@ -198,13 +198,13 @@ EmbeddedAssemblies::map_assembly_store (dynamic_local_string header->store_id, application_config.number_of_assembly_store_files ); - abort (); + Helpers::abort_application (); } AssemblyStoreRuntimeData &rd = assembly_stores[header->store_id]; if (rd.data_start != nullptr) { log_fatal (LOG_ASSEMBLY, "Assembly store '%s' has a duplicate ID (%u)", entry_name.get (), header->store_id); - abort (); + Helpers::abort_application (); } constexpr size_t header_size = sizeof(AssemblyStoreHeader); @@ -277,7 +277,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus if (!zip_read_cd_info (fd, cd_offset, cd_size, cd_entries)) { log_fatal (LOG_ASSEMBLY, "Failed to read the EOCD record from APK file %s", apk_name); - exit (FATAL_EXIT_NO_ASSEMBLIES); + Helpers::abort_application (); } #ifdef DEBUG log_info (LOG_ASSEMBLY, "Central directory offset: %u", cd_offset); @@ -287,7 +287,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus off_t retval = ::lseek (fd, static_cast(cd_offset), SEEK_SET); if (retval < 0) { log_fatal (LOG_ASSEMBLY, "Failed to seek to central directory position in the APK file %s. %s (result: %d; errno: %d)", apk_name, std::strerror (errno), retval, errno); - exit (FATAL_EXIT_NO_ASSEMBLIES); + Helpers::abort_application (); } std::vector buf (cd_size); @@ -306,7 +306,7 @@ EmbeddedAssemblies::zip_load_entries (int fd, const char *apk_name, [[maybe_unus ssize_t nread = read (fd, buf.data (), static_cast(buf.size ())); if (static_cast(nread) != cd_size) { log_fatal (LOG_ASSEMBLY, "Failed to read Central Directory from the APK archive %s. %s (nread: %d; errno: %d)", apk_name, std::strerror (errno), nread, errno); - exit (FATAL_EXIT_NO_ASSEMBLIES); + Helpers::abort_application (); } if (application_config.have_assembly_store) { diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc index de453cd2990..3550435dc75 100644 --- a/src/monodroid/jni/embedded-assemblies.cc +++ b/src/monodroid/jni/embedded-assemblies.cc @@ -81,11 +81,11 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (header->magic == COMPRESSED_DATA_MAGIC) { if (XA_UNLIKELY (compressed_assemblies.descriptors == nullptr)) { log_fatal (LOG_ASSEMBLY, "Compressed assembly found but no descriptor defined"); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } if (XA_UNLIKELY (header->descriptor_index >= compressed_assemblies.count)) { log_fatal (LOG_ASSEMBLY, "Invalid compressed assembly descriptor index %u", header->descriptor_index); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } CompressedAssemblyDescriptor &cad = compressed_assemblies.descriptors[header->descriptor_index]; @@ -93,7 +93,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (!cad.loaded) { if (XA_UNLIKELY (cad.data == nullptr)) { log_fatal (LOG_ASSEMBLY, "Invalid compressed assembly descriptor at %u: no data", header->descriptor_index); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } bool log_timing = FastTiming::enabled () && !FastTiming::is_bare_mode (); @@ -105,7 +105,7 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (header->uncompressed_length != cad.uncompressed_file_size) { if (header->uncompressed_length > cad.uncompressed_file_size) { log_fatal (LOG_ASSEMBLY, "Compressed assembly '%s' is larger than when the application was built (expected at most %u, got %u). Assemblies don't grow just like that!", name, cad.uncompressed_file_size, header->uncompressed_length); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } else { log_debug (LOG_ASSEMBLY, "Compressed assembly '%s' is smaller than when the application was built. Adjusting accordingly.", name); } @@ -122,12 +122,12 @@ EmbeddedAssemblies::get_assembly_data (uint8_t *data, uint32_t data_size, [[mayb if (ret < 0) { log_fatal (LOG_ASSEMBLY, "Decompression of assembly %s failed with code %d", name, ret); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } if (static_cast(ret) != cad.uncompressed_file_size) { log_debug (LOG_ASSEMBLY, "Decompression of assembly %s yielded a different size (expected %lu, got %u)", name, cad.uncompressed_file_size, static_cast(ret)); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } cad.loaded = true; } @@ -371,20 +371,20 @@ EmbeddedAssemblies::assembly_store_open_from_bundles (dynamic_local_stringmapping_index >= application_config.number_of_assemblies_in_apk) { log_fatal (LOG_ASSEMBLY, "Invalid assembly index %u, exceeds the maximum index of %u", hash_entry->mapping_index, application_config.number_of_assemblies_in_apk - 1); - abort (); + Helpers::abort_application (); } AssemblyStoreSingleAssemblyRuntimeData &assembly_runtime_info = assembly_store_bundled_assemblies[hash_entry->mapping_index]; if (assembly_runtime_info.image_data == nullptr) { if (hash_entry->store_id >= application_config.number_of_assembly_store_files) { log_fatal (LOG_ASSEMBLY, "Invalid assembly store ID %u, exceeds the maximum of %u", hash_entry->store_id, application_config.number_of_assembly_store_files - 1); - abort (); + Helpers::abort_application (); } AssemblyStoreRuntimeData &rd = assembly_stores[hash_entry->store_id]; if (hash_entry->local_store_index >= rd.assembly_count) { log_fatal (LOG_ASSEMBLY, "Invalid index %u into local store assembly descriptor array", hash_entry->local_store_index); - abort (); + Helpers::abort_application (); } AssemblyStoreAssemblyDescriptor *bba = &rd.assemblies[hash_entry->local_store_index]; @@ -553,7 +553,7 @@ EmbeddedAssemblies::binary_search (const Key *key, const Entry *base, size_t nme // This is a coding error on our part, crash! if (base == nullptr) { log_fatal (LOG_ASSEMBLY, "Map address not passed to binary_search"); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } [[maybe_unused]] @@ -912,7 +912,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, size_t size, cons if (mmap_info.area == MAP_FAILED) { log_fatal (LOG_DEFAULT, "Could not `mmap` apk fd %d entry `%s`: %s", fd, filename, strerror (errno)); - exit (FATAL_EXIT_CANNOT_FIND_APK); + Helpers::abort_application (); } mmap_info.size = offsetSize; @@ -933,7 +933,7 @@ EmbeddedAssemblies::gather_bundled_assemblies_from_apk (const char* apk, monodro if ((fd = open (apk, O_RDONLY)) < 0) { log_error (LOG_DEFAULT, "ERROR: Unable to load application package %s.", apk); - exit (FATAL_EXIT_NO_ASSEMBLIES); + Helpers::abort_application (); } log_info (LOG_ASSEMBLY, "APK %s FD: %d", apk, fd); @@ -1202,7 +1202,7 @@ EmbeddedAssemblies::try_load_typemaps_from_directory (const char *path) std::unique_ptr index_data = typemap_load_index (dir_fd, dir_path.get (), index_name); if (!index_data) { log_fatal (LOG_ASSEMBLY, "typemap: unable to load TypeMap data index from '%s/%s'", dir_path.get (), index_name); - exit (FATAL_EXIT_NO_ASSEMBLIES); // TODO: use a new error code here + Helpers::abort_application (); } for (size_t i = 0; i < type_map_count; i++) { diff --git a/src/monodroid/jni/helpers.cc b/src/monodroid/jni/helpers.cc new file mode 100644 index 00000000000..e3103c04597 --- /dev/null +++ b/src/monodroid/jni/helpers.cc @@ -0,0 +1,9 @@ +#include "helpers.hh" + +using namespace xamarin::android; + +[[noreturn]] void +Helpers::abort_application () noexcept +{ + std::abort (); +} diff --git a/src/monodroid/jni/helpers.hh b/src/monodroid/jni/helpers.hh index 2ea8f8ca197..2725b4d428c 100644 --- a/src/monodroid/jni/helpers.hh +++ b/src/monodroid/jni/helpers.hh @@ -2,6 +2,7 @@ #define __HELPERS_HH #include +#include #include "java-interop-util.h" #include "platform-compat.hh" @@ -21,8 +22,7 @@ namespace xamarin::android if (XA_UNLIKELY (__builtin_add_overflow (a, b, &ret))) { log_fatal (LOG_DEFAULT, "Integer overflow on addition at %s:%u", file, line); - exit (FATAL_EXIT_OUT_OF_MEMORY); - return static_cast(0); + abort_application (); } return ret; @@ -46,12 +46,13 @@ namespace xamarin::android if (XA_UNLIKELY (__builtin_mul_overflow (a, b, &ret))) { log_fatal (LOG_DEFAULT, "Integer overflow on multiplication at %s:%u", file, line); - exit (FATAL_EXIT_OUT_OF_MEMORY); - return static_cast(0); + abort_application (); } return ret; } + + [[noreturn]] static void abort_application () noexcept; }; } #endif // __HELPERS_HH diff --git a/src/monodroid/jni/mono-log-adapter.cc b/src/monodroid/jni/mono-log-adapter.cc index beda04c2c6f..da8e4ee3a52 100644 --- a/src/monodroid/jni/mono-log-adapter.cc +++ b/src/monodroid/jni/mono-log-adapter.cc @@ -43,7 +43,7 @@ MonodroidRuntime::mono_log_handler (const char *log_domain, const char *log_leve __android_log_write (prio, log_domain, message); if (fatal) { - abort (); + Helpers::abort_application (); } } diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc index 7fb2a67dcb3..18e13c1a016 100644 --- a/src/monodroid/jni/monodroid-glue.cc +++ b/src/monodroid/jni/monodroid-glue.cc @@ -205,7 +205,7 @@ MonodroidRuntime::setup_bundled_app (const char *dso_name) log_info (LOG_DEFAULT, "No libapp!"); if (!androidSystem.is_embedded_dso_mode_enabled ()) { log_fatal (LOG_BUNDLE, "bundled app initialization error"); - exit (FATAL_EXIT_CANNOT_LOAD_BUNDLE); + Helpers::abort_application (); } else { log_info (LOG_BUNDLE, "bundled app not found in the APK, ignoring."); return; @@ -236,7 +236,7 @@ MonodroidRuntime::thread_start ([[maybe_unused]] MonoProfiler *prof, [[maybe_unu if (r != JNI_OK) { #if DEBUG log_fatal (LOG_DEFAULT, "ERROR: Unable to attach current thread to the Java VM!"); - exit (FATAL_EXIT_ATTACH_JVM_FAILED); + Helpers::abort_application (); #endif } } @@ -733,7 +733,7 @@ MonodroidRuntime::mono_runtime_init ([[maybe_unused]] dynamic_local_stringhandle_type, info->refs_added, info->weak_handle); - abort (); + Helpers::abort_application (); } } @@ -1291,7 +1291,7 @@ MonodroidRuntime::init_internal_api_dso (void *handle) { if (handle == nullptr) { log_fatal (LOG_DEFAULT, "Internal API library is required"); - exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); + Helpers::abort_application (); } // There's a very, very small chance of a race condition here, but it should be acceptable and we can save some time @@ -1314,7 +1314,7 @@ MonodroidRuntime::init_internal_api_dso (void *handle) // We COULD ignore this situation, but if the function is missing it means we messed something up and thus // it *is* a fatal error. log_fatal (LOG_DEFAULT, "Unable to properly close Internal API library, shutdown function '%s' not found in the module", MonoAndroidInternalCalls::SHUTDOWN_FUNCTION_NAME); - exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); + Helpers::abort_application (); } api_shutdown (); } @@ -1324,13 +1324,13 @@ MonodroidRuntime::init_internal_api_dso (void *handle) auto api_init = reinterpret_cast(java_interop_lib_symbol (handle, MonoAndroidInternalCalls::INIT_FUNCTION_NAME, nullptr)); if (api_init == nullptr) { log_fatal (LOG_DEFAULT, "Unable to initialize Internal API library, init function '%s' not found in the module", MonoAndroidInternalCalls::INIT_FUNCTION_NAME); - exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); + Helpers::abort_application (); } log_debug (LOG_DEFAULT, "Initializing Internal API library %p", handle); if (!api_init (api)) { log_fatal (LOG_DEFAULT, "Failed to initialize Internal API library"); - exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); + Helpers::abort_application (); } } #endif // ndef NET diff --git a/src/monodroid/jni/new_delete.cc b/src/monodroid/jni/new_delete.cc index 2e853a501f6..074dfe35610 100644 --- a/src/monodroid/jni/new_delete.cc +++ b/src/monodroid/jni/new_delete.cc @@ -1,5 +1,7 @@ #include +#include "helpers.hh" + namespace std { struct nothrow_t {}; @@ -21,7 +23,7 @@ operator new (size_t size) void* p = do_alloc (size); if (p == nullptr) { log_fatal (LOG_DEFAULT, "Out of memory in the `new` operator"); - exit (FATAL_EXIT_OUT_OF_MEMORY); + xamarin::android::Helpers::abort_application (); } return p; diff --git a/src/monodroid/jni/pinvoke-override-api.cc b/src/monodroid/jni/pinvoke-override-api.cc index 8b82f971541..ab808b33646 100644 --- a/src/monodroid/jni/pinvoke-override-api.cc +++ b/src/monodroid/jni/pinvoke-override-api.cc @@ -531,7 +531,7 @@ MonodroidRuntime::monodroid_pinvoke_override (const char *library_name, const ch PinvokeEntry const& e = internal_pinvokes[i]; log_fatal (LOG_ASSEMBLY, "\t'%s'=%p (hash: 0x%zx)", e.name, e.func, e.hash); } - abort (); + Helpers::abort_application (); } return entry->func; diff --git a/src/monodroid/jni/strings.hh b/src/monodroid/jni/strings.hh index dc9c718f633..bf41b519b44 100644 --- a/src/monodroid/jni/strings.hh +++ b/src/monodroid/jni/strings.hh @@ -541,7 +541,7 @@ namespace xamarin::android::internal size_t slen = strlen (s); if (offset + count > slen) { log_fatal (LOG_DEFAULT, "Attempt to assign data from a string exceeds the source string length"); - exit (1); + Helpers::abort_application (); } } @@ -746,7 +746,7 @@ namespace xamarin::android::internal "Index %u is out of range (0 - %u)", access_index, idx ); - exit (1); + Helpers::abort_application (); } force_inline void ensure_have_extra (size_t length) noexcept @@ -758,7 +758,7 @@ namespace xamarin::android::internal "Attempt to store too much data in a buffer (capacity: %u; exceeded by: %u)", buffer.size (), needed_space - buffer.size () ); - abort (); + Helpers::abort_application (); } } diff --git a/src/monodroid/jni/timezones.cc b/src/monodroid/jni/timezones.cc index 4d04351e20a..4e8a31df37f 100644 --- a/src/monodroid/jni/timezones.cc +++ b/src/monodroid/jni/timezones.cc @@ -40,7 +40,7 @@ init () if (AndroidEnvironment_NotifyTimeZoneChanged == nullptr) { log_fatal (LOG_DEFAULT, "Unable to find Android.Runtime.AndroidEnvironment.NotifyTimeZoneChanged()!"); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } } diff --git a/src/monodroid/jni/util.cc b/src/monodroid/jni/util.cc index 7f9d4930487..ecc4a8f05f0 100644 --- a/src/monodroid/jni/util.cc +++ b/src/monodroid/jni/util.cc @@ -158,7 +158,7 @@ Util::monodroid_load_assembly (MonoAssemblyLoadContextGCHandle alc_handle, const if (assm == nullptr || status != MonoImageOpenStatus::MONO_IMAGE_OK) { log_fatal (LOG_DEFAULT, "Unable to find assembly '%s'.", basename); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } return assm; } @@ -186,7 +186,7 @@ Util::monodroid_load_assembly (MonoDomain *domain, const char *basename) if (!assm) { log_fatal (LOG_DEFAULT, "Unable to find assembly '%s'.", basename); - exit (FATAL_EXIT_MISSING_ASSEMBLY); + Helpers::abort_application (); } return assm; } diff --git a/src/monodroid/jni/xamarin-android-app-context.cc b/src/monodroid/jni/xamarin-android-app-context.cc index e54ae912b06..3654491b944 100644 --- a/src/monodroid/jni/xamarin-android-app-context.cc +++ b/src/monodroid/jni/xamarin-android-app-context.cc @@ -52,7 +52,7 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas marshal_methods_number_of_classes - 1, class_index ); - abort (); + Helpers::abort_application (); } // We need to do that, as Mono APIs cannot be invoked from threads that aren't attached to the runtime. @@ -111,7 +111,7 @@ MonodroidRuntime::get_function_pointer (uint32_t mono_image_index, uint32_t clas } } - abort (); + Helpers::abort_application (); } void