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